summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/cam_ccb.h12
-rw-r--r--sys/cam/ctl/scsi_ctl.c23
-rw-r--r--sys/dev/isp/isp_freebsd.c20
3 files changed, 49 insertions, 6 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 251d62d..1d56ac7 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -1084,7 +1084,17 @@ struct ccb_notify_acknowledge {
u_int tag_id; /* Tag for immediate notify */
u_int seq_id; /* Tar for target of notify */
u_int initiator_id; /* Initiator Identifier */
- u_int arg; /* Function specific */
+ u_int arg; /* Response information */
+ /*
+ * Lower byte of arg is one of RESPONSE CODE values defined below
+ * (subset of response codes from SPL-4 and FCP-4 specifications),
+ * upper 3 bytes is code-specific ADDITIONAL RESPONSE INFORMATION.
+ */
+#define CAM_RSP_TMF_COMPLETE 0x00
+#define CAM_RSP_TMF_REJECTED 0x04
+#define CAM_RSP_TMF_FAILED 0x05
+#define CAM_RSP_TMF_SUCCEEDED 0x08
+#define CAM_RSP_TMF_INCORRECT_LUN 0x09
};
/* HBA engine structures. */
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 2705240..abdbdcd 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -1552,6 +1552,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
/*
* Queue this back down to the SIM as an immediate notify.
*/
+ done_ccb->ccb_h.status = CAM_REQ_INPROG;
done_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
xpt_action(done_ccb);
break;
@@ -2040,6 +2041,28 @@ ctlfe_done(union ctl_io *io)
*/
ccb->ccb_h.status = CAM_REQ_INPROG;
ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
+ switch (io->taskio.task_status) {
+ case CTL_TASK_FUNCTION_COMPLETE:
+ ccb->cna2.arg = CAM_RSP_TMF_COMPLETE;
+ break;
+ case CTL_TASK_FUNCTION_SUCCEEDED:
+ ccb->cna2.arg = CAM_RSP_TMF_SUCCEEDED;
+ ccb->ccb_h.flags |= CAM_SEND_STATUS;
+ break;
+ case CTL_TASK_FUNCTION_REJECTED:
+ ccb->cna2.arg = CAM_RSP_TMF_REJECTED;
+ ccb->ccb_h.flags |= CAM_SEND_STATUS;
+ break;
+ case CTL_TASK_LUN_DOES_NOT_EXIST:
+ ccb->cna2.arg = CAM_RSP_TMF_INCORRECT_LUN;
+ ccb->ccb_h.flags |= CAM_SEND_STATUS;
+ break;
+ case CTL_TASK_FUNCTION_NOT_SUPPORTED:
+ ccb->cna2.arg = CAM_RSP_TMF_FAILED;
+ ccb->ccb_h.flags |= CAM_SEND_STATUS;
+ break;
+ }
+ ccb->cna2.arg |= scsi_3btoul(io->taskio.task_resp) << 8;
xpt_action(ccb);
} else if (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) {
if (softc->flags & CTLFE_LUN_WILDCARD) {
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 4400cde..2289f54 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -856,7 +856,7 @@ static void isp_handle_platform_atio7(ispsoftc_t *, at7_entry_t *);
static void isp_handle_platform_ctio(ispsoftc_t *, void *);
static void isp_handle_platform_notify_fc(ispsoftc_t *, in_fcentry_t *);
static void isp_handle_platform_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *);
-static int isp_handle_platform_target_notify_ack(ispsoftc_t *, isp_notify_t *);
+static int isp_handle_platform_target_notify_ack(ispsoftc_t *, isp_notify_t *, uint32_t rsp);
static void isp_handle_platform_target_tmf(ispsoftc_t *, isp_notify_t *);
static void isp_target_mark_aborted(ispsoftc_t *, union ccb *);
static void isp_target_mark_aborted_early(ispsoftc_t *, tstate_t *, uint32_t);
@@ -2761,7 +2761,7 @@ isp_handle_platform_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *inot)
}
static int
-isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp)
+isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp, uint32_t rsp)
{
if (isp->isp_state != ISP_RUNSTATE) {
@@ -2796,6 +2796,15 @@ isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp)
cto->ct_oxid = aep->at_hdr.ox_id;
cto->ct_flags = CT7_SENDSTATUS|CT7_NOACK|CT7_NO_DATA|CT7_FLAG_MODE1;
cto->ct_flags |= (aep->at_ta_len >> 12) << CT7_TASK_ATTR_SHIFT;
+ if (rsp != 0) {
+ cto->ct_scsi_status |= (FCP_RSPLEN_VALID << 8);
+ cto->rsp.m1.ct_resplen = 4;
+ ISP_MEMZERO(cto->rsp.m1.ct_resp, sizeof (cto->rsp.m1.ct_resp));
+ cto->rsp.m1.ct_resp[0] = rsp & 0xff;
+ cto->rsp.m1.ct_resp[1] = (rsp >> 8) & 0xff;
+ cto->rsp.m1.ct_resp[2] = (rsp >> 16) & 0xff;
+ cto->rsp.m1.ct_resp[3] = (rsp >> 24) & 0xff;
+ }
return (isp_target_put_entry(isp, &local));
}
@@ -3642,7 +3651,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
xpt_done(ccb);
break;
}
- if (isp_handle_platform_target_notify_ack(isp, &ntp->rd.nt)) {
+ if (isp_handle_platform_target_notify_ack(isp, &ntp->rd.nt,
+ (ccb->ccb_h.flags & CAM_SEND_STATUS) ? ccb->cna2.arg : 0)) {
rls_lun_statep(isp, tptr);
cam_freeze_devq(ccb->ccb_h.path);
cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
@@ -4407,11 +4417,11 @@ changed:
/*
* This is device arrival/departure notification
*/
- isp_handle_platform_target_notify_ack(isp, notify);
+ isp_handle_platform_target_notify_ack(isp, notify, 0);
break;
default:
isp_prt(isp, ISP_LOGALL, "target notify code 0x%x", notify->nt_ncode);
- isp_handle_platform_target_notify_ack(isp, notify);
+ isp_handle_platform_target_notify_ack(isp, notify, 0);
break;
}
break;
OpenPOWER on IntegriCloud