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