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;
44 * Function used to take exposed devices to OS as offline.
46 void pqisrc_take_devices_offline(pqisrc_softstate_t *softs)
48 pqi_scsi_dev_t *device = NULL;
52 for(i = 0; i < PQI_MAX_DEVICES; i++) {
53 for(j = 0; j < PQI_MAX_MULTILUN; j++) {
54 if(softs->device_list[i][j] == NULL)
56 device = softs->device_list[i][j];
57 pqisrc_remove_device(softs, device);
65 * Function used to take adapter offline.
67 void pqisrc_take_ctrl_offline(pqisrc_softstate_t *softs)
72 softs->ctrl_online = false;
73 pqisrc_trigger_nmi_sis(softs);
74 os_complete_outstanding_cmds_nodevice(softs);
75 pqisrc_take_devices_offline(softs);
81 * Timer handler for the adapter heart-beat.
83 void pqisrc_heartbeat_timer_handler(pqisrc_softstate_t *softs)
86 uint8_t take_offline = false;
90 num_intrs = OS_ATOMIC64_READ(softs, num_intrs);
92 if (PQI_NEW_HEARTBEAT_MECHANISM(softs)) {
93 if (CTRLR_HEARTBEAT_CNT(softs) == softs->prev_heartbeat_count) {
95 goto take_ctrl_offline;
97 softs->prev_heartbeat_count = CTRLR_HEARTBEAT_CNT(softs);
98 DBG_INFO("CTRLR_HEARTBEAT_CNT(softs) = %lx \
99 softs->prev_heartbeat_count = %lx\n",
100 CTRLR_HEARTBEAT_CNT(softs), softs->prev_heartbeat_count);
102 if (num_intrs == softs->prev_num_intrs) {
103 softs->num_heartbeats_requested++;
104 if (softs->num_heartbeats_requested > PQI_MAX_HEARTBEAT_REQUESTS) {
106 goto take_ctrl_offline;
108 softs->pending_events[PQI_EVENT_HEARTBEAT].pending = true;
110 pqisrc_ack_all_events((void*)softs);
113 softs->num_heartbeats_requested = 0;
115 softs->prev_num_intrs = num_intrs;
120 DBG_ERR("controller is offline\n");
121 pqisrc_take_ctrl_offline(softs);
122 os_stop_heartbeat_timer(softs);
128 * Conditional variable management routine for internal commands.
130 int pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb){
134 int ret = PQI_STATUS_SUCCESS;
135 uint32_t loop_cnt = 0;
137 while (rcb->req_pending == true) {
138 OS_SLEEP(500); /* Micro sec */
140 /*Polling needed for FreeBSD : since ithread routine is not scheduled
141 during bootup, we could use polling until interrupts are
142 enabled (using 'if (cold)'to check for the boot time before
143 interrupts are enabled). */
144 IS_POLLING_REQUIRED(softs);
146 if (loop_cnt++ == PQISRC_CMD_TIMEOUT_CNT) {
147 DBG_ERR("ERR: Requested cmd timed out !!!\n");
148 ret = PQI_STATUS_TIMEOUT;
152 if (pqisrc_ctrl_offline(softs)) {
153 DBG_ERR("Controller is Offline");
154 ret = PQI_STATUS_FAILURE;
159 rcb->req_pending = true;
166 /* Function used to validate the device wwid. */
167 boolean_t pqisrc_device_equal(pqi_scsi_dev_t *dev1,
168 pqi_scsi_dev_t *dev2)
170 return dev1->wwid == dev2->wwid;
173 /* Function used to validate the device scsi3addr. */
174 boolean_t pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2)
176 return memcmp(scsi3addr1, scsi3addr2, 8) == 0;
179 /* Function used to validate hba_lunid */
180 boolean_t pqisrc_is_hba_lunid(uint8_t *scsi3addr)
182 return pqisrc_scsi3addr_equal(scsi3addr, (uint8_t*)RAID_CTLR_LUNID);
185 /* Function used to validate type of device */
186 boolean_t pqisrc_is_logical_device(pqi_scsi_dev_t *device)
188 return !device->is_physical_device;
191 /* Function used to sanitize inquiry string */
192 void pqisrc_sanitize_inquiry_string(unsigned char *s, int len)
194 boolean_t terminated = false;
198 for (; len > 0; (--len, ++s)) {
201 if (terminated || *s < 0x20 || *s > 0x7e)
208 static char *raid_levels[] = {
219 /* Get the RAID level from the index */
220 char *pqisrc_raidlevel_to_string(uint8_t raid_level)
223 if (raid_level < ARRAY_SIZE(raid_levels))
224 return raid_levels[raid_level];
230 /* Debug routine for displaying device info */
231 void pqisrc_display_device_info(pqisrc_softstate_t *softs,
232 char *action, pqi_scsi_dev_t *device)
234 DBG_INFO( "%s scsi BTL %d:%d:%d: %.8s %.16s %-12s SSDSmartPathCap%c En%c Exp%c qd=%d\n",
241 pqisrc_raidlevel_to_string(device->raid_level),
242 device->offload_config ? '+' : '-',
243 device->offload_enabled_pending ? '+' : '-',
244 device->expose_device ? '+' : '-',
245 device->queue_depth);
246 pqisrc_raidlevel_to_string(device->raid_level); /* To use this function */
249 /* validate the structure sizes */
250 void check_struct_sizes()
253 ASSERT(sizeof(SCSI3Addr_struct)== 2);
254 ASSERT(sizeof(PhysDevAddr_struct) == 8);
255 ASSERT(sizeof(LogDevAddr_struct)== 8);
256 ASSERT(sizeof(LUNAddr_struct)==8);
257 ASSERT(sizeof(RequestBlock_struct) == 20);
258 ASSERT(sizeof(MoreErrInfo_struct)== 8);
259 ASSERT(sizeof(ErrorInfo_struct)== 48);
260 ASSERT(sizeof(IOCTL_Command_struct)== 86);
261 ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42);
262 ASSERT(sizeof(struct bmic_host_wellness_time)== 20);
263 ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8);
264 ASSERT(sizeof(struct admin_q_param)== 4);
265 ASSERT(sizeof(struct pqi_registers)== 256);
266 ASSERT(sizeof(struct ioa_registers)== 4128);
267 ASSERT(sizeof(struct pqi_pref_settings)==4);
268 ASSERT(sizeof(struct pqi_cap)== 20);
269 ASSERT(sizeof(iu_header_t)== 4);
270 ASSERT(sizeof(gen_adm_req_iu_t)== 64);
271 ASSERT(sizeof(gen_adm_resp_iu_t)== 64);
272 ASSERT(sizeof(op_q_params) == 9);
273 ASSERT(sizeof(raid_path_error_info_elem_t)== 276);
274 ASSERT(sizeof(aio_path_error_info_elem_t)== 276);
275 ASSERT(sizeof(struct init_base_struct)== 24);
276 ASSERT(sizeof(pqi_iu_layer_desc_t)== 16);
277 ASSERT(sizeof(pqi_dev_cap_t)== 576);
278 ASSERT(sizeof(pqi_aio_req_t)== 128);
279 ASSERT(sizeof(pqisrc_raid_req_t)== 128);
280 ASSERT(sizeof(pqi_tmf_req_t)== 32);
281 ASSERT(sizeof(struct pqi_io_response)== 16);
282 ASSERT(sizeof(struct sense_header_scsi)== 8);
283 ASSERT(sizeof(reportlun_header_t)==8);
284 ASSERT(sizeof(reportlun_ext_entry_t)== 24);
285 ASSERT(sizeof(reportlun_data_ext_t)== 32);
286 ASSERT(sizeof(raidmap_data_t)==8);
287 ASSERT(sizeof(pqisrc_raid_map_t)== 8256);
288 ASSERT(sizeof(bmic_ident_ctrl_t)== 325);
289 ASSERT(sizeof(bmic_ident_physdev_t)==2048);