1 /*-
2 * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26
27 #include "smartpqi_includes.h"
28
29 /* read and modify controller diagnostic option - PQI_PTRAID_UPDATE_ON_RESCAN_LUNS */
30 void
pqisrc_ctrl_diagnostic_options(pqisrc_softstate_t * softs)31 pqisrc_ctrl_diagnostic_options(pqisrc_softstate_t *softs)
32 {
33 int ret = PQI_STATUS_SUCCESS;
34 uint32_t diags_options = 0;
35 pqisrc_raid_req_t request;
36
37 DBG_NOTE("IN\n");
38
39 memset(&request, 0, sizeof(request));
40 /* read diags options of controller */
41 ret = pqisrc_build_send_raid_request(softs, &request,
42 (void*)&diags_options,
43 sizeof(diags_options),
44 BMIC_SENSE_DIAGS_OPTIONS,
45 0, (uint8_t *)RAID_CTLR_LUNID, NULL);
46 if (ret != PQI_STATUS_SUCCESS) {
47 DBG_WARN("Request failed for BMIC Sense Diags Option command."
48 "ret:%d\n",ret);
49 return;
50 }
51 DBG_NOTE("diags options data after read: %#x\n",diags_options);
52 diags_options |= PQI_PTRAID_UPDATE_ON_RESCAN_LUNS;
53 DBG_NOTE("diags options data to write: %#x\n",diags_options);
54 memset(&request, 0, sizeof(request));
55 /* write specified diags options to controller */
56 ret = pqisrc_build_send_raid_request(softs, &request,
57 (void*)&diags_options,
58 sizeof(diags_options),
59 BMIC_SET_DIAGS_OPTIONS,
60 0, (uint8_t *)RAID_CTLR_LUNID, NULL);
61 if (ret != PQI_STATUS_SUCCESS)
62 DBG_WARN("Request failed for BMIC Set Diags Option command."
63 "ret:%d\n",ret);
64 #if 0
65 diags_options = 0;
66 memset(&request, 0, sizeof(request));
67 ret = pqisrc_build_send_raid_request(softs, &request,
68 (void*)&diags_options,
69 sizeof(diags_options),
70 BMIC_SENSE_DIAGS_OPTIONS,
71 0, (uint8_t *)RAID_CTLR_LUNID, NULL);
72 if (ret != PQI_STATUS_SUCCESS)
73 DBG_WARN("Request failed for BMIC Sense Diags Option command."
74 "ret:%d\n",ret);
75 DBG_NOTE("diags options after re-read: %#x\n",diags_options);
76 #endif
77 DBG_NOTE("OUT\n");
78 }
79
80 /*
81 * Function used to validate the adapter health.
82 */
83 boolean_t
pqisrc_ctrl_offline(pqisrc_softstate_t * softs)84 pqisrc_ctrl_offline(pqisrc_softstate_t *softs)
85 {
86 DBG_FUNC("IN\n");
87
88 DBG_FUNC("OUT\n");
89
90 return !softs->ctrl_online;
91 }
92
93 /* Function used set/clear legacy INTx bit in Legacy Interrupt INTx
94 * mask clear pqi register
95 */
96 void
pqisrc_configure_legacy_intx(pqisrc_softstate_t * softs,boolean_t enable_intx)97 pqisrc_configure_legacy_intx(pqisrc_softstate_t *softs, boolean_t enable_intx)
98 {
99 uint32_t intx_mask;
100 uint32_t *reg_addr __unused;
101
102 DBG_FUNC("IN\n");
103
104 if (enable_intx)
105 reg_addr = &softs->pqi_reg->legacy_intr_mask_clr;
106 else
107 reg_addr = &softs->pqi_reg->legacy_intr_mask_set;
108
109 intx_mask = PCI_MEM_GET32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR);
110 intx_mask |= PQISRC_LEGACY_INTX_MASK;
111 PCI_MEM_PUT32(softs, reg_addr, PQI_LEGACY_INTR_MASK_CLR ,intx_mask);
112
113 DBG_FUNC("OUT\n");
114 }
115
116 /*
117 * Function used to take exposed devices to OS as offline.
118 */
119 void
pqisrc_take_devices_offline(pqisrc_softstate_t * softs)120 pqisrc_take_devices_offline(pqisrc_softstate_t *softs)
121 {
122 pqi_scsi_dev_t *device = NULL;
123 int i,j;
124
125 DBG_FUNC("IN\n");
126 for(i = 0; i < PQI_MAX_DEVICES; i++) {
127 for(j = 0; j < PQI_MAX_MULTILUN; j++) {
128 if(softs->device_list[i][j] == NULL)
129 continue;
130 device = softs->device_list[i][j];
131 pqisrc_remove_device(softs, device);
132 }
133 }
134
135 DBG_FUNC("OUT\n");
136 }
137
138 /*
139 * Function used to take adapter offline.
140 */
141 void
pqisrc_take_ctrl_offline(pqisrc_softstate_t * softs)142 pqisrc_take_ctrl_offline(pqisrc_softstate_t *softs)
143 {
144 DBG_FUNC("IN\n");
145
146 softs->ctrl_online = false;
147
148 int lockupcode = 0;
149
150 if (SIS_IS_KERNEL_PANIC(softs)) {
151 lockupcode = PCI_MEM_GET32(softs, &softs->ioa_reg->mb[7], LEGACY_SIS_SRCV_OFFSET_MAILBOX_7);
152 DBG_ERR("Controller FW is not running, Lockup code = %x\n", lockupcode);
153 }
154 else {
155 pqisrc_trigger_nmi_sis(softs);
156 }
157
158 os_complete_outstanding_cmds_nodevice(softs);
159 pqisrc_wait_for_rescan_complete(softs);
160 pqisrc_take_devices_offline(softs);
161
162 DBG_FUNC("OUT\n");
163 }
164
165 /*
166 * Timer handler for the adapter heart-beat.
167 */
168 void
pqisrc_heartbeat_timer_handler(pqisrc_softstate_t * softs)169 pqisrc_heartbeat_timer_handler(pqisrc_softstate_t *softs)
170 {
171 uint8_t take_offline = false;
172
173 DBG_FUNC("IN\n");
174
175 if (CTRLR_HEARTBEAT_CNT(softs) == softs->prev_heartbeat_count) {
176 take_offline = true;
177 goto take_ctrl_offline;
178 }
179 softs->prev_heartbeat_count = CTRLR_HEARTBEAT_CNT(softs);
180 DBG_INFO("CTRLR_HEARTBEAT_CNT(softs) = %lx \
181 softs->prev_heartbeat_count = %lx\n",
182 CTRLR_HEARTBEAT_CNT(softs), softs->prev_heartbeat_count);
183
184 take_ctrl_offline:
185 if (take_offline){
186 DBG_ERR("controller is offline\n");
187 pqisrc_take_ctrl_offline(softs);
188 os_stop_heartbeat_timer(softs);
189 }
190 DBG_FUNC("OUT\n");
191 }
192
193 /*
194 * Conditional variable management routine for internal commands.
195 */
196 int
pqisrc_wait_on_condition(pqisrc_softstate_t * softs,rcb_t * rcb,uint32_t timeout_in_msec)197 pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb,
198 uint32_t timeout_in_msec)
199 {
200 DBG_FUNC("IN\n");
201
202 int ret = PQI_STATUS_SUCCESS;
203
204 /* 1 msec = 500 usec * 2 */
205 uint32_t loop_cnt = timeout_in_msec * 2;
206 uint32_t i = 0;
207
208 while (rcb->req_pending == true) {
209 OS_SLEEP(500); /* Micro sec */
210 /* Polling needed for FreeBSD : since ithread routine is not scheduled
211 * during bootup, we could use polling until interrupts are
212 * enabled (using 'if (cold)'to check for the boot time before
213 * interrupts are enabled). */
214 IS_POLLING_REQUIRED(softs);
215
216 if ((timeout_in_msec != TIMEOUT_INFINITE) && (i++ == loop_cnt)) {
217 DBG_ERR("ERR: Requested cmd timed out !!!\n");
218 ret = PQI_STATUS_TIMEOUT;
219 rcb->timedout = true;
220 break;
221 }
222
223 if (pqisrc_ctrl_offline(softs)) {
224 DBG_ERR("Controller is Offline");
225 ret = PQI_STATUS_FAILURE;
226 break;
227 }
228
229 }
230 rcb->req_pending = true;
231
232 DBG_FUNC("OUT\n");
233
234 return ret;
235 }
236
237 /* Function used to validate the device wwid. */
238 boolean_t
pqisrc_device_equal(pqi_scsi_dev_t * dev1,pqi_scsi_dev_t * dev2)239 pqisrc_device_equal(pqi_scsi_dev_t *dev1,
240 pqi_scsi_dev_t *dev2)
241 {
242 return dev1->wwid == dev2->wwid;
243 }
244
245 /* Function used to validate the device scsi3addr. */
246 boolean_t
pqisrc_scsi3addr_equal(uint8_t * scsi3addr1,uint8_t * scsi3addr2)247 pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2)
248 {
249 return memcmp(scsi3addr1, scsi3addr2, 8) == 0;
250 }
251
252 /* Function used to validate hba_lunid */
253 boolean_t
pqisrc_is_hba_lunid(uint8_t * scsi3addr)254 pqisrc_is_hba_lunid(uint8_t *scsi3addr)
255 {
256 return pqisrc_scsi3addr_equal(scsi3addr, (uint8_t*)RAID_CTLR_LUNID);
257 }
258
259 /* Function used to validate type of device */
260 boolean_t
pqisrc_is_logical_device(pqi_scsi_dev_t * device)261 pqisrc_is_logical_device(pqi_scsi_dev_t *device)
262 {
263 return !device->is_physical_device;
264 }
265
266 /* Function used to sanitize inquiry string */
267 void
pqisrc_sanitize_inquiry_string(unsigned char * s,int len)268 pqisrc_sanitize_inquiry_string(unsigned char *s, int len)
269 {
270 boolean_t terminated = false;
271
272 DBG_FUNC("IN\n");
273
274 for (; len > 0; (--len, ++s)) {
275 if (*s == 0)
276 terminated = true;
277 if (terminated || *s < 0x20 || *s > 0x7e)
278 *s = ' ';
279 }
280
281 DBG_FUNC("OUT\n");
282 }
283
284 static char *raid_levels[] = {
285 "RAID 0",
286 "RAID 4",
287 "RAID 1(1+0)",
288 "RAID 5",
289 "RAID 5+1",
290 "RAID ADG",
291 "RAID 1(ADM)",
292 };
293
294 /* Get the RAID level from the index */
295 char *
pqisrc_raidlevel_to_string(uint8_t raid_level)296 pqisrc_raidlevel_to_string(uint8_t raid_level)
297 {
298 DBG_FUNC("IN\n");
299 if (raid_level < ARRAY_SIZE(raid_levels))
300 return raid_levels[raid_level];
301 DBG_FUNC("OUT\n");
302
303 return " ";
304 }
305
306 /* Debug routine for displaying device info */
pqisrc_display_device_info(pqisrc_softstate_t * softs,char * action,pqi_scsi_dev_t * device)307 void pqisrc_display_device_info(pqisrc_softstate_t *softs,
308 char *action, pqi_scsi_dev_t *device)
309 {
310 if (device->is_physical_device) {
311 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s "
312 "SSDSmartPathCap%c En%c Exp%c qd=%d\n",
313 action,
314 device->bus,
315 device->target,
316 device->lun,
317 device->vendor,
318 device->model,
319 "Physical",
320 device->offload_config ? '+' : '-',
321 device->offload_enabled_pending ? '+' : '-',
322 device->expose_device ? '+' : '-',
323 device->queue_depth);
324 } else if (device->devtype == RAID_DEVICE) {
325 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s "
326 "SSDSmartPathCap%c En%c Exp%c qd=%d\n",
327 action,
328 device->bus,
329 device->target,
330 device->lun,
331 device->vendor,
332 device->model,
333 "Controller",
334 device->offload_config ? '+' : '-',
335 device->offload_enabled_pending ? '+' : '-',
336 device->expose_device ? '+' : '-',
337 device->queue_depth);
338 } else if (device->devtype == CONTROLLER_DEVICE) {
339 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s "
340 "SSDSmartPathCap%c En%c Exp%c qd=%d\n",
341 action,
342 device->bus,
343 device->target,
344 device->lun,
345 device->vendor,
346 device->model,
347 "External",
348 device->offload_config ? '+' : '-',
349 device->offload_enabled_pending ? '+' : '-',
350 device->expose_device ? '+' : '-',
351 device->queue_depth);
352 } else {
353 DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s "
354 "SSDSmartPathCap%c En%c Exp%c qd=%d devtype=%d\n",
355 action,
356 device->bus,
357 device->target,
358 device->lun,
359 device->vendor,
360 device->model,
361 pqisrc_raidlevel_to_string(device->raid_level),
362 device->offload_config ? '+' : '-',
363 device->offload_enabled_pending ? '+' : '-',
364 device->expose_device ? '+' : '-',
365 device->queue_depth,
366 device->devtype);
367 pqisrc_raidlevel_to_string(device->raid_level); /* To use this function */
368 }
369 }
370
371 /* validate the structure sizes */
372 void
check_struct_sizes(void)373 check_struct_sizes(void)
374 {
375
376 ASSERT(sizeof(SCSI3Addr_struct)== 2);
377 ASSERT(sizeof(PhysDevAddr_struct) == 8);
378 ASSERT(sizeof(LogDevAddr_struct)== 8);
379 ASSERT(sizeof(LUNAddr_struct)==8);
380 ASSERT(sizeof(RequestBlock_struct) == 20);
381 ASSERT(sizeof(MoreErrInfo_struct)== 8);
382 ASSERT(sizeof(ErrorInfo_struct)== 48);
383 /* Checking the size of IOCTL_Command_struct for both
384 64 bit and 32 bit system*/
385 ASSERT(sizeof(IOCTL_Command_struct)== 86 ||
386 sizeof(IOCTL_Command_struct)== 82);
387 ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42);
388 ASSERT(sizeof(struct bmic_host_wellness_time)== 20);
389 ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8);
390 ASSERT(sizeof(struct admin_q_param)== 4);
391 ASSERT(sizeof(struct pqi_registers)== 256);
392 ASSERT(sizeof(struct ioa_registers)== 4128);
393 ASSERT(sizeof(struct pqi_pref_settings)==4);
394 ASSERT(sizeof(struct pqi_cap)== 20);
395 ASSERT(sizeof(iu_header_t)== 4);
396 ASSERT(sizeof(gen_adm_req_iu_t)== 64);
397 ASSERT(sizeof(gen_adm_resp_iu_t)== 64);
398 ASSERT(sizeof(op_q_params) == 9);
399 ASSERT(sizeof(raid_path_error_info_elem_t)== 276);
400 ASSERT(sizeof(aio_path_error_info_elem_t)== 276);
401 ASSERT(sizeof(struct init_base_struct)== 24);
402 ASSERT(sizeof(pqi_iu_layer_desc_t)== 16);
403 ASSERT(sizeof(pqi_dev_cap_t)== 576);
404 ASSERT(sizeof(pqi_aio_req_t)== 128);
405 ASSERT(sizeof(pqisrc_raid_req_t)== 128);
406 ASSERT(sizeof(pqi_raid_tmf_req_t)== 32);
407 ASSERT(sizeof(pqi_aio_tmf_req_t)== 32);
408 ASSERT(sizeof(struct pqi_io_response)== 16);
409 ASSERT(sizeof(struct sense_header_scsi)== 8);
410 ASSERT(sizeof(reportlun_header_t)==8);
411 ASSERT(sizeof(reportlun_ext_entry_t)== 24);
412 ASSERT(sizeof(reportlun_data_ext_t)== 32);
413 ASSERT(sizeof(raidmap_data_t)==8);
414 ASSERT(sizeof(pqisrc_raid_map_t)== 8256);
415 ASSERT(sizeof(bmic_ident_ctrl_t)== 325);
416 ASSERT(sizeof(bmic_ident_physdev_t)==2048);
417
418 }
419
420 uint32_t
pqisrc_count_num_scsi_active_requests_on_dev(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)421 pqisrc_count_num_scsi_active_requests_on_dev(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
422 {
423 uint32_t i, active_io = 0;
424 rcb_t* rcb;
425
426 for(i = 1; i <= softs->max_outstanding_io; i++) {
427 rcb = &softs->rcb[i];
428 if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) {
429 active_io++;
430 }
431 }
432 return active_io;
433 }
434
435 void
check_device_pending_commands_to_complete(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)436 check_device_pending_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
437 {
438 uint32_t tag = softs->max_outstanding_io, active_requests;
439 uint64_t timeout = 0, delay_in_usec = 1000; //In micro Seconds
440 rcb_t* rcb;
441
442 DBG_FUNC("IN\n");
443
444 active_requests = pqisrc_count_num_scsi_active_requests_on_dev(softs, device);
445
446 DBG_WARN("Device Outstanding IO count = %u\n", active_requests);
447
448 if(!active_requests)
449 return;
450
451 do {
452 rcb = &softs->rcb[tag];
453 if(rcb && IS_OS_SCSICMD(rcb) && (rcb->dvp == device) && rcb->req_pending) {
454 OS_BUSYWAIT(delay_in_usec);
455 timeout += delay_in_usec;
456 }
457 else
458 tag--;
459 if(timeout >= PQISRC_PENDING_IO_TIMEOUT_USEC) {
460 DBG_WARN("timed out waiting for pending IO\n");
461 return;
462 }
463 } while(tag);
464
465 }
466
467 inline uint64_t
pqisrc_increment_device_active_io(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)468 pqisrc_increment_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
469 {
470 #if PQISRC_DEVICE_IO_COUNTER
471 /*Increment device active io count by one*/
472 return OS_ATOMIC64_INC(&device->active_requests);
473 #endif
474 }
475
476 inline uint64_t
pqisrc_decrement_device_active_io(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)477 pqisrc_decrement_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
478 {
479 #if PQISRC_DEVICE_IO_COUNTER
480 /*Decrement device active io count by one*/
481 return OS_ATOMIC64_DEC(&device->active_requests);
482 #endif
483 }
484
485 inline void
pqisrc_init_device_active_io(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)486 pqisrc_init_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
487 {
488 #if PQISRC_DEVICE_IO_COUNTER
489 /* Reset device count to Zero */
490 OS_ATOMIC64_INIT(&device->active_requests, 0);
491 #endif
492 }
493
494 inline uint64_t
pqisrc_read_device_active_io(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)495 pqisrc_read_device_active_io(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
496 {
497 #if PQISRC_DEVICE_IO_COUNTER
498 /* read device active count*/
499 return OS_ATOMIC64_READ(&device->active_requests);
500 #endif
501 }
502
503 void
pqisrc_wait_for_device_commands_to_complete(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)504 pqisrc_wait_for_device_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
505 {
506 uint64_t timeout_in_usec = 0, delay_in_usec = 1000; //In microseconds
507
508 DBG_FUNC("IN\n");
509
510 if(!softs->ctrl_online)
511 return;
512
513 #if PQISRC_DEVICE_IO_COUNTER
514 DBG_NOTE("Device Outstanding IO count = %ld\n", pqisrc_read_device_active_io(softs, device));
515
516 while(pqisrc_read_device_active_io(softs, device)) {
517 OS_BUSYWAIT(delay_in_usec); // In microseconds
518 if(!softs->ctrl_online) {
519 DBG_WARN("Controller Offline was detected.\n");
520 }
521 timeout_in_usec += delay_in_usec;
522 if(timeout_in_usec >= PQISRC_PENDING_IO_TIMEOUT_USEC) {
523 DBG_WARN("timed out waiting for pending IO. DeviceOutStandingIo's=%ld\n",
524 pqisrc_read_device_active_io(softs, device));
525 return;
526 }
527 }
528 #else
529 check_device_pending_commands_to_complete(softs, device);
530 #endif
531 }
532