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