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){
156 int ret = PQI_STATUS_SUCCESS;
157 uint32_t loop_cnt = 0;
159 while (rcb->req_pending == true) {
160 OS_SLEEP(500); /* Micro sec */
162 /*Polling needed for FreeBSD : since ithread routine is not scheduled
163 during bootup, we could use polling until interrupts are
164 enabled (using 'if (cold)'to check for the boot time before
165 interrupts are enabled). */
166 IS_POLLING_REQUIRED(softs);
168 if (loop_cnt++ == PQISRC_CMD_TIMEOUT_CNT) {
169 DBG_ERR("ERR: Requested cmd timed out !!!\n");
170 ret = PQI_STATUS_TIMEOUT;
174 if (pqisrc_ctrl_offline(softs)) {
175 DBG_ERR("Controller is Offline");
176 ret = PQI_STATUS_FAILURE;
181 rcb->req_pending = true;
188 /* Function used to validate the device wwid. */
189 boolean_t pqisrc_device_equal(pqi_scsi_dev_t *dev1,
190 pqi_scsi_dev_t *dev2)
192 return dev1->wwid == dev2->wwid;
195 /* Function used to validate the device scsi3addr. */
196 boolean_t pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2)
198 return memcmp(scsi3addr1, scsi3addr2, 8) == 0;
201 /* Function used to validate hba_lunid */
202 boolean_t pqisrc_is_hba_lunid(uint8_t *scsi3addr)
204 return pqisrc_scsi3addr_equal(scsi3addr, (uint8_t*)RAID_CTLR_LUNID);
207 /* Function used to validate type of device */
208 boolean_t pqisrc_is_logical_device(pqi_scsi_dev_t *device)
210 return !device->is_physical_device;
213 /* Function used to sanitize inquiry string */
214 void pqisrc_sanitize_inquiry_string(unsigned char *s, int len)
216 boolean_t terminated = false;
220 for (; len > 0; (--len, ++s)) {
223 if (terminated || *s < 0x20 || *s > 0x7e)
230 static char *raid_levels[] = {
240 /* Get the RAID level from the index */
241 char *pqisrc_raidlevel_to_string(uint8_t raid_level)
244 if (raid_level < ARRAY_SIZE(raid_levels))
245 return raid_levels[raid_level];
251 /* Debug routine for displaying device info */
252 void pqisrc_display_device_info(pqisrc_softstate_t *softs,
253 char *action, pqi_scsi_dev_t *device)
255 DBG_INFO( "%s scsi BTL %d:%d:%d: %.8s %.16s %-12s SSDSmartPathCap%c En%c Exp%c qd=%d\n",
262 pqisrc_raidlevel_to_string(device->raid_level),
263 device->offload_config ? '+' : '-',
264 device->offload_enabled_pending ? '+' : '-',
265 device->expose_device ? '+' : '-',
266 device->queue_depth);
267 pqisrc_raidlevel_to_string(device->raid_level); /* To use this function */
270 /* validate the structure sizes */
271 void check_struct_sizes()
274 ASSERT(sizeof(SCSI3Addr_struct)== 2);
275 ASSERT(sizeof(PhysDevAddr_struct) == 8);
276 ASSERT(sizeof(LogDevAddr_struct)== 8);
277 ASSERT(sizeof(LUNAddr_struct)==8);
278 ASSERT(sizeof(RequestBlock_struct) == 20);
279 ASSERT(sizeof(MoreErrInfo_struct)== 8);
280 ASSERT(sizeof(ErrorInfo_struct)== 48);
281 ASSERT(sizeof(IOCTL_Command_struct)== 86);
282 ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42);
283 ASSERT(sizeof(struct bmic_host_wellness_time)== 20);
284 ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8);
285 ASSERT(sizeof(struct admin_q_param)== 4);
286 ASSERT(sizeof(struct pqi_registers)== 256);
287 ASSERT(sizeof(struct ioa_registers)== 4128);
288 ASSERT(sizeof(struct pqi_pref_settings)==4);
289 ASSERT(sizeof(struct pqi_cap)== 20);
290 ASSERT(sizeof(iu_header_t)== 4);
291 ASSERT(sizeof(gen_adm_req_iu_t)== 64);
292 ASSERT(sizeof(gen_adm_resp_iu_t)== 64);
293 ASSERT(sizeof(op_q_params) == 9);
294 ASSERT(sizeof(raid_path_error_info_elem_t)== 276);
295 ASSERT(sizeof(aio_path_error_info_elem_t)== 276);
296 ASSERT(sizeof(struct init_base_struct)== 24);
297 ASSERT(sizeof(pqi_iu_layer_desc_t)== 16);
298 ASSERT(sizeof(pqi_dev_cap_t)== 576);
299 ASSERT(sizeof(pqi_aio_req_t)== 128);
300 ASSERT(sizeof(pqisrc_raid_req_t)== 128);
301 ASSERT(sizeof(pqi_tmf_req_t)== 32);
302 ASSERT(sizeof(struct pqi_io_response)== 16);
303 ASSERT(sizeof(struct sense_header_scsi)== 8);
304 ASSERT(sizeof(reportlun_header_t)==8);
305 ASSERT(sizeof(reportlun_ext_entry_t)== 24);
306 ASSERT(sizeof(reportlun_data_ext_t)== 32);
307 ASSERT(sizeof(raidmap_data_t)==8);
308 ASSERT(sizeof(pqisrc_raid_map_t)== 8256);
309 ASSERT(sizeof(bmic_ident_ctrl_t)== 325);
310 ASSERT(sizeof(bmic_ident_physdev_t)==2048);