Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 295

kernel-2.6.18-238.el5.src.rpm

From: Tomas Henzl <thenzl@redhat.com>
Date: Sun, 29 Aug 2010 15:49:52 -0400
Subject: [block] cciss: add support for multi-lun tape devices
Message-id: <1283097002-3341-54-git-send-email-thenzl@redhat.com>
Patchwork-id: 27912
O-Subject: [RHEL6 PATCH 53/63] cciss: Add support for multi-lun tape devices
Bugzilla: 568830
RH-Acked-by: Neil Horman <nhorman@redhat.com>

Add support for multi-lun tape devices

diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index aa2f101..216a44d 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -382,16 +382,50 @@ cciss_scsi_add_entry(int ctlr, int hostno,
 	/* assumes hba[ctlr]->scsi_ctlr->lock is held */ 
 	int n = ccissscsi[ctlr].ndevices;
 	struct cciss_scsi_dev_t *sd;
+	int i, bus, target, lun;
+	unsigned char addr1[8], addr2[8];
 
 	if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
 		printk("cciss%d: Too many devices, "
 			"some will be inaccessible.\n", ctlr);
 		return -1;
 	}
-	sd = &ccissscsi[ctlr].dev[n];
-	if (find_bus_target_lun(ctlr, &sd->bus, &sd->target, &sd->lun) != 0)
-		return -1;
 
+	bus = target = -1;
+	lun = 0;
+	/* Is this device a non-zero lun of a multi-lun device */
+	/* byte 4 of the 8-byte LUN addr will contain the logical unit no. */
+	if (scsi3addr[4] != 0) {
+		/* Search through our list and find the device which */
+		/* has the same 8 byte LUN address, excepting byte 4. */
+		/* Assign the same bus and target for this new LUN. */
+		/* Use the logical unit number from the firmware. */
+		memcpy(addr1, scsi3addr, 8);
+		addr1[4] = 0;
+		for (i = 0; i < n; i++) {
+			sd = &ccissscsi[ctlr].dev[i];
+			memcpy(addr2, sd->scsi3addr, 8);
+			addr2[4] = 0;
+			/* differ only in byte 4? */
+			if (memcmp(addr1, addr2, 8) == 0) {
+				bus = sd->bus;
+				target = sd->target;
+				lun = scsi3addr[4];
+				break;
+			}
+		}
+	}
+
+	sd = &ccissscsi[ctlr].dev[n];
+	if (lun == 0) {
+		if (find_bus_target_lun(ctlr,
+			&sd->bus, &sd->target, &sd->lun) != 0)
+			return -1;
+	} else {
+		sd->bus = bus;
+		sd->target = target;
+		sd->lun = lun;
+	}
 	added[*nadded].bus = sd->bus;
 	added[*nadded].target = sd->target;
 	added[*nadded].lun = sd->lun;
@@ -451,10 +485,12 @@ static void fixup_botched_add(int ctlr, char *scsi3addr)
 	unsigned long flags;
 	int i, j;
 	CPQ_TAPE_LOCK(ctlr, flags);
-	for (i=0;i<ccissscsi[ctlr].ndevices;i++) {
-		if (memcmp(scsi3addr, ccissscsi[ctlr].dev[i].scsi3addr, 8) == 0) {
-			for (j=i;j<ccissscsi[ctlr].ndevices-1;j++)
-				ccissscsi[ctlr].dev[j] = ccissscsi[ctlr].dev[j+1];
+	for (i = 0; i < ccissscsi[ctlr].ndevices; i++) {
+		if (memcmp(scsi3addr, 
+				ccissscsi[ctlr].dev[i].scsi3addr, 8) == 0) {
+			for (j = i; j < ccissscsi[ctlr].ndevices-1; j++)
+				ccissscsi[ctlr].dev[j] = 
+					ccissscsi[ctlr].dev[j+1];
 			ccissscsi[ctlr].ndevices--;
 			break;
 		}
@@ -478,8 +514,10 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
 	int nadded, nremoved;
 	struct Scsi_Host *sh = NULL;
 
-	added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA, GFP_KERNEL);
-	removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA, GFP_KERNEL);
+	added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA,
+			GFP_KERNEL);
+	removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA,
+			GFP_KERNEL);
 
 	if (!added || !removed) {
 		printk(KERN_WARNING "cciss%d: Out of memory in "
@@ -580,7 +618,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
 		goto free_and_out;
 
 	/* Notify scsi mid layer of any removed devices */
-	for (i=0;i<nremoved;i++) {
+	for (i = 0; i < nremoved; i++) {
 		struct scsi_device *sdev =
 			scsi_device_lookup(sh, removed[i].bus,
 				removed[i].target, removed[i].lun);
@@ -591,13 +629,15 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
 			/* We don't expect to get here. */
 			/* future cmds to this device will get selection */
 			/* timeout as if the device was gone. */
-			printk(KERN_WARNING "cciss%d: didn't find c%db%dt%dl%d\n for removal.",
-				ctlr, hostno, removed[i].bus, removed[i].target, removed[i].lun);
+			printk(KERN_WARNING "cciss%d: didn't find "
+				"c%db%dt%dl%d\n for removal.",
+				ctlr, hostno, removed[i].bus, 
+				removed[i].target, removed[i].lun);
 		}
 	}
 
 	/* Notify scsi mid layer of any added devices */
-	for (i=0;i<nadded;i++) {
+	for (i = 0; i < nadded; i++) {
 		int rc;
 		rc = scsi_add_device(sh, added[i].bus,
 			added[i].target, added[i].lun);
@@ -615,7 +655,7 @@ adjust_cciss_scsi_table(int ctlr, int hostno,
 free_and_out:
 	kfree(added);
 	kfree(removed);
- 	return 0;
+	return 0;
 }
 
 static int