1 /*-
2 * Copyright 2016-2023 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 * CAM interface for smartpqi driver
28 */
29
30 #include "smartpqi_includes.h"
31
32 /*
33 * Set cam sim properties of the smartpqi adapter.
34 */
35 static void
update_sim_properties(struct cam_sim * sim,struct ccb_pathinq * cpi)36 update_sim_properties(struct cam_sim *sim, struct ccb_pathinq *cpi)
37 {
38
39 pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
40 cam_sim_softc(sim);
41
42 device_t dev = softs->os_specific.pqi_dev;
43
44 DBG_FUNC("IN\n");
45
46 cpi->version_num = 1;
47 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
48 cpi->target_sprt = 0;
49 cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
50 cpi->hba_eng_cnt = 0;
51 cpi->max_lun = PQI_MAX_MULTILUN;
52 cpi->max_target = MAX_TARGET_DEVICES;
53 cpi->maxio = (softs->pqi_cap.max_sg_elem - 1) * PAGE_SIZE;
54 cpi->initiator_id = 255;
55 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN-1);
56 cpi->sim_vid[sizeof(cpi->sim_vid)-1] = '\0';
57 strncpy(cpi->hba_vid, "Microsemi", HBA_IDLEN-1);
58 cpi->hba_vid[sizeof(cpi->hba_vid)-1] = '\0';
59 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN-1);
60 cpi->dev_name[sizeof(cpi->dev_name)-1] = '\0';
61 cpi->unit_number = cam_sim_unit(sim);
62 cpi->bus_id = cam_sim_bus(sim);
63 cpi->base_transfer_speed = 1200000; /* Base bus speed in KB/sec */
64 cpi->protocol = PROTO_SCSI;
65 cpi->protocol_version = SCSI_REV_SPC4;
66 cpi->transport = XPORT_SPI;
67 cpi->transport_version = 2;
68 cpi->ccb_h.status = CAM_REQ_CMP;
69 cpi->hba_vendor = pci_get_vendor(dev);
70 cpi->hba_device = pci_get_device(dev);
71 cpi->hba_subvendor = pci_get_subvendor(dev);
72 cpi->hba_subdevice = pci_get_subdevice(dev);
73
74
75 DBG_FUNC("OUT\n");
76 }
77
78 /*
79 * Get transport settings of the smartpqi adapter.
80 */
81 static void
get_transport_settings(struct pqisrc_softstate * softs,struct ccb_trans_settings * cts)82 get_transport_settings(struct pqisrc_softstate *softs,
83 struct ccb_trans_settings *cts)
84 {
85 struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
86 struct ccb_trans_settings_sas *sas = &cts->xport_specific.sas;
87 struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi;
88
89 DBG_FUNC("IN\n");
90
91 cts->protocol = PROTO_SCSI;
92 cts->protocol_version = SCSI_REV_SPC4;
93 cts->transport = XPORT_SPI;
94 cts->transport_version = 2;
95 spi->valid = CTS_SPI_VALID_DISC;
96 spi->flags = CTS_SPI_FLAGS_DISC_ENB;
97 scsi->valid = CTS_SCSI_VALID_TQ;
98 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
99 sas->valid = CTS_SAS_VALID_SPEED;
100 cts->ccb_h.status = CAM_REQ_CMP;
101
102 DBG_FUNC("OUT\n");
103 }
104
105 /*
106 * Add the target to CAM layer and rescan, when a new device is found
107 */
108 void
os_add_device(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)109 os_add_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
110 {
111 union ccb *ccb;
112 uint64_t lun;
113
114 DBG_FUNC("IN\n");
115
116 lun = (device->is_multi_lun) ? CAM_LUN_WILDCARD : device->lun;
117 if(softs->os_specific.sim_registered) {
118 if ((ccb = xpt_alloc_ccb_nowait()) == NULL) {
119 DBG_ERR("rescan failed (can't allocate CCB)\n");
120 return;
121 }
122
123 if (xpt_create_path(&ccb->ccb_h.path, NULL,
124 cam_sim_path(softs->os_specific.sim),
125 device->target, lun) != CAM_REQ_CMP) {
126 DBG_ERR("rescan failed (can't create path)\n");
127 xpt_free_ccb(ccb);
128 return;
129 }
130 xpt_rescan(ccb);
131 }
132
133 DBG_FUNC("OUT\n");
134 }
135
136 /*
137 * Remove the device from CAM layer when deleted or hot removed
138 */
139 void
os_remove_device(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)140 os_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
141 {
142 struct cam_path *tmppath = NULL;
143 uint64_t lun;
144
145 DBG_FUNC("IN\n");
146
147 lun = (device->is_multi_lun) ? CAM_LUN_WILDCARD : device->lun;
148 if(softs->os_specific.sim_registered) {
149 if (xpt_create_path(&tmppath, NULL,
150 cam_sim_path(softs->os_specific.sim),
151 device->target, lun) != CAM_REQ_CMP) {
152 DBG_ERR("unable to create path for async event\n");
153 return;
154 }
155 xpt_async(AC_LOST_DEVICE, tmppath, NULL);
156 xpt_free_path(tmppath);
157 /* softs->device_list[device->target][device->lun] = NULL; */
158 int index = pqisrc_find_device_list_index(softs,device);
159 if (index >= 0 && index < PQI_MAX_DEVICES)
160 softs->dev_list[index] = NULL;
161 pqisrc_free_device(softs, device);
162 }
163
164 DBG_FUNC("OUT\n");
165
166 }
167
168 /*
169 * Function to release the frozen simq
170 */
171 static void
pqi_release_camq(rcb_t * rcb)172 pqi_release_camq(rcb_t *rcb)
173 {
174 pqisrc_softstate_t *softs;
175 struct ccb_scsiio *csio;
176
177 csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
178 softs = rcb->softs;
179
180 DBG_FUNC("IN\n");
181
182 if (softs->os_specific.pqi_flags & PQI_FLAG_BUSY) {
183 softs->os_specific.pqi_flags &= ~PQI_FLAG_BUSY;
184 if (csio->ccb_h.status & CAM_RELEASE_SIMQ)
185 xpt_release_simq(xpt_path_sim(csio->ccb_h.path), 0);
186 else
187 csio->ccb_h.status |= CAM_RELEASE_SIMQ;
188 }
189
190 DBG_FUNC("OUT\n");
191 }
192
193 static void
pqi_synch_request(rcb_t * rcb)194 pqi_synch_request(rcb_t *rcb)
195 {
196 pqisrc_softstate_t *softs = rcb->softs;
197
198 DBG_IO("IN rcb = %p\n", rcb);
199
200 if (!(rcb->cm_flags & PQI_CMD_MAPPED))
201 return;
202
203 if (rcb->bcount != 0 ) {
204 if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
205 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
206 rcb->cm_datamap,BUS_DMASYNC_POSTREAD);
207 if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
208 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
209 rcb->cm_datamap,BUS_DMASYNC_POSTWRITE);
210 bus_dmamap_unload(softs->os_specific.pqi_buffer_dmat,
211 rcb->cm_datamap);
212 }
213 rcb->cm_flags &= ~PQI_CMD_MAPPED;
214
215 if(rcb->sgt && rcb->nseg)
216 os_mem_free(rcb->softs, (void*)rcb->sgt,
217 rcb->nseg*sizeof(sgt_t));
218
219 DBG_IO("OUT\n");
220 }
221
222 /*
223 * Function to dma-unmap the completed request
224 */
225 static inline void
pqi_unmap_request(rcb_t * rcb)226 pqi_unmap_request(rcb_t *rcb)
227 {
228 DBG_IO("IN rcb = %p\n", rcb);
229
230 pqi_synch_request(rcb);
231 pqisrc_put_tag(&rcb->softs->taglist, rcb->tag);
232
233 DBG_IO("OUT\n");
234 }
235
236 /*
237 * Construct meaningful LD name for volume here.
238 */
239 static void
smartpqi_fix_ld_inquiry(pqisrc_softstate_t * softs,struct ccb_scsiio * csio)240 smartpqi_fix_ld_inquiry(pqisrc_softstate_t *softs, struct ccb_scsiio *csio)
241 {
242 struct scsi_inquiry_data *inq = NULL;
243 uint8_t *cdb = NULL;
244 pqi_scsi_dev_t *device = NULL;
245
246 DBG_FUNC("IN\n");
247
248 if (pqisrc_ctrl_offline(softs))
249 return;
250
251 cdb = (csio->ccb_h.flags & CAM_CDB_POINTER) ?
252 (uint8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes;
253
254 if(cdb[0] == INQUIRY &&
255 (cdb[1] & SI_EVPD) == 0 &&
256 (csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN &&
257 csio->dxfer_len >= SHORT_INQUIRY_LENGTH) {
258
259 inq = (struct scsi_inquiry_data *)csio->data_ptr;
260
261 /* device = softs->device_list[csio->ccb_h.target_id][csio->ccb_h.target_lun]; */
262 int target = csio->ccb_h.target_id;
263 int lun = csio->ccb_h.target_lun;
264 int index = pqisrc_find_btl_list_index(softs,softs->bus_id,target,lun);
265 if (index != INVALID_ELEM)
266 device = softs->dev_list[index];
267
268 /* Let the disks be probed and dealt with via CAM. Only for LD
269 let it fall through and inquiry be tweaked */
270 if( !device || !pqisrc_is_logical_device(device) ||
271 (device->devtype != DISK_DEVICE) ||
272 pqisrc_is_external_raid_device(device)) {
273 return;
274 }
275
276 strncpy(inq->vendor, device->vendor,
277 SID_VENDOR_SIZE-1);
278 inq->vendor[sizeof(inq->vendor)-1] = '\0';
279 strncpy(inq->product,
280 pqisrc_raidlevel_to_string(device->raid_level),
281 SID_PRODUCT_SIZE-1);
282 inq->product[sizeof(inq->product)-1] = '\0';
283 strncpy(inq->revision, device->volume_offline?"OFF":"OK",
284 SID_REVISION_SIZE-1);
285 inq->revision[sizeof(inq->revision)-1] = '\0';
286 }
287
288 DBG_FUNC("OUT\n");
289 }
290
291 static void
pqi_complete_scsi_io(struct ccb_scsiio * csio,rcb_t * rcb)292 pqi_complete_scsi_io(struct ccb_scsiio *csio, rcb_t *rcb)
293 {
294 uint32_t release_tag;
295 pqisrc_softstate_t *softs = rcb->softs;
296
297 DBG_IO("IN scsi io = %p\n", csio);
298
299 pqi_synch_request(rcb);
300 smartpqi_fix_ld_inquiry(rcb->softs, csio);
301 pqi_release_camq(rcb);
302 release_tag = rcb->tag;
303 os_reset_rcb(rcb);
304 pqisrc_put_tag(&softs->taglist, release_tag);
305 xpt_done((union ccb *)csio);
306
307 DBG_FUNC("OUT\n");
308 }
309
310 /*
311 * Handle completion of a command - pass results back through the CCB
312 */
313 void
os_io_response_success(rcb_t * rcb)314 os_io_response_success(rcb_t *rcb)
315 {
316 struct ccb_scsiio *csio;
317
318 DBG_IO("IN rcb = %p\n", rcb);
319
320 if (rcb == NULL)
321 panic("rcb is null");
322
323 csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
324
325 if (csio == NULL)
326 panic("csio is null");
327
328 rcb->status = PQI_STATUS_SUCCESS;
329 csio->ccb_h.status = CAM_REQ_CMP;
330
331 pqi_complete_scsi_io(csio, rcb);
332
333 DBG_IO("OUT\n");
334 }
335
336 static void
copy_sense_data_to_csio(struct ccb_scsiio * csio,uint8_t * sense_data,uint16_t sense_data_len)337 copy_sense_data_to_csio(struct ccb_scsiio *csio,
338 uint8_t *sense_data, uint16_t sense_data_len)
339 {
340 DBG_IO("IN csio = %p\n", csio);
341
342 memset(&csio->sense_data, 0, csio->sense_len);
343
344 sense_data_len = (sense_data_len > csio->sense_len) ?
345 csio->sense_len : sense_data_len;
346
347 if (sense_data)
348 memcpy(&csio->sense_data, sense_data, sense_data_len);
349
350 if (csio->sense_len > sense_data_len)
351 csio->sense_resid = csio->sense_len - sense_data_len;
352 else
353 csio->sense_resid = 0;
354
355 DBG_IO("OUT\n");
356 }
357
358 /*
359 * Error response handling for raid IO
360 */
361 void
os_raid_response_error(rcb_t * rcb,raid_path_error_info_elem_t * err_info)362 os_raid_response_error(rcb_t *rcb, raid_path_error_info_elem_t *err_info)
363 {
364 struct ccb_scsiio *csio;
365 pqisrc_softstate_t *softs;
366
367 DBG_IO("IN\n");
368
369 csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
370
371 if (csio == NULL)
372 panic("csio is null");
373
374 softs = rcb->softs;
375
376 csio->ccb_h.status = CAM_REQ_CMP_ERR;
377
378 if (!err_info || !rcb->dvp) {
379 DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
380 err_info, rcb->dvp);
381 goto error_out;
382 }
383
384 csio->scsi_status = err_info->status;
385
386 if (csio->ccb_h.func_code == XPT_SCSI_IO) {
387 /*
388 * Handle specific SCSI status values.
389 */
390 switch(csio->scsi_status) {
391 case PQI_RAID_STATUS_QUEUE_FULL:
392 csio->ccb_h.status = CAM_REQ_CMP;
393 DBG_ERR("Queue Full error\n");
394 break;
395 /* check condition, sense data included */
396 case PQI_RAID_STATUS_CHECK_CONDITION:
397 {
398 uint16_t sense_data_len =
399 LE_16(err_info->sense_data_len);
400 uint8_t *sense_data = NULL;
401 if (sense_data_len)
402 sense_data = err_info->data;
403
404 copy_sense_data_to_csio(csio, sense_data, sense_data_len);
405 csio->ccb_h.status = CAM_SCSI_STATUS_ERROR
406 | CAM_AUTOSNS_VALID
407 | CAM_REQ_CMP_ERR;
408
409 }
410 break;
411
412 case PQI_RAID_DATA_IN_OUT_UNDERFLOW:
413 {
414 uint32_t resid = 0;
415 resid = rcb->bcount-err_info->data_out_transferred;
416 csio->resid = resid;
417 csio->ccb_h.status = CAM_REQ_CMP;
418 }
419 break;
420 default:
421 csio->ccb_h.status = CAM_REQ_CMP;
422 break;
423 }
424 }
425
426 error_out:
427 pqi_complete_scsi_io(csio, rcb);
428
429 DBG_IO("OUT\n");
430 }
431
432 /*
433 * Error response handling for aio.
434 */
435 void
os_aio_response_error(rcb_t * rcb,aio_path_error_info_elem_t * err_info)436 os_aio_response_error(rcb_t *rcb, aio_path_error_info_elem_t *err_info)
437 {
438 struct ccb_scsiio *csio;
439 pqisrc_softstate_t *softs;
440
441 DBG_IO("IN\n");
442
443 if (rcb == NULL)
444 panic("rcb is null");
445
446 rcb->status = PQI_STATUS_SUCCESS;
447 csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
448 if (csio == NULL)
449 panic("csio is null");
450
451 softs = rcb->softs;
452
453 if (!err_info || !rcb->dvp) {
454 csio->ccb_h.status = CAM_REQ_CMP_ERR;
455 DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
456 err_info, rcb->dvp);
457 goto error_out;
458 }
459
460 switch (err_info->service_resp) {
461 case PQI_AIO_SERV_RESPONSE_COMPLETE:
462 csio->ccb_h.status = err_info->status;
463 break;
464 case PQI_AIO_SERV_RESPONSE_FAILURE:
465 switch(err_info->status) {
466 case PQI_AIO_STATUS_IO_ABORTED:
467 csio->ccb_h.status = CAM_REQ_ABORTED;
468 DBG_WARN_BTL(rcb->dvp, "IO aborted\n");
469 break;
470 case PQI_AIO_STATUS_UNDERRUN:
471 csio->ccb_h.status = CAM_REQ_CMP;
472 csio->resid =
473 LE_32(err_info->resd_count);
474 break;
475 case PQI_AIO_STATUS_OVERRUN:
476 csio->ccb_h.status = CAM_REQ_CMP;
477 break;
478 case PQI_AIO_STATUS_AIO_PATH_DISABLED:
479 DBG_WARN_BTL(rcb->dvp,"AIO Path Disabled\n");
480 /* Timed out TMF response comes here */
481 if (rcb->tm_req) {
482 rcb->req_pending = false;
483 rcb->status = PQI_STATUS_SUCCESS;
484 DBG_ERR("AIO Disabled for TMF\n");
485 return;
486 }
487 rcb->dvp->aio_enabled = false;
488 rcb->dvp->offload_enabled = false;
489 csio->ccb_h.status |= CAM_REQUEUE_REQ;
490 break;
491 case PQI_AIO_STATUS_IO_ERROR:
492 case PQI_AIO_STATUS_IO_NO_DEVICE:
493 case PQI_AIO_STATUS_INVALID_DEVICE:
494 default:
495 DBG_WARN_BTL(rcb->dvp,"IO Error/Invalid/No device\n");
496 csio->ccb_h.status |=
497 CAM_SCSI_STATUS_ERROR;
498 break;
499 }
500 break;
501 case PQI_AIO_SERV_RESPONSE_TMF_COMPLETE:
502 case PQI_AIO_SERV_RESPONSE_TMF_SUCCEEDED:
503 DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
504 (err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_COMPLETE) ? "COMPLETE" : "SUCCEEDED");
505 rcb->status = PQI_STATUS_SUCCESS;
506 rcb->req_pending = false;
507 return;
508 case PQI_AIO_SERV_RESPONSE_TMF_REJECTED:
509 case PQI_AIO_SERV_RESPONSE_TMF_INCORRECT_LUN:
510 DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
511 (err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_REJECTED) ? "REJECTED" : "INCORRECT LUN");
512 rcb->status = PQI_STATUS_TIMEOUT;
513 rcb->req_pending = false;
514 return;
515 default:
516 DBG_WARN_BTL(rcb->dvp,"Scsi Status Error\n");
517 csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
518 break;
519 }
520
521 if(err_info->data_pres == DATA_PRESENT_SENSE_DATA ) {
522 csio->scsi_status = PQI_AIO_STATUS_CHECK_CONDITION;
523 uint8_t *sense_data = NULL;
524 unsigned sense_data_len = LE_16(err_info->data_len);
525 if (sense_data_len)
526 sense_data = err_info->data;
527 DBG_INFO("SCSI_STATUS_CHECK_COND sense size %u\n",
528 sense_data_len);
529 copy_sense_data_to_csio(csio, sense_data, sense_data_len);
530 csio->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
531 }
532
533 error_out:
534 pqi_complete_scsi_io(csio, rcb);
535 DBG_IO("OUT\n");
536 }
537
538 static void
pqi_freeze_ccb(union ccb * ccb)539 pqi_freeze_ccb(union ccb *ccb)
540 {
541 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
542 ccb->ccb_h.status |= CAM_DEV_QFRZN;
543 xpt_freeze_devq(ccb->ccb_h.path, 1);
544 }
545 }
546
547 /*
548 * Command-mapping helper function - populate this command's s/g table.
549 */
550 static void
pqi_request_map_helper(void * arg,bus_dma_segment_t * segs,int nseg,int error)551 pqi_request_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
552 {
553 rcb_t *rcb = (rcb_t *)arg;
554 pqisrc_softstate_t *softs = rcb->softs;
555 union ccb *ccb;
556
557 if (error || nseg > softs->pqi_cap.max_sg_elem)
558 {
559 DBG_ERR_BTL(rcb->dvp, "map failed err = %d or nseg(%d) > sgelem(%u)\n",
560 error, nseg, softs->pqi_cap.max_sg_elem);
561 goto error_io;
562 }
563
564 rcb->sgt = os_mem_alloc(softs, nseg * sizeof(sgt_t));
565
566 if (!rcb->sgt) {
567 DBG_ERR_BTL(rcb->dvp, "os_mem_alloc() failed; nseg = %d\n", nseg);
568 goto error_io;
569 }
570
571 rcb->nseg = nseg;
572 for (int i = 0; i < nseg; i++) {
573 rcb->sgt[i].addr = segs[i].ds_addr;
574 rcb->sgt[i].len = segs[i].ds_len;
575 rcb->sgt[i].flags = 0;
576 }
577
578 if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
579 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
580 rcb->cm_datamap, BUS_DMASYNC_PREREAD);
581 if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
582 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
583 rcb->cm_datamap, BUS_DMASYNC_PREWRITE);
584
585 /* Call IO functions depending on pd or ld */
586 rcb->status = PQI_STATUS_FAILURE;
587
588 error = pqisrc_build_send_io(softs, rcb);
589
590 if (error) {
591 rcb->req_pending = false;
592 DBG_ERR_BTL(rcb->dvp, "Build IO failed, error = %d\n", error);
593 } else {
594 /* Successfully IO was submitted to the device. */
595 return;
596 }
597
598 error_io:
599 ccb = rcb->cm_ccb;
600 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
601 pqi_freeze_ccb(ccb);
602 pqi_unmap_request(rcb);
603 xpt_done(ccb);
604 return;
605 }
606
607 /*
608 * Function to dma-map the request buffer
609 */
610 static int
pqi_map_request(rcb_t * rcb)611 pqi_map_request(rcb_t *rcb)
612 {
613 pqisrc_softstate_t *softs = rcb->softs;
614 int bsd_status = BSD_SUCCESS;
615 union ccb *ccb = rcb->cm_ccb;
616
617 DBG_FUNC("IN\n");
618
619 /* check that mapping is necessary */
620 if (rcb->cm_flags & PQI_CMD_MAPPED)
621 return BSD_SUCCESS;
622
623 rcb->cm_flags |= PQI_CMD_MAPPED;
624
625 if (rcb->bcount) {
626 bsd_status = bus_dmamap_load_ccb(softs->os_specific.pqi_buffer_dmat,
627 rcb->cm_datamap, ccb, pqi_request_map_helper, rcb, 0);
628 if (bsd_status != BSD_SUCCESS && bsd_status != EINPROGRESS) {
629 DBG_ERR_BTL(rcb->dvp, "bus_dmamap_load_ccb failed, return status = %d transfer length = %u\n",
630 bsd_status, rcb->bcount);
631 return bsd_status;
632 }
633 } else {
634 /*
635 * Set up the command to go to the controller. If there are no
636 * data buffers associated with the command then it can bypass
637 * busdma.
638 */
639 /* Call IO functions depending on pd or ld */
640 rcb->status = PQI_STATUS_FAILURE;
641
642 if (pqisrc_build_send_io(softs, rcb) != PQI_STATUS_SUCCESS) {
643 bsd_status = EIO;
644 }
645 }
646
647 DBG_FUNC("OUT error = %d\n", bsd_status);
648
649 return bsd_status;
650 }
651
652 /*
653 * Function to clear the request control block
654 */
655 void
os_reset_rcb(rcb_t * rcb)656 os_reset_rcb(rcb_t *rcb)
657 {
658 rcb->error_info = NULL;
659 rcb->req = NULL;
660 rcb->status = -1;
661 rcb->tag = INVALID_ELEM;
662 rcb->dvp = NULL;
663 rcb->cdbp = NULL;
664 rcb->softs = NULL;
665 rcb->cm_flags = 0;
666 rcb->cm_data = NULL;
667 rcb->bcount = 0;
668 rcb->nseg = 0;
669 rcb->sgt = NULL;
670 rcb->cm_ccb = NULL;
671 rcb->encrypt_enable = false;
672 rcb->ioaccel_handle = 0;
673 rcb->resp_qid = 0;
674 rcb->req_pending = false;
675 rcb->tm_req = false;
676 }
677
678 /*
679 * Callback function for the lun rescan
680 */
681 static void
smartpqi_lunrescan_cb(struct cam_periph * periph,union ccb * ccb)682 smartpqi_lunrescan_cb(struct cam_periph *periph, union ccb *ccb)
683 {
684 xpt_free_path(ccb->ccb_h.path);
685 xpt_free_ccb(ccb);
686 }
687
688
689 /*
690 * Function to rescan the lun
691 */
692 static void
smartpqi_lun_rescan(struct pqisrc_softstate * softs,int target,int lun)693 smartpqi_lun_rescan(struct pqisrc_softstate *softs, int target,
694 int lun)
695 {
696 union ccb *ccb = NULL;
697 cam_status status = 0;
698 struct cam_path *path = NULL;
699
700 DBG_FUNC("IN\n");
701
702 ccb = xpt_alloc_ccb_nowait();
703 if (ccb == NULL) {
704 DBG_ERR("Unable to alloc ccb for lun rescan\n");
705 return;
706 }
707
708 status = xpt_create_path(&path, NULL,
709 cam_sim_path(softs->os_specific.sim), target, lun);
710 if (status != CAM_REQ_CMP) {
711 DBG_ERR("xpt_create_path status(%d) != CAM_REQ_CMP \n",
712 status);
713 xpt_free_ccb(ccb);
714 return;
715 }
716
717 memset(ccb, 0, sizeof(union ccb));
718 xpt_setup_ccb(&ccb->ccb_h, path, 5);
719 ccb->ccb_h.func_code = XPT_SCAN_LUN;
720 ccb->ccb_h.cbfcnp = smartpqi_lunrescan_cb;
721 ccb->crcn.flags = CAM_FLAG_NONE;
722
723 xpt_action(ccb);
724
725 DBG_FUNC("OUT\n");
726 }
727
728 /*
729 * Function to rescan the lun under each target
730 */
731 void
smartpqi_target_rescan(struct pqisrc_softstate * softs)732 smartpqi_target_rescan(struct pqisrc_softstate *softs)
733 {
734 pqi_scsi_dev_t *device;
735 int index;
736
737 DBG_FUNC("IN\n");
738
739 for(index = 0; index < PQI_MAX_DEVICES; index++){
740 /* if(softs->device_list[target][lun]){ */
741 if(softs->dev_list[index] != NULL) {
742 device = softs->dev_list[index];
743 DBG_INFO("calling smartpqi_lun_rescan with TL = %d:%d\n",device->target,device->lun);
744 smartpqi_lun_rescan(softs, device->target, device->lun);
745 }
746 }
747
748 DBG_FUNC("OUT\n");
749 }
750
751 /*
752 * Set the mode of tagged command queueing for the current task.
753 */
754 uint8_t
os_get_task_attr(rcb_t * rcb)755 os_get_task_attr(rcb_t *rcb)
756 {
757 union ccb *ccb = rcb->cm_ccb;
758 uint8_t tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
759
760 switch(ccb->csio.tag_action) {
761 case MSG_HEAD_OF_Q_TAG:
762 tag_action = SOP_TASK_ATTRIBUTE_HEAD_OF_QUEUE;
763 break;
764 case MSG_ORDERED_Q_TAG:
765 tag_action = SOP_TASK_ATTRIBUTE_ORDERED;
766 break;
767 case MSG_SIMPLE_Q_TAG:
768 default:
769 tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
770 break;
771 }
772 return tag_action;
773 }
774
775 /*
776 * Complete all outstanding commands
777 */
778 void
os_complete_outstanding_cmds_nodevice(pqisrc_softstate_t * softs)779 os_complete_outstanding_cmds_nodevice(pqisrc_softstate_t *softs)
780 {
781 int tag = 0;
782 pqi_scsi_dev_t *dvp = NULL;
783
784 DBG_FUNC("IN\n");
785
786 for (tag = 1; tag <= softs->max_outstanding_io; tag++) {
787 rcb_t *prcb = &softs->rcb[tag];
788 dvp = prcb->dvp;
789 if(prcb->req_pending && prcb->cm_ccb ) {
790 prcb->req_pending = false;
791 prcb->cm_ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_REQ_CMP;
792 pqi_complete_scsi_io(&prcb->cm_ccb->csio, prcb);
793 if (dvp)
794 pqisrc_decrement_device_active_io(softs, dvp);
795 }
796 }
797
798 DBG_FUNC("OUT\n");
799 }
800
801 /*
802 * IO handling functionality entry point
803 */
804 static int
pqisrc_io_start(struct cam_sim * sim,union ccb * ccb)805 pqisrc_io_start(struct cam_sim *sim, union ccb *ccb)
806 {
807 rcb_t *rcb;
808 uint32_t tag;
809 pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
810 cam_sim_softc(sim);
811 int32_t error;
812 pqi_scsi_dev_t *dvp;
813 int target, lun, index;
814
815 DBG_FUNC("IN\n");
816
817 /* if( softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun] == NULL ) { */
818 target = ccb->ccb_h.target_id;
819 lun = ccb->ccb_h.target_lun;
820 index = pqisrc_find_btl_list_index(softs,softs->bus_id,target,lun);
821
822 if (index == INVALID_ELEM) {
823 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
824 DBG_INFO("Invalid index/device!!!, Device BTL %u:%d:%d\n", softs->bus_id, target, lun);
825 return ENXIO;
826 }
827
828 if( softs->dev_list[index] == NULL ) {
829 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
830 DBG_INFO("Device = %d not there\n", ccb->ccb_h.target_id);
831 return ENXIO;
832 }
833
834 /* DBG_INFO("starting IO on BTL = %d:%d:%d index = %d\n",softs->bus_id,target,lun,index); */
835
836 /* dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */
837 dvp = softs->dev_list[index];
838 /* Check controller state */
839 if (IN_PQI_RESET(softs)) {
840 ccb->ccb_h.status = CAM_SCSI_BUS_RESET
841 | CAM_BUSY | CAM_REQ_INPROG;
842 DBG_WARN("Device = %d BUSY/IN_RESET\n", ccb->ccb_h.target_id);
843 return ENXIO;
844 }
845 /* Check device state */
846 if (pqisrc_ctrl_offline(softs) || DEV_GONE(dvp)) {
847 ccb->ccb_h.status = CAM_DEV_NOT_THERE | CAM_REQ_CMP;
848 DBG_WARN("Device = %d GONE/OFFLINE\n", ccb->ccb_h.target_id);
849 return ENXIO;
850 }
851 /* Check device reset */
852 if (DEVICE_RESET(dvp)) {
853 ccb->ccb_h.status = CAM_SCSI_BUSY | CAM_REQ_INPROG | CAM_BUSY;
854 DBG_WARN("Device %d reset returned busy\n", ccb->ccb_h.target_id);
855 return EBUSY;
856 }
857
858 if (dvp->expose_device == false) {
859 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
860 DBG_INFO("Device = %d not exposed\n", ccb->ccb_h.target_id);
861 return ENXIO;
862 }
863
864 tag = pqisrc_get_tag(&softs->taglist);
865 if( tag == INVALID_ELEM ) {
866 DBG_ERR("Get Tag failed\n");
867 xpt_freeze_simq(softs->os_specific.sim, 1);
868 softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
869 ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ);
870 return EIO;
871 }
872
873 DBG_IO("tag = %u &softs->taglist : %p\n", tag, &softs->taglist);
874
875 rcb = &softs->rcb[tag];
876 os_reset_rcb(rcb);
877 rcb->tag = tag;
878 rcb->softs = softs;
879 rcb->cmdlen = ccb->csio.cdb_len;
880 ccb->ccb_h.sim_priv.entries[0].ptr = rcb;
881
882 rcb->cm_ccb = ccb;
883 /* rcb->dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */
884 rcb->dvp = softs->dev_list[index];
885
886 rcb->cm_data = (void *)ccb->csio.data_ptr;
887 rcb->bcount = ccb->csio.dxfer_len;
888
889 /*
890 * Submit the request to the adapter.
891 *
892 * Note that this may fail if we're unable to map the request (and
893 * if we ever learn a transport layer other than simple, may fail
894 * if the adapter rejects the command).
895 */
896 if ((error = pqi_map_request(rcb)) != BSD_SUCCESS) {
897 xpt_freeze_simq(softs->os_specific.sim, 1);
898 if (error == EINPROGRESS) {
899 /* Release simq in the completion */
900 softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
901 error = BSD_SUCCESS;
902 } else {
903 rcb->req_pending = false;
904 ccb->ccb_h.status |= CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
905 DBG_WARN("Requeue req error = %d target = %d\n", error,
906 ccb->ccb_h.target_id);
907 pqi_unmap_request(rcb);
908 error = EIO;
909 }
910 }
911
912 DBG_FUNC("OUT error = %d\n", error);
913
914 return error;
915 }
916
917 static inline int
pqi_tmf_status_to_bsd_tmf_status(int pqi_status,rcb_t * rcb)918 pqi_tmf_status_to_bsd_tmf_status(int pqi_status, rcb_t *rcb)
919 {
920 if (PQI_STATUS_SUCCESS == pqi_status &&
921 PQI_STATUS_SUCCESS == rcb->status)
922 return BSD_SUCCESS;
923 else
924 return EIO;
925 }
926
927 /*
928 * Abort a task, task management functionality
929 */
930 static int
pqisrc_scsi_abort_task(pqisrc_softstate_t * softs,union ccb * ccb)931 pqisrc_scsi_abort_task(pqisrc_softstate_t *softs, union ccb *ccb)
932 {
933 rcb_t *rcb = NULL;
934 struct ccb_hdr *ccb_h = &ccb->ccb_h;
935 rcb_t *prcb = ccb->ccb_h.sim_priv.entries[0].ptr;
936 uint32_t tag;
937 int rval;
938
939 DBG_FUNC("IN\n");
940
941 tag = pqisrc_get_tag(&softs->taglist);
942 rcb = &softs->rcb[tag];
943 rcb->tag = tag;
944
945 if (rcb->dvp == NULL) {
946 DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
947 rval = ENXIO;
948 goto error_tmf;
949 }
950
951 rcb->tm_req = true;
952
953 rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, prcb,
954 SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK);
955
956 if ((rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb)) == BSD_SUCCESS)
957 ccb->ccb_h.status = CAM_REQ_ABORTED;
958
959 error_tmf:
960 os_reset_rcb(rcb);
961 pqisrc_put_tag(&softs->taglist, tag);
962
963 DBG_FUNC("OUT rval = %d\n", rval);
964
965 return rval;
966 }
967
968 /*
969 * Abort a taskset, task management functionality
970 */
971 static int
pqisrc_scsi_abort_task_set(pqisrc_softstate_t * softs,union ccb * ccb)972 pqisrc_scsi_abort_task_set(pqisrc_softstate_t *softs, union ccb *ccb)
973 {
974 struct ccb_hdr *ccb_h = &ccb->ccb_h;
975 rcb_t *rcb = NULL;
976 uint32_t tag;
977 int rval;
978
979 DBG_FUNC("IN\n");
980
981 tag = pqisrc_get_tag(&softs->taglist);
982 rcb = &softs->rcb[tag];
983 rcb->tag = tag;
984 rcb->cm_ccb = ccb;
985
986 if (rcb->dvp == NULL) {
987 DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
988 rval = ENXIO;
989 goto error_tmf;
990 }
991
992 rcb->tm_req = true;
993
994 rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, NULL,
995 SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK_SET);
996
997 rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
998
999 error_tmf:
1000 os_reset_rcb(rcb);
1001 pqisrc_put_tag(&softs->taglist, tag);
1002
1003 DBG_FUNC("OUT rval = %d\n", rval);
1004
1005 return rval;
1006 }
1007
1008 /*
1009 * Target reset task management functionality
1010 */
1011 static int
pqisrc_target_reset(pqisrc_softstate_t * softs,union ccb * ccb)1012 pqisrc_target_reset( pqisrc_softstate_t *softs, union ccb *ccb)
1013 {
1014
1015 /* pqi_scsi_dev_t *devp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */
1016 struct ccb_hdr *ccb_h = &ccb->ccb_h;
1017 rcb_t *rcb = NULL;
1018 uint32_t tag;
1019 int rval;
1020
1021 int bus, target, lun;
1022 int index;
1023
1024 DBG_FUNC("IN\n");
1025
1026 bus = softs->bus_id;
1027 target = ccb->ccb_h.target_id;
1028 lun = ccb->ccb_h.target_lun;
1029
1030 index = pqisrc_find_btl_list_index(softs,bus,target,lun);
1031 if (index == INVALID_ELEM) {
1032 DBG_ERR("device not found at BTL %d:%d:%d\n",bus,target,lun);
1033 return (-1);
1034 }
1035
1036 pqi_scsi_dev_t *devp = softs->dev_list[index];
1037 if (devp == NULL) {
1038 DBG_ERR("bad target %d, tmf type : 0x%x\n", ccb_h->target_id, ccb_h->func_code);
1039 return (-1);
1040 }
1041
1042 tag = pqisrc_get_tag(&softs->taglist);
1043 rcb = &softs->rcb[tag];
1044 rcb->tag = tag;
1045 rcb->cm_ccb = ccb;
1046
1047 rcb->tm_req = true;
1048
1049 rval = pqisrc_send_tmf(softs, devp, rcb, NULL,
1050 SOP_TASK_MANAGEMENT_LUN_RESET);
1051
1052 rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
1053
1054 devp->reset_in_progress = false;
1055
1056 os_reset_rcb(rcb);
1057 pqisrc_put_tag(&softs->taglist, tag);
1058
1059 DBG_FUNC("OUT rval = %d\n", rval);
1060
1061 return rval;
1062
1063 }
1064
1065 /*
1066 * cam entry point of the smartpqi module.
1067 */
1068 static void
smartpqi_cam_action(struct cam_sim * sim,union ccb * ccb)1069 smartpqi_cam_action(struct cam_sim *sim, union ccb *ccb)
1070 {
1071 struct pqisrc_softstate *softs = cam_sim_softc(sim);
1072 struct ccb_hdr *ccb_h = &ccb->ccb_h;
1073
1074 DBG_FUNC("IN\n");
1075
1076 switch (ccb_h->func_code) {
1077 case XPT_SCSI_IO:
1078 {
1079 if(!pqisrc_io_start(sim, ccb)) {
1080 return;
1081 }
1082 break;
1083 }
1084 case XPT_CALC_GEOMETRY:
1085 {
1086 struct ccb_calc_geometry *ccg;
1087 ccg = &ccb->ccg;
1088 if (ccg->block_size == 0) {
1089 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1090 ccb->ccb_h.status |= CAM_REQ_INVALID;
1091 break;
1092 }
1093 cam_calc_geometry(ccg, /* extended */ 1);
1094 ccb->ccb_h.status = CAM_REQ_CMP;
1095 break;
1096 }
1097 case XPT_PATH_INQ:
1098 {
1099 update_sim_properties(sim, &ccb->cpi);
1100 ccb->ccb_h.status = CAM_REQ_CMP;
1101 break;
1102 }
1103 case XPT_GET_TRAN_SETTINGS:
1104 get_transport_settings(softs, &ccb->cts);
1105 ccb->ccb_h.status = CAM_REQ_CMP;
1106 break;
1107 case XPT_ABORT:
1108 if(pqisrc_scsi_abort_task(softs, ccb)) {
1109 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1110 xpt_done(ccb);
1111 DBG_ERR("Abort task failed on %d\n",
1112 ccb->ccb_h.target_id);
1113 return;
1114 }
1115 break;
1116 case XPT_TERM_IO:
1117 if (pqisrc_scsi_abort_task_set(softs, ccb)) {
1118 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1119 DBG_ERR("Abort task set failed on %d\n",
1120 ccb->ccb_h.target_id);
1121 xpt_done(ccb);
1122 return;
1123 }
1124 break;
1125 case XPT_RESET_DEV:
1126 if(pqisrc_target_reset(softs, ccb)) {
1127 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1128 DBG_ERR("Target reset failed on %d\n",
1129 ccb->ccb_h.target_id);
1130 xpt_done(ccb);
1131 return;
1132 } else {
1133 ccb->ccb_h.status = CAM_REQ_CMP;
1134 }
1135 break;
1136 case XPT_RESET_BUS:
1137 ccb->ccb_h.status = CAM_REQ_CMP;
1138 break;
1139 case XPT_SET_TRAN_SETTINGS:
1140 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1141 return;
1142 default:
1143 DBG_WARN("UNSUPPORTED FUNC CODE\n");
1144 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1145 break;
1146 }
1147 xpt_done(ccb);
1148
1149 DBG_FUNC("OUT\n");
1150 }
1151
1152 /*
1153 * Function to poll the response, when interrupts are unavailable
1154 * This also serves supporting crash dump.
1155 */
1156 static void
smartpqi_poll(struct cam_sim * sim)1157 smartpqi_poll(struct cam_sim *sim)
1158 {
1159 struct pqisrc_softstate *softs = cam_sim_softc(sim);
1160 int i;
1161
1162 for (i = 1; i < softs->intr_count; i++ )
1163 pqisrc_process_response_queue(softs, i);
1164 }
1165
1166 /*
1167 * Function to adjust the queue depth of a device
1168 */
1169 void
smartpqi_adjust_queue_depth(struct cam_path * path,uint32_t queue_depth)1170 smartpqi_adjust_queue_depth(struct cam_path *path, uint32_t queue_depth)
1171 {
1172 struct ccb_relsim crs;
1173
1174 DBG_FUNC("IN\n");
1175
1176 memset(&crs, 0, sizeof(struct ccb_relsim));
1177 xpt_setup_ccb(&crs.ccb_h, path, 5);
1178 crs.ccb_h.func_code = XPT_REL_SIMQ;
1179 crs.ccb_h.flags = CAM_DEV_QFREEZE;
1180 crs.release_flags = RELSIM_ADJUST_OPENINGS;
1181 crs.openings = queue_depth;
1182 xpt_action((union ccb *)&crs);
1183 if(crs.ccb_h.status != CAM_REQ_CMP) {
1184 printf("XPT_REL_SIMQ failed stat=%d\n", crs.ccb_h.status);
1185 }
1186
1187 DBG_FUNC("OUT\n");
1188 }
1189
1190 /*
1191 * Function to register async callback for setting queue depth
1192 */
1193 static void
smartpqi_async(void * callback_arg,u_int32_t code,struct cam_path * path,void * arg)1194 smartpqi_async(void *callback_arg, u_int32_t code,
1195 struct cam_path *path, void *arg)
1196 {
1197 struct pqisrc_softstate *softs;
1198 softs = (struct pqisrc_softstate*)callback_arg;
1199
1200 DBG_FUNC("IN\n");
1201
1202 switch (code) {
1203 case AC_FOUND_DEVICE:
1204 {
1205 struct ccb_getdev *cgd;
1206 cgd = (struct ccb_getdev *)arg;
1207 if (cgd == NULL) {
1208 break;
1209 }
1210 uint32_t t_id = cgd->ccb_h.target_id;
1211
1212 /* if (t_id <= (PQI_CTLR_INDEX - 1)) { */
1213 if (t_id >= PQI_CTLR_INDEX) {
1214 if (softs != NULL) {
1215 /* pqi_scsi_dev_t *dvp = softs->device_list[t_id][cgd->ccb_h.target_lun]; */
1216 int lun = cgd->ccb_h.target_lun;
1217 int index = pqisrc_find_btl_list_index(softs,softs->bus_id,t_id,lun);
1218 if (index != INVALID_ELEM) {
1219 pqi_scsi_dev_t *dvp = softs->dev_list[index];
1220 if (dvp == NULL) {
1221 DBG_ERR("Target is null, target id=%u\n", t_id);
1222 break;
1223 }
1224 smartpqi_adjust_queue_depth(path, dvp->queue_depth);
1225 }
1226 }
1227 }
1228 break;
1229 }
1230 default:
1231 break;
1232 }
1233
1234 DBG_FUNC("OUT\n");
1235 }
1236
1237 /*
1238 * Function to register sim with CAM layer for smartpqi driver
1239 */
1240 int
register_sim(struct pqisrc_softstate * softs,int card_index)1241 register_sim(struct pqisrc_softstate *softs, int card_index)
1242 {
1243 int max_transactions;
1244 union ccb *ccb = NULL;
1245 cam_status status = 0;
1246 struct ccb_setasync csa;
1247 struct cam_sim *sim;
1248
1249 DBG_FUNC("IN\n");
1250
1251 max_transactions = softs->max_io_for_scsi_ml;
1252 softs->os_specific.devq = cam_simq_alloc(max_transactions);
1253 if (softs->os_specific.devq == NULL) {
1254 DBG_ERR("cam_simq_alloc failed txns = %d\n",
1255 max_transactions);
1256 return ENOMEM;
1257 }
1258
1259 sim = cam_sim_alloc(smartpqi_cam_action, \
1260 smartpqi_poll, "smartpqi", softs, \
1261 card_index, &softs->os_specific.cam_lock, \
1262 1, max_transactions, softs->os_specific.devq);
1263 if (sim == NULL) {
1264 DBG_ERR("cam_sim_alloc failed txns = %d\n",
1265 max_transactions);
1266 cam_simq_free(softs->os_specific.devq);
1267 return ENOMEM;
1268 }
1269
1270 softs->os_specific.sim = sim;
1271 mtx_lock(&softs->os_specific.cam_lock);
1272 status = xpt_bus_register(sim, softs->os_specific.pqi_dev, 0);
1273 if (status != CAM_SUCCESS) {
1274 DBG_ERR("xpt_bus_register failed status=%d\n", status);
1275 cam_sim_free(softs->os_specific.sim, FALSE);
1276 cam_simq_free(softs->os_specific.devq);
1277 mtx_unlock(&softs->os_specific.cam_lock);
1278 return ENXIO;
1279 }
1280
1281 softs->os_specific.sim_registered = TRUE;
1282 ccb = xpt_alloc_ccb_nowait();
1283 if (ccb == NULL) {
1284 DBG_ERR("xpt_create_path failed\n");
1285 return ENXIO;
1286 }
1287
1288 if (xpt_create_path(&ccb->ccb_h.path, NULL,
1289 cam_sim_path(softs->os_specific.sim),
1290 CAM_TARGET_WILDCARD,
1291 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1292 DBG_ERR("xpt_create_path failed\n");
1293 xpt_free_ccb(ccb);
1294 xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
1295 cam_sim_free(softs->os_specific.sim, TRUE);
1296 mtx_unlock(&softs->os_specific.cam_lock);
1297 return ENXIO;
1298 }
1299 /*
1300 * Callback to set the queue depth per target which is
1301 * derived from the FW.
1302 */
1303 softs->os_specific.path = ccb->ccb_h.path;
1304 memset(&csa, 0, sizeof(struct ccb_setasync));
1305 xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
1306 csa.ccb_h.func_code = XPT_SASYNC_CB;
1307 csa.event_enable = AC_FOUND_DEVICE;
1308 csa.callback = smartpqi_async;
1309 csa.callback_arg = softs;
1310 xpt_action((union ccb *)&csa);
1311 if (csa.ccb_h.status != CAM_REQ_CMP) {
1312 DBG_ERR("Unable to register smartpqi_aysnc handler: %d!\n",
1313 csa.ccb_h.status);
1314 }
1315
1316 mtx_unlock(&softs->os_specific.cam_lock);
1317 DBG_FUNC("OUT\n");
1318
1319 return BSD_SUCCESS;
1320 }
1321
1322 /*
1323 * Function to deregister smartpqi sim from cam layer
1324 */
1325 void
deregister_sim(struct pqisrc_softstate * softs)1326 deregister_sim(struct pqisrc_softstate *softs)
1327 {
1328 struct ccb_setasync csa;
1329
1330 DBG_FUNC("IN\n");
1331
1332 if (softs->os_specific.mtx_init) {
1333 mtx_lock(&softs->os_specific.cam_lock);
1334 }
1335
1336 memset(&csa, 0, sizeof(struct ccb_setasync));
1337 xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
1338 csa.ccb_h.func_code = XPT_SASYNC_CB;
1339 csa.event_enable = 0;
1340 csa.callback = smartpqi_async;
1341 csa.callback_arg = softs;
1342 xpt_action((union ccb *)&csa);
1343 xpt_free_path(softs->os_specific.path);
1344
1345 if (softs->os_specific.sim) {
1346 xpt_release_simq(softs->os_specific.sim, 0);
1347 xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
1348 softs->os_specific.sim_registered = FALSE;
1349 cam_sim_free(softs->os_specific.sim, FALSE);
1350 softs->os_specific.sim = NULL;
1351 }
1352
1353 if (softs->os_specific.mtx_init) {
1354 mtx_unlock(&softs->os_specific.cam_lock);
1355 }
1356 if (softs->os_specific.devq != NULL) {
1357 cam_simq_free(softs->os_specific.devq);
1358 }
1359 if (softs->os_specific.mtx_init) {
1360 mtx_destroy(&softs->os_specific.cam_lock);
1361 softs->os_specific.mtx_init = FALSE;
1362 }
1363
1364 mtx_destroy(&softs->os_specific.map_lock);
1365
1366 DBG_FUNC("OUT\n");
1367 }
1368
1369 void
os_rescan_target(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)1370 os_rescan_target(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
1371 {
1372 struct cam_path *tmppath = NULL;
1373
1374 DBG_FUNC("IN\n");
1375
1376 if(softs->os_specific.sim_registered) {
1377 if (xpt_create_path(&tmppath, NULL,
1378 cam_sim_path(softs->os_specific.sim),
1379 device->target, device->lun) != CAM_REQ_CMP) {
1380 DBG_ERR("unable to create path for async event!!! Bus: %d Target: %d Lun: %d\n",
1381 device->bus, device->target, device->lun);
1382 return;
1383 }
1384 xpt_async(AC_INQ_CHANGED, tmppath, NULL);
1385 xpt_free_path(tmppath);
1386 }
1387
1388 device->scsi_rescan = false;
1389
1390 DBG_FUNC("OUT\n");
1391 }
1392