[PATCH] 5/6 2.5.44 scsi multi-path IO - lower layer (adapter) changes

From: Patrick Mansfield (patmans@us.ibm.com)
Date: Fri Oct 25 2002 - 17:23:30 EST


SCSI low-layer (adapter drivers) multi-path IO changes

 53c700.c | 27 +++++++++++++++++--------
 aic7xxx/aic7xxx_linux.c | 27 ++++++++++++++++---------
 ips.c | 13 ++++++++++--
 qlogicfc.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 99 insertions(+), 19 deletions(-)

diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
--- a/drivers/scsi/53c700.c Fri Oct 25 11:26:47 2002
+++ b/drivers/scsi/53c700.c Fri Oct 25 11:26:47 2002
@@ -1084,7 +1084,7 @@
                 DEBUG(("scsi%d: (%d:%d) RESELECTED!\n",
                        host->host_no, reselection_id, lun));
                 /* clear the reselection indicator */
- SDp = scsi_find_device(host, 0, reselection_id, lun);
+ SDp = scsi_locate_sdev(host->host_no, 0, reselection_id, lun);
                 if(unlikely(SDp == NULL)) {
                         printk(KERN_ERR "scsi%d: (%d:%d) HAS NO device\n",
                                host->host_no, reselection_id, lun);
@@ -1506,6 +1506,7 @@
                 if(sstat0 & SCSI_RESET_DETECTED) {
                         Scsi_Device *SDp;
                         int i;
+ struct scsi_traverse_hndl strav_hndl;
 
                         hostdata->state = NCR_700_HOST_BUSY;
 
@@ -1513,7 +1514,7 @@
                                host->host_no, SCp, SCp == NULL ? NULL : SCp->host_scribble, dsp, dsp - hostdata->pScript);
 
                         /* clear all the negotiated parameters */
- for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next)
+ scsi_for_each_host_sdev(&strav_hndl, SDp, host->host_no)
                                 SDp->hostdata = 0;
                         
                         /* clear all the slots and their pending commands */
@@ -1726,6 +1727,7 @@
         struct Scsi_Host *host;
         struct NCR_700_Host_Parameters *hostdata;
         Scsi_Device *SDp;
+ struct scsi_traverse_hndl strav_hndl;
 
         host = scsi_host_hn_get(host_no);
         if(host == NULL)
@@ -1740,8 +1742,10 @@
         len += sprintf(&buf[len],"\
 Target Depth Active Next Tag\n\
 ====== ===== ====== ========\n");
- for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) {
- len += sprintf(&buf[len]," %2d:%2d %4d %4d %4d\n", SDp->id, SDp->lun, SDp->current_queue_depth, NCR_700_get_depth(SDp), SDp->current_tag);
+ scsi_for_each_host_sdev(&strav_hndl, SDp, host->host_no) {
+ len += scsi_paths_proc_print_paths(SDp, &buf[len],
+ "%2d:%2d:%2d:%2d");
+ len += sprintf(&buf[len]," %4d %4d %4d\n", SDp->current_queue_depth, NCR_700_get_depth(SDp), SDp->current_tag);
         }
         if((len -= offset) <= 0)
                 return 0;
@@ -1814,13 +1818,13 @@
                  * tag queuing per LUN. We only support it per PUN because
                  * of potential reselection issues */
                 printk(KERN_NOTICE "scsi%d: (%d:%d) beginning blk layer TCQ\n",
- SCp->device->host->host_no, SCp->target, SCp->lun);
+ SCp->host->host_no, SCp->target, SCp->lun);
                 scsi_activate_tcq(SCp->device, NCR_700_MAX_TAGS);
         }
 
         if(blk_rq_tagged(SCp->request)
            && (hostdata->tag_negotiated &(1<<SCp->target)) == 0) {
- printk(KERN_INFO "scsi%d: (%d:%d) Enabling Tag Command Queuing\n", SCp->device->host->host_no, SCp->target, SCp->lun);
+ printk(KERN_INFO "scsi%d: (%d:%d) Enabling Tag Command Queuing\n", SCp->host->host_no, SCp->target, SCp->lun);
                 hostdata->tag_negotiated |= (1<<SCp->target);
                 NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING);
         }
@@ -1833,7 +1837,7 @@
          * */
         if(!blk_rq_tagged(SCp->request)
            && (hostdata->tag_negotiated &(1<<SCp->target))) {
- printk(KERN_INFO "scsi%d: (%d:%d) Disabling Tag Command Queuing\n", SCp->device->host->host_no, SCp->target, SCp->lun);
+ printk(KERN_INFO "scsi%d: (%d:%d) Disabling Tag Command Queuing\n", SCp->host->host_no, SCp->target, SCp->lun);
                 hostdata->tag_negotiated &= ~(1<<SCp->target);
         }
 
@@ -2003,12 +2007,19 @@
 STATIC int
 NCR_700_slave_attach(Scsi_Device *SDp)
 {
+ struct Scsi_Host *host;
         /* to do here: allocate memory; build a queue_full list */
         if(SDp->tagged_supported) {
                 /* do TCQ stuff here */
         } else {
                 /* initialise to default depth */
- scsi_adjust_queue_depth(SDp, 0, SDp->host->cmd_per_lun);
+ host = scsi_get_host(SDp);
+ if (!host)
+ /*
+ * Probably a BUG.
+ */
+ return 1;
+ scsi_adjust_queue_depth(SDp, 0, host->cmd_per_lun);
         }
         return 0;
 }
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux.c b/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- a/drivers/scsi/aic7xxx/aic7xxx_linux.c Fri Oct 25 11:26:47 2002
+++ b/drivers/scsi/aic7xxx/aic7xxx_linux.c Fri Oct 25 11:26:47 2002
@@ -1452,8 +1452,12 @@
 {
         struct ahc_softc *ahc;
         u_long flags;
+ struct Scsi_Host *shost;
 
- ahc = *((struct ahc_softc **)device->host->hostdata);
+ shost = scsi_get_host(device);
+ if (!shost)
+ return 1;
+ ahc = *((struct ahc_softc **)shost->hostdata);
         ahc_lock(ahc, &flags);
         ahc_linux_device_queue_depth(ahc, device);
         ahc_unlock(ahc, &flags);
@@ -1470,11 +1474,14 @@
         struct ahc_initiator_tinfo *targ_info;
         struct ahc_tmode_tstate *tstate;
         uint8_t tags;
+ struct scsi_path_id path;
+
+ scsi_get_path(device, &path);
 
         ahc_compile_devinfo(&devinfo,
- device->channel == 0 ? ahc->our_id : ahc->our_id_b,
- device->id, device->lun,
- device->channel == 0 ? 'A' : 'B',
+ path.spi_channel == 0 ? ahc->our_id : ahc->our_id_b,
+ path.spi_id, path.spi_lun,
+ path.spi_channel == 0 ? 'A' : 'B',
                             ROLE_INITIATOR);
         targ_info = ahc_fetch_transinfo(ahc, devinfo.channel,
                                         devinfo.our_scsiid,
@@ -1506,8 +1513,8 @@
                 /* device->queue_depth = tags; */
                 ahc_set_tags(ahc, &devinfo, AHC_QUEUE_TAGGED);
                 printf("scsi%d:%c:%d:%d: Tagged Queuing enabled. Depth %d\n",
- ahc->platform_data->host->host_no, device->channel + 'A',
- device->id, device->lun, tags);
+ ahc->platform_data->host->host_no, path.spi_channel + 'A',
+ path.spi_id, path.spi_lun, tags);
         } else {
                 /*
                  * We allow the OS to queue 2 untagged transactions to
@@ -1516,7 +1523,7 @@
                  * some latency.
                 device->queue_depth = 2;
                  */
- scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun);
+ scsi_adjust_queue_depth(device, 0, path.spi_shpnt->cmd_per_lun);
         }
 }
 
@@ -2727,8 +2734,10 @@
         int extended;
         struct ahc_softc *ahc;
         unsigned char *buf;
+ struct scsi_path_id path;
 
- ahc = *((struct ahc_softc **)disk->device->host->hostdata);
+ scsi_get_path(disk->device, &path);
+ ahc = *((struct ahc_softc **)path.spi_shpnt->hostdata);
         buf = scsi_bios_ptable(bdev);
 
         if (buf) {
@@ -2744,7 +2753,7 @@
 
         if (aic7xxx_extended != 0)
                 extended = 1;
- else if (disk->device->channel == 0)
+ else if (path.spi_channel == 0)
                 extended = (ahc->flags & AHC_EXTENDED_TRANS_A) != 0;
         else
                 extended = (ahc->flags & AHC_EXTENDED_TRANS_B) != 0;
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c Fri Oct 25 11:26:47 2002
+++ b/drivers/scsi/ips.c Fri Oct 25 11:26:47 2002
@@ -1782,10 +1782,15 @@
    int heads;
    int sectors;
    int cylinders;
+ struct Scsi_Host *host;
 
    METHOD_TRACE("ips_biosparam", 1);
 
- ha = (ips_ha_t *) disk->device->host->hostdata;
+ host = scsi_get_host(disk->device);
+ if (host == NULL)
+ return (0);
+
+ ha = (ips_ha_t *) host->hostdata;
 
    if (!ha)
       /* ?!?! host adater info invalid */
@@ -1877,8 +1882,12 @@
 {
    ips_ha_t *ha;
    int min;
+ struct Scsi_Host *sh;
 
- ha = IPS_HA(SDptr->host);
+ sh = scsi_get_host(SDptr);
+ if (!sh)
+ return 1;
+ ha = IPS_HA(sh);
    if (SDptr->tagged_supported) {
       min = ha->max_cmds / 2;
       if (min <= 16)
diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
--- a/drivers/scsi/qlogicfc.c Fri Oct 25 11:26:48 2002
+++ b/drivers/scsi/qlogicfc.c Fri Oct 25 11:26:48 2002
@@ -679,6 +679,8 @@
 static void isp2x00_print_status_entry(struct Status_Entry *);
 #endif
 
+static void do_isp2x00_flush_all_SCSI_cmds(unsigned long arg);
+
 static inline void isp2x00_enable_irqs(struct Scsi_Host *host)
 {
         outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL);
@@ -1154,6 +1156,13 @@
 
         DEBUG(isp2x00_print_scsi_cmd(Cmnd));
 
+ if (hostdata->adapter_state == AS_LOOP_DOWN) {
+ Cmnd->result = DID_NO_CONNECT << 16;
+ if (Cmnd->scsi_done)
+ (*Cmnd->scsi_done) (Cmnd);
+ return 0;
+ }
+
         if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {
                 isp2x00_make_portdb(host);
                 hostdata->adapter_state = AS_LOOP_GOOD;
@@ -1469,6 +1478,7 @@
                 case LOOP_DOWN:
                         printk("qlogicfc%d : Link is Down\n", hostdata->host_id);
                         hostdata->adapter_state = AS_LOOP_DOWN;
+ do_isp2x00_flush_all_SCSI_cmds((unsigned long) host);
                         break;
                 case CONNECTION_MODE:
                         printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1));
@@ -2222,6 +2232,47 @@
 }
 
 #endif /* DEBUG_ISP2x00 */
+
+/*
+ * Flush all SCSI commands we have.
+ */
+void do_isp2x00_flush_all_SCSI_cmds(unsigned long arg)
+{
+ struct Scsi_Host * host = (struct Scsi_Host *) arg;
+ struct isp2x00_hostdata * hostdata;
+ int i;
+
+ hostdata = (struct isp2x00_hostdata *) host->hostdata;
+
+ printk("qlogicfc%d : Flushing all SCSI commands?\n", hostdata->host_id);
+ for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++){
+ if (hostdata->handle_ptrs[i] ){
+ Scsi_Cmnd *Cmnd = hostdata->handle_ptrs[i];
+
+ if (Cmnd->use_sg)
+ pci_unmap_sg(hostdata->pci_dev,
+ (struct scatterlist *)Cmnd->buffer,
+ Cmnd->use_sg,
+ scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
+ else if (Cmnd->request_bufflen &&
+ Cmnd->sc_data_direction != PCI_DMA_NONE) {
+ pci_unmap_page(hostdata->pci_dev,
+ Cmnd->SCp.dma_handle,
+ Cmnd->request_bufflen,
+ scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
+ }
+
+ Cmnd->result = DID_NO_CONNECT << 16;
+
+ if (Cmnd->scsi_done){
+ (*Cmnd->scsi_done) (Cmnd);
+ }
+ else printk("qlogicfc%d : done is null?\n", hostdata->host_id);
+ hostdata->handle_ptrs[i] = NULL;
+ hostdata->handle_serials[i] = 0;
+ }
+ }
+}
 
 MODULE_LICENSE("GPL");
 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Oct 31 2002 - 22:00:29 EST