Author: mav
Date: Mon Oct  5 09:16:55 2015
New Revision: 288754
URL: https://svnweb.freebsd.org/changeset/base/288754

Log:
  MFC r287774: Implement QUERY TASK, QUERY TASK SET and QUERY ASYNC EVENT.
  
  Now we support most of SAM-5 task management.

Modified:
  stable/10/sys/cam/ctl/ctl.c
  stable/10/sys/cam/ctl/ctl_error.c
  stable/10/sys/cam/ctl/ctl_error.h
  stable/10/sys/cam/ctl/ctl_frontend_iscsi.c
  stable/10/sys/cam/ctl/ctl_io.h
  stable/10/sys/cam/ctl/ctl_util.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cam/ctl/ctl.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl.c Mon Oct  5 09:16:01 2015        (r288753)
+++ stable/10/sys/cam/ctl/ctl.c Mon Oct  5 09:16:55 2015        (r288754)
@@ -414,11 +414,14 @@ static int ctl_scsiio(struct ctl_scsiio 
 static int ctl_bus_reset(struct ctl_softc *ctl_softc, union ctl_io *io);
 static int ctl_target_reset(struct ctl_softc *ctl_softc, union ctl_io *io,
                            ctl_ua_type ua_type);
-static int ctl_lun_reset(struct ctl_lun *lun, union ctl_io *io,
+static int ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io,
                         ctl_ua_type ua_type);
+static int ctl_lun_reset(struct ctl_softc *ctl_softc, union ctl_io *io);
 static int ctl_abort_task(union ctl_io *io);
 static int ctl_abort_task_set(union ctl_io *io);
+static int ctl_query_task(union ctl_io *io, int task_set);
 static int ctl_i_t_nexus_reset(union ctl_io *io);
+static int ctl_query_async_event(union ctl_io *io);
 static void ctl_run_task(union ctl_io *io);
 #ifdef CTL_IO_DELAY
 static void ctl_datamove_timer_wakeup(void *arg);
@@ -7364,8 +7367,9 @@ ctl_report_supported_tmf(struct ctl_scsi
        ctsio->kern_rel_offset = 0;
 
        data = (struct scsi_report_supported_tmf_data *)ctsio->kern_data_ptr;
-       data->byte1 |= RST_ATS | RST_ATSS | RST_CTSS | RST_LURS | RST_TRS;
-       data->byte2 |= RST_ITNRS;
+       data->byte1 |= RST_ATS | RST_ATSS | RST_CTSS | RST_LURS | RST_QTS |
+           RST_TRS;
+       data->byte2 |= RST_QAES | RST_QTSS | RST_ITNRS;
 
        ctl_set_success(ctsio);
        ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
@@ -11375,10 +11379,10 @@ ctl_target_reset(struct ctl_softc *softc
                if (port != NULL &&
                    ctl_lun_map_to_port(port, lun->lun) >= CTL_MAX_LUNS)
                        continue;
-               retval += ctl_lun_reset(lun, io, ua_type);
+               retval += ctl_do_lun_reset(lun, io, ua_type);
        }
        mtx_unlock(&softc->ctl_lock);
-
+       io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
        return (retval);
 }
 
@@ -11404,7 +11408,7 @@ ctl_target_reset(struct ctl_softc *softc
  * XXX KDM for now, we're setting unit attention for all initiators.
  */
 static int
-ctl_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type)
+ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type)
 {
        union ctl_io *xio;
 #if 0
@@ -11452,6 +11456,39 @@ ctl_lun_reset(struct ctl_lun *lun, union
        return (0);
 }
 
+static int
+ctl_lun_reset(struct ctl_softc *softc, union ctl_io *io)
+{
+       struct ctl_lun *lun;
+       uint32_t targ_lun;
+       int retval;
+
+       targ_lun = io->io_hdr.nexus.targ_mapped_lun;
+       mtx_lock(&softc->ctl_lock);
+       if ((targ_lun >= CTL_MAX_LUNS) ||
+           (lun = softc->ctl_luns[targ_lun]) == NULL) {
+               mtx_unlock(&softc->ctl_lock);
+               io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST;
+               return (1);
+       }
+       retval = ctl_do_lun_reset(lun, io, CTL_UA_LUN_RESET);
+       mtx_unlock(&softc->ctl_lock);
+       io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
+
+       if ((io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC) == 0) {
+               union ctl_ha_msg msg_info;
+
+               msg_info.hdr.msg_type = CTL_MSG_MANAGE_TASKS;
+               msg_info.hdr.nexus = io->io_hdr.nexus;
+               msg_info.task.task_action = CTL_TASK_LUN_RESET;
+               msg_info.hdr.original_sc = NULL;
+               msg_info.hdr.serializing_sc = NULL;
+               ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info,
+                   sizeof(msg_info.task), M_WAITOK);
+       }
+       return (retval);
+}
+
 static void
 ctl_abort_tasks_lun(struct ctl_lun *lun, uint32_t targ_port, uint32_t init_id,
     int other_sc)
@@ -11507,10 +11544,10 @@ ctl_abort_task_set(union ctl_io *io)
         */
        targ_lun = io->io_hdr.nexus.targ_mapped_lun;
        mtx_lock(&softc->ctl_lock);
-       if ((targ_lun < CTL_MAX_LUNS) && (softc->ctl_luns[targ_lun] != NULL))
-               lun = softc->ctl_luns[targ_lun];
-       else {
+       if ((targ_lun >= CTL_MAX_LUNS) ||
+           (lun = softc->ctl_luns[targ_lun]) == NULL) {
                mtx_unlock(&softc->ctl_lock);
+               io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST;
                return (1);
        }
 
@@ -11525,6 +11562,7 @@ ctl_abort_task_set(union ctl_io *io)
                    (io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC) != 0);
        }
        mtx_unlock(&lun->lun_lock);
+       io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
        return (0);
 }
 
@@ -11562,6 +11600,7 @@ ctl_i_t_nexus_reset(union ctl_io *io)
                mtx_unlock(&lun->lun_lock);
        }
        mtx_unlock(&softc->ctl_lock);
+       io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
        return (0);
 }
 
@@ -11586,11 +11625,10 @@ ctl_abort_task(union ctl_io *io)
         */
        targ_lun = io->io_hdr.nexus.targ_mapped_lun;
        mtx_lock(&softc->ctl_lock);
-       if ((targ_lun < CTL_MAX_LUNS)
-        && (softc->ctl_luns[targ_lun] != NULL))
-               lun = softc->ctl_luns[targ_lun];
-       else {
+       if ((targ_lun >= CTL_MAX_LUNS) ||
+           (lun = softc->ctl_luns[targ_lun]) == NULL) {
                mtx_unlock(&softc->ctl_lock);
+               io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST;
                return (1);
        }
 
@@ -11696,6 +11734,77 @@ ctl_abort_task(union ctl_io *io)
                       io->taskio.tag_type);
 #endif
        }
+       io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
+       return (0);
+}
+
+static int
+ctl_query_task(union ctl_io *io, int task_set)
+{
+       union ctl_io *xio;
+       struct ctl_lun *lun;
+       struct ctl_softc *softc;
+       int found = 0;
+       uint32_t targ_lun;
+
+       softc = control_softc;
+       targ_lun = io->io_hdr.nexus.targ_mapped_lun;
+       mtx_lock(&softc->ctl_lock);
+       if ((targ_lun >= CTL_MAX_LUNS) ||
+           (lun = softc->ctl_luns[targ_lun]) == NULL) {
+               mtx_unlock(&softc->ctl_lock);
+               io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST;
+               return (1);
+       }
+       mtx_lock(&lun->lun_lock);
+       mtx_unlock(&softc->ctl_lock);
+       for (xio = (union ctl_io *)TAILQ_FIRST(&lun->ooa_queue); xio != NULL;
+            xio = (union ctl_io *)TAILQ_NEXT(&xio->io_hdr, ooa_links)) {
+
+               if ((xio->io_hdr.nexus.targ_port != io->io_hdr.nexus.targ_port)
+                || (xio->io_hdr.nexus.initid != io->io_hdr.nexus.initid)
+                || (xio->io_hdr.flags & CTL_FLAG_ABORT))
+                       continue;
+
+               if (task_set || xio->scsiio.tag_num == io->taskio.tag_num) {
+                       found = 1;
+                       break;
+               }
+       }
+       mtx_unlock(&lun->lun_lock);
+       if (found)
+               io->taskio.task_status = CTL_TASK_FUNCTION_SUCCEEDED;
+       else
+               io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
+       return (0);
+}
+
+static int
+ctl_query_async_event(union ctl_io *io)
+{
+       struct ctl_lun *lun;
+       struct ctl_softc *softc;
+       ctl_ua_type ua;
+       uint32_t targ_lun, initidx;
+
+       softc = control_softc;
+       targ_lun = io->io_hdr.nexus.targ_mapped_lun;
+       mtx_lock(&softc->ctl_lock);
+       if ((targ_lun >= CTL_MAX_LUNS) ||
+           (lun = softc->ctl_luns[targ_lun]) == NULL) {
+               mtx_unlock(&softc->ctl_lock);
+               io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST;
+               return (1);
+       }
+       mtx_lock(&lun->lun_lock);
+       mtx_unlock(&softc->ctl_lock);
+       initidx = ctl_get_initindex(&io->io_hdr.nexus);
+       ua = ctl_build_qae(lun, initidx, io->taskio.task_resp);
+       mtx_unlock(&lun->lun_lock);
+       if (ua != CTL_UA_NONE)
+               io->taskio.task_status = CTL_TASK_FUNCTION_SUCCEEDED;
+       else
+               io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
        return (0);
 }
 
@@ -11704,41 +11813,12 @@ ctl_run_task(union ctl_io *io)
 {
        struct ctl_softc *softc = control_softc;
        int retval = 1;
-       const char *task_desc;
 
        CTL_DEBUG_PRINT(("ctl_run_task\n"));
-
        KASSERT(io->io_hdr.io_type == CTL_IO_TASK,
-           ("ctl_run_task: Unextected io_type %d\n",
-            io->io_hdr.io_type));
-
-       task_desc = ctl_scsi_task_string(&io->taskio);
-       if (task_desc != NULL) {
-#ifdef NEEDTOPORT
-               csevent_log(CSC_CTL | CSC_SHELF_SW |
-                           CTL_TASK_REPORT,
-                           csevent_LogType_Trace,
-                           csevent_Severity_Information,
-                           csevent_AlertLevel_Green,
-                           csevent_FRU_Firmware,
-                           csevent_FRU_Unknown,
-                           "CTL: received task: %s",task_desc);
-#endif
-       } else {
-#ifdef NEEDTOPORT
-               csevent_log(CSC_CTL | CSC_SHELF_SW |
-                           CTL_TASK_REPORT,
-                           csevent_LogType_Trace,
-                           csevent_Severity_Information,
-                           csevent_AlertLevel_Green,
-                           csevent_FRU_Firmware,
-                           csevent_FRU_Unknown,
-                           "CTL: received unknown task "
-                           "type: %d (%#x)",
-                           io->taskio.task_action,
-                           io->taskio.task_action);
-#endif
-       }
+           ("ctl_run_task: Unextected io_type %d\n", io->io_hdr.io_type));
+       io->taskio.task_status = CTL_TASK_FUNCTION_NOT_SUPPORTED;
+       bzero(io->taskio.task_resp, sizeof(io->taskio.task_resp));
        switch (io->taskio.task_action) {
        case CTL_TASK_ABORT_TASK:
                retval = ctl_abort_task(io);
@@ -11752,36 +11832,9 @@ ctl_run_task(union ctl_io *io)
        case CTL_TASK_I_T_NEXUS_RESET:
                retval = ctl_i_t_nexus_reset(io);
                break;
-       case CTL_TASK_LUN_RESET: {
-               struct ctl_lun *lun;
-               uint32_t targ_lun;
-
-               targ_lun = io->io_hdr.nexus.targ_mapped_lun;
-               mtx_lock(&softc->ctl_lock);
-               if ((targ_lun < CTL_MAX_LUNS)
-                && (softc->ctl_luns[targ_lun] != NULL))
-                       lun = softc->ctl_luns[targ_lun];
-               else {
-                       mtx_unlock(&softc->ctl_lock);
-                       retval = 1;
-                       break;
-               }
-               retval = ctl_lun_reset(lun, io, CTL_UA_LUN_RESET);
-               mtx_unlock(&softc->ctl_lock);
-
-               if ((io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC) == 0) {
-                       union ctl_ha_msg msg_info;
-
-                       msg_info.hdr.msg_type = CTL_MSG_MANAGE_TASKS;
-                       msg_info.hdr.nexus = io->io_hdr.nexus;
-                       msg_info.task.task_action = CTL_TASK_LUN_RESET;
-                       msg_info.hdr.original_sc = NULL;
-                       msg_info.hdr.serializing_sc = NULL;
-                       ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info,
-                           sizeof(msg_info.task), M_WAITOK);
-               }
+       case CTL_TASK_LUN_RESET:
+               retval = ctl_lun_reset(softc, io);
                break;
-       }
        case CTL_TASK_TARGET_RESET:
                retval = ctl_target_reset(softc, io, CTL_UA_TARG_RESET);
                break;
@@ -11792,9 +11845,18 @@ ctl_run_task(union ctl_io *io)
                break;
        case CTL_TASK_PORT_LOGOUT:
                break;
+       case CTL_TASK_QUERY_TASK:
+               retval = ctl_query_task(io, 0);
+               break;
+       case CTL_TASK_QUERY_TASK_SET:
+               retval = ctl_query_task(io, 1);
+               break;
+       case CTL_TASK_QUERY_ASYNC_EVENT:
+               retval = ctl_query_async_event(io);
+               break;
        default:
-               printf("ctl_run_task: got unknown task management event %d\n",
-                      io->taskio.task_action);
+               printf("%s: got unknown task management event %d\n",
+                      __func__, io->taskio.task_action);
                break;
        }
        if (retval == 0)

Modified: stable/10/sys/cam/ctl/ctl_error.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_error.c   Mon Oct  5 09:16:01 2015        
(r288753)
+++ stable/10/sys/cam/ctl/ctl_error.c   Mon Oct  5 09:16:55 2015        
(r288754)
@@ -365,62 +365,35 @@ ctl_set_ua(struct ctl_scsiio *ctsio, int
                      SSD_ELEM_NONE);
 }
 
-ctl_ua_type
-ctl_build_ua(struct ctl_lun *lun, uint32_t initidx,
-    struct scsi_sense_data *sense, scsi_sense_data_type sense_format)
+static void
+ctl_ua_to_acsq(ctl_ua_type ua_to_build, int *asc, int *ascq,
+    ctl_ua_type *ua_to_clear)
 {
-       ctl_ua_type *ua;
-       ctl_ua_type ua_to_build, ua_to_clear;
-       int asc, ascq;
-       uint32_t p, i;
-
-       mtx_assert(&lun->lun_lock, MA_OWNED);
-       p = initidx / CTL_MAX_INIT_PER_PORT;
-       if ((ua = lun->pending_ua[p]) == NULL) {
-               mtx_unlock(&lun->lun_lock);
-               ua = malloc(sizeof(ctl_ua_type) * CTL_MAX_INIT_PER_PORT,
-                   M_CTL, M_WAITOK);
-               mtx_lock(&lun->lun_lock);
-               if (lun->pending_ua[p] == NULL) {
-                       lun->pending_ua[p] = ua;
-                       for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++)
-                               ua[i] = CTL_UA_POWERON;
-               } else {
-                       free(ua, M_CTL);
-                       ua = lun->pending_ua[p];
-               }
-       }
-       i = initidx % CTL_MAX_INIT_PER_PORT;
-       if (ua[i] == CTL_UA_NONE)
-               return (CTL_UA_NONE);
-
-       ua_to_build = (1 << (ffs(ua[i]) - 1));
-       ua_to_clear = ua_to_build;
 
        switch (ua_to_build) {
        case CTL_UA_POWERON:
                /* 29h/01h  POWER ON OCCURRED */
-               asc = 0x29;
-               ascq = 0x01;
-               ua_to_clear = ~0;
+               *asc = 0x29;
+               *ascq = 0x01;
+               *ua_to_clear = ~0;
                break;
        case CTL_UA_BUS_RESET:
                /* 29h/02h  SCSI BUS RESET OCCURRED */
-               asc = 0x29;
-               ascq = 0x02;
-               ua_to_clear = ~0;
+               *asc = 0x29;
+               *ascq = 0x02;
+               *ua_to_clear = ~0;
                break;
        case CTL_UA_TARG_RESET:
                /* 29h/03h  BUS DEVICE RESET FUNCTION OCCURRED*/
-               asc = 0x29;
-               ascq = 0x03;
-               ua_to_clear = ~0;
+               *asc = 0x29;
+               *ascq = 0x03;
+               *ua_to_clear = ~0;
                break;
        case CTL_UA_I_T_NEXUS_LOSS:
                /* 29h/07h  I_T NEXUS LOSS OCCURRED */
-               asc = 0x29;
-               ascq = 0x07;
-               ua_to_clear = ~0;
+               *asc = 0x29;
+               *ascq = 0x07;
+               *ua_to_clear = ~0;
                break;
        case CTL_UA_LUN_RESET:
                /* 29h/00h  POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
@@ -428,62 +401,128 @@ ctl_build_ua(struct ctl_lun *lun, uint32
                 * Since we don't have a specific ASC/ASCQ pair for a LUN
                 * reset, just return the generic reset code.
                 */
-               asc = 0x29;
-               ascq = 0x00;
+               *asc = 0x29;
+               *ascq = 0x00;
                break;
        case CTL_UA_LUN_CHANGE:
                /* 3Fh/0Eh  REPORTED LUNS DATA HAS CHANGED */
-               asc = 0x3F;
-               ascq = 0x0E;
+               *asc = 0x3F;
+               *ascq = 0x0E;
                break;
        case CTL_UA_MODE_CHANGE:
                /* 2Ah/01h  MODE PARAMETERS CHANGED */
-               asc = 0x2A;
-               ascq = 0x01;
+               *asc = 0x2A;
+               *ascq = 0x01;
                break;
        case CTL_UA_LOG_CHANGE:
                /* 2Ah/02h  LOG PARAMETERS CHANGED */
-               asc = 0x2A;
-               ascq = 0x02;
+               *asc = 0x2A;
+               *ascq = 0x02;
                break;
        case CTL_UA_INQ_CHANGE:
                /* 3Fh/03h  INQUIRY DATA HAS CHANGED */
-               asc = 0x3F;
-               ascq = 0x03;
+               *asc = 0x3F;
+               *ascq = 0x03;
                break;
        case CTL_UA_RES_PREEMPT:
                /* 2Ah/03h  RESERVATIONS PREEMPTED */
-               asc = 0x2A;
-               ascq = 0x03;
+               *asc = 0x2A;
+               *ascq = 0x03;
                break;
        case CTL_UA_RES_RELEASE:
                /* 2Ah/04h  RESERVATIONS RELEASED */
-               asc = 0x2A;
-               ascq = 0x04;
+               *asc = 0x2A;
+               *ascq = 0x04;
                break;
        case CTL_UA_REG_PREEMPT:
                /* 2Ah/05h  REGISTRATIONS PREEMPTED */
-               asc = 0x2A;
-               ascq = 0x05;
+               *asc = 0x2A;
+               *ascq = 0x05;
                break;
        case CTL_UA_ASYM_ACC_CHANGE:
-               /* 2Ah/06n  ASYMMETRIC ACCESS STATE CHANGED */
-               asc = 0x2A;
-               ascq = 0x06;
+               /* 2Ah/06h  ASYMMETRIC ACCESS STATE CHANGED */
+               *asc = 0x2A;
+               *ascq = 0x06;
                break;
        case CTL_UA_CAPACITY_CHANGED:
-               /* 2Ah/09n  CAPACITY DATA HAS CHANGED */
-               asc = 0x2A;
-               ascq = 0x09;
+               /* 2Ah/09h  CAPACITY DATA HAS CHANGED */
+               *asc = 0x2A;
+               *ascq = 0x09;
                break;
        case CTL_UA_THIN_PROV_THRES:
-               /* 38h/07n  THIN PROVISIONING SOFT THRESHOLD REACHED */
-               asc = 0x38;
-               ascq = 0x07;
+               /* 38h/07h  THIN PROVISIONING SOFT THRESHOLD REACHED */
+               *asc = 0x38;
+               *ascq = 0x07;
                break;
        default:
-               panic("ctl_build_ua: Unknown UA %x", ua_to_build);
+               panic("%s: Unknown UA %x", __func__, ua_to_build);
+       }
+}
+
+ctl_ua_type
+ctl_build_qae(struct ctl_lun *lun, uint32_t initidx, uint8_t *resp)
+{
+       ctl_ua_type ua;
+       ctl_ua_type ua_to_build, ua_to_clear;
+       int asc, ascq;
+       uint32_t p, i;
+
+       mtx_assert(&lun->lun_lock, MA_OWNED);
+       p = initidx / CTL_MAX_INIT_PER_PORT;
+       i = initidx % CTL_MAX_INIT_PER_PORT;
+       if (lun->pending_ua[p] == NULL)
+               ua = CTL_UA_POWERON;
+       else
+               ua = lun->pending_ua[p][i];
+       if (ua == CTL_UA_NONE)
+               return (CTL_UA_NONE);
+
+       ua_to_build = (1 << (ffs(ua) - 1));
+       ua_to_clear = ua_to_build;
+       ctl_ua_to_acsq(ua_to_build, &asc, &ascq, &ua_to_clear);
+
+       resp[0] = SSD_KEY_UNIT_ATTENTION;
+       if (ua_to_build == ua)
+               resp[0] |= 0x10;
+       else
+               resp[0] |= 0x20;
+       resp[1] = asc;
+       resp[2] = ascq;
+       return (ua);
+}
+
+ctl_ua_type
+ctl_build_ua(struct ctl_lun *lun, uint32_t initidx,
+    struct scsi_sense_data *sense, scsi_sense_data_type sense_format)
+{
+       ctl_ua_type *ua;
+       ctl_ua_type ua_to_build, ua_to_clear;
+       int asc, ascq;
+       uint32_t p, i;
+
+       mtx_assert(&lun->lun_lock, MA_OWNED);
+       p = initidx / CTL_MAX_INIT_PER_PORT;
+       if ((ua = lun->pending_ua[p]) == NULL) {
+               mtx_unlock(&lun->lun_lock);
+               ua = malloc(sizeof(ctl_ua_type) * CTL_MAX_INIT_PER_PORT,
+                   M_CTL, M_WAITOK);
+               mtx_lock(&lun->lun_lock);
+               if (lun->pending_ua[p] == NULL) {
+                       lun->pending_ua[p] = ua;
+                       for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++)
+                               ua[i] = CTL_UA_POWERON;
+               } else {
+                       free(ua, M_CTL);
+                       ua = lun->pending_ua[p];
+               }
        }
+       i = initidx % CTL_MAX_INIT_PER_PORT;
+       if (ua[i] == CTL_UA_NONE)
+               return (CTL_UA_NONE);
+
+       ua_to_build = (1 << (ffs(ua[i]) - 1));
+       ua_to_clear = ua_to_build;
+       ctl_ua_to_acsq(ua_to_build, &asc, &ascq, &ua_to_clear);
 
        ctl_set_sense_data(sense,
                           /*lun*/ NULL,

Modified: stable/10/sys/cam/ctl/ctl_error.h
==============================================================================
--- stable/10/sys/cam/ctl/ctl_error.h   Mon Oct  5 09:16:01 2015        
(r288753)
+++ stable/10/sys/cam/ctl/ctl_error.h   Mon Oct  5 09:16:55 2015        
(r288754)
@@ -57,6 +57,7 @@ void ctl_sense_to_desc(struct scsi_sense
 void ctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src,
                        struct scsi_sense_data_fixed *sense_dest);
 void ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq);
+ctl_ua_type ctl_build_qae(struct ctl_lun *lun, uint32_t initidx, uint8_t 
*resp);
 ctl_ua_type ctl_build_ua(struct ctl_lun *lun, uint32_t initidx,
     struct scsi_sense_data *sense, scsi_sense_data_type sense_format);
 void ctl_set_overlapped_cmd(struct ctl_scsiio *ctsio);

Modified: stable/10/sys/cam/ctl/ctl_frontend_iscsi.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_frontend_iscsi.c  Mon Oct  5 09:16:01 2015        
(r288753)
+++ stable/10/sys/cam/ctl/ctl_frontend_iscsi.c  Mon Oct  5 09:16:55 2015        
(r288754)
@@ -660,12 +660,31 @@ cfiscsi_pdu_handle_task_request(struct i
 #endif
                io->taskio.task_action = CTL_TASK_TARGET_RESET;
                break;
+       case BHSTMR_FUNCTION_QUERY_TASK:
+#if 0
+               CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_QUERY_TASK");
+#endif
+               io->taskio.task_action = CTL_TASK_QUERY_TASK;
+               io->taskio.tag_num = bhstmr->bhstmr_referenced_task_tag;
+               break;
+       case BHSTMR_FUNCTION_QUERY_TASK_SET:
+#if 0
+               CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_QUERY_TASK_SET");
+#endif
+               io->taskio.task_action = CTL_TASK_QUERY_TASK_SET;
+               break;
        case BHSTMR_FUNCTION_I_T_NEXUS_RESET:
 #if 0
                CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_I_T_NEXUS_RESET");
 #endif
                io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET;
                break;
+       case BHSTMR_FUNCTION_QUERY_ASYNC_EVENT:
+#if 0
+               CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_QUERY_ASYNC_EVENT");
+#endif
+               io->taskio.task_action = CTL_TASK_QUERY_ASYNC_EVENT;
+               break;
        default:
                CFISCSI_SESSION_DEBUG(cs, "unsupported function 0x%x",
                    bhstmr->bhstmr_function & ~0x80);
@@ -2837,18 +2856,23 @@ cfiscsi_task_management_done(union ctl_i
            response->ip_bhs;
        bhstmr2->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_RESPONSE;
        bhstmr2->bhstmr_flags = 0x80;
-       if (io->io_hdr.status == CTL_SUCCESS) {
+       switch (io->taskio.task_status) {
+       case CTL_TASK_FUNCTION_COMPLETE:
                bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_COMPLETE;
-       } else {
-               /*
-                * XXX: How to figure out what exactly went wrong?  iSCSI spec
-                *      expects us to provide detailed error, e.g. "Task does
-                *      not exist" or "LUN does not exist".
-                */
-               CFISCSI_SESSION_DEBUG(cs, 
"BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED");
-               bhstmr2->bhstmr_response =
-                   BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED;
+               break;
+       case CTL_TASK_FUNCTION_SUCCEEDED:
+               bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_SUCCEEDED;
+               break;
+       case CTL_TASK_LUN_DOES_NOT_EXIST:
+               bhstmr2->bhstmr_response = BHSTMR_RESPONSE_LUN_DOES_NOT_EXIST;
+               break;
+       case CTL_TASK_FUNCTION_NOT_SUPPORTED:
+       default:
+               bhstmr2->bhstmr_response = 
BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED;
+               break;
        }
+       memcpy(bhstmr2->bhstmr_additional_reponse_information,
+           io->taskio.task_resp, sizeof(io->taskio.task_resp));
        bhstmr2->bhstmr_initiator_task_tag = bhstmr->bhstmr_initiator_task_tag;
 
        ctl_free_io(io);

Modified: stable/10/sys/cam/ctl/ctl_io.h
==============================================================================
--- stable/10/sys/cam/ctl/ctl_io.h      Mon Oct  5 09:16:01 2015        
(r288753)
+++ stable/10/sys/cam/ctl/ctl_io.h      Mon Oct  5 09:16:55 2015        
(r288754)
@@ -328,9 +328,20 @@ typedef enum {
        CTL_TASK_TARGET_RESET,
        CTL_TASK_BUS_RESET,
        CTL_TASK_PORT_LOGIN,
-       CTL_TASK_PORT_LOGOUT
+       CTL_TASK_PORT_LOGOUT,
+       CTL_TASK_QUERY_TASK,
+       CTL_TASK_QUERY_TASK_SET,
+       CTL_TASK_QUERY_ASYNC_EVENT
 } ctl_task_type;
 
+typedef enum {
+       CTL_TASK_FUNCTION_COMPLETE,
+       CTL_TASK_FUNCTION_SUCCEEDED,
+       CTL_TASK_FUNCTION_REJECTED,
+       CTL_TASK_LUN_DOES_NOT_EXIST,
+       CTL_TASK_FUNCTION_NOT_SUPPORTED
+} ctl_task_status;
+
 /*
  * Task management I/O structure.  Aborts, bus resets, etc., are sent using
  * this structure.
@@ -343,6 +354,8 @@ struct ctl_taskio {
        ctl_task_type           task_action; /* Target Reset, Abort, etc.  */
        uint32_t                tag_num;     /* tag number */
        ctl_tag_type            tag_type;    /* simple, ordered, etc. */
+       uint8_t                 task_status; /* Complete, Succeeded, etc. */
+       uint8_t                 task_resp[3];/* Response information */
 };
 
 typedef enum {

Modified: stable/10/sys/cam/ctl/ctl_util.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_util.c    Mon Oct  5 09:16:01 2015        
(r288753)
+++ stable/10/sys/cam/ctl/ctl_util.c    Mon Oct  5 09:16:55 2015        
(r288754)
@@ -89,7 +89,10 @@ static struct ctl_task_desc ctl_task_tab
        {CTL_TASK_TARGET_RESET, "Target Reset"},
        {CTL_TASK_BUS_RESET, "Bus Reset"},
        {CTL_TASK_PORT_LOGIN, "Port Login"},
-       {CTL_TASK_PORT_LOGOUT, "Port Logout"}
+       {CTL_TASK_PORT_LOGOUT, "Port Logout"},
+       {CTL_TASK_QUERY_TASK, "Query Task"},
+       {CTL_TASK_QUERY_TASK_SET, "Query Task Set"},
+       {CTL_TASK_QUERY_ASYNC_EVENT, "Query Async Event"}
 };
 
 void
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to