svn commit: r216368 - head/sys/dev/mps

Kenneth D. Merry ken at FreeBSD.org
Sat Dec 11 00:36:35 UTC 2010


Author: ken
Date: Sat Dec 11 00:36:35 2010
New Revision: 216368
URL: http://svn.freebsd.org/changeset/base/216368

Log:
  Fix setting LUN numbers in the mps(4) driver.
  
  Prior to this change, the addressing method wasn't getting set, and
  so the LUN field could be set incorrectly in some instances.
  
  This fix should allow for LUN numbers up to 16777215 (and return an error
  for anything larger, which wouldn't fit into the flat addressing model).
  
  Submitted by:	scottl (in part)

Modified:
  head/sys/dev/mps/mps_sas.c

Modified: head/sys/dev/mps/mps_sas.c
==============================================================================
--- head/sys/dev/mps/mps_sas.c	Fri Dec 10 23:57:55 2010	(r216367)
+++ head/sys/dev/mps/mps_sas.c	Sat Dec 11 00:36:35 2010	(r216368)
@@ -121,6 +121,7 @@ struct mpssas_devprobe {
 
 MALLOC_DEFINE(M_MPSSAS, "MPSSAS", "MPS SAS memory");
 
+static __inline int mpssas_set_lun(uint8_t *lun, u_int ccblun);
 static struct mpssas_target * mpssas_alloc_target(struct mpssas_softc *,
     struct mpssas_target *);
 static struct mpssas_target * mpssas_find_target(struct mpssas_softc *, int,
@@ -163,6 +164,43 @@ static void mpssas_resetdev_complete(str
 static void mpssas_freeze_device(struct mpssas_softc *, struct mpssas_target *);
 static void mpssas_unfreeze_device(struct mpssas_softc *, struct mpssas_target *) __unused;
 
+/*
+ * Abstracted so that the driver can be backwards and forwards compatible
+ * with future versions of CAM that will provide this functionality.
+ */
+#define MPS_SET_LUN(lun, ccblun)	\
+	mpssas_set_lun(lun, ccblun)
+
+static __inline int
+mpssas_set_lun(uint8_t *lun, u_int ccblun)
+{
+	uint64_t *newlun;
+
+	newlun = (uint64_t *)lun;
+	*newlun = 0;
+	if (ccblun <= 0xff) {
+		/* Peripheral device address method, LUN is 0 to 255 */
+		lun[1] = ccblun;
+	} else if (ccblun <= 0x3fff) {
+		/* Flat space address method, LUN is <= 16383 */
+		scsi_ulto2b(ccblun, lun);
+		lun[0] |= 0x40;
+	} else if (ccblun <= 0xffffff) {
+		/* Extended flat space address method, LUN is <= 16777215 */
+		scsi_ulto3b(ccblun, &lun[1]);
+		/* Extended Flat space address method */
+		lun[0] = 0xc0;
+		/* Length = 1, i.e. LUN is 3 bytes long */
+		lun[0] |= 0x10;
+		/* Extended Address Method */
+		lun[0] |= 0x02;
+	} else {
+		return (EINVAL);
+	}
+
+	return (0);
+}
+
 static struct mpssas_target *
 mpssas_alloc_target(struct mpssas_softc *sassc, struct mpssas_target *probe)
 {
@@ -1366,14 +1404,12 @@ mpssas_action_scsiio(struct mpssas_softc
 		break;
 	}
 
-	/* XXX Need to handle multi-level LUNs */
-	if (csio->ccb_h.target_lun > 255) {
+	if (MPS_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) {
 		mps_free_command(sc, cm);
 		ccb->ccb_h.status = CAM_LUN_INVALID;
 		xpt_done(ccb);
 		return;
 	}
-	req->LUN[1] = csio->ccb_h.target_lun;
 
 	if (csio->ccb_h.flags & CAM_CDB_POINTER)
 		bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len);


More information about the svn-src-all mailing list