2 * Copyright (c) 2018 Microsemi Corporation.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include "smartpqi_includes.h"
32 * Function used to validate the adapter health.
34 boolean_t pqisrc_ctrl_offline(pqisrc_softstate_t *softs)
40 return !softs->ctrl_online;
43 /* Function used set/clear legacy INTx bit in Legacy Interrupt INTx
44 * mask clear pqi register
46 void pqisrc_configure_legacy_intx(pqisrc_softstate_t *softs, boolean_t enable_intx)
49 uint32_t *reg_addr = NULL;
54 reg_addr = &softs->pqi_reg->legacy_intr_mask_clr;
56 reg_addr = &softs->pqi_reg->legacy_intr_mask_set;
58 intx_mask = PCI_MEM_GET32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR);
59 intx_mask |= PQISRC_LEGACY_INTX_MASK;
60 PCI_MEM_PUT32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR ,intx_mask);
66 * Function used to take exposed devices to OS as offline.
68 void pqisrc_take_devices_offline(pqisrc_softstate_t *softs)
70 pqi_scsi_dev_t *device = NULL;
74 for(i = 0; i < PQI_MAX_DEVICES; i++) {
75 for(j = 0; j < PQI_MAX_MULTILUN; j++) {
76 if(softs->device_list[i][j] == NULL)
78 device = softs->device_list[i][j];
79 pqisrc_remove_device(softs, device);
87 * Function used to take adapter offline.
89 void pqisrc_take_ctrl_offline(pqisrc_softstate_t *softs)
94 softs->ctrl_online = false;
95 pqisrc_trigger_nmi_sis(softs);
96 os_complete_outstanding_cmds_nodevice(softs);
97 pqisrc_take_devices_offline(softs);
103 * Timer handler for the adapter heart-beat.
105 void pqisrc_heartbeat_timer_handler(pqisrc_softstate_t *softs)
108 uint8_t take_offline = false;
112 num_intrs = OS_ATOMIC64_READ(softs, num_intrs);
114 if (PQI_NEW_HEARTBEAT_MECHANISM(softs)) {
115 if (CTRLR_HEARTBEAT_CNT(softs) == softs->prev_heartbeat_count) {
117 goto take_ctrl_offline;
119 softs->prev_heartbeat_count = CTRLR_HEARTBEAT_CNT(softs);
120 DBG_INFO("CTRLR_HEARTBEAT_CNT(softs) = %lx \
121 softs->prev_heartbeat_count = %lx\n",
122 CTRLR_HEARTBEAT_CNT(softs), softs->prev_heartbeat_count);
124 if (num_intrs == softs->prev_num_intrs) {
125 softs->num_heartbeats_requested++;
126 if (softs->num_heartbeats_requested > PQI_MAX_HEARTBEAT_REQUESTS) {
128 goto take_ctrl_offline;
130 softs->pending_events[PQI_EVENT_HEARTBEAT].pending = true;
132 pqisrc_ack_all_events((void*)softs);
135 softs->num_heartbeats_requested = 0;
137 softs->prev_num_intrs = num_intrs;
142 DBG_ERR("controller is offline\n");
143 pqisrc_take_ctrl_offline(softs);
144 os_stop_heartbeat_timer(softs);
150 * Conditional variable management routine for internal commands.
152 int pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb){
155 int ret = PQI_STATUS_SUCCESS;
156 uint32_t loop_cnt = 0;
158 while (rcb->req_pending == true) {
159 OS_SLEEP(500); /* Micro sec */
161 /*Polling needed for FreeBSD : since ithread routine is not scheduled
162 during bootup, we could use polling until interrupts are
163 enabled (using 'if (cold)'to check for the boot time before
164 interrupts are enabled). */
165 IS_POLLING_REQUIRED(softs);
167 if (loop_cnt++ == PQISRC_CMD_TIMEOUT_CNT) {
168 DBG_ERR("ERR: Requested cmd timed out !!!\n");
169 ret = PQI_STATUS_TIMEOUT;
173 if (pqisrc_ctrl_offline(softs)) {
174 DBG_ERR("Controller is Offline");
175 ret = PQI_STATUS_FAILURE;
179 rcb->req_pending = true;
186 /* Function used to validate the device wwid. */
187 boolean_t pqisrc_device_equal(pqi_scsi_dev_t *dev1,
188 pqi_scsi_dev_t *dev2)
190 return dev1->wwid == dev2->wwid;
193 /* Function used to validate the device scsi3addr. */
194 boolean_t pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2)
196 return memcmp(scsi3addr1, scsi3addr2, 8) == 0;
199 /* Function used to validate hba_lunid */
200 boolean_t pqisrc_is_hba_lunid(uint8_t *scsi3addr)
202 return pqisrc_scsi3addr_equal(scsi3addr, (uint8_t*)RAID_CTLR_LUNID);
205 /* Function used to validate type of device */
206 boolean_t pqisrc_is_logical_device(pqi_scsi_dev_t *device)
208 return !device->is_physical_device;
211 /* Function used to sanitize inquiry string */
212 void pqisrc_sanitize_inquiry_string(unsigned char *s, int len)
214 boolean_t terminated = false;
218 for (; len > 0; (--len, ++s)) {
221 if (terminated || *s < 0x20 || *s > 0x7e)
228 static char *raid_levels[] = {
238 /* Get the RAID level from the index */
239 char *pqisrc_raidlevel_to_string(uint8_t raid_level)
242 if (raid_level < ARRAY_SIZE(raid_levels))
243 return raid_levels[raid_level];
249 /* Debug routine for displaying device info */
250 void pqisrc_display_device_info(pqisrc_softstate_t *softs,
251 char *action, pqi_scsi_dev_t *device)
253 DBG_INFO( "%s scsi BTL %d:%d:%d: %.8s %.16s %-12s SSDSmartPathCap%c En%c Exp%c qd=%d\n",
260 pqisrc_raidlevel_to_string(device->raid_level),
261 device->offload_config ? '+' : '-',
262 device->offload_enabled_pending ? '+' : '-',
263 device->expose_device ? '+' : '-',
264 device->queue_depth);
265 pqisrc_raidlevel_to_string(device->raid_level); /* To use this function */
268 /* validate the structure sizes */
269 void check_struct_sizes()
272 ASSERT(sizeof(SCSI3Addr_struct)== 2);
273 ASSERT(sizeof(PhysDevAddr_struct) == 8);
274 ASSERT(sizeof(LogDevAddr_struct)== 8);
275 ASSERT(sizeof(LUNAddr_struct)==8);
276 ASSERT(sizeof(RequestBlock_struct) == 20);
277 ASSERT(sizeof(MoreErrInfo_struct)== 8);
278 ASSERT(sizeof(ErrorInfo_struct)== 48);
279 ASSERT(sizeof(IOCTL_Command_struct)== 86);
280 ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42);
281 ASSERT(sizeof(struct bmic_host_wellness_time)== 20);
282 ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8);
283 ASSERT(sizeof(struct admin_q_param)== 4);
284 ASSERT(sizeof(struct pqi_registers)== 256);
285 ASSERT(sizeof(struct ioa_registers)== 4128);
286 ASSERT(sizeof(struct pqi_pref_settings)==4);
287 ASSERT(sizeof(struct pqi_cap)== 20);
288 ASSERT(sizeof(iu_header_t)== 4);
289 ASSERT(sizeof(gen_adm_req_iu_t)== 64);
290 ASSERT(sizeof(gen_adm_resp_iu_t)== 64);
291 ASSERT(sizeof(op_q_params) == 9);
292 ASSERT(sizeof(raid_path_error_info_elem_t)== 276);
293 ASSERT(sizeof(aio_path_error_info_elem_t)== 276);
294 ASSERT(sizeof(struct init_base_struct)== 24);
295 ASSERT(sizeof(pqi_iu_layer_desc_t)== 16);
296 ASSERT(sizeof(pqi_dev_cap_t)== 576);
297 ASSERT(sizeof(pqi_aio_req_t)== 128);
298 ASSERT(sizeof(pqisrc_raid_req_t)== 128);
299 ASSERT(sizeof(pqi_tmf_req_t)== 32);
300 ASSERT(sizeof(struct pqi_io_response)== 16);
301 ASSERT(sizeof(struct sense_header_scsi)== 8);
302 ASSERT(sizeof(reportlun_header_t)==8);
303 ASSERT(sizeof(reportlun_ext_entry_t)== 24);
304 ASSERT(sizeof(reportlun_data_ext_t)== 32);
305 ASSERT(sizeof(raidmap_data_t)==8);
306 ASSERT(sizeof(pqisrc_raid_map_t)== 8256);
307 ASSERT(sizeof(bmic_ident_ctrl_t)== 325);
308 ASSERT(sizeof(bmic_ident_physdev_t)==2048);