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