summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>2012-06-26 14:51:35 +0000
committerken <ken@FreeBSD.org>2012-06-26 14:51:35 +0000
commit877f7e22dc80676c9ece47bf58c4a6bdc79be4c7 (patch)
tree7b016bc8afd686b682aaffe21bfcace67afaf0e7 /sys/cam
parent4183957bce956b38c2e2189a30e2a92d9dc592af (diff)
downloadFreeBSD-src-877f7e22dc80676c9ece47bf58c4a6bdc79be4c7.zip
FreeBSD-src-877f7e22dc80676c9ece47bf58c4a6bdc79be4c7.tar.gz
Fix an issue that caused the kernel to panic inside CTL when trying
to attach to target capable HBAs that implement the old immediate notify (XPT_IMMED_NOTIFY) and notify acknowledge (XPT_NOTIFY_ACK) CCBs. The new API has been in place since SVN change 196008 in 2009. The solution is two-fold: fix CTL to handle the responses from the HBAs, and convert the HBA drivers in question to use the new API. These drivers have not been tested with CTL, so how well they will interoperate with CTL is unknown. scsi_target.c: Update the userland target example code to use the new immediate notify API. scsi_ctl.c: Detect when an immediate notify CCB is returned with CAM_REQ_INVALID or CAM_PROVIDE_FAIL status, and just free it. Fix a duplicate assignment. aic79xx.c, aic79xx_osm.c: Update the aic79xx driver to use the new API. Target mode is not enabled on for this driver, so the changes will have no practical effect. aic7xxx.c, aic7xxx_osm.c: Update the aic7xxx driver to use the new API. sbp_targ.c: Update the firewire target code to work with the new API. mpt_cam.c: Update the mpt(4) driver to work with the new API. Target mode is only enabled for Fibre Channel mpt(4) devices. MFC after: 3 days
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/ctl/scsi_ctl.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 0563f72..044b9a9 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -558,7 +558,6 @@ ctlferegister(struct cam_periph *periph, void *arg)
TAILQ_INIT(&softc->work_queue);
softc->periph = periph;
- softc->parent_softc = bus_softc;
callout_init_mtx(&softc->dma_callout, sim->mtx, /*flags*/ 0);
periph->softc = softc;
@@ -628,12 +627,22 @@ ctlferegister(struct cam_periph *periph, void *arg)
xpt_action(new_ccb);
softc->inots_sent++;
status = new_ccb->ccb_h.status;
- if (status != CAM_REQ_INPROG) {
- free(new_ccb, M_CTLFE);
+ if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
+ /*
+ * Note that we don't free the CCB here. If the
+ * status is not CAM_REQ_INPROG, then we're
+ * probably talking to a SIM that says it is
+ * target-capable but doesn't support the
+ * XPT_IMMEDIATE_NOTIFY CCB. i.e. it supports the
+ * older API. In that case, it'll call xpt_done()
+ * on the CCB, and we need to free it in our done
+ * routine as a result.
+ */
break;
}
}
- if (i == 0) {
+ if ((i == 0)
+ || (status != CAM_REQ_INPROG)) {
xpt_print(periph->path, "%s: could not allocate immediate "
"notify CCBs, status 0x%x\n", __func__, status);
return (CAM_REQ_CMP_ERR);
@@ -1460,12 +1469,29 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
*/
send_ctl_io = 0;
break;
+ case CAM_REQ_INVALID:
+ case CAM_PROVIDE_FAIL:
default:
- xpt_print(periph->path, "%s: "
- "unsupported CAM status 0x%x\n",
- __func__, status);
- send_ctl_io = 0;
- break;
+ /*
+ * We should only get here if we're talking
+ * to a talking to a SIM that is target
+ * capable but supports the old API. In
+ * that case, we need to just free the CCB.
+ * If we actually send a notify acknowledge,
+ * it will send that back with an error as
+ * well.
+ */
+
+ if ((status != CAM_REQ_INVALID)
+ && (status != CAM_PROVIDE_FAIL))
+ xpt_print(periph->path, "%s: "
+ "unsupported CAM status "
+ "0x%x\n", __func__, status);
+
+ ctl_free_io(io);
+ ctlfe_free_ccb(periph, done_ccb);
+
+ return;
}
if (send_ctl_io != 0) {
ctl_queue(io);
OpenPOWER on IntegriCloud