Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Oct 2015 09:16:56 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r288754 - stable/10/sys/cam/ctl
Message-ID:  <201510050916.t959GuFv028123@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201510050916.t959GuFv028123>