xref: /freebsd/sys/dev/smartpqi/smartpqi_cam.c (revision 85732ac8)
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  */
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  */
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  */
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  */
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  */
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  */
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
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
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  */
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  */
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
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 (DEV_RESET(dvp)) {
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
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
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
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  */
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  */
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  */
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
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  */
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  */
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