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