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