Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Oct 2015 17:24:19 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r289881 - head/sys/cam/ctl
Message-ID:  <201510241724.t9OHOJo4001518@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sat Oct 24 17:24:19 2015
New Revision: 289881
URL: https://svnweb.freebsd.org/changeset/base/289881

Log:
  Give CTL support for PIM_EXTLUNS when talking to CAM.
  
  CTL itself still lives in flat LUN space, but it can generate extended
  numbers if CAM SIM reports such capability.

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl.h
  head/sys/cam/ctl/ctl_frontend_cam_sim.c
  head/sys/cam/ctl/ctl_frontend_iscsi.c
  head/sys/cam/ctl/scsi_ctl.c

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Sat Oct 24 15:23:44 2015	(r289880)
+++ head/sys/cam/ctl/ctl.c	Sat Oct 24 17:24:19 2015	(r289881)
@@ -3533,6 +3533,67 @@ ctl_lun_map_to_port(struct ctl_port *por
 	return (UINT32_MAX);
 }
 
+uint32_t
+ctl_decode_lun(uint64_t encoded)
+{
+	uint8_t lun[8];
+	uint32_t result = 0xffffffff;
+
+	be64enc(lun, encoded);
+	switch (lun[0] & RPL_LUNDATA_ATYP_MASK) {
+	case RPL_LUNDATA_ATYP_PERIPH:
+		if ((lun[0] & 0x3f) == 0 && lun[2] == 0 && lun[3] == 0 &&
+		    lun[4] == 0 && lun[5] == 0 && lun[6] == 0 && lun[7] == 0)
+			result = lun[1];
+		break;
+	case RPL_LUNDATA_ATYP_FLAT:
+		if (lun[2] == 0 && lun[3] == 0 && lun[4] == 0 && lun[5] == 0 &&
+		    lun[6] == 0 && lun[7] == 0)
+			result = ((lun[0] & 0x3f) << 8) + lun[1];
+		break;
+	case RPL_LUNDATA_ATYP_EXTLUN:
+		switch (lun[0] & RPL_LUNDATA_EXT_EAM_MASK) {
+		case 0x02:
+			switch (lun[0] & RPL_LUNDATA_EXT_LEN_MASK) {
+			case 0x00:
+				result = lun[1];
+				break;
+			case 0x10:
+				result = (lun[1] << 16) + (lun[2] << 8) +
+				    lun[3];
+				break;
+			case 0x20:
+				if (lun[1] == 0 && lun[6] == 0 && lun[7] == 0)
+					result = (lun[2] << 24) +
+					    (lun[3] << 16) + (lun[4] << 8) +
+					    lun[5];
+				break;
+			}
+			break;
+		case RPL_LUNDATA_EXT_EAM_NOT_SPEC:
+			result = 0xffffffff;
+			break;
+		}
+		break;
+	}
+	return (result);
+}
+
+uint64_t
+ctl_encode_lun(uint32_t decoded)
+{
+	uint64_t l = decoded;
+
+	if (l <= 0xff)
+		return (((uint64_t)RPL_LUNDATA_ATYP_PERIPH << 56) | (l << 48));
+	if (l <= 0x3fff)
+		return (((uint64_t)RPL_LUNDATA_ATYP_FLAT << 56) | (l << 48));
+	if (l <= 0xffffff)
+		return (((uint64_t)(RPL_LUNDATA_ATYP_EXTLUN | 0x12) << 56) |
+		    (l << 32));
+	return ((((uint64_t)RPL_LUNDATA_ATYP_EXTLUN | 0x22) << 56) | (l << 16));
+}
+
 static struct ctl_port *
 ctl_io_port(struct ctl_io_hdr *io_hdr)
 {
@@ -9056,36 +9117,9 @@ ctl_report_luns(struct ctl_scsiio *ctsio
 		if (lun == NULL)
 			continue;
 
-		if (targ_lun_id <= 0xff) {
-			/*
-			 * Peripheral addressing method, bus number 0.
-			 */
-			lun_data->luns[num_filled].lundata[0] =
-				RPL_LUNDATA_ATYP_PERIPH;
-			lun_data->luns[num_filled].lundata[1] = targ_lun_id;
-			num_filled++;
-		} else if (targ_lun_id <= 0x3fff) {
-			/*
-			 * Flat addressing method.
-			 */
-			lun_data->luns[num_filled].lundata[0] =
-				RPL_LUNDATA_ATYP_FLAT | (targ_lun_id >> 8);
-			lun_data->luns[num_filled].lundata[1] =
-				(targ_lun_id & 0xff);
-			num_filled++;
-		} else if (targ_lun_id <= 0xffffff) {
-			/*
-			 * Extended flat addressing method.
-			 */
-			lun_data->luns[num_filled].lundata[0] =
-			    RPL_LUNDATA_ATYP_EXTLUN | 0x12;
-			scsi_ulto3b(targ_lun_id,
-			    &lun_data->luns[num_filled].lundata[1]);
-			num_filled++;
-		} else {
-			printf("ctl_report_luns: bogus LUN number %jd, "
-			       "skipping\n", (intmax_t)targ_lun_id);
-		}
+		be64enc(lun_data->luns[num_filled++].lundata,
+		    ctl_encode_lun(targ_lun_id));
+
 		/*
 		 * According to SPC-3, rev 14 section 6.21:
 		 *

Modified: head/sys/cam/ctl/ctl.h
==============================================================================
--- head/sys/cam/ctl/ctl.h	Sat Oct 24 15:23:44 2015	(r289880)
+++ head/sys/cam/ctl/ctl.h	Sat Oct 24 17:24:19 2015	(r289881)
@@ -191,6 +191,9 @@ void ctl_clr_ua_all(struct ctl_lun *lun,
 void ctl_clr_ua_allluns(struct ctl_softc *ctl_softc, uint32_t initidx,
     ctl_ua_type ua_type);
 
+uint32_t ctl_decode_lun(uint64_t encoded);
+uint64_t ctl_encode_lun(uint32_t decoded);
+
 void ctl_isc_announce_lun(struct ctl_lun *lun);
 void ctl_isc_announce_port(struct ctl_port *port);
 void ctl_isc_announce_iid(struct ctl_port *port, int iid);

Modified: head/sys/cam/ctl/ctl_frontend_cam_sim.c
==============================================================================
--- head/sys/cam/ctl/ctl_frontend_cam_sim.c	Sat Oct 24 15:23:44 2015	(r289880)
+++ head/sys/cam/ctl/ctl_frontend_cam_sim.c	Sat Oct 24 17:24:19 2015	(r289881)
@@ -549,7 +549,8 @@ cfcs_action(struct cam_sim *sim, union c
 		io->io_hdr.io_type = CTL_IO_SCSI;
 		io->io_hdr.nexus.initid = 1;
 		io->io_hdr.nexus.targ_port = softc->port.targ_port;
-		io->io_hdr.nexus.targ_lun = ccb->ccb_h.target_lun;
+		io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+		    CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
 		/*
 		 * This tag scheme isn't the best, since we could in theory
 		 * have a very long-lived I/O and tag collision, especially
@@ -638,7 +639,8 @@ cfcs_action(struct cam_sim *sim, union c
 		io->io_hdr.io_type = CTL_IO_TASK;
 		io->io_hdr.nexus.initid = 1;
 		io->io_hdr.nexus.targ_port = softc->port.targ_port;
-		io->io_hdr.nexus.targ_lun = ccb->ccb_h.target_lun;
+		io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+		    CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
 		io->taskio.task_action = CTL_TASK_ABORT_TASK;
 		io->taskio.tag_num = abort_ccb->csio.tag_id;
 		switch (abort_ccb->csio.tag_action) {
@@ -733,7 +735,8 @@ cfcs_action(struct cam_sim *sim, union c
 		io->io_hdr.io_type = CTL_IO_TASK;
 		io->io_hdr.nexus.initid = 1;
 		io->io_hdr.nexus.targ_port = softc->port.targ_port;
-		io->io_hdr.nexus.targ_lun = ccb->ccb_h.target_lun;
+		io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+		    CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
 		if (ccb->ccb_h.func_code == XPT_RESET_BUS)
 			io->taskio.task_action = CTL_TASK_BUS_RESET;
 		else
@@ -760,7 +763,7 @@ cfcs_action(struct cam_sim *sim, union c
 		cpi->version_num = 0;
 		cpi->hba_inquiry = PI_TAG_ABLE;
 		cpi->target_sprt = 0;
-		cpi->hba_misc = 0;
+		cpi->hba_misc = PIM_EXTLUNS;
 		cpi->hba_eng_cnt = 0;
 		cpi->max_target = 1;
 		cpi->max_lun = 1024;

Modified: head/sys/cam/ctl/ctl_frontend_iscsi.c
==============================================================================
--- head/sys/cam/ctl/ctl_frontend_iscsi.c	Sat Oct 24 15:23:44 2015	(r289880)
+++ head/sys/cam/ctl/ctl_frontend_iscsi.c	Sat Oct 24 17:24:19 2015	(r289881)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/capsicum.h>
 #include <sys/condvar.h>
+#include <sys/endian.h>
 #include <sys/file.h>
 #include <sys/kernel.h>
 #include <sys/kthread.h>
@@ -416,62 +417,6 @@ cfiscsi_pdu_queue(struct icl_pdu *respon
 	CFISCSI_SESSION_UNLOCK(cs);
 }
 
-static uint32_t
-cfiscsi_decode_lun(uint64_t encoded)
-{
-	uint8_t lun[8];
-	uint32_t result;
-
-	/*
-	 * The LUN field in iSCSI PDUs may look like an ordinary 64 bit number,
-	 * but is in fact an evil, multidimensional structure defined
-	 * in SCSI Architecture Model 5 (SAM-5), section 4.6.
-	 */
-	memcpy(lun, &encoded, sizeof(lun));
-	switch (lun[0] & 0xC0) {
-	case 0x00:
-		if ((lun[0] & 0x3f) != 0 || lun[2] != 0 || lun[3] != 0 ||
-		    lun[4] != 0 || lun[5] != 0 || lun[6] != 0 || lun[7] != 0) {
-			CFISCSI_WARN("malformed LUN "
-			    "(peripheral device addressing method): 0x%jx",
-			    (uintmax_t)encoded);
-			result = 0xffffffff;
-			break;
-		}
-		result = lun[1];
-		break;
-	case 0x40:
-		if (lun[2] != 0 || lun[3] != 0 || lun[4] != 0 || lun[5] != 0 ||
-		    lun[6] != 0 || lun[7] != 0) {
-			CFISCSI_WARN("malformed LUN "
-			    "(flat address space addressing method): 0x%jx",
-			    (uintmax_t)encoded);
-			result = 0xffffffff;
-			break;
-		}
-		result = ((lun[0] & 0x3f) << 8) + lun[1];
-		break;
-	case 0xC0:
-		if (lun[0] != 0xD2 || lun[4] != 0 || lun[5] != 0 ||
-		    lun[6] != 0 || lun[7] != 0) {
-			CFISCSI_WARN("malformed LUN (extended flat "
-			    "address space addressing method): 0x%jx",
-			    (uintmax_t)encoded);
-			result = 0xffffffff;
-			break;
-		}
-		result = (lun[1] << 16) + (lun[2] << 8) + lun[3];
-		break;
-	default:
-		CFISCSI_WARN("unsupported LUN format 0x%jx",
-		    (uintmax_t)encoded);
-		result = 0xffffffff;
-		break;
-	}
-
-	return (result);
-}
-
 static void
 cfiscsi_pdu_handle_nop_out(struct icl_pdu *request)
 {
@@ -566,7 +511,7 @@ cfiscsi_pdu_handle_scsi_command(struct i
 	io->io_hdr.io_type = CTL_IO_SCSI;
 	io->io_hdr.nexus.initid = cs->cs_ctl_initid;
 	io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port;
-	io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhssc->bhssc_lun);
+	io->io_hdr.nexus.targ_lun = ctl_decode_lun(be64toh(bhssc->bhssc_lun));
 	io->scsiio.tag_num = bhssc->bhssc_initiator_task_tag;
 	switch ((bhssc->bhssc_flags & BHSSC_FLAGS_ATTR)) {
 	case BHSSC_FLAGS_ATTR_UNTAGGED:
@@ -622,7 +567,7 @@ cfiscsi_pdu_handle_task_request(struct i
 	io->io_hdr.io_type = CTL_IO_TASK;
 	io->io_hdr.nexus.initid = cs->cs_ctl_initid;
 	io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port;
-	io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhstmr->bhstmr_lun);
+	io->io_hdr.nexus.targ_lun = ctl_decode_lun(be64toh(bhstmr->bhstmr_lun));
 	io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */
 
 	switch (bhstmr->bhstmr_function & ~0x80) {

Modified: head/sys/cam/ctl/scsi_ctl.c
==============================================================================
--- head/sys/cam/ctl/scsi_ctl.c	Sat Oct 24 15:23:44 2015	(r289880)
+++ head/sys/cam/ctl/scsi_ctl.c	Sat Oct 24 17:24:19 2015	(r289881)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2008, 2009 Silicon Graphics International Corp.
+ * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -73,13 +74,14 @@ __FBSDID("$FreeBSD$");
 #include <cam/ctl/ctl_error.h>
 
 struct ctlfe_softc {
-	struct ctl_port port;
-	path_id_t path_id;
-	target_id_t target_id;
-	u_int	maxio;
+	struct ctl_port	port;
+	path_id_t	path_id;
+	target_id_t	target_id;
+	uint32_t	hba_misc;
+	u_int		maxio;
 	struct cam_sim *sim;
-	char port_name[DEV_IDLEN];
-	struct mtx lun_softc_mtx;
+	char		port_name[DEV_IDLEN];
+	struct mtx	lun_softc_mtx;
 	STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list;
 	STAILQ_ENTRY(ctlfe_softc) links;
 };
@@ -355,6 +357,7 @@ ctlfeasync(void *callback_arg, uint32_t 
 		softc->path_id = cpi->ccb_h.path_id;
 		softc->target_id = cpi->initiator_id;
 		softc->sim = xpt_path_sim(path);
+		softc->hba_misc = cpi->hba_misc;
 		if (cpi->maxio != 0)
 			softc->maxio = cpi->maxio;
 		else
@@ -1166,7 +1169,12 @@ ctlfedone(struct cam_periph *periph, uni
 		io->io_hdr.io_type = CTL_IO_SCSI;
 		io->io_hdr.nexus.initid = atio->init_id;
 		io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
-		io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun;
+		if (bus_softc->hba_misc & PIM_EXTLUNS) {
+			io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+			    CAM_EXTLUN_BYTE_SWIZZLE(atio->ccb_h.target_lun));
+		} else {
+			io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun;
+		}
 		io->scsiio.tag_num = atio->tag_id;
 		switch (atio->tag_action) {
 		case CAM_TAG_ACTION_NONE:
@@ -1440,7 +1448,12 @@ ctlfedone(struct cam_periph *periph, uni
 		inot->ccb_h.io_ptr = io;
 		io->io_hdr.nexus.initid = inot->initiator_id;
 		io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
-		io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun;
+		if (bus_softc->hba_misc & PIM_EXTLUNS) {
+			io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+			    CAM_EXTLUN_BYTE_SWIZZLE(inot->ccb_h.target_lun));
+		} else {
+			io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun;
+		}
 		/* XXX KDM should this be the tag_id? */
 		io->taskio.tag_num = inot->seq_id;
 
@@ -1820,9 +1833,11 @@ ctlfe_lun_enable(void *arg, int lun_id)
 	cam_status status;
 
 	bus_softc = (struct ctlfe_softc *)arg;
+	if (bus_softc->hba_misc & PIM_EXTLUNS)
+		lun_id = CAM_EXTLUN_BYTE_SWIZZLE(ctl_encode_lun(lun_id));
 
 	status = xpt_create_path(&path, /*periph*/ NULL,
-				  bus_softc->path_id, bus_softc->target_id, lun_id);
+	    bus_softc->path_id, bus_softc->target_id, lun_id);
 	/* XXX KDM need some way to return status to CTL here? */
 	if (status != CAM_REQ_CMP) {
 		printf("%s: could not create path, status %#x\n", __func__,
@@ -1879,6 +1894,8 @@ ctlfe_lun_disable(void *arg, int lun_id)
 	struct ctlfe_lun_softc *lun_softc;
 
 	softc = (struct ctlfe_softc *)arg;
+	if (softc->hba_misc & PIM_EXTLUNS)
+		lun_id = CAM_EXTLUN_BYTE_SWIZZLE(ctl_encode_lun(lun_id));
 
 	mtx_lock(&softc->lun_softc_mtx);
 	STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {



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