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