diff --git a/qla_isp/common/isp_stds.h b/qla_isp/common/isp_stds.h index cb904862a..5c4ee3fcb 100644 --- a/qla_isp/common/isp_stds.h +++ b/qla_isp/common/isp_stds.h @@ -173,6 +173,7 @@ typedef struct { #define FCP_SNSLEN_VALID 0x02 #define FCP_RSPLEN_VALID 0x01 +#define FCP_MAX_RSPLEN 0x8 /* * FCP Response Code Definitions * Source: NCITS T10, Project 1144D, Revision 08 (aka FCP2r08) @@ -185,6 +186,8 @@ typedef struct { #define FCP_RSPNS_EROFS 3 #define FCP_RSPNS_TMF_REJECT 4 #define FCP_RSPNS_TMF_FAILED 5 +#define FCP_RSPNS_TMF_SUCCEEDED 8 +#define FCP_RSPNS_TMF_INCORRECT_LUN 9 /* unconverted miscellany */ diff --git a/qla_isp/common/isp_tpublic.h b/qla_isp/common/isp_tpublic.h index 98b0a89af..364d76f1b 100644 --- a/qla_isp/common/isp_tpublic.h +++ b/qla_isp/common/isp_tpublic.h @@ -85,7 +85,7 @@ typedef enum { QOUT_DISABLE, /* the argument is a pointer to a enadis_t */ QOUT_TMD_START, /* the argument is a pointer to a tmd_cmd_t */ QOUT_TMD_DONE, /* the argument is a pointer to a tmd_xact_t */ - QOUT_NOTIFY, /* the argument is a pointer to a isp_notify_t */ + QOUT_NOTIFY, /* the argument is a pointer to a notify_t */ QOUT_HBA_UNREG /* the argument is a pointer to a hba_register_t */ } tact_e; @@ -102,7 +102,7 @@ typedef enum { QIN_DISABLE, /* the argument is a pointer to a enadis_t */ QIN_TMD_CONT, /* the argument is a pointer to a tmd_xact_t */ QIN_TMD_FIN, /* the argument is a pointer to a tmd_cmd_t */ - QIN_NOTIFY_ACK, /* the argument is a pointer to a isp_notify_t */ + QIN_NOTIFY_ACK, /* the argument is a pointer to a notify_t */ QIN_HBA_UNREG, /* the argument is a pointer to a hba_register_t */ } qact_e; diff --git a/qla_isp/linux/isp_linux.c b/qla_isp/linux/isp_linux.c index 77c507180..60049a804 100644 --- a/qla_isp/linux/isp_linux.c +++ b/qla_isp/linux/isp_linux.c @@ -1267,9 +1267,17 @@ isp_taction(qact_e action, void *arg) 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; - WARN_ON(isp_target_put_entry(isp, &local)); /* XXX FIX ME XXX */ - break; - } + + /* set response */ + cto->ct_scsi_status = (FCP_RSPLEN_VALID << 8); + cto->rsp.m1.ct_resplen = FCP_MAX_RSPLEN; + ISP_MEMZERO(cto->rsp.m1.ct_resp, FCP_MAX_RSPLEN); + cto->rsp.m1.ct_resp[3] = ins->tmf_resp; + isp_prt(isp, ISP_LOGINFO, "[%llx] TMF response. status %d", + (ull)ins->notify.nt_tagval, ins->tmf_resp); + WARN_ON(isp_target_put_entry(isp, &local)); /* XXX FIX ME XXX */ + break; + } /* * This case is for a responding to an ABTS frame diff --git a/qla_isp/linux/isp_linux.h b/qla_isp/linux/isp_linux.h index 79300285f..d77ace0cf 100644 --- a/qla_isp/linux/isp_linux.h +++ b/qla_isp/linux/isp_linux.h @@ -957,6 +957,7 @@ struct notify { isp_notify_t notify; uint8_t qentry[QENTRY_LEN]; /* original immediate notify entry */ uint8_t qevalid; + uint8_t tmf_resp; }; #endif /* diff --git a/qla_isp/linux/isp_scst.c b/qla_isp/linux/isp_scst.c index f5da89425..f3260eaf3 100644 --- a/qla_isp/linux/isp_scst.c +++ b/qla_isp/linux/isp_scst.c @@ -722,7 +722,7 @@ abort_all_tasks(bus_chan_t *bc, uint64_t iid) } static void -scsi_target_notify(isp_notify_t *np) +scsi_target_notify(notify_t *ins) { bus_t *bp; bus_chan_t *bc; @@ -732,6 +732,7 @@ scsi_target_notify(isp_notify_t *np) uint16_t lun; uint8_t lunbuf[8]; unsigned long flags; + isp_notify_t *np = &ins->notify; spin_lock_irqsave(&scsi_target_lock, flags); bp = bus_from_notify(np); @@ -841,9 +842,10 @@ scsi_target_notify(isp_notify_t *np) lun = np->nt_lun; } FLATLUN_TO_L0LUN(lunbuf, lun); - if (scst_rx_mgmt_fn_lun(ini->ini_scst_sess, fn, lunbuf, sizeof(lunbuf), 1, np) < 0) { - np->nt_failed = 1; - goto notify_ack; + if (scst_rx_mgmt_fn_lun(ini->ini_scst_sess, fn, lunbuf, + sizeof(lunbuf), 1, ins) < 0) { + np->nt_failed = 1; + goto notify_ack; } } return; @@ -853,7 +855,7 @@ err_no_ini: np->nt_failed = 1; notify_ack: ini_put(bc, ini); - (*bp->h.r_action) (QIN_NOTIFY_ACK, np); + (*bp->h.r_action) (QIN_NOTIFY_ACK, ins); } static void @@ -922,9 +924,9 @@ scsi_target_handler(qact_e action, void *arg) } case QOUT_NOTIFY: { - isp_notify_t *np = arg; - scsi_target_notify(np); - break; + notify_t *ins = arg; + scsi_target_notify(ins); + break; } case QOUT_HBA_UNREG: { @@ -1275,15 +1277,41 @@ isp_on_free_cmd(struct scst_cmd *scst_cmd) (*bp->h.r_action)(QIN_TMD_FIN, tmd); } +static int +isp_task_mgmt_fn_get_resp(int scst_mgmt_status) +{ + switch (scst_mgmt_status) { + case SCST_MGMT_STATUS_SUCCESS: + return FCP_RSPNS_TMF_SUCCEEDED; + + case SCST_MGMT_STATUS_TASK_NOT_EXIST: + return FCP_RSPNS_BADCMND; + + case SCST_MGMT_STATUS_LUN_NOT_EXIST: + return FCP_RSPNS_TMF_INCORRECT_LUN; + + case SCST_MGMT_STATUS_FN_NOT_SUPPORTED: + case SCST_MGMT_STATUS_REJECTED: + return FCP_RSPNS_TMF_REJECT; + + case SCST_MGMT_STATUS_FAILED: + default: + return FCP_RSPNS_TMF_FAILED; + } +} + static void isp_task_mgmt_fn_done(struct scst_mgmt_cmd *mgmt_cmd) { - isp_notify_t *np = mgmt_cmd->tgt_priv; + notify_t *ins = scst_mgmt_cmd_get_tgt_priv(mgmt_cmd); + isp_notify_t *np = &ins->notify; bus_t *bp = bus_from_notify(np); + ins->tmf_resp = + isp_task_mgmt_fn_get_resp(scst_mgmt_cmd_get_status(mgmt_cmd)); ini_put(&bp->bchan[np->nt_channel], np->nt_ini); BUS_DBG(bp, "NOTIFY_ACK[%llx]\n", np->nt_tagval); - (*bp->h.r_action) (QIN_NOTIFY_ACK, np); + (*bp->h.r_action) (QIN_NOTIFY_ACK, ins); } static DEFINE_MUTEX(proc_mutex); @@ -1294,7 +1322,7 @@ static DEFINE_MUTEX(proc_mutex); #if !defined(CONFIG_PPC) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)) -static int strncasecmp(const char *s1, const char *s2, size_t n) +int strncasecmp(const char *s1, const char *s2, size_t n) { int c1, c2; do {