Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 15 Jul 2007 23:51:54 +0000 (16:51 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 15 Jul 2007 23:51:54 +0000 (16:51 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (166 commits)
  [SCSI] ibmvscsi: convert to use the data buffer accessors
  [SCSI] dc395x: convert to use the data buffer accessors
  [SCSI] ncr53c8xx: convert to use the data buffer accessors
  [SCSI] sym53c8xx: convert to use the data buffer accessors
  [SCSI] ppa: coding police and printk levels
  [SCSI] aic7xxx_old: remove redundant GFP_ATOMIC from kmalloc
  [SCSI] i2o: remove redundant GFP_ATOMIC from kmalloc from device.c
  [SCSI] remove the dead CYBERSTORMIII_SCSI option
  [SCSI] don't build scsi_dma_{map,unmap} for !HAS_DMA
  [SCSI] Clean up scsi_add_lun a bit
  [SCSI] 53c700: Remove printk, which triggers because of low scsi clock on SNI RMs
  [SCSI] sni_53c710: Cleanup
  [SCSI] qla4xxx: Fix underrun/overrun conditions
  [SCSI] megaraid_mbox: use mutex instead of semaphore
  [SCSI] aacraid: add 51245, 51645 and 52245 adapters to documentation.
  [SCSI] qla2xxx: update version to 8.02.00-k1.
  [SCSI] qla2xxx: add support for NPIV
  [SCSI] stex: use resid for xfer len information
  [SCSI] Add Brownie 1200U3P to blacklist
  [SCSI] scsi.c: convert to use the data buffer accessors
  ...

15 files changed:
1  2 
drivers/ieee1394/sbp2.c
drivers/message/fusion/mptspi.c
drivers/scsi/Kconfig
drivers/scsi/NCR5380.c
drivers/scsi/aacraid/linit.c
drivers/scsi/esp_scsi.c
drivers/scsi/ipr.c
drivers/scsi/ips.c
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/nsp32.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_scan.c

diff --combined drivers/ieee1394/sbp2.c
index e0c385a3b45079efc796904d588733a3f5a08449,ce86ff226a283c2e185c7bcbe93c6261c906914c..e882cb951b474e06a11a861327f8dde7c73d316f
@@@ -118,13 -118,14 +118,13 @@@ MODULE_PARM_DESC(max_speed, "Force max 
                 "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
  
  /*
 - * Set serialize_io to 1 if you'd like only one scsi command sent
 - * down to us at a time (debugging). This might be necessary for very
 - * badly behaved sbp2 devices.
 + * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
 + * This is and always has been buggy in multiple subtle ways. See above TODOs.
   */
  static int sbp2_serialize_io = 1;
 -module_param_named(serialize_io, sbp2_serialize_io, int, 0444);
 -MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers "
 -               "(default = 1, faster = 0)");
 +module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
 +MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
 +               "(default = Y, faster but buggy = N)");
  
  /*
   * Bump up max_sectors if you'd like to support very large sized
@@@ -153,9 -154,9 +153,9 @@@ MODULE_PARM_DESC(max_sectors, "Change m
   * are possible on OXFW911 and newer Oxsemi bridges.
   */
  static int sbp2_exclusive_login = 1;
 -module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644);
 +module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
  MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
 -               "(default = 1)");
 +               "(default = Y, use N for concurrent initiators)");
  
  /*
   * If any of the following workarounds is required for your device to work,
@@@ -193,27 -194,6 +193,27 @@@ MODULE_PARM_DESC(workarounds, "Work aro
        ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
        ", or a combination)");
  
 +/*
 + * This influences the format of the sysfs attribute
 + * /sys/bus/scsi/devices/.../ieee1394_id.
 + *
 + * The default format is like in older kernels:  %016Lx:%d:%d
 + * It contains the target's EUI-64, a number given to the logical unit by
 + * the ieee1394 driver's nodemgr (starting at 0), and the LUN.
 + *
 + * The long format is:  %016Lx:%06x:%04x
 + * It contains the target's EUI-64, the unit directory's directory_ID as per
 + * IEEE 1212 clause 7.7.19, and the LUN.  This format comes closest to the
 + * format of SBP(-3) target port and logical unit identifier as per SAM (SCSI
 + * Architecture Model) rev.2 to 4 annex A.  Therefore and because it is
 + * independent of the implementation of the ieee1394 nodemgr, the longer format
 + * is recommended for future use.
 + */
 +static int sbp2_long_sysfs_ieee1394_id;
 +module_param_named(long_ieee1394_id, sbp2_long_sysfs_ieee1394_id, bool, 0644);
 +MODULE_PARM_DESC(long_ieee1394_id, "8+3+2 bytes format of ieee1394_id in sysfs "
 +               "(default = backwards-compatible = N, SAM-conforming = Y)");
 +
  
  #define SBP2_INFO(fmt, args...)       HPSB_INFO("sbp2: "fmt, ## args)
  #define SBP2_ERR(fmt, args...)        HPSB_ERR("sbp2: "fmt, ## args)
@@@ -1509,69 -1489,6 +1509,6 @@@ static void sbp2_prep_command_orb_sg(st
        }
  }
  
- static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
-                                       struct sbp2_fwhost_info *hi,
-                                       struct sbp2_command_info *cmd,
-                                       struct scatterlist *sgpnt,
-                                       u32 orb_direction,
-                                       unsigned int scsi_request_bufflen,
-                                       void *scsi_request_buffer,
-                                       enum dma_data_direction dma_dir)
- {
-       cmd->dma_dir = dma_dir;
-       cmd->dma_size = scsi_request_bufflen;
-       cmd->dma_type = CMD_DMA_SINGLE;
-       cmd->cmd_dma = dma_map_single(hi->host->device.parent,
-                                     scsi_request_buffer,
-                                     cmd->dma_size, cmd->dma_dir);
-       orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-       orb->misc |= ORB_SET_DIRECTION(orb_direction);
-       /* handle case where we get a command w/o s/g enabled
-        * (but check for transfers larger than 64K) */
-       if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-               orb->data_descriptor_lo = cmd->cmd_dma;
-               orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
-       } else {
-               /* The buffer is too large. Turn this into page tables. */
-               struct sbp2_unrestricted_page_table *sg_element =
-                                               &cmd->scatter_gather_element[0];
-               u32 sg_count, sg_len;
-               dma_addr_t sg_addr;
-               orb->data_descriptor_lo = cmd->sge_dma;
-               orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-               /* fill out our SBP-2 page tables; split up the large buffer */
-               sg_count = 0;
-               sg_len = scsi_request_bufflen;
-               sg_addr = cmd->cmd_dma;
-               while (sg_len) {
-                       sg_element[sg_count].segment_base_lo = sg_addr;
-                       if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-                               sg_element[sg_count].length_segment_base_hi =
-                                       PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
-                               sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
-                               sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
-                       } else {
-                               sg_element[sg_count].length_segment_base_hi =
-                                       PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
-                               sg_len = 0;
-                       }
-                       sg_count++;
-               }
-               orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-               sbp2util_cpu_to_be32_buffer(sg_element,
-                               (sizeof(struct sbp2_unrestricted_page_table)) *
-                               sg_count);
-       }
- }
  static void sbp2_create_command_orb(struct sbp2_lu *lu,
                                    struct sbp2_command_info *cmd,
                                    unchar *scsi_cmd,
                orb->data_descriptor_hi = 0x0;
                orb->data_descriptor_lo = 0x0;
                orb->misc |= ORB_SET_DIRECTION(1);
-       } else if (scsi_use_sg)
+       } else
                sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
                                         orb_direction, dma_dir);
-       else
-               sbp2_prep_command_orb_no_sg(orb, hi, cmd, sgpnt, orb_direction,
-                                           scsi_request_bufflen,
-                                           scsi_request_buffer, dma_dir);
  
        sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
  
@@@ -1710,15 -1623,15 +1643,15 @@@ static int sbp2_send_command(struct sbp
                             void (*done)(struct scsi_cmnd *))
  {
        unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
-       unsigned int request_bufflen = SCpnt->request_bufflen;
+       unsigned int request_bufflen = scsi_bufflen(SCpnt);
        struct sbp2_command_info *cmd;
  
        cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
        if (!cmd)
                return -EIO;
  
-       sbp2_create_command_orb(lu, cmd, scsi_cmd, SCpnt->use_sg,
-                               request_bufflen, SCpnt->request_buffer,
+       sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
+                               request_bufflen, scsi_sglist(SCpnt),
                                SCpnt->sc_data_direction);
        sbp2_link_orb_command(lu, cmd);
  
@@@ -2120,14 -2033,8 +2053,14 @@@ static ssize_t sbp2_sysfs_ieee1394_id_s
        if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0]))
                return 0;
  
 -      return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)lu->ne->guid,
 -                     lu->ud->id, ORB_SET_LUN(lu->lun));
 +      if (sbp2_long_sysfs_ieee1394_id)
 +              return sprintf(buf, "%016Lx:%06x:%04x\n",
 +                              (unsigned long long)lu->ne->guid,
 +                              lu->ud->directory_id, ORB_SET_LUN(lu->lun));
 +      else
 +              return sprintf(buf, "%016Lx:%d:%d\n",
 +                              (unsigned long long)lu->ne->guid,
 +                              lu->ud->id, ORB_SET_LUN(lu->lun));
  }
  
  MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");
index 37bf65348372c8b629651ff2f2c3128182a2e653,e06f41c6fb1176d8e1658a17a214401c2eda3d50..6b3e0c00952b69566177fdb97d9d128cf0533a91
@@@ -4,7 -4,7 +4,7 @@@
   *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
   *
   *  Copyright (c) 1999-2007 LSI Logic Corporation
-  *  (mailto:mpt_linux_developer@lsi.com)
+  *  (mailto:DL-MPTFusionLinux@lsi.com)
   *
   */
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@@ -44,7 -44,6 +44,6 @@@
  */
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  
- #include "linux_compat.h"     /* linux-2.6 tweaks */
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
@@@ -727,15 -726,13 +726,15 @@@ static int mptspi_slave_configure(struc
        struct _MPT_SCSI_HOST *hd =
                (struct _MPT_SCSI_HOST *)sdev->host->hostdata;
        VirtTarget *vtarget = scsi_target(sdev)->hostdata;
 -      int ret = mptscsih_slave_configure(sdev);
 +      int ret;
 +
 +      mptspi_initTarget(hd, vtarget, sdev);
 +
 +      ret = mptscsih_slave_configure(sdev);
  
        if (ret)
                return ret;
  
 -      mptspi_initTarget(hd, vtarget, sdev);
 -
        ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x"
                " max_offset=0x%02x max_width=%d\n", hd->ioc->name,
                sdev->id, spi_min_period(scsi_target(sdev)),
diff --combined drivers/scsi/Kconfig
index eb46cb0e3cb7e488495397e400fd866013b1b649,ed0ca1508027aaa97193f5ecf1e052d6228f8fbc..9d2119b53ac9d1f9ad23f720bf81d0e020f16609
@@@ -10,6 -10,7 +10,7 @@@ config RAID_ATTR
  config SCSI
        tristate "SCSI device support"
        depends on BLOCK
+       select SCSI_DMA if HAS_DMA
        ---help---
          If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
          any other SCSI device under Linux, say Y and make sure that you know
          However, do not compile this as a module if your root file system
          (the one containing the directory /) is located on a SCSI device.
  
+ config SCSI_DMA
+       bool
+       default n
  config SCSI_TGT
        tristate "SCSI target support"
        depends on SCSI && EXPERIMENTAL
@@@ -60,7 -65,6 +65,7 @@@ config BLK_DEV_S
        depends on SCSI
        ---help---
          If you want to use SCSI hard disks, Fibre Channel disks,
 +        Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
          USB storage or the SCSI or parallel port version of
          the IOMEGA ZIP drive, say Y and read the SCSI-HOWTO,
          the Disk-HOWTO and the Multi-Disk-HOWTO, available from
@@@ -739,7 -743,7 +744,7 @@@ config SCSI_GENERIC_NCR53C40
  
  config SCSI_IBMMCA
        tristate "IBMMCA SCSI support"
-       depends on MCA_LEGACY && SCSI
+       depends on MCA && SCSI
        ---help---
          This is support for the IBM SCSI adapter found in many of the PS/2
          series computers.  These machines have an MCA bus, so you need to
@@@ -1007,6 -1011,11 +1012,11 @@@ config SCSI_STE
          To compile this driver as a module, choose M here: the
          module will be called stex.
  
+ config 53C700_BE_BUS
+       bool
+       depends on SCSI_A4000T || SCSI_ZORRO7XX || MVME16x_SCSI || BVME6000_SCSI
+       default y
  config SCSI_SYM53C8XX_2
        tristate "SYM53C8XX Version 2 SCSI support"
        depends on PCI && SCSI
@@@ -1533,7 -1542,6 +1543,7 @@@ source "drivers/scsi/arm/Kconfig
  config JAZZ_ESP
        bool "MIPS JAZZ FAS216 SCSI support"
        depends on MACH_JAZZ && SCSI
 +      select SCSI_SPI_ATTRS
        help
          This is the driver for the onboard SCSI host adapter of MIPS Magnum
          4000, Acer PICA, Olivetti M700-10 and a few other identical OEM
@@@ -1611,13 -1619,25 +1621,25 @@@ config FASTLANE_SCS
          If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use
          one in the near future, say Y to this question. Otherwise, say N.
  
- config SCSI_AMIGA7XX
-       bool "Amiga NCR53c710 SCSI support (EXPERIMENTAL)"
-       depends on AMIGA && SCSI && EXPERIMENTAL && BROKEN
+ config SCSI_A4000T
+       tristate "A4000T NCR53c710 SCSI support (EXPERIMENTAL)"
+       depends on AMIGA && SCSI && EXPERIMENTAL
+       select SCSI_SPI_ATTRS
        help
-         Support for various NCR53c710-based SCSI controllers on the Amiga.
+         If you have an Amiga 4000T and have SCSI devices connected to the
+         built-in SCSI controller, say Y. Otherwise, say N.
+         To compile this driver as a module, choose M here: the
+         module will be called a4000t.
+ config SCSI_ZORRO7XX
+       tristate "Zorro NCR53c710 SCSI support (EXPERIMENTAL)"
+       depends on ZORRO && SCSI && EXPERIMENTAL
+       select SCSI_SPI_ATTRS
+       help
+         Support for various NCR53c710-based SCSI controllers on Zorro
+         expansion boards for the Amiga.
          This includes:
-           - the builtin SCSI controller on the Amiga 4000T,
            - the Amiga 4091 Zorro III SCSI-2 controller,
            - the MacroSystem Development's WarpEngine Amiga SCSI-2 controller
              (info at
            - the SCSI controller on the Phase5 Blizzard PowerUP 603e+
              accelerator card for the Amiga 1200,
            - the SCSI controller on the GVP Turbo 040/060 accelerator.
-         Note that all of the above SCSI controllers, except for the builtin
-         SCSI controller on the Amiga 4000T, reside on the Zorro expansion
-         bus, so you also have to enable Zorro bus support if you want to use
-         them.
  
  config OKTAGON_SCSI
        tristate "BSC Oktagon SCSI support (EXPERIMENTAL)"
@@@ -1712,8 -1728,8 +1730,8 @@@ config MVME147_SCS
          single-board computer.
  
  config MVME16x_SCSI
-       bool "NCR53C710 SCSI driver for MVME16x"
-       depends on MVME16x && SCSI && BROKEN
+       tristate "NCR53C710 SCSI driver for MVME16x"
+       depends on MVME16x && SCSI
        select SCSI_SPI_ATTRS
        help
          The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
          will want to say Y to this question.
  
  config BVME6000_SCSI
-       bool "NCR53C710 SCSI driver for BVME6000"
-       depends on BVME6000 && SCSI && BROKEN
+       tristate "NCR53C710 SCSI driver for BVME6000"
+       depends on BVME6000 && SCSI
        select SCSI_SPI_ATTRS
        help
          The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
          SCSI controller chip.  Almost everyone using one of these boards
          will want to say Y to this question.
  
- config SCSI_NCR53C7xx_FAST
-       bool "allow FAST-SCSI [10MHz]"
-       depends on SCSI_AMIGA7XX || MVME16x_SCSI || BVME6000_SCSI
-       help
-         This will enable 10MHz FAST-SCSI transfers with your host
-         adapter. Some systems have problems with that speed, so it's safest
-         to say N here.
  config SUN3_SCSI
        tristate "Sun3 NCR5380 SCSI"
        depends on SUN3 && SCSI
@@@ -1758,7 -1766,6 +1768,7 @@@ config SUN3X_ES
  config SCSI_SUNESP
        tristate "Sparc ESP Scsi Driver"
        depends on SBUS && SCSI
 +      select SCSI_SPI_ATTRS
        help
          This is the driver for the Sun ESP SCSI host adapter. The ESP
          chipset is present in most SPARC SBUS-based computers.
          To compile this driver as a module, choose M here: the
          module will be called esp.
  
- #      bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI
  config ZFCP
        tristate "FCP host bus adapter driver for IBM eServer zSeries"
        depends on S390 && QDIO && SCSI
diff --combined drivers/scsi/NCR5380.c
index 88ea5a1fb606d8b8bb7c91c7c9bb2a4721e43bd9,37de6b37b0843249f5f702ff3b03e585b98bb142..f8e449a98d29e03f9c03a491bbea94c7b158ceb7
@@@ -347,7 -347,7 +347,7 @@@ static int NCR5380_poll_politely(struc
                if((r & bit) == val)
                        return 0;
                if(!in_interrupt())
-                       yield();
+                       cond_resched();
                else
                        cpu_relax();
        }
  static struct {
        unsigned char value;
        const char *name;
- } phases[] = {
+ } phases[] __maybe_unused = {
        {PHASE_DATAOUT, "DATAOUT"}, 
        {PHASE_DATAIN, "DATAIN"}, 
        {PHASE_CMDOUT, "CMDOUT"}, 
@@@ -575,7 -575,8 +575,8 @@@ static irqreturn_t __init probe_intr(in
   *    Locks: none, irqs must be enabled on entry
   */
  
- static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
+ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
+                                               int possible)
  {
        NCR5380_local_declare();
        struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
   *    Locks: none
   */
  
- static void __init NCR5380_print_options(struct Scsi_Host *instance)
+ static void __init __maybe_unused
+ NCR5380_print_options(struct Scsi_Host *instance)
  {
        printk(" generic options"
  #ifdef AUTOPROBE_IRQ
@@@ -703,8 -705,8 +705,8 @@@ char *lprint_command(unsigned char *cmd
  static
  char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
  
- static
int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, off_t offset, int length, int inout)
+ static int __maybe_unused NCR5380_proc_info(struct Scsi_Host *instance,
      char *buffer, char **start, off_t offset, int length, int inout)
  {
        char *pos = buffer;
        struct NCR5380_hostdata *hostdata;
@@@ -2625,7 -2627,7 +2627,7 @@@ static void NCR5380_reselect(struct Scs
  #ifdef REAL_DMA
  static void NCR5380_dma_complete(NCR5380_instance * instance) {
        NCR5380_local_declare();
 -      struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata * instance->hostdata);
 +      struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
        int transferred;
        NCR5380_setup(instance);
  
index 5c487ff096c7dca723374944c7751ebdf03d7629,4fda01e97f4600d77982c19e8a25e8d6d3104801..d76e1a8cb93a20016de8da68d44bd72c3a92ae8a
  #include <linux/pci.h>
  #include <linux/slab.h>
  #include <linux/spinlock.h>
- #include <linux/dma-mapping.h>
  #include <linux/syscalls.h>
  #include <linux/delay.h>
- #include <linux/smp_lock.h>
  #include <linux/kthread.h>
  #include <asm/semaphore.h>
  
@@@ -223,12 -221,12 +221,12 @@@ static struct aac_driver_ident aac_driv
        { aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
        { aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
        { aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
-       { aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell PERC2/QC */
+       { aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_34SG }, /* Dell PERC2/QC */
        { aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4, AAC_QUIRK_34SG }, /* HP NetRAID-4M */
  
        { aac_rx_init, "aacraid",  "DELL    ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */
        { aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */
-       { aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */
+       { aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Catch All */
        { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Rocket Catch All */
        { aac_nark_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec NEMER/ARK Catch All */
  };
@@@ -403,10 -401,6 +401,6 @@@ static int aac_biosparm(struct scsi_dev
  
  static int aac_slave_configure(struct scsi_device *sdev)
  {
-       if (sdev_channel(sdev) == CONTAINER_CHANNEL) {
-               sdev->skip_ms_page_8 = 1;
-               sdev->skip_ms_page_3f = 1;
-       }
        if ((sdev->type == TYPE_DISK) &&
                        (sdev_channel(sdev) != CONTAINER_CHANNEL)) {
                if (expose_physicals == 0)
        return 0;
  }
  
+ /**
+  *    aac_change_queue_depth          -       alter queue depths
+  *    @sdev:  SCSI device we are considering
+  *    @depth: desired queue depth
+  *
+  *    Alters queue depths for target device based on the host adapter's
+  *    total capacity and the queue depth supported by the target device.
+  */
+ static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
+ {
+       if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
+           (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
+               struct scsi_device * dev;
+               struct Scsi_Host *host = sdev->host;
+               unsigned num = 0;
+               __shost_for_each_device(dev, host) {
+                       if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
+                           (sdev_channel(dev) == CONTAINER_CHANNEL))
+                               ++num;
+                       ++num;
+               }
+               if (num >= host->can_queue)
+                       num = host->can_queue - 1;
+               if (depth > (host->can_queue - num))
+                       depth = host->can_queue - num;
+               if (depth > 256)
+                       depth = 256;
+               else if (depth < 2)
+                       depth = 2;
+               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
+       } else
+               scsi_adjust_queue_depth(sdev, 0, 1);
+       return sdev->queue_depth;
+ }
  static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
  {
        struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
@@@ -548,6 -579,14 +579,14 @@@ static int aac_eh_reset(struct scsi_cmn
                ssleep(1);
        }
        printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
+       /*
+        * This adapter needs a blind reset, only do so for Adapters that
+        * support a register, instead of a commanded, reset.
+        */
+       if ((aac->supplement_adapter_info.SupportedOptions2 &
+         le32_to_cpu(AAC_OPTION_MU_RESET|AAC_OPTION_IGNORE_RESET)) ==
+         le32_to_cpu(AAC_OPTION_MU_RESET))
+               aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */
        return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
  }
  
@@@ -731,15 -770,21 +770,21 @@@ static ssize_t aac_show_bios_version(st
        return len;
  }
  
- static ssize_t aac_show_serial_number(struct class_device *class_dev,
-               char *buf)
+ ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
  {
        struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
        int len = 0;
  
        if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
-               len = snprintf(buf, PAGE_SIZE, "%x\n",
+               len = snprintf(buf, PAGE_SIZE, "%06X\n",
                  le32_to_cpu(dev->adapter_info.serial[0]));
+       if (len &&
+         !memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[
+           sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)+2-len],
+         buf, len))
+               len = snprintf(buf, PAGE_SIZE, "%.*s\n",
+                 (int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo),
+                 dev->supplement_adapter_info.MfgPcbaSerialNo);
        return len;
  }
  
@@@ -755,6 -800,31 +800,31 @@@ static ssize_t aac_show_max_id(struct c
          class_to_shost(class_dev)->max_id);
  }
  
+ static ssize_t aac_store_reset_adapter(struct class_device *class_dev,
+               const char *buf, size_t count)
+ {
+       int retval = -EACCES;
+       if (!capable(CAP_SYS_ADMIN))
+               return retval;
+       retval = aac_reset_adapter((struct aac_dev*)class_to_shost(class_dev)->hostdata, buf[0] == '!');
+       if (retval >= 0)
+               retval = count;
+       return retval;
+ }
+ static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
+               char *buf)
+ {
+       struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+       int len, tmp;
+       tmp = aac_adapter_check_health(dev);
+       if ((tmp == 0) && dev->in_reset)
+               tmp = -EBUSY;
+       len = snprintf(buf, PAGE_SIZE, "0x%x", tmp);
+       return len;
+ }
  
  static struct class_device_attribute aac_model = {
        .attr = {
@@@ -812,6 -882,14 +882,14 @@@ static struct class_device_attribute aa
        },
        .show = aac_show_max_id,
  };
+ static struct class_device_attribute aac_reset = {
+       .attr = {
+               .name = "reset_host",
+               .mode = S_IWUSR|S_IRUGO,
+       },
+       .store = aac_store_reset_adapter,
+       .show = aac_show_reset_adapter,
+ };
  
  static struct class_device_attribute *aac_attrs[] = {
        &aac_model,
        &aac_serial_number,
        &aac_max_channel,
        &aac_max_id,
+       &aac_reset,
        NULL
  };
  
@@@ -848,6 -927,7 +927,7 @@@ static struct scsi_host_template aac_dr
        .bios_param                     = aac_biosparm, 
        .shost_attrs                    = aac_attrs,
        .slave_configure                = aac_slave_configure,
+       .change_queue_depth             = aac_change_queue_depth,
        .eh_abort_handler               = aac_eh_abort,
        .eh_host_reset_handler          = aac_eh_reset,
        .can_queue                      = AAC_NUM_IO_FIB,       
        .emulated                       = 1,
  };
  
 +static void __aac_shutdown(struct aac_dev * aac)
 +{
 +      kthread_stop(aac->thread);
 +      aac_send_shutdown(aac);
 +      aac_adapter_disable_int(aac);
 +      free_irq(aac->pdev->irq, aac);
 +}
 +
  static int __devinit aac_probe_one(struct pci_dev *pdev,
                const struct pci_device_id *id)
  {
        return 0;
  
   out_deinit:
 -      kthread_stop(aac->thread);
 -      aac_send_shutdown(aac);
 -      aac_adapter_disable_int(aac);
 -      free_irq(pdev->irq, aac);
 +      __aac_shutdown(aac);
   out_unmap:
        aac_fib_map_free(aac);
        pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
@@@ -1043,8 -1118,7 +1123,8 @@@ static void aac_shutdown(struct pci_de
  {
        struct Scsi_Host *shost = pci_get_drvdata(dev);
        struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
 -      aac_send_shutdown(aac);
 +      scsi_block_requests(shost);
 +      __aac_shutdown(aac);
  }
  
  static void __devexit aac_remove_one(struct pci_dev *pdev)
  
        scsi_remove_host(shost);
  
 -      kthread_stop(aac->thread);
 -
 -      aac_send_shutdown(aac);
 -      aac_adapter_disable_int(aac);
 +      __aac_shutdown(aac);
        aac_fib_map_free(aac);
        pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
                        aac->comm_phys);
        kfree(aac->queues);
  
 -      free_irq(pdev->irq, aac);
        aac_adapter_ioremap(aac, 0);
        
        kfree(aac->fibs);
@@@ -1086,7 -1164,7 +1166,7 @@@ static int __init aac_init(void
  {
        int error;
        
-       printk(KERN_INFO "Adaptec %s driver (%s)\n",
+       printk(KERN_INFO "Adaptec %s driver %s\n",
          AAC_DRIVERNAME, aac_driver_version);
  
        error = pci_register_driver(&aac_pci_driver);
diff --combined drivers/scsi/esp_scsi.c
index 71caf2ded6badcfd90dad000804f00782cfe591c,c1d50e669c4317bb5879c8eb0be7c5aeb3946190..77b06a983fa763023f245c010fb738616c7d18bc
@@@ -324,17 -324,14 +324,14 @@@ static void esp_reset_esp(struct esp *e
  static void esp_map_dma(struct esp *esp, struct scsi_cmnd *cmd)
  {
        struct esp_cmd_priv *spriv = ESP_CMD_PRIV(cmd);
-       struct scatterlist *sg = cmd->request_buffer;
+       struct scatterlist *sg = scsi_sglist(cmd);
        int dir = cmd->sc_data_direction;
        int total, i;
  
        if (dir == DMA_NONE)
                return;
  
-       BUG_ON(cmd->use_sg == 0);
-       spriv->u.num_sg = esp->ops->map_sg(esp, sg,
-                                          cmd->use_sg, dir);
+       spriv->u.num_sg = esp->ops->map_sg(esp, sg, scsi_sg_count(cmd), dir);
        spriv->cur_residue = sg_dma_len(sg);
        spriv->cur_sg = sg;
  
@@@ -407,8 -404,7 +404,7 @@@ static void esp_unmap_dma(struct esp *e
        if (dir == DMA_NONE)
                return;
  
-       esp->ops->unmap_sg(esp, cmd->request_buffer,
-                          spriv->u.num_sg, dir);
+       esp->ops->unmap_sg(esp, scsi_sglist(cmd), spriv->u.num_sg, dir);
  }
  
  static void esp_save_pointers(struct esp *esp, struct esp_cmd_entry *ent)
@@@ -921,7 -917,7 +917,7 @@@ static void esp_event_queue_full(struc
  static int esp_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
  {
        struct scsi_device *dev = cmd->device;
-       struct esp *esp = host_to_esp(dev->host);
+       struct esp *esp = shost_priv(dev->host);
        struct esp_cmd_priv *spriv;
        struct esp_cmd_entry *ent;
  
@@@ -2033,7 -2029,6 +2029,7 @@@ static void esp_reset_cleanup(struct es
                        starget_for_each_device(tp->starget, NULL,
                                                esp_clear_hold);
        }
 +      esp->flags &= ~ESP_FLAG_RESETTING;
  }
  
  /* Runs under host->lock */
@@@ -2357,7 -2352,7 +2353,7 @@@ EXPORT_SYMBOL(scsi_esp_unregister)
  
  static int esp_slave_alloc(struct scsi_device *dev)
  {
-       struct esp *esp = host_to_esp(dev->host);
+       struct esp *esp = shost_priv(dev->host);
        struct esp_target_data *tp = &esp->target[dev->id];
        struct esp_lun_data *lp;
  
  
  static int esp_slave_configure(struct scsi_device *dev)
  {
-       struct esp *esp = host_to_esp(dev->host);
+       struct esp *esp = shost_priv(dev->host);
        struct esp_target_data *tp = &esp->target[dev->id];
        int goal_tags, queue_depth;
  
@@@ -2423,7 -2418,7 +2419,7 @@@ static void esp_slave_destroy(struct sc
  
  static int esp_eh_abort_handler(struct scsi_cmnd *cmd)
  {
-       struct esp *esp = host_to_esp(cmd->device->host);
+       struct esp *esp = shost_priv(cmd->device->host);
        struct esp_cmd_entry *ent, *tmp;
        struct completion eh_done;
        unsigned long flags;
@@@ -2539,7 -2534,7 +2535,7 @@@ out_failure
  
  static int esp_eh_bus_reset_handler(struct scsi_cmnd *cmd)
  {
-       struct esp *esp = host_to_esp(cmd->device->host);
+       struct esp *esp = shost_priv(cmd->device->host);
        struct completion eh_reset;
        unsigned long flags;
  
  /* All bets are off, reset the entire device.  */
  static int esp_eh_host_reset_handler(struct scsi_cmnd *cmd)
  {
-       struct esp *esp = host_to_esp(cmd->device->host);
+       struct esp *esp = shost_priv(cmd->device->host);
        unsigned long flags;
  
        spin_lock_irqsave(esp->host->host_lock, flags);
@@@ -2615,7 -2610,7 +2611,7 @@@ EXPORT_SYMBOL(scsi_esp_template)
  
  static void esp_get_signalling(struct Scsi_Host *host)
  {
-       struct esp *esp = host_to_esp(host);
+       struct esp *esp = shost_priv(host);
        enum spi_signal_type type;
  
        if (esp->flags & ESP_FLAG_DIFFERENTIAL)
  static void esp_set_offset(struct scsi_target *target, int offset)
  {
        struct Scsi_Host *host = dev_to_shost(target->dev.parent);
-       struct esp *esp = host_to_esp(host);
+       struct esp *esp = shost_priv(host);
        struct esp_target_data *tp = &esp->target[target->id];
  
        tp->nego_goal_offset = offset;
  static void esp_set_period(struct scsi_target *target, int period)
  {
        struct Scsi_Host *host = dev_to_shost(target->dev.parent);
-       struct esp *esp = host_to_esp(host);
+       struct esp *esp = shost_priv(host);
        struct esp_target_data *tp = &esp->target[target->id];
  
        tp->nego_goal_period = period;
  static void esp_set_width(struct scsi_target *target, int width)
  {
        struct Scsi_Host *host = dev_to_shost(target->dev.parent);
-       struct esp *esp = host_to_esp(host);
+       struct esp *esp = shost_priv(host);
        struct esp_target_data *tp = &esp->target[target->id];
  
        tp->nego_goal_width = (width ? 1 : 0);
diff --combined drivers/scsi/ipr.c
index b3bf77f1ec050e62785067b9d38826ccb52948d4,072f5771565823284eaa5c273203facc2d9bf027..f142eafb6fc748ab5d7aa8c2c99ad38aa77a6c33
@@@ -539,32 -539,6 +539,6 @@@ struct ipr_cmnd *ipr_get_free_ipr_cmnd(
        return ipr_cmd;
  }
  
- /**
-  * ipr_unmap_sglist - Unmap scatterlist if mapped
-  * @ioa_cfg:  ioa config struct
-  * @ipr_cmd:  ipr command struct
-  *
-  * Return value:
-  *    nothing
-  **/
- static void ipr_unmap_sglist(struct ipr_ioa_cfg *ioa_cfg,
-                            struct ipr_cmnd *ipr_cmd)
- {
-       struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
-       if (ipr_cmd->dma_use_sg) {
-               if (scsi_cmd->use_sg > 0) {
-                       pci_unmap_sg(ioa_cfg->pdev, scsi_cmd->request_buffer,
-                                    scsi_cmd->use_sg,
-                                    scsi_cmd->sc_data_direction);
-               } else {
-                       pci_unmap_single(ioa_cfg->pdev, ipr_cmd->dma_handle,
-                                        scsi_cmd->request_bufflen,
-                                        scsi_cmd->sc_data_direction);
-               }
-       }
- }
  /**
   * ipr_mask_and_clear_interrupts - Mask all and clear specified interrupts
   * @ioa_cfg:  ioa config struct
@@@ -677,7 -651,7 +651,7 @@@ static void ipr_scsi_eh_done(struct ipr
  
        scsi_cmd->result |= (DID_ERROR << 16);
  
-       ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+       scsi_dma_unmap(ipr_cmd->scsi_cmd);
        scsi_cmd->scsi_done(scsi_cmd);
        list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
  }
@@@ -2465,7 -2439,6 +2439,7 @@@ restart
  /**
   * ipr_read_trace - Dump the adapter trace
   * @kobj:             kobject struct
 + * @bin_attr:         bin_attribute struct
   * @buf:              buffer
   * @off:              offset
   * @count:            buffer size
   * Return value:
   *    number of bytes printed to buffer
   **/
 -static ssize_t ipr_read_trace(struct kobject *kobj, char *buf,
 -                            loff_t off, size_t count)
 +static ssize_t ipr_read_trace(struct kobject *kobj,
 +                            struct bin_attribute *bin_attr,
 +                            char *buf, loff_t off, size_t count)
  {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *shost = class_to_shost(cdev);
@@@ -3168,7 -3140,6 +3142,7 @@@ static struct class_device_attribute *i
  /**
   * ipr_read_dump - Dump the adapter
   * @kobj:             kobject struct
 + * @bin_attr:         bin_attribute struct
   * @buf:              buffer
   * @off:              offset
   * @count:            buffer size
   * Return value:
   *    number of bytes printed to buffer
   **/
 -static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
 -                            loff_t off, size_t count)
 +static ssize_t ipr_read_dump(struct kobject *kobj,
 +                           struct bin_attribute *bin_attr,
 +                           char *buf, loff_t off, size_t count)
  {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *shost = class_to_shost(cdev);
@@@ -3331,7 -3301,6 +3305,7 @@@ static int ipr_free_dump(struct ipr_ioa
  /**
   * ipr_write_dump - Setup dump state of adapter
   * @kobj:             kobject struct
 + * @bin_attr:         bin_attribute struct
   * @buf:              buffer
   * @off:              offset
   * @count:            buffer size
   * Return value:
   *    number of bytes printed to buffer
   **/
 -static ssize_t ipr_write_dump(struct kobject *kobj, char *buf,
 -                            loff_t off, size_t count)
 +static ssize_t ipr_write_dump(struct kobject *kobj,
 +                            struct bin_attribute *bin_attr,
 +                            char *buf, loff_t off, size_t count)
  {
        struct class_device *cdev = container_of(kobj,struct class_device,kobj);
        struct Scsi_Host *shost = class_to_shost(cdev);
@@@ -4298,93 -4266,55 +4272,55 @@@ static irqreturn_t ipr_isr(int irq, voi
  static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
                           struct ipr_cmnd *ipr_cmd)
  {
-       int i;
-       struct scatterlist *sglist;
+       int i, nseg;
+       struct scatterlist *sg;
        u32 length;
        u32 ioadl_flags = 0;
        struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
        struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
        struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
  
-       length = scsi_cmd->request_bufflen;
-       if (length == 0)
+       length = scsi_bufflen(scsi_cmd);
+       if (!length)
                return 0;
  
-       if (scsi_cmd->use_sg) {
-               ipr_cmd->dma_use_sg = pci_map_sg(ioa_cfg->pdev,
-                                                scsi_cmd->request_buffer,
-                                                scsi_cmd->use_sg,
-                                                scsi_cmd->sc_data_direction);
-               if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
-                       ioadl_flags = IPR_IOADL_FLAGS_WRITE;
-                       ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
-                       ioarcb->write_data_transfer_length = cpu_to_be32(length);
-                       ioarcb->write_ioadl_len =
-                               cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
-               } else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
-                       ioadl_flags = IPR_IOADL_FLAGS_READ;
-                       ioarcb->read_data_transfer_length = cpu_to_be32(length);
-                       ioarcb->read_ioadl_len =
-                               cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
-               }
-               sglist = scsi_cmd->request_buffer;
-               if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
-                       ioadl = ioarcb->add_data.u.ioadl;
-                       ioarcb->write_ioadl_addr =
-                               cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
-                                           offsetof(struct ipr_ioarcb, add_data));
-                       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
-               }
+       nseg = scsi_dma_map(scsi_cmd);
+       if (nseg < 0) {
+               dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
+               return -1;
+       }
  
-               for (i = 0; i < ipr_cmd->dma_use_sg; i++) {
-                       ioadl[i].flags_and_data_len =
-                               cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i]));
-                       ioadl[i].address =
-                               cpu_to_be32(sg_dma_address(&sglist[i]));
-               }
+       ipr_cmd->dma_use_sg = nseg;
+       if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
+               ioadl_flags = IPR_IOADL_FLAGS_WRITE;
+               ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
+               ioarcb->write_data_transfer_length = cpu_to_be32(length);
+               ioarcb->write_ioadl_len =
+                       cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
+       } else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
+               ioadl_flags = IPR_IOADL_FLAGS_READ;
+               ioarcb->read_data_transfer_length = cpu_to_be32(length);
+               ioarcb->read_ioadl_len =
+                       cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg);
+       }
  
-               if (likely(ipr_cmd->dma_use_sg)) {
-                       ioadl[i-1].flags_and_data_len |=
-                               cpu_to_be32(IPR_IOADL_FLAGS_LAST);
-                       return 0;
-               } else
-                       dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
-       } else {
-               if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
-                       ioadl_flags = IPR_IOADL_FLAGS_WRITE;
-                       ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
-                       ioarcb->write_data_transfer_length = cpu_to_be32(length);
-                       ioarcb->write_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
-               } else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) {
-                       ioadl_flags = IPR_IOADL_FLAGS_READ;
-                       ioarcb->read_data_transfer_length = cpu_to_be32(length);
-                       ioarcb->read_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
-               }
+       if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
+               ioadl = ioarcb->add_data.u.ioadl;
+               ioarcb->write_ioadl_addr =
+                       cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+                                   offsetof(struct ipr_ioarcb, add_data));
+               ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
+       }
  
-               ipr_cmd->dma_handle = pci_map_single(ioa_cfg->pdev,
-                                                    scsi_cmd->request_buffer, length,
-                                                    scsi_cmd->sc_data_direction);
-               if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) {
-                       ioadl = ioarcb->add_data.u.ioadl;
-                       ioarcb->write_ioadl_addr =
-                               cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
-                                           offsetof(struct ipr_ioarcb, add_data));
-                       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
-                       ipr_cmd->dma_use_sg = 1;
-                       ioadl[0].flags_and_data_len =
-                               cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST);
-                       ioadl[0].address = cpu_to_be32(ipr_cmd->dma_handle);
-                       return 0;
-               } else
-                       dev_err(&ioa_cfg->pdev->dev, "pci_map_single failed!\n");
+       scsi_for_each_sg(scsi_cmd, sg, ipr_cmd->dma_use_sg, i) {
+               ioadl[i].flags_and_data_len =
+                       cpu_to_be32(ioadl_flags | sg_dma_len(sg));
+               ioadl[i].address = cpu_to_be32(sg_dma_address(sg));
        }
  
-       return -1;
+       ioadl[i-1].flags_and_data_len |= cpu_to_be32(IPR_IOADL_FLAGS_LAST);
+       return 0;
  }
  
  /**
@@@ -4447,7 -4377,7 +4383,7 @@@ static void ipr_erp_done(struct ipr_cmn
                        res->needs_sync_complete = 1;
                res->in_erp = 0;
        }
-       ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+       scsi_dma_unmap(ipr_cmd->scsi_cmd);
        list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
        scsi_cmd->scsi_done(scsi_cmd);
  }
@@@ -4825,7 -4755,7 +4761,7 @@@ static void ipr_erp_start(struct ipr_io
                break;
        }
  
-       ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+       scsi_dma_unmap(ipr_cmd->scsi_cmd);
        list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
        scsi_cmd->scsi_done(scsi_cmd);
  }
@@@ -4846,10 -4776,10 +4782,10 @@@ static void ipr_scsi_done(struct ipr_cm
        struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
        u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
  
-       scsi_cmd->resid = be32_to_cpu(ipr_cmd->ioasa.residual_data_len);
+       scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len));
  
        if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
-               ipr_unmap_sglist(ioa_cfg, ipr_cmd);
+               scsi_dma_unmap(ipr_cmd->scsi_cmd);
                list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
                scsi_cmd->scsi_done(scsi_cmd);
        } else
@@@ -5373,12 -5303,18 +5309,12 @@@ static const u16 ipr_blocked_processors
   **/
  static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
  {
 -      u8 rev_id;
        int i;
  
 -      if (ioa_cfg->type == 0x5702) {
 -              if (pci_read_config_byte(ioa_cfg->pdev, PCI_REVISION_ID,
 -                                       &rev_id) == PCIBIOS_SUCCESSFUL) {
 -                      if (rev_id < 4) {
 -                              for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++){
 -                                      if (__is_processor(ipr_blocked_processors[i]))
 -                                              return 1;
 -                              }
 -                      }
 +      if ((ioa_cfg->type == 0x5702) && (ioa_cfg->pdev->revision < 4)) {
 +              for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++){
 +                      if (__is_processor(ipr_blocked_processors[i]))
 +                              return 1;
                }
        }
        return 0;
@@@ -7535,7 -7471,13 +7471,7 @@@ static int __devinit ipr_probe_ioa(stru
        else
                ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
  
 -      rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &ioa_cfg->revid);
 -
 -      if (rc != PCIBIOS_SUCCESSFUL) {
 -              dev_err(&pdev->dev, "Failed to read PCI revision ID\n");
 -              rc = -EIO;
 -              goto out_scsi_host_put;
 -      }
 +      ioa_cfg->revid = pdev->revision;
  
        ipr_regs_pci = pci_resource_start(pdev, 0);
  
diff --combined drivers/scsi/ips.c
index 40f148e0833f485034e1f30f5a93756f05abb42c,f9fce70f396af6e489d9ae0d15968dddbf2064ca..9f8ed6b8157651023b4b25e976fdd672570107a3
@@@ -211,19 -211,6 +211,6 @@@ module_param(ips, charp, 0)
  #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
  #endif
  
- #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
- #include <linux/blk.h>
- #include "sd.h"
- #define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
- #define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
- #ifndef __devexit_p
- #define __devexit_p(x) x
- #endif
- #else
- #define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0)
- #define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0)
- #endif
  #define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \
                           DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \
                           PCI_DMA_BIDIRECTIONAL : \
@@@ -381,24 -368,13 +368,13 @@@ static struct scsi_host_template ips_dr
        .eh_abort_handler       = ips_eh_abort,
        .eh_host_reset_handler  = ips_eh_reset,
        .proc_name              = "ips",
- #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
        .proc_info              = ips_proc_info,
        .slave_configure        = ips_slave_configure,
- #else
-       .proc_info              = ips_proc24_info,
-       .select_queue_depths    = ips_select_queue_depth,
- #endif
        .bios_param             = ips_biosparam,
        .this_id                = -1,
        .sg_tablesize           = IPS_MAX_SG,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       .use_new_eh_code        = 1,
- #endif
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)  &&  LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-     .highmem_io          = 1,   
- #endif
  };
  
  
@@@ -731,7 -707,7 +707,7 @@@ ips_release(struct Scsi_Host *sh
        /* free IRQ */
        free_irq(ha->irq, ha);
  
-       IPS_REMOVE_HOST(sh);
+       scsi_remove_host(sh);
        scsi_host_put(sh);
  
        ips_released_controllers++;
@@@ -813,7 -789,6 +789,6 @@@ int ips_eh_abort(struct scsi_cmnd *SC
        ips_ha_t *ha;
        ips_copp_wait_item_t *item;
        int ret;
-       unsigned long cpu_flags;
        struct Scsi_Host *host;
  
        METHOD_TRACE("ips_eh_abort", 1);
        if (!ha->active)
                return (FAILED);
  
-       IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+       spin_lock(host->host_lock);
  
        /* See if the command is on the copp queue */
        item = ha->copp_waitlist.head;
                ret = (FAILED);
        }
  
-       IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+       spin_unlock(host->host_lock);
        return ret;
  }
  
@@@ -1129,7 -1104,7 +1104,7 @@@ static int ips_queue(struct scsi_cmnd *
                /* A Reset IOCTL is only sent by the boot CD in extreme cases.           */
                /* There can never be any system activity ( network or disk ), but check */
                /* anyway just as a good practice.                                       */
-               pt = (ips_passthru_t *) SC->request_buffer;
+               pt = (ips_passthru_t *) scsi_sglist(SC);
                if ((pt->CoppCP.cmd.reset.op_code == IPS_CMD_RESET_CHANNEL) &&
                    (pt->CoppCP.cmd.reset.adapter_flag == 1)) {
                        if (ha->scb_activelist.count != 0) {
  /*   Set bios geometry for the controller                                   */
  /*                                                                          */
  /****************************************************************************/
- static int
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- ips_biosparam(Disk * disk, kdev_t dev, int geom[])
- {
-       ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata;
-       unsigned long capacity = disk->capacity;
- #else
- ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-             sector_t capacity, int geom[])
+ static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+                        sector_t capacity, int geom[])
  {
        ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
- #endif
        int heads;
        int sectors;
        int cylinders;
        return (0);
  }
  
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /* ips_proc24_info is a wrapper around ips_proc_info *
-  * for compatibility with the 2.4 scsi parameters    */
- static int
- ips_proc24_info(char *buffer, char **start, off_t offset, int length,
-                             int hostno, int func)
- {
-       int i;
-       for (i = 0; i < ips_next_controller; i++) {
-               if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
-                       return ips_proc_info(ips_sh[i], buffer, start,
-                                            offset, length, func);
-               }
-       }
-       return -EINVAL; 
- }
- /****************************************************************************/
- /*                                                                          */
- /* Routine Name: ips_select_queue_depth                                     */
- /*                                                                          */
- /* Routine Description:                                                     */
- /*                                                                          */
- /*   Select queue depths for the devices on the contoller                   */
- /*                                                                          */
- /****************************************************************************/
- static void
- ips_select_queue_depth(struct Scsi_Host *host, struct scsi_device * scsi_devs)
- {
-       struct scsi_device *device;
-       ips_ha_t *ha;
-       int count = 0;
-       int min;
-       ha = IPS_HA(host);
-       min = ha->max_cmds / 4;
-       for (device = scsi_devs; device; device = device->next) {
-               if (device->host == host) {
-                       if ((device->channel == 0) && (device->type == 0))
-                               count++;
-               }
-       }
-       for (device = scsi_devs; device; device = device->next) {
-               if (device->host == host) {
-                       if ((device->channel == 0) && (device->type == 0)) {
-                               device->queue_depth =
-                                   (ha->max_cmds - 1) / count;
-                               if (device->queue_depth < min)
-                                       device->queue_depth = min;
-                       } else {
-                               device->queue_depth = 2;
-                       }
-                       if (device->queue_depth < 2)
-                               device->queue_depth = 2;
-               }
-       }
- }
- #else
  /****************************************************************************/
  /*                                                                          */
  /* Routine Name: ips_slave_configure                                        */
@@@ -1316,7 -1219,6 +1219,6 @@@ ips_slave_configure(struct scsi_device 
        SDptr->skip_ms_page_3f = 1;
        return 0;
  }
- #endif
  
  /****************************************************************************/
  /*                                                                          */
@@@ -1331,7 -1233,6 +1233,6 @@@ static irqreturn_
  do_ipsintr(int irq, void *dev_id)
  {
        ips_ha_t *ha;
-       unsigned long cpu_flags;
        struct Scsi_Host *host;
        int irqstatus;
  
                return IRQ_HANDLED;
        }
  
-       IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+       spin_lock(host->host_lock);
  
        if (!ha->active) {
-               IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+               spin_unlock(host->host_lock);
                return IRQ_HANDLED;
        }
  
        irqstatus = (*ha->func.intr) (ha);
  
-       IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+       spin_unlock(host->host_lock);
  
        /* start the next command */
        ips_next(ha, IPS_INTR_ON);
@@@ -1606,30 -1507,22 +1507,22 @@@ static int ips_is_passthru(struct scsi_
        if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) &&
            (SC->device->channel == 0) &&
            (SC->device->id == IPS_ADAPTER_ID) &&
-           (SC->device->lun == 0) && SC->request_buffer) {
-               if ((!SC->use_sg) && SC->request_bufflen &&
-                   (((char *) SC->request_buffer)[0] == 'C') &&
-                   (((char *) SC->request_buffer)[1] == 'O') &&
-                   (((char *) SC->request_buffer)[2] == 'P') &&
-                   (((char *) SC->request_buffer)[3] == 'P'))
-                       return 1;
-               else if (SC->use_sg) {
-                       struct scatterlist *sg = SC->request_buffer;
-                       char  *buffer; 
-                       /* kmap_atomic() ensures addressability of the user buffer.*/
-                       /* local_irq_save() protects the KM_IRQ0 address slot.     */
-                       local_irq_save(flags);
-                       buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; 
-                       if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
-                           buffer[2] == 'P' && buffer[3] == 'P') {
-                               kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-                               local_irq_restore(flags);
-                               return 1;
-                       }
-                       kunmap_atomic(buffer - sg->offset, KM_IRQ0);
-                       local_irq_restore(flags);
-               }
+           (SC->device->lun == 0) && scsi_sglist(SC)) {
+                 struct scatterlist *sg = scsi_sglist(SC);
+                 char  *buffer;
+                 /* kmap_atomic() ensures addressability of the user buffer.*/
+                 /* local_irq_save() protects the KM_IRQ0 address slot.     */
+                 local_irq_save(flags);
+                 buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+                 if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
+                     buffer[2] == 'P' && buffer[3] == 'P') {
+                         kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+                         local_irq_restore(flags);
+                         return 1;
+                 }
+                 kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+                 local_irq_restore(flags);
        }
        return 0;
  }
@@@ -1680,18 -1573,14 +1573,14 @@@ ips_make_passthru(ips_ha_t *ha, struct 
  {
        ips_passthru_t *pt;
        int length = 0;
-       int ret;
+       int i, ret;
+         struct scatterlist *sg = scsi_sglist(SC);
  
        METHOD_TRACE("ips_make_passthru", 1);
  
-       if (!SC->use_sg) {
-               length = SC->request_bufflen;
-       } else {
-               struct scatterlist *sg = SC->request_buffer;
-               int i;
-               for (i = 0; i < SC->use_sg; i++)
-                       length += sg[i].length;
-       }
+         scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i)
+                 length += sg[i].length;
        if (length < sizeof (ips_passthru_t)) {
                /* wrong size */
                DEBUG_VAR(1, "(%s%d) Passthru structure wrong size",
@@@ -2115,7 -2004,7 +2004,7 @@@ ips_cleanup_passthru(ips_ha_t * ha, ips
  
        METHOD_TRACE("ips_cleanup_passthru", 1);
  
-       if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) {
+       if ((!scb) || (!scb->scsi_cmd) || (!scsi_sglist(scb->scsi_cmd))) {
                DEBUG_VAR(1, "(%s%d) couldn't cleanup after passthru",
                          ips_name, ha->host_num);
  
@@@ -2730,7 -2619,6 +2619,6 @@@ ips_next(ips_ha_t * ha, int intr
        struct scsi_cmnd *q;
        ips_copp_wait_item_t *item;
        int ret;
-       unsigned long cpu_flags = 0;
        struct Scsi_Host *host;
        METHOD_TRACE("ips_next", 1);
  
         * this command won't time out
         */
        if (intr == IPS_INTR_ON)
-               IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+               spin_lock(host->host_lock);
  
        if ((ha->subsys->param[3] & 0x300000)
            && (ha->scb_activelist.count == 0)) {
                item = ips_removeq_copp_head(&ha->copp_waitlist);
                ha->num_ioctl++;
                if (intr == IPS_INTR_ON)
-                       IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+                       spin_unlock(host->host_lock);
                scb->scsi_cmd = item->scsi_cmd;
                kfree(item);
  
                ret = ips_make_passthru(ha, scb->scsi_cmd, scb, intr);
  
                if (intr == IPS_INTR_ON)
-                       IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+                       spin_lock(host->host_lock);
                switch (ret) {
                case IPS_FAILURE:
                        if (scb->scsi_cmd) {
                SC = ips_removeq_wait(&ha->scb_waitlist, q);
  
                if (intr == IPS_INTR_ON)
-                       IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); /* Unlock HA after command is taken off queue */
+                       spin_unlock(host->host_lock);   /* Unlock HA after command is taken off queue */
  
                SC->result = DID_OK;
                SC->host_scribble = NULL;
                /* copy in the CDB */
                memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
  
-               /* Now handle the data buffer */
-               if (SC->use_sg) {
+                 scb->sg_count = scsi_dma_map(SC);
+                 BUG_ON(scb->sg_count < 0);
+               if (scb->sg_count) {
                        struct scatterlist *sg;
                        int i;
  
-                       sg = SC->request_buffer;
-                       scb->sg_count = pci_map_sg(ha->pcidev, sg, SC->use_sg,
-                                                  SC->sc_data_direction);
                        scb->flags |= IPS_SCB_MAP_SG;
-                       for (i = 0; i < scb->sg_count; i++) {
+                         scsi_for_each_sg(SC, sg, scb->sg_count, i) {
                                if (ips_fill_scb_sg_single
-                                   (ha, sg_dma_address(&sg[i]), scb, i,
-                                    sg_dma_len(&sg[i])) < 0)
+                                   (ha, sg_dma_address(sg), scb, i,
+                                    sg_dma_len(sg)) < 0)
                                        break;
                        }
                        scb->dcdb.transfer_length = scb->data_len;
                } else {
-                       if (SC->request_bufflen) {
-                               scb->data_busaddr =
-                                   pci_map_single(ha->pcidev,
-                                                  SC->request_buffer,
-                                                  SC->request_bufflen,
-                                                  SC->sc_data_direction);
-                               scb->flags |= IPS_SCB_MAP_SINGLE;
-                               ips_fill_scb_sg_single(ha, scb->data_busaddr,
-                                                      scb, 0,
-                                                      SC->request_bufflen);
-                               scb->dcdb.transfer_length = scb->data_len;
-                       } else {
-                               scb->data_busaddr = 0L;
-                               scb->sg_len = 0;
-                               scb->data_len = 0;
-                               scb->dcdb.transfer_length = 0;
-                       }
+                         scb->data_busaddr = 0L;
+                         scb->sg_len = 0;
+                         scb->data_len = 0;
+                         scb->dcdb.transfer_length = 0;
                }
  
                scb->dcdb.cmd_attribute =
                        scb->dcdb.transfer_length = 0;
                }
                if (intr == IPS_INTR_ON)
-                       IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+                       spin_lock(host->host_lock);
  
                ret = ips_send_cmd(ha, scb);
  
        }                       /* end while */
  
        if (intr == IPS_INTR_ON)
-               IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
+               spin_unlock(host->host_lock);
  }
  
  /****************************************************************************/
@@@ -3377,52 -3250,32 +3250,32 @@@ ips_done(ips_ha_t * ha, ips_scb_t * scb
                 * the rest of the data and continue.
                 */
                if ((scb->breakup) || (scb->sg_break)) {
+                         struct scatterlist *sg;
+                         int sg_dma_index, ips_sg_index = 0;
                        /* we had a data breakup */
                        scb->data_len = 0;
  
-                       if (scb->sg_count) {
-                               /* S/G request */
-                               struct scatterlist *sg;
-                               int ips_sg_index = 0;
-                               int sg_dma_index;
-                               sg = scb->scsi_cmd->request_buffer;
-                               /* Spin forward to last dma chunk */
-                               sg_dma_index = scb->breakup;
-                               /* Take care of possible partial on last chunk */
-                               ips_fill_scb_sg_single(ha,
-                                                      sg_dma_address(&sg
-                                                                     [sg_dma_index]),
-                                                      scb, ips_sg_index++,
-                                                      sg_dma_len(&sg
-                                                                 [sg_dma_index]));
-                               for (; sg_dma_index < scb->sg_count;
-                                    sg_dma_index++) {
-                                       if (ips_fill_scb_sg_single
-                                           (ha,
-                                            sg_dma_address(&sg[sg_dma_index]),
-                                            scb, ips_sg_index++,
-                                            sg_dma_len(&sg[sg_dma_index])) < 0)
-                                               break;
+                         sg = scsi_sglist(scb->scsi_cmd);
  
-                               }
+                         /* Spin forward to last dma chunk */
+                         sg_dma_index = scb->breakup;
  
-                       } else {
-                               /* Non S/G Request */
-                               (void) ips_fill_scb_sg_single(ha,
-                                                             scb->
-                                                             data_busaddr +
-                                                             (scb->sg_break *
-                                                              ha->max_xfer),
-                                                             scb, 0,
-                                                             scb->scsi_cmd->
-                                                             request_bufflen -
-                                                             (scb->sg_break *
-                                                              ha->max_xfer));
-                       }
+                       /* Take care of possible partial on last chunk */
+                         ips_fill_scb_sg_single(ha,
+                                                sg_dma_address(&sg[sg_dma_index]),
+                                                scb, ips_sg_index++,
+                                                sg_dma_len(&sg[sg_dma_index]));
+                         for (; sg_dma_index < scsi_sg_count(scb->scsi_cmd);
+                              sg_dma_index++) {
+                                 if (ips_fill_scb_sg_single
+                                     (ha,
+                                      sg_dma_address(&sg[sg_dma_index]),
+                                      scb, ips_sg_index++,
+                                      sg_dma_len(&sg[sg_dma_index])) < 0)
+                                         break;
+                         }
  
                        scb->dcdb.transfer_length = scb->data_len;
                        scb->dcdb.cmd_attribute |=
@@@ -3653,32 -3506,27 +3506,27 @@@ ips_send_wait(ips_ha_t * ha, ips_scb_t 
  static void
  ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
  {
-       if (scmd->use_sg) {
-               int i;
-               unsigned int min_cnt, xfer_cnt;
-               char *cdata = (char *) data;
-               unsigned char *buffer;
-               unsigned long flags;
-               struct scatterlist *sg = scmd->request_buffer;
-               for (i = 0, xfer_cnt = 0;
-                    (i < scmd->use_sg) && (xfer_cnt < count); i++) {
-                       min_cnt = min(count - xfer_cnt, sg[i].length);
-                       /* kmap_atomic() ensures addressability of the data buffer.*/
-                       /* local_irq_save() protects the KM_IRQ0 address slot.     */
-                       local_irq_save(flags);
-                       buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
-                       memcpy(buffer, &cdata[xfer_cnt], min_cnt);
-                       kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
-                       local_irq_restore(flags);
-                       xfer_cnt += min_cnt;
-               }
-       } else {
-               unsigned int min_cnt = min(count, scmd->request_bufflen);
-               memcpy(scmd->request_buffer, data, min_cnt);
-       }
+         int i;
+         unsigned int min_cnt, xfer_cnt;
+         char *cdata = (char *) data;
+         unsigned char *buffer;
+         unsigned long flags;
+         struct scatterlist *sg = scsi_sglist(scmd);
+         for (i = 0, xfer_cnt = 0;
+              (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+                 min_cnt = min(count - xfer_cnt, sg[i].length);
+                 /* kmap_atomic() ensures addressability of the data buffer.*/
+                 /* local_irq_save() protects the KM_IRQ0 address slot.     */
+                 local_irq_save(flags);
+                 buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
+                 memcpy(buffer, &cdata[xfer_cnt], min_cnt);
+                 kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+                 local_irq_restore(flags);
+                 xfer_cnt += min_cnt;
+         }
  }
  
  /****************************************************************************/
  static void
  ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
  {
-       if (scmd->use_sg) {
-               int i;
-               unsigned int min_cnt, xfer_cnt;
-               char *cdata = (char *) data;
-               unsigned char *buffer;
-               unsigned long flags;
-               struct scatterlist *sg = scmd->request_buffer;
-               for (i = 0, xfer_cnt = 0;
-                    (i < scmd->use_sg) && (xfer_cnt < count); i++) {
-                       min_cnt = min(count - xfer_cnt, sg[i].length);
-                       /* kmap_atomic() ensures addressability of the data buffer.*/
-                       /* local_irq_save() protects the KM_IRQ0 address slot.     */
-                       local_irq_save(flags);
-                       buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
-                       memcpy(&cdata[xfer_cnt], buffer, min_cnt);
-                       kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
-                       local_irq_restore(flags);
-                       xfer_cnt += min_cnt;
-               }
-       } else {
-               unsigned int min_cnt = min(count, scmd->request_bufflen);
-               memcpy(data, scmd->request_buffer, min_cnt);
-       }
+         int i;
+         unsigned int min_cnt, xfer_cnt;
+         char *cdata = (char *) data;
+         unsigned char *buffer;
+         unsigned long flags;
+         struct scatterlist *sg = scsi_sglist(scmd);
+         for (i = 0, xfer_cnt = 0;
+              (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+                 min_cnt = min(count - xfer_cnt, sg[i].length);
+                 /* kmap_atomic() ensures addressability of the data buffer.*/
+                 /* local_irq_save() protects the KM_IRQ0 address slot.     */
+                 local_irq_save(flags);
+                 buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset;
+                 memcpy(&cdata[xfer_cnt], buffer, min_cnt);
+                 kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+                 local_irq_restore(flags);
+                 xfer_cnt += min_cnt;
+         }
  }
  
  /****************************************************************************/
@@@ -4350,7 -4193,7 +4193,7 @@@ ips_rdcap(ips_ha_t * ha, ips_scb_t * sc
  
        METHOD_TRACE("ips_rdcap", 1);
  
-       if (scb->scsi_cmd->request_bufflen < 8)
+       if (scsi_bufflen(scb->scsi_cmd) < 8)
                return (0);
  
        cap.lba =
@@@ -4735,8 -4578,7 +4578,7 @@@ ips_freescb(ips_ha_t * ha, ips_scb_t * 
  
        METHOD_TRACE("ips_freescb", 1);
        if (scb->flags & IPS_SCB_MAP_SG)
-               pci_unmap_sg(ha->pcidev, scb->scsi_cmd->request_buffer,
-                            scb->scsi_cmd->use_sg, IPS_DMA_DIR(scb));
+                 scsi_dma_unmap(scb->scsi_cmd);
        else if (scb->flags & IPS_SCB_MAP_SINGLE)
                pci_unmap_single(ha->pcidev, scb->data_busaddr, scb->data_len,
                                 IPS_DMA_DIR(scb));
@@@ -7004,7 -6846,6 +6846,6 @@@ ips_register_scsi(int index
        kfree(oldha);
        ips_sh[index] = sh;
        ips_ha[index] = ha;
-       IPS_SCSI_SET_DEVICE(sh, ha);
  
        /* Store away needed values for later use */
        sh->io_port = ha->io_addr;
        sh->cmd_per_lun = sh->hostt->cmd_per_lun;
        sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
        sh->use_clustering = sh->hostt->use_clustering;
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
        sh->max_sectors = 128;
- #endif
  
        sh->max_id = ha->ntargets;
        sh->max_lun = ha->nlun;
        sh->max_channel = ha->nbus - 1;
        sh->can_queue = ha->max_cmds - 1;
  
-       IPS_ADD_HOST(sh, NULL);
+       scsi_add_host(sh, NULL);
+       scsi_scan_host(sh);
        return 0;
  }
  
@@@ -7069,7 -6909,7 +6909,7 @@@ ips_module_init(void
                return -ENODEV;
        ips_driver_template.module = THIS_MODULE;
        ips_order_controllers();
-       if (IPS_REGISTER_HOSTS(&ips_driver_template)) {
+       if (!ips_detect(&ips_driver_template)) {
                pci_unregister_driver(&ips_pci_driver);
                return -ENODEV;
        }
  static void __exit
  ips_module_exit(void)
  {
-       IPS_UNREGISTER_HOSTS(&ips_driver_template);
        pci_unregister_driver(&ips_pci_driver);
        unregister_reboot_notifier(&ips_notifier);
  }
@@@ -7148,6 -6987,7 +6987,6 @@@ ips_init_phase1(struct pci_dev *pci_dev
        uint32_t mem_addr;
        uint32_t io_len;
        uint32_t mem_len;
 -      uint8_t revision_id;
        uint8_t bus;
        uint8_t func;
        uint8_t irq;
                }
        }
  
 -      /* get the revision ID */
 -      if (pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id)) {
 -              IPS_PRINTK(KERN_WARNING, pci_dev, "Can't get revision id.\n");
 -              return -1;
 -      }
 -
        subdevice_id = pci_dev->subsystem_device;
  
        /* found a controller */
        ha->mem_ptr = mem_ptr;
        ha->ioremap_ptr = ioremap_ptr;
        ha->host_num = (uint32_t) index;
 -      ha->revision_id = revision_id;
 +      ha->revision_id = pci_dev->revision;
        ha->slot_num = PCI_SLOT(pci_dev->devfn);
        ha->device_id = pci_dev->device;
        ha->subdevice_id = subdevice_id;
@@@ -7436,15 -7282,9 +7275,9 @@@ ips_init_phase2(int index
        return SUCCESS;
  }
  
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
  MODULE_LICENSE("GPL");
- #endif
  MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
- #ifdef MODULE_VERSION
  MODULE_VERSION(IPS_VER_STRING);
- #endif
  
  
  /*
index 5dfda9778c80b009b03ca242d23c0d9614099631,6a2c1ac42442c69b69c68192da5b84fc8887d075..860a52c090f408fb4bbdccad73675a72bc78a361
@@@ -39,6 -39,7 +39,7 @@@
  #include "lpfc_version.h"
  #include "lpfc_compat.h"
  #include "lpfc_crtn.h"
+ #include "lpfc_vport.h"
  
  #define LPFC_DEF_DEVLOSS_TMO 30
  #define LPFC_MIN_DEVLOSS_TMO 1
@@@ -76,116 -77,156 +77,156 @@@ static ssize_
  lpfc_info_show(struct class_device *cdev, char *buf)
  {
        struct Scsi_Host *host = class_to_shost(cdev);
        return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
  }
  
  static ssize_t
  lpfc_serialnum_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
  }
  
  static ssize_t
  lpfc_modeldesc_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
  }
  
  static ssize_t
  lpfc_modelname_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
  }
  
  static ssize_t
  lpfc_programtype_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
  }
  
  static ssize_t
- lpfc_portnum_show(struct class_device *cdev, char *buf)
+ lpfc_vportnum_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
  }
  
  static ssize_t
  lpfc_fwrev_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        char fwrev[32];
        lpfc_decode_firmware_rev(phba, fwrev, 1);
-       return snprintf(buf, PAGE_SIZE, "%s\n",fwrev);
+       return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev);
  }
  
  static ssize_t
  lpfc_hdw_show(struct class_device *cdev, char *buf)
  {
        char hdw[9];
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        lpfc_vpd_t *vp = &phba->vpd;
        lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
        return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
  }
  static ssize_t
  lpfc_option_rom_version_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
  }
  static ssize_t
  lpfc_state_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-       int len = 0;
-       switch (phba->hba_state) {
-       case LPFC_STATE_UNKNOWN:
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       int  len = 0;
+       switch (phba->link_state) {
+       case LPFC_LINK_UNKNOWN:
        case LPFC_WARM_START:
        case LPFC_INIT_START:
        case LPFC_INIT_MBX_CMDS:
        case LPFC_LINK_DOWN:
+       case LPFC_HBA_ERROR:
                len += snprintf(buf + len, PAGE_SIZE-len, "Link Down\n");
                break;
        case LPFC_LINK_UP:
-       case LPFC_LOCAL_CFG_LINK:
-               len += snprintf(buf + len, PAGE_SIZE-len, "Link Up\n");
-               break;
-       case LPFC_FLOGI:
-       case LPFC_FABRIC_CFG_LINK:
-       case LPFC_NS_REG:
-       case LPFC_NS_QRY:
-       case LPFC_BUILD_DISC_LIST:
-       case LPFC_DISC_AUTH:
        case LPFC_CLEAR_LA:
-               len += snprintf(buf + len, PAGE_SIZE-len,
-                               "Link Up - Discovery\n");
-               break;
        case LPFC_HBA_READY:
-               len += snprintf(buf + len, PAGE_SIZE-len,
-                               "Link Up - Ready:\n");
+               len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - \n");
+               switch (vport->port_state) {
+                       len += snprintf(buf + len, PAGE_SIZE-len,
+                                       "initializing\n");
+                       break;
+               case LPFC_LOCAL_CFG_LINK:
+                       len += snprintf(buf + len, PAGE_SIZE-len,
+                                       "Configuring Link\n");
+                       break;
+               case LPFC_FDISC:
+               case LPFC_FLOGI:
+               case LPFC_FABRIC_CFG_LINK:
+               case LPFC_NS_REG:
+               case LPFC_NS_QRY:
+               case LPFC_BUILD_DISC_LIST:
+               case LPFC_DISC_AUTH:
+                       len += snprintf(buf + len, PAGE_SIZE - len,
+                                       "Discovery\n");
+                       break;
+               case LPFC_VPORT_READY:
+                       len += snprintf(buf + len, PAGE_SIZE - len, "Ready\n");
+                       break;
+               case LPFC_VPORT_FAILED:
+                       len += snprintf(buf + len, PAGE_SIZE - len, "Failed\n");
+                       break;
+               case LPFC_VPORT_UNKNOWN:
+                       len += snprintf(buf + len, PAGE_SIZE - len,
+                                       "Unknown\n");
+                       break;
+               }
                if (phba->fc_topology == TOPOLOGY_LOOP) {
-                       if (phba->fc_flag & FC_PUBLIC_LOOP)
+                       if (vport->fc_flag & FC_PUBLIC_LOOP)
                                len += snprintf(buf + len, PAGE_SIZE-len,
                                                "   Public Loop\n");
                        else
                                len += snprintf(buf + len, PAGE_SIZE-len,
                                                "   Private Loop\n");
                } else {
-                       if (phba->fc_flag & FC_FABRIC)
+                       if (vport->fc_flag & FC_FABRIC)
                                len += snprintf(buf + len, PAGE_SIZE-len,
                                                "   Fabric\n");
                        else
                                                "   Point-2-Point\n");
                }
        }
        return len;
  }
  
  static ssize_t
  lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
-       return snprintf(buf, PAGE_SIZE, "%d\n", phba->fc_map_cnt +
-                                                       phba->fc_unmap_cnt);
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       vport->fc_map_cnt + vport->fc_unmap_cnt);
  }
  
  
  static int
- lpfc_issue_lip(struct Scsi_Host *host)
+ lpfc_issue_lip(struct Scsi_Host *shost)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba *) host->hostdata;
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        LPFC_MBOXQ_t *pmboxq;
        int mbxstatus = MBXERR_ERROR;
  
-       if ((phba->fc_flag & FC_OFFLINE_MODE) ||
-           (phba->fc_flag & FC_BLOCK_MGMT_IO) ||
-           (phba->hba_state != LPFC_HBA_READY))
+       if ((vport->fc_flag & FC_OFFLINE_MODE) ||
+           (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) ||
+           (vport->port_state != LPFC_VPORT_READY))
                return -EPERM;
  
        pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
        }
  
        lpfc_set_loopback_flag(phba);
-       if (mbxstatus == MBX_TIMEOUT)
-               pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-       else
+       if (mbxstatus != MBX_TIMEOUT)
                mempool_free(pmboxq, phba->mbox_mem_pool);
  
        if (mbxstatus == MBXERR_ERROR)
@@@ -320,8 -362,10 +362,10 @@@ lpfc_selective_reset(struct lpfc_hba *p
  static ssize_t
  lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        int status = -EINVAL;
  
        if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
  static ssize_t
  lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
  }
  
  static ssize_t
  lpfc_board_mode_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        char  * state;
  
-       if (phba->hba_state == LPFC_HBA_ERROR)
+       if (phba->link_state == LPFC_HBA_ERROR)
                state = "error";
-       else if (phba->hba_state == LPFC_WARM_START)
+       else if (phba->link_state == LPFC_WARM_START)
                state = "warm start";
-       else if (phba->hba_state == LPFC_INIT_START)
+       else if (phba->link_state == LPFC_INIT_START)
                state = "offline";
        else
                state = "online";
  static ssize_t
  lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        struct completion online_compl;
        int status=0;
  
                return -EIO;
  }
  
+ int
+ lpfc_get_hba_info(struct lpfc_hba *phba,
+                 uint32_t *mxri, uint32_t *axri,
+                 uint32_t *mrpi, uint32_t *arpi,
+                 uint32_t *mvpi, uint32_t *avpi)
+ {
+       struct lpfc_sli   *psli = &phba->sli;
+       LPFC_MBOXQ_t *pmboxq;
+       MAILBOX_t *pmb;
+       int rc = 0;
+       /*
+        * prevent udev from issuing mailbox commands until the port is
+        * configured.
+        */
+       if (phba->link_state < LPFC_LINK_DOWN ||
+           !phba->mbox_mem_pool ||
+           (phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
+               return 0;
+       if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
+               return 0;
+       pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!pmboxq)
+               return 0;
+       memset(pmboxq, 0, sizeof (LPFC_MBOXQ_t));
+       pmb = &pmboxq->mb;
+       pmb->mbxCommand = MBX_READ_CONFIG;
+       pmb->mbxOwner = OWN_HOST;
+       pmboxq->context1 = NULL;
+       if ((phba->pport->fc_flag & FC_OFFLINE_MODE) ||
+               (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
+               rc = MBX_NOT_FINISHED;
+       else
+               rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+       if (rc != MBX_SUCCESS) {
+               if (rc != MBX_TIMEOUT)
+                       mempool_free(pmboxq, phba->mbox_mem_pool);
+               return 0;
+       }
+       if (mrpi)
+               *mrpi = pmb->un.varRdConfig.max_rpi;
+       if (arpi)
+               *arpi = pmb->un.varRdConfig.avail_rpi;
+       if (mxri)
+               *mxri = pmb->un.varRdConfig.max_xri;
+       if (axri)
+               *axri = pmb->un.varRdConfig.avail_xri;
+       if (mvpi)
+               *mvpi = pmb->un.varRdConfig.max_vpi;
+       if (avpi)
+               *avpi = pmb->un.varRdConfig.avail_vpi;
+       mempool_free(pmboxq, phba->mbox_mem_pool);
+       return 1;
+ }
+ static ssize_t
+ lpfc_max_rpi_show(struct class_device *cdev, char *buf)
+ {
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       uint32_t cnt;
+       if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL))
+               return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
+       return snprintf(buf, PAGE_SIZE, "Unknown\n");
+ }
+ static ssize_t
+ lpfc_used_rpi_show(struct class_device *cdev, char *buf)
+ {
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       uint32_t cnt, acnt;
+       if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL))
+               return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
+       return snprintf(buf, PAGE_SIZE, "Unknown\n");
+ }
+ static ssize_t
+ lpfc_max_xri_show(struct class_device *cdev, char *buf)
+ {
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       uint32_t cnt;
+       if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL))
+               return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
+       return snprintf(buf, PAGE_SIZE, "Unknown\n");
+ }
+ static ssize_t
+ lpfc_used_xri_show(struct class_device *cdev, char *buf)
+ {
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       uint32_t cnt, acnt;
+       if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL))
+               return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
+       return snprintf(buf, PAGE_SIZE, "Unknown\n");
+ }
+ static ssize_t
+ lpfc_max_vpi_show(struct class_device *cdev, char *buf)
+ {
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       uint32_t cnt;
+       if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL))
+               return snprintf(buf, PAGE_SIZE, "%d\n", cnt);
+       return snprintf(buf, PAGE_SIZE, "Unknown\n");
+ }
+ static ssize_t
+ lpfc_used_vpi_show(struct class_device *cdev, char *buf)
+ {
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       uint32_t cnt, acnt;
+       if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt))
+               return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt));
+       return snprintf(buf, PAGE_SIZE, "Unknown\n");
+ }
+ static ssize_t
+ lpfc_npiv_info_show(struct class_device *cdev, char *buf)
+ {
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       if (!(phba->max_vpi))
+               return snprintf(buf, PAGE_SIZE, "NPIV Not Supported\n");
+       if (vport->port_type == LPFC_PHYSICAL_PORT)
+               return snprintf(buf, PAGE_SIZE, "NPIV Physical\n");
+       return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
+ }
  static ssize_t
  lpfc_poll_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
  
        return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
  }
@@@ -402,8 -605,9 +605,9 @@@ static ssize_
  lpfc_poll_store(struct class_device *cdev, const char *buf,
                size_t count)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        uint32_t creg_val;
        uint32_t old_val;
        int val=0;
        if ((val & 0x3) != val)
                return -EINVAL;
  
-       spin_lock_irq(phba->host->host_lock);
+       spin_lock_irq(&phba->hbalock);
  
        old_val = phba->cfg_poll;
  
                        lpfc_poll_start_timer(phba);
                }
        } else if (val != 0x0) {
-               spin_unlock_irq(phba->host->host_lock);
+               spin_unlock_irq(&phba->hbalock);
                return -EINVAL;
        }
  
        if (!(val & DISABLE_FCP_RING_INT) &&
            (old_val & DISABLE_FCP_RING_INT))
        {
-               spin_unlock_irq(phba->host->host_lock);
+               spin_unlock_irq(&phba->hbalock);
                del_timer(&phba->fcp_poll_timer);
-               spin_lock_irq(phba->host->host_lock);
+               spin_lock_irq(&phba->hbalock);
                creg_val = readl(phba->HCregaddr);
                creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
                writel(creg_val, phba->HCregaddr);
  
        phba->cfg_poll = val;
  
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
  
        return strlen(buf);
  }
  static ssize_t \
  lpfc_##attr##_show(struct class_device *cdev, char *buf) \
  { \
-       struct Scsi_Host *host = class_to_shost(cdev);\
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
+       struct Scsi_Host  *shost = class_to_shost(cdev);\
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+       struct lpfc_hba   *phba = vport->phba;\
        int val = 0;\
        val = phba->cfg_##attr;\
        return snprintf(buf, PAGE_SIZE, "%d\n",\
  static ssize_t \
  lpfc_##attr##_show(struct class_device *cdev, char *buf) \
  { \
-       struct Scsi_Host *host = class_to_shost(cdev);\
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
+       struct Scsi_Host  *shost = class_to_shost(cdev);\
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+       struct lpfc_hba   *phba = vport->phba;\
        int val = 0;\
        val = phba->cfg_##attr;\
        return snprintf(buf, PAGE_SIZE, "%#x\n",\
@@@ -514,8 -720,9 +720,9 @@@ lpfc_##attr##_set(struct lpfc_hba *phba
  static ssize_t \
  lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
  { \
-       struct Scsi_Host *host = class_to_shost(cdev);\
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;\
+       struct Scsi_Host  *shost = class_to_shost(cdev);\
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+       struct lpfc_hba   *phba = vport->phba;\
        int val=0;\
        if (!isdigit(buf[0]))\
                return -EINVAL;\
@@@ -576,7 -783,7 +783,7 @@@ static CLASS_DEVICE_ATTR(serialnum, S_I
  static CLASS_DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
  static CLASS_DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
  static CLASS_DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
- static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_portnum_show, NULL);
+ static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
  static CLASS_DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
  static CLASS_DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
  static CLASS_DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
@@@ -592,6 -799,13 +799,13 @@@ static CLASS_DEVICE_ATTR(management_ver
  static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
                         lpfc_board_mode_show, lpfc_board_mode_store);
  static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
+ static CLASS_DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
+ static CLASS_DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
+ static CLASS_DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
+ static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
+ static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
+ static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
+ static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
  
  
  static char *lpfc_soft_wwn_key = "C99G71SL8032A";
@@@ -600,8 -814,9 +814,9 @@@ static ssize_
  lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
                                size_t count)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        unsigned int cnt = count;
  
        /*
@@@ -634,8 -849,10 +849,10 @@@ static CLASS_DEVICE_ATTR(lpfc_soft_wwn_
  static ssize_t
  lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        return snprintf(buf, PAGE_SIZE, "0x%llx\n",
                        (unsigned long long)phba->cfg_soft_wwpn);
  }
  static ssize_t
  lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        struct completion online_compl;
        int stat1=0, stat2=0;
        unsigned int i, j, cnt=count;
                }
        }
        phba->cfg_soft_wwpn = wwn_to_u64(wwpn);
-       fc_host_port_name(host) = phba->cfg_soft_wwpn;
+       fc_host_port_name(shost) = phba->cfg_soft_wwpn;
        if (phba->cfg_soft_wwnn)
-               fc_host_node_name(host) = phba->cfg_soft_wwnn;
+               fc_host_node_name(shost) = phba->cfg_soft_wwnn;
  
        dev_printk(KERN_NOTICE, &phba->pcidev->dev,
                   "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
@@@ -777,6 -995,15 +995,15 @@@ MODULE_PARM_DESC(lpfc_poll, "FCP ring p
  static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
                         lpfc_poll_show, lpfc_poll_store);
  
+ int  lpfc_sli_mode = 0;
+ module_param(lpfc_sli_mode, int, 0);
+ MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"
+                " 0 - auto (SLI-3 if supported),"
+                " 2 - select SLI-2 even on SLI-3 capable HBAs,"
+                " 3 - select SLI-3");
+ LPFC_ATTR_R(npiv_enable, 0, 0, 1, "Enable NPIV functionality");
  /*
  # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
  # until the timer expires. Value range is [0,255]. Default value is 30.
@@@ -790,8 -1017,9 +1017,9 @@@ MODULE_PARM_DESC(lpfc_nodev_tmo
  static ssize_t
  lpfc_nodev_tmo_show(struct class_device *cdev, char *buf)
  {
-       struct Scsi_Host *host = class_to_shost(cdev);
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        int val = 0;
        val = phba->cfg_devloss_tmo;
        return snprintf(buf, PAGE_SIZE, "%d\n",
@@@ -832,13 -1060,19 +1060,19 @@@ lpfc_nodev_tmo_init(struct lpfc_hba *ph
  static void
  lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba)
  {
+       struct lpfc_vport *vport;
+       struct Scsi_Host  *shost;
        struct lpfc_nodelist  *ndlp;
  
-       spin_lock_irq(phba->host->host_lock);
-       list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp)
-               if (ndlp->rport)
-                       ndlp->rport->dev_loss_tmo = phba->cfg_devloss_tmo;
-       spin_unlock_irq(phba->host->host_lock);
+       list_for_each_entry(vport, &phba->port_list, listentry) {
+               shost = lpfc_shost_from_vport(vport);
+               spin_lock_irq(shost->host_lock);
+               list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
+                       if (ndlp->rport)
+                               ndlp->rport->dev_loss_tmo =
+                                       phba->cfg_devloss_tmo;
+               spin_unlock_irq(shost->host_lock);
+       }
  }
  
  static int
@@@ -945,6 -1179,33 +1179,33 @@@ LPFC_ATTR_R(lun_queue_depth, 30, 1, 128
  LPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192,
            "Max number of FCP commands we can queue to a lpfc HBA");
  
+ /*
+ # peer_port_login:  This parameter allows/prevents logins
+ # between peer ports hosted on the same physical port.
+ # When this parameter is set 0 peer ports of same physical port
+ # are not allowed to login to each other.
+ # When this parameter is set 1 peer ports of same physical port
+ # are allowed to login to each other.
+ # Default value of this parameter is 0.
+ */
+ LPFC_ATTR_R(peer_port_login, 0, 0, 1,
+           "Allow peer ports on the same physical port to login to each "
+           "other.");
+ /*
+ # vport_restrict_login:  This parameter allows/prevents logins
+ # between Virtual Ports and remote initiators.
+ # When this parameter is not set (0) Virtual Ports will accept PLOGIs from
+ # other initiators and will attempt to PLOGI all remote ports.
+ # When this parameter is set (1) Virtual Ports will reject PLOGIs from
+ # remote ports and will not attempt to PLOGI to other initiators.
+ # This parameter does not restrict to the physical port.
+ # This parameter does not restrict logins to Fabric resident remote ports.
+ # Default value of this parameter is 1.
+ */
+ LPFC_ATTR_RW(vport_restrict_login, 1, 0, 1,
+           "Restrict virtual ports login to remote initiators.");
  /*
  # Some disk devices have a "select ID" or "select Target" capability.
  # From a protocol standpoint "select ID" usually means select the
@@@ -1088,7 -1349,8 +1349,8 @@@ LPFC_ATTR_RW(poll_tmo, 10, 1, 255
  LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible");
  
  
- struct class_device_attribute *lpfc_host_attrs[] = {
+ struct class_device_attribute *lpfc_hba_attrs[] = {
        &class_device_attr_info,
        &class_device_attr_serialnum,
        &class_device_attr_modeldesc,
        &class_device_attr_lpfc_log_verbose,
        &class_device_attr_lpfc_lun_queue_depth,
        &class_device_attr_lpfc_hba_queue_depth,
+       &class_device_attr_lpfc_peer_port_login,
+       &class_device_attr_lpfc_vport_restrict_login,
        &class_device_attr_lpfc_nodev_tmo,
        &class_device_attr_lpfc_devloss_tmo,
        &class_device_attr_lpfc_fcp_class,
        &class_device_attr_lpfc_multi_ring_type,
        &class_device_attr_lpfc_fdmi_on,
        &class_device_attr_lpfc_max_luns,
+       &class_device_attr_lpfc_npiv_enable,
        &class_device_attr_nport_evt_cnt,
        &class_device_attr_management_version,
        &class_device_attr_board_mode,
+       &class_device_attr_max_vpi,
+       &class_device_attr_used_vpi,
+       &class_device_attr_max_rpi,
+       &class_device_attr_used_rpi,
+       &class_device_attr_max_xri,
+       &class_device_attr_used_xri,
+       &class_device_attr_npiv_info,
        &class_device_attr_issue_reset,
        &class_device_attr_lpfc_poll,
        &class_device_attr_lpfc_poll_tmo,
  };
  
  static ssize_t
 -sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
 +sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
 +                 char *buf, loff_t off, size_t count)
  {
        size_t buf_off;
-       struct Scsi_Host *host = class_to_shost(container_of(kobj,
-                                            struct class_device, kobj));
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct class_device *cdev = container_of(kobj, struct class_device,
+                                                kobj);
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
  
        if ((off + count) > FF_REG_AREA_SIZE)
                return -ERANGE;
        if (off % 4 || count % 4 || (unsigned long)buf % 4)
                return -EINVAL;
  
-       spin_lock_irq(phba->host->host_lock);
-       if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
-               spin_unlock_irq(phba->host->host_lock);
+       if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
                return -EPERM;
        }
  
+       spin_lock_irq(&phba->hbalock);
        for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t))
                writel(*((uint32_t *)(buf + buf_off)),
                       phba->ctrl_regs_memmap_p + off + buf_off);
  
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
  
        return count;
  }
  
  static ssize_t
 -sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
 +sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
 +                char *buf, loff_t off, size_t count)
  {
        size_t buf_off;
        uint32_t * tmp_ptr;
-       struct Scsi_Host *host = class_to_shost(container_of(kobj,
-                                            struct class_device, kobj));
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct class_device *cdev = container_of(kobj, struct class_device,
+                                                kobj);
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
  
        if (off > FF_REG_AREA_SIZE)
                return -ERANGE;
        if (off % 4 || count % 4 || (unsigned long)buf % 4)
                return -EINVAL;
  
-       spin_lock_irq(phba->host->host_lock);
+       spin_lock_irq(&phba->hbalock);
  
        for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) {
                tmp_ptr = (uint32_t *)(buf + buf_off);
                *tmp_ptr = readl(phba->ctrl_regs_memmap_p + off + buf_off);
        }
  
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
  
        return count;
  }
@@@ -1202,6 -1474,7 +1476,6 @@@ static struct bin_attribute sysfs_ctlre
        .attr = {
                .name = "ctlreg",
                .mode = S_IRUSR | S_IWUSR,
 -              .owner = THIS_MODULE,
        },
        .size = 256,
        .read = sysfs_ctlreg_read,
  
  
  static void
- sysfs_mbox_idle (struct lpfc_hba * phba)
+ sysfs_mbox_idle(struct lpfc_hba *phba)
  {
        phba->sysfs_mbox.state = SMBOX_IDLE;
        phba->sysfs_mbox.offset = 0;
  }
  
  static ssize_t
 -sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
 +sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
 +               char *buf, loff_t off, size_t count)
  {
-       struct Scsi_Host * host =
-               class_to_shost(container_of(kobj, struct class_device, kobj));
-       struct lpfc_hba * phba = (struct lpfc_hba*)host->hostdata;
-       struct lpfcMboxq * mbox = NULL;
+       struct class_device *cdev = container_of(kobj, struct class_device,
+                                                kobj);
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       struct lpfcMboxq  *mbox = NULL;
  
        if ((count + off) > MAILBOX_CMD_SIZE)
                return -ERANGE;
                memset(mbox, 0, sizeof (LPFC_MBOXQ_t));
        }
  
-       spin_lock_irq(host->host_lock);
+       spin_lock_irq(&phba->hbalock);
  
        if (off == 0) {
                if (phba->sysfs_mbox.mbox)
        } else {
                if (phba->sysfs_mbox.state  != SMBOX_WRITING ||
                    phba->sysfs_mbox.offset != off           ||
-                   phba->sysfs_mbox.mbox   == NULL ) {
+                   phba->sysfs_mbox.mbox   == NULL) {
                        sysfs_mbox_idle(phba);
-                       spin_unlock_irq(host->host_lock);
+                       spin_unlock_irq(&phba->hbalock);
                        return -EAGAIN;
                }
        }
  
        phba->sysfs_mbox.offset = off + count;
  
-       spin_unlock_irq(host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
  
        return count;
  }
  
  static ssize_t
 -sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
 +sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
 +              char *buf, loff_t off, size_t count)
  {
-       struct Scsi_Host *host =
-               class_to_shost(container_of(kobj, struct class_device,
-                                           kobj));
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct class_device *cdev = container_of(kobj, struct class_device,
+                                                kobj);
+       struct Scsi_Host  *shost = class_to_shost(cdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        int rc;
  
        if (off > MAILBOX_CMD_SIZE)
        if (off && count == 0)
                return 0;
  
-       spin_lock_irq(phba->host->host_lock);
+       spin_lock_irq(&phba->hbalock);
  
        if (off == 0 &&
            phba->sysfs_mbox.state  == SMBOX_WRITING &&
                case MBX_SET_MASK:
                case MBX_SET_SLIM:
                case MBX_SET_DEBUG:
-                       if (!(phba->fc_flag & FC_OFFLINE_MODE)) {
+                       if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
                                printk(KERN_WARNING "mbox_read:Command 0x%x "
                                       "is illegal in on-line state\n",
                                       phba->sysfs_mbox.mbox->mb.mbxCommand);
                                sysfs_mbox_idle(phba);
-                               spin_unlock_irq(phba->host->host_lock);
+                               spin_unlock_irq(&phba->hbalock);
                                return -EPERM;
                        }
                case MBX_LOAD_SM:
                        printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n",
                               phba->sysfs_mbox.mbox->mb.mbxCommand);
                        sysfs_mbox_idle(phba);
-                       spin_unlock_irq(phba->host->host_lock);
+                       spin_unlock_irq(&phba->hbalock);
                        return -EPERM;
                default:
                        printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n",
                               phba->sysfs_mbox.mbox->mb.mbxCommand);
                        sysfs_mbox_idle(phba);
-                       spin_unlock_irq(phba->host->host_lock);
+                       spin_unlock_irq(&phba->hbalock);
                        return -EPERM;
                }
  
-               if (phba->fc_flag & FC_BLOCK_MGMT_IO) {
+               phba->sysfs_mbox.mbox->vport = vport;
+               if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
                        sysfs_mbox_idle(phba);
-                       spin_unlock_irq(host->host_lock);
+                       spin_unlock_irq(&phba->hbalock);
                        return  -EAGAIN;
                }
  
-               if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+               if ((vport->fc_flag & FC_OFFLINE_MODE) ||
                    (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
  
-                       spin_unlock_irq(phba->host->host_lock);
+                       spin_unlock_irq(&phba->hbalock);
                        rc = lpfc_sli_issue_mbox (phba,
                                                  phba->sysfs_mbox.mbox,
                                                  MBX_POLL);
-                       spin_lock_irq(phba->host->host_lock);
+                       spin_lock_irq(&phba->hbalock);
  
                } else {
-                       spin_unlock_irq(phba->host->host_lock);
+                       spin_unlock_irq(&phba->hbalock);
                        rc = lpfc_sli_issue_mbox_wait (phba,
                                                       phba->sysfs_mbox.mbox,
                                lpfc_mbox_tmo_val(phba,
                                    phba->sysfs_mbox.mbox->mb.mbxCommand) * HZ);
-                       spin_lock_irq(phba->host->host_lock);
+                       spin_lock_irq(&phba->hbalock);
                }
  
                if (rc != MBX_SUCCESS) {
                        if (rc == MBX_TIMEOUT) {
-                               phba->sysfs_mbox.mbox->mbox_cmpl =
-                                       lpfc_sli_def_mbox_cmpl;
                                phba->sysfs_mbox.mbox = NULL;
                        }
                        sysfs_mbox_idle(phba);
-                       spin_unlock_irq(host->host_lock);
+                       spin_unlock_irq(&phba->hbalock);
                        return  (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
                }
                phba->sysfs_mbox.state = SMBOX_READING;
                 phba->sysfs_mbox.state  != SMBOX_READING) {
                printk(KERN_WARNING  "mbox_read: Bad State\n");
                sysfs_mbox_idle(phba);
-               spin_unlock_irq(host->host_lock);
+               spin_unlock_irq(&phba->hbalock);
                return -EAGAIN;
        }
  
        if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
                sysfs_mbox_idle(phba);
  
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
  
        return count;
  }
@@@ -1425,6 -1699,7 +1702,6 @@@ static struct bin_attribute sysfs_mbox_
        .attr = {
                .name = "mbox",
                .mode = S_IRUSR | S_IWUSR,
 -              .owner = THIS_MODULE,
        },
        .size = MAILBOX_CMD_SIZE,
        .read = sysfs_mbox_read,
  };
  
  int
- lpfc_alloc_sysfs_attr(struct lpfc_hba *phba)
+ lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
  {
-       struct Scsi_Host *host = phba->host;
+       struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
        int error;
  
-       error = sysfs_create_bin_file(&host->shost_classdev.kobj,
-                                                       &sysfs_ctlreg_attr);
+       error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
+                                     &sysfs_ctlreg_attr);
        if (error)
                goto out;
  
-       error = sysfs_create_bin_file(&host->shost_classdev.kobj,
-                                                       &sysfs_mbox_attr);
+       error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
+                                     &sysfs_mbox_attr);
        if (error)
                goto out_remove_ctlreg_attr;
  
        return 0;
  out_remove_ctlreg_attr:
-       sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
+       sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
  out:
        return error;
  }
  
  void
- lpfc_free_sysfs_attr(struct lpfc_hba *phba)
+ lpfc_free_sysfs_attr(struct lpfc_vport *vport)
  {
-       struct Scsi_Host *host = phba->host;
+       struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
  
-       sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_mbox_attr);
-       sysfs_remove_bin_file(&host->shost_classdev.kobj, &sysfs_ctlreg_attr);
+       sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_mbox_attr);
+       sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
  }
  
  
  static void
  lpfc_get_host_port_id(struct Scsi_Host *shost)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
        /* note: fc_myDID already in cpu endianness */
-       fc_host_port_id(shost) = phba->fc_myDID;
+       fc_host_port_id(shost) = vport->fc_myDID;
  }
  
  static void
  lpfc_get_host_port_type(struct Scsi_Host *shost)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
  
        spin_lock_irq(shost->host_lock);
  
-       if (phba->hba_state == LPFC_HBA_READY) {
+       if (vport->port_type == LPFC_NPIV_PORT) {
+               fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
+       } else if (lpfc_is_link_up(phba)) {
                if (phba->fc_topology == TOPOLOGY_LOOP) {
-                       if (phba->fc_flag & FC_PUBLIC_LOOP)
+                       if (vport->fc_flag & FC_PUBLIC_LOOP)
                                fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
                        else
                                fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
                } else {
-                       if (phba->fc_flag & FC_FABRIC)
+                       if (vport->fc_flag & FC_FABRIC)
                                fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
                        else
                                fc_host_port_type(shost) = FC_PORTTYPE_PTP;
  static void
  lpfc_get_host_port_state(struct Scsi_Host *shost)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
  
        spin_lock_irq(shost->host_lock);
  
-       if (phba->fc_flag & FC_OFFLINE_MODE)
+       if (vport->fc_flag & FC_OFFLINE_MODE)
                fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
        else {
-               switch (phba->hba_state) {
-               case LPFC_STATE_UNKNOWN:
-               case LPFC_WARM_START:
-               case LPFC_INIT_START:
-               case LPFC_INIT_MBX_CMDS:
+               switch (phba->link_state) {
+               case LPFC_LINK_UNKNOWN:
                case LPFC_LINK_DOWN:
                        fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
                        break;
                case LPFC_LINK_UP:
-               case LPFC_LOCAL_CFG_LINK:
-               case LPFC_FLOGI:
-               case LPFC_FABRIC_CFG_LINK:
-               case LPFC_NS_REG:
-               case LPFC_NS_QRY:
-               case LPFC_BUILD_DISC_LIST:
-               case LPFC_DISC_AUTH:
                case LPFC_CLEAR_LA:
                case LPFC_HBA_READY:
                        /* Links up, beyond this port_type reports state */
  static void
  lpfc_get_host_speed(struct Scsi_Host *shost)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
  
        spin_lock_irq(shost->host_lock);
  
-       if (phba->hba_state == LPFC_HBA_READY) {
+       if (lpfc_is_link_up(phba)) {
                switch(phba->fc_linkspeed) {
                        case LA_1GHZ_LINK:
                                fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
  static void
  lpfc_get_host_fabric_name (struct Scsi_Host *shost)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        u64 node_name;
  
        spin_lock_irq(shost->host_lock);
  
-       if ((phba->fc_flag & FC_FABRIC) ||
+       if ((vport->fc_flag & FC_FABRIC) ||
            ((phba->fc_topology == TOPOLOGY_LOOP) &&
-            (phba->fc_flag & FC_PUBLIC_LOOP)))
+            (vport->fc_flag & FC_PUBLIC_LOOP)))
                node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
        else
                /* fabric is local port if there is no F/FL_Port */
-               node_name = wwn_to_u64(phba->fc_nodename.u.wwn);
+               node_name = wwn_to_u64(vport->fc_nodename.u.wwn);
  
        spin_unlock_irq(shost->host_lock);
  
        fc_host_fabric_name(shost) = node_name;
  }
  
- static void
- lpfc_get_host_symbolic_name (struct Scsi_Host *shost)
- {
-       struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata;
-       spin_lock_irq(shost->host_lock);
-       lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
-       spin_unlock_irq(shost->host_lock);
- }
  static struct fc_host_statistics *
  lpfc_get_stats(struct Scsi_Host *shost)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       struct lpfc_sli   *psli = &phba->sli;
        struct fc_host_statistics *hs = &phba->link_stats;
        struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
        LPFC_MBOXQ_t *pmboxq;
        unsigned long seconds;
        int rc = 0;
  
-       if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+       /*
+        * prevent udev from issuing mailbox commands until the port is
+        * configured.
+        */
+       if (phba->link_state < LPFC_LINK_DOWN ||
+           !phba->mbox_mem_pool ||
+           (phba->sli.sli_flag & LPFC_SLI2_ACTIVE) == 0)
+               return NULL;
+       if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
                return NULL;
  
        pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        pmb->mbxCommand = MBX_READ_STATUS;
        pmb->mbxOwner = OWN_HOST;
        pmboxq->context1 = NULL;
+       pmboxq->vport = vport;
  
-       if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+       if ((vport->fc_flag & FC_OFFLINE_MODE) ||
                (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
                rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
        else
                rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
  
        if (rc != MBX_SUCCESS) {
-               if (rc == MBX_TIMEOUT)
-                       pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               else
+               if (rc != MBX_TIMEOUT)
                        mempool_free(pmboxq, phba->mbox_mem_pool);
                return NULL;
        }
        pmb->mbxCommand = MBX_READ_LNK_STAT;
        pmb->mbxOwner = OWN_HOST;
        pmboxq->context1 = NULL;
+       pmboxq->vport = vport;
  
-       if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+       if ((vport->fc_flag & FC_OFFLINE_MODE) ||
            (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
                rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
        else
                rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
  
        if (rc != MBX_SUCCESS) {
-               if (rc == MBX_TIMEOUT)
-                       pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               else
-                       mempool_free( pmboxq, phba->mbox_mem_pool);
+               if (rc != MBX_TIMEOUT)
+                       mempool_free(pmboxq, phba->mbox_mem_pool);
                return NULL;
        }
  
  static void
  lpfc_reset_stats(struct Scsi_Host *shost)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
-       struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       struct lpfc_sli   *psli = &phba->sli;
+       struct lpfc_lnk_stat *lso = &psli->lnk_stat_offsets;
        LPFC_MBOXQ_t *pmboxq;
        MAILBOX_t *pmb;
        int rc = 0;
  
-       if (phba->fc_flag & FC_BLOCK_MGMT_IO)
+       if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO)
                return;
  
        pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        pmb->mbxOwner = OWN_HOST;
        pmb->un.varWords[0] = 0x1; /* reset request */
        pmboxq->context1 = NULL;
+       pmboxq->vport = vport;
  
-       if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+       if ((vport->fc_flag & FC_OFFLINE_MODE) ||
                (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
                rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
        else
                rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
  
        if (rc != MBX_SUCCESS) {
-               if (rc == MBX_TIMEOUT)
-                       pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               else
+               if (rc != MBX_TIMEOUT)
                        mempool_free(pmboxq, phba->mbox_mem_pool);
                return;
        }
        pmb->mbxCommand = MBX_READ_LNK_STAT;
        pmb->mbxOwner = OWN_HOST;
        pmboxq->context1 = NULL;
+       pmboxq->vport = vport;
  
-       if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+       if ((vport->fc_flag & FC_OFFLINE_MODE) ||
            (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
                rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
        else
                rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
  
        if (rc != MBX_SUCCESS) {
-               if (rc == MBX_TIMEOUT)
-                       pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               else
+               if (rc != MBX_TIMEOUT)
                        mempool_free( pmboxq, phba->mbox_mem_pool);
                return;
        }
  static struct lpfc_nodelist *
  lpfc_get_node_by_target(struct scsi_target *starget)
  {
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
+       struct Scsi_Host  *shost = dev_to_shost(starget->dev.parent);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
        struct lpfc_nodelist *ndlp;
  
        spin_lock_irq(shost->host_lock);
        /* Search for this, mapped, target ID */
-       list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
+       list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
                if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
                    starget->id == ndlp->nlp_sid) {
                        spin_unlock_irq(shost->host_lock);
@@@ -1887,8 -2156,66 +2158,66 @@@ struct fc_function_template lpfc_transp
        .get_host_fabric_name = lpfc_get_host_fabric_name,
        .show_host_fabric_name = 1,
  
-       .get_host_symbolic_name = lpfc_get_host_symbolic_name,
-       .show_host_symbolic_name = 1,
+       /*
+        * The LPFC driver treats linkdown handling as target loss events
+        * so there are no sysfs handlers for link_down_tmo.
+        */
+       .get_fc_host_stats = lpfc_get_stats,
+       .reset_fc_host_stats = lpfc_reset_stats,
+       .dd_fcrport_size = sizeof(struct lpfc_rport_data),
+       .show_rport_maxframe_size = 1,
+       .show_rport_supported_classes = 1,
+       .set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
+       .show_rport_dev_loss_tmo = 1,
+       .get_starget_port_id  = lpfc_get_starget_port_id,
+       .show_starget_port_id = 1,
+       .get_starget_node_name = lpfc_get_starget_node_name,
+       .show_starget_node_name = 1,
+       .get_starget_port_name = lpfc_get_starget_port_name,
+       .show_starget_port_name = 1,
+       .issue_fc_host_lip = lpfc_issue_lip,
+       .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
+       .terminate_rport_io = lpfc_terminate_rport_io,
+       .vport_create = lpfc_vport_create,
+       .vport_delete = lpfc_vport_delete,
+       .dd_fcvport_size = sizeof(struct lpfc_vport *),
+ };
+ struct fc_function_template lpfc_vport_transport_functions = {
+       /* fixed attributes the driver supports */
+       .show_host_node_name = 1,
+       .show_host_port_name = 1,
+       .show_host_supported_classes = 1,
+       .show_host_supported_fc4s = 1,
+       .show_host_supported_speeds = 1,
+       .show_host_maxframe_size = 1,
+       /* dynamic attributes the driver supports */
+       .get_host_port_id = lpfc_get_host_port_id,
+       .show_host_port_id = 1,
+       .get_host_port_type = lpfc_get_host_port_type,
+       .show_host_port_type = 1,
+       .get_host_port_state = lpfc_get_host_port_state,
+       .show_host_port_state = 1,
+       /* active_fc4s is shown but doesn't change (thus no get function) */
+       .show_host_active_fc4s = 1,
+       .get_host_speed = lpfc_get_host_speed,
+       .show_host_speed = 1,
+       .get_host_fabric_name = lpfc_get_host_fabric_name,
+       .show_host_fabric_name = 1,
  
        /*
         * The LPFC driver treats linkdown handling as target loss events
        .issue_fc_host_lip = lpfc_issue_lip,
        .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk,
        .terminate_rport_io = lpfc_terminate_rport_io,
+       .vport_disable = lpfc_vport_disable,
  };
  
  void
@@@ -1939,6 -2268,9 +2270,9 @@@ lpfc_get_cfgparam(struct lpfc_hba *phba
        lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
        lpfc_max_luns_init(phba, lpfc_max_luns);
        lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
+       lpfc_peer_port_login_init(phba, lpfc_peer_port_login);
+       lpfc_npiv_enable_init(phba, lpfc_npiv_enable);
+       lpfc_vport_restrict_login_init(phba, lpfc_vport_restrict_login);
        lpfc_use_msi_init(phba, lpfc_use_msi);
        lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
        lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
index 955b2e48d04192579615d6030311e43688b2aae9,4a50e0a21470ae17ef9847d855610df449ecc473..f81f85ee190f1cd2cb8e0597ac2d5a6c7ffab2e5
@@@ -27,6 -27,7 +27,7 @@@
  #include <linux/kthread.h>
  #include <linux/pci.h>
  #include <linux/spinlock.h>
+ #include <linux/ctype.h>
  
  #include <scsi/scsi.h>
  #include <scsi/scsi_device.h>
  #include "lpfc.h"
  #include "lpfc_logmsg.h"
  #include "lpfc_crtn.h"
+ #include "lpfc_vport.h"
  #include "lpfc_version.h"
+ #include "lpfc_vport.h"
  
  static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
  static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
  static int lpfc_post_rcv_buf(struct lpfc_hba *);
  
  static struct scsi_transport_template *lpfc_transport_template = NULL;
+ static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
  static DEFINE_IDR(lpfc_hba_index);
  
  /************************************************************************/
  /*                                                                      */
  /*    lpfc_config_port_prep                                             */
@@@ -61,7 -67,7 +67,7 @@@
  /*                                                                      */
  /************************************************************************/
  int
- lpfc_config_port_prep(struct lpfc_hba * phba)
+ lpfc_config_port_prep(struct lpfc_hba *phba)
  {
        lpfc_vpd_t *vp = &phba->vpd;
        int i = 0, rc;
  
        pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!pmb) {
-               phba->hba_state = LPFC_HBA_ERROR;
+               phba->link_state = LPFC_HBA_ERROR;
                return -ENOMEM;
        }
  
        mb = &pmb->mb;
-       phba->hba_state = LPFC_INIT_MBX_CMDS;
+       phba->link_state = LPFC_INIT_MBX_CMDS;
  
        if (lpfc_is_LC_HBA(phba->pcidev->device)) {
                if (init_key) {
                rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
  
                if (rc != MBX_SUCCESS) {
-                       lpfc_printf_log(phba,
-                                       KERN_ERR,
-                                       LOG_MBOX,
+                       lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
                                        "%d:0324 Config Port initialization "
                                        "error, mbxCmd x%x READ_NVPARM, "
                                        "mbxStatus x%x\n",
                        return -ERESTART;
                }
                memcpy(phba->wwnn, (char *)mb->un.varRDnvp.nodename,
-                      sizeof (mb->un.varRDnvp.nodename));
+                      sizeof(phba->wwnn));
+               memcpy(phba->wwpn, (char *)mb->un.varRDnvp.portname,
+                      sizeof(phba->wwpn));
        }
  
+       phba->sli3_options = 0x0;
        /* Setup and issue mailbox READ REV command */
        lpfc_read_rev(phba, pmb);
        rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
        if (rc != MBX_SUCCESS) {
-               lpfc_printf_log(phba,
-                               KERN_ERR,
-                               LOG_INIT,
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "%d:0439 Adapter failed to init, mbxCmd x%x "
                                "READ_REV, mbxStatus x%x\n",
                                phba->brd_no,
                return -ERESTART;
        }
  
        /*
         * The value of rr must be 1 since the driver set the cv field to 1.
         * This setting requires the FW to set all revision fields.
                return -ERESTART;
        }
  
+       if (phba->sli_rev == 3 && !mb->un.varRdRev.v3rsp)
+               return -EINVAL;
        /* Save information as VPD data */
        vp->rev.rBit = 1;
+       memcpy(&vp->sli3Feat, &mb->un.varRdRev.sli3Feat, sizeof(uint32_t));
        vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
        memcpy(vp->rev.sli1FwName, (char*) mb->un.varRdRev.sli1FwName, 16);
        vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
        vp->rev.postKernRev = mb->un.varRdRev.postKernRev;
        vp->rev.opFwRev = mb->un.varRdRev.opFwRev;
  
+       /* If the sli feature level is less then 9, we must
+        * tear down all RPIs and VPIs on link down if NPIV
+        * is enabled.
+        */
+       if (vp->rev.feaLevelHigh < 9)
+               phba->sli3_options |= LPFC_SLI3_VPORT_TEARDOWN;
        if (lpfc_is_LC_HBA(phba->pcidev->device))
                memcpy(phba->RandomData, (char *)&mb->un.varWords[24],
                                                sizeof (phba->RandomData));
                if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
                        mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
                lpfc_sli_pcimem_bcopy(pmb->context2, lpfc_vpd_data + offset,
-                                                       mb->un.varDmp.word_cnt);
+                                     mb->un.varDmp.word_cnt);
                offset += mb->un.varDmp.word_cnt;
        } while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
        lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
@@@ -212,48 -230,34 +230,34 @@@ out_free_mbox
  /*                                                                      */
  /************************************************************************/
  int
- lpfc_config_port_post(struct lpfc_hba * phba)
+ lpfc_config_port_post(struct lpfc_hba *phba)
  {
+       struct lpfc_vport *vport = phba->pport;
        LPFC_MBOXQ_t *pmb;
        MAILBOX_t *mb;
        struct lpfc_dmabuf *mp;
        struct lpfc_sli *psli = &phba->sli;
        uint32_t status, timeout;
-       int i, j, rc;
+       int i, j;
+       int rc;
  
        pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!pmb) {
-               phba->hba_state = LPFC_HBA_ERROR;
+               phba->link_state = LPFC_HBA_ERROR;
                return -ENOMEM;
        }
        mb = &pmb->mb;
  
-       lpfc_config_link(phba, pmb);
-       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
-       if (rc != MBX_SUCCESS) {
-               lpfc_printf_log(phba,
-                               KERN_ERR,
-                               LOG_INIT,
-                               "%d:0447 Adapter failed init, mbxCmd x%x "
-                               "CONFIG_LINK mbxStatus x%x\n",
-                               phba->brd_no,
-                               mb->mbxCommand, mb->mbxStatus);
-               phba->hba_state = LPFC_HBA_ERROR;
-               mempool_free( pmb, phba->mbox_mem_pool);
-               return -EIO;
-       }
        /* Get login parameters for NID.  */
-       lpfc_read_sparam(phba, pmb);
+       lpfc_read_sparam(phba, pmb, 0);
+       pmb->vport = vport;
        if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
-               lpfc_printf_log(phba,
-                               KERN_ERR,
-                               LOG_INIT,
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "%d:0448 Adapter failed init, mbxCmd x%x "
                                "READ_SPARM mbxStatus x%x\n",
                                phba->brd_no,
                                mb->mbxCommand, mb->mbxStatus);
-               phba->hba_state = LPFC_HBA_ERROR;
+               phba->link_state = LPFC_HBA_ERROR;
                mp = (struct lpfc_dmabuf *) pmb->context1;
                mempool_free( pmb, phba->mbox_mem_pool);
                lpfc_mbuf_free(phba, mp->virt, mp->phys);
  
        mp = (struct lpfc_dmabuf *) pmb->context1;
  
-       memcpy(&phba->fc_sparam, mp->virt, sizeof (struct serv_parm));
+       memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
        pmb->context1 = NULL;
  
        if (phba->cfg_soft_wwnn)
-               u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
+               u64_to_wwn(phba->cfg_soft_wwnn,
+                          vport->fc_sparam.nodeName.u.wwn);
        if (phba->cfg_soft_wwpn)
-               u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
-       memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName,
+               u64_to_wwn(phba->cfg_soft_wwpn,
+                          vport->fc_sparam.portName.u.wwn);
+       memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
               sizeof (struct lpfc_name));
-       memcpy(&phba->fc_portname, &phba->fc_sparam.portName,
+       memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
               sizeof (struct lpfc_name));
        /* If no serial number in VPD data, use low 6 bytes of WWNN */
        /* This should be consolidated into parse_vpd ? - mr */
        if (phba->SerialNumber[0] == 0) {
                uint8_t *outptr;
  
-               outptr = &phba->fc_nodename.u.s.IEEE[0];
+               outptr = &vport->fc_nodename.u.s.IEEE[0];
                for (i = 0; i < 12; i++) {
                        status = *outptr++;
                        j = ((status & 0xf0) >> 4);
        }
  
        lpfc_read_config(phba, pmb);
+       pmb->vport = vport;
        if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
-               lpfc_printf_log(phba,
-                               KERN_ERR,
-                               LOG_INIT,
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "%d:0453 Adapter failed to init, mbxCmd x%x "
                                "READ_CONFIG, mbxStatus x%x\n",
                                phba->brd_no,
                                mb->mbxCommand, mb->mbxStatus);
-               phba->hba_state = LPFC_HBA_ERROR;
+               phba->link_state = LPFC_HBA_ERROR;
                mempool_free( pmb, phba->mbox_mem_pool);
                return -EIO;
        }
            || ((phba->cfg_link_speed == LINK_SPEED_10G)
                && !(phba->lmt & LMT_10Gb))) {
                /* Reset link speed to auto */
-               lpfc_printf_log(phba,
-                       KERN_WARNING,
-                       LOG_LINK_EVENT,
+               lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT,
                        "%d:1302 Invalid speed for this board: "
                        "Reset link speed to auto: x%x\n",
                        phba->brd_no,
                        phba->cfg_link_speed = LINK_SPEED_AUTO;
        }
  
-       phba->hba_state = LPFC_LINK_DOWN;
+       phba->link_state = LPFC_LINK_DOWN;
  
        /* Only process IOCBs on ring 0 till hba_state is READY */
        if (psli->ring[psli->extra_ring].cmdringaddr)
                psli->ring[psli->next_ring].flag |= LPFC_STOP_IOCB_EVENT;
  
        /* Post receive buffers for desired rings */
-       lpfc_post_rcv_buf(phba);
+       if (phba->sli_rev != 3)
+               lpfc_post_rcv_buf(phba);
  
        /* Enable appropriate host interrupts */
-       spin_lock_irq(phba->host->host_lock);
+       spin_lock_irq(&phba->hbalock);
        status = readl(phba->HCregaddr);
        status |= HC_MBINT_ENA | HC_ERINT_ENA | HC_LAINT_ENA;
        if (psli->num_rings > 0)
  
        writel(status, phba->HCregaddr);
        readl(phba->HCregaddr); /* flush */
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
  
        /*
         * Setup the ring 0 (els)  timeout handler
         */
        timeout = phba->fc_ratov << 1;
-       mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
+       mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
+       mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+       phba->hb_outstanding = 0;
+       phba->last_completion_time = jiffies;
  
        lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
        pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+       pmb->vport = vport;
        rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
        lpfc_set_loopback_flag(phba);
        if (rc != MBX_SUCCESS) {
-               lpfc_printf_log(phba,
-                               KERN_ERR,
-                               LOG_INIT,
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "%d:0454 Adapter failed to init, mbxCmd x%x "
                                "INIT_LINK, mbxStatus x%x\n",
                                phba->brd_no,
                writel(0xffffffff, phba->HAregaddr);
                readl(phba->HAregaddr); /* flush */
  
-               phba->hba_state = LPFC_HBA_ERROR;
+               phba->link_state = LPFC_HBA_ERROR;
                if (rc != MBX_BUSY)
                        mempool_free(pmb, phba->mbox_mem_pool);
                return -EIO;
  /*                                                                      */
  /************************************************************************/
  int
- lpfc_hba_down_prep(struct lpfc_hba * phba)
+ lpfc_hba_down_prep(struct lpfc_hba *phba)
  {
+       struct lpfc_vport *vport = phba->pport;
        /* Disable interrupts */
        writel(0, phba->HCregaddr);
        readl(phba->HCregaddr); /* flush */
  
-       /* Cleanup potential discovery resources */
-       lpfc_els_flush_rscn(phba);
-       lpfc_els_flush_cmd(phba);
-       lpfc_disc_flush_list(phba);
+       list_for_each_entry(vport, &phba->port_list, listentry) {
+               lpfc_cleanup_discovery_resources(vport);
+       }
  
-       return (0);
+       return 0;
  }
  
  /************************************************************************/
  /*                                                                      */
  /************************************************************************/
  int
- lpfc_hba_down_post(struct lpfc_hba * phba)
+ lpfc_hba_down_post(struct lpfc_hba *phba)
  {
        struct lpfc_sli *psli = &phba->sli;
        struct lpfc_sli_ring *pring;
        struct lpfc_dmabuf *mp, *next_mp;
        int i;
  
-       /* Cleanup preposted buffers on the ELS ring */
-       pring = &psli->ring[LPFC_ELS_RING];
-       list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
-               list_del(&mp->list);
-               pring->postbufq_cnt--;
-               lpfc_mbuf_free(phba, mp->virt, mp->phys);
-               kfree(mp);
+       if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
+               lpfc_sli_hbqbuf_free_all(phba);
+       else {
+               /* Cleanup preposted buffers on the ELS ring */
+               pring = &psli->ring[LPFC_ELS_RING];
+               list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
+                       list_del(&mp->list);
+                       pring->postbufq_cnt--;
+                       lpfc_mbuf_free(phba, mp->virt, mp->phys);
+                       kfree(mp);
+               }
        }
  
        for (i = 0; i < psli->num_rings; i++) {
        return 0;
  }
  
+ /* HBA heart beat timeout handler */
+ void
+ lpfc_hb_timeout(unsigned long ptr)
+ {
+       struct lpfc_hba *phba;
+       unsigned long iflag;
+       phba = (struct lpfc_hba *)ptr;
+       spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
+       if (!(phba->pport->work_port_events & WORKER_HB_TMO))
+               phba->pport->work_port_events |= WORKER_HB_TMO;
+       spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+       if (phba->work_wait)
+               wake_up(phba->work_wait);
+       return;
+ }
+ static void
+ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
+ {
+       unsigned long drvr_flag;
+       spin_lock_irqsave(&phba->hbalock, drvr_flag);
+       phba->hb_outstanding = 0;
+       spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+       mempool_free(pmboxq, phba->mbox_mem_pool);
+       if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) &&
+               !(phba->link_state == LPFC_HBA_ERROR) &&
+               !(phba->pport->fc_flag & FC_UNLOADING))
+               mod_timer(&phba->hb_tmofunc,
+                       jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+       return;
+ }
+ void
+ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
+ {
+       LPFC_MBOXQ_t *pmboxq;
+       int retval;
+       struct lpfc_sli *psli = &phba->sli;
+       if ((phba->link_state == LPFC_HBA_ERROR) ||
+               (phba->pport->fc_flag & FC_UNLOADING) ||
+               (phba->pport->fc_flag & FC_OFFLINE_MODE))
+               return;
+       spin_lock_irq(&phba->pport->work_port_lock);
+       /* If the timer is already canceled do nothing */
+       if (!(phba->pport->work_port_events & WORKER_HB_TMO)) {
+               spin_unlock_irq(&phba->pport->work_port_lock);
+               return;
+       }
+       if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ,
+               jiffies)) {
+               spin_unlock_irq(&phba->pport->work_port_lock);
+               if (!phba->hb_outstanding)
+                       mod_timer(&phba->hb_tmofunc,
+                               jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+               else
+                       mod_timer(&phba->hb_tmofunc,
+                               jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+               return;
+       }
+       spin_unlock_irq(&phba->pport->work_port_lock);
+       /* If there is no heart beat outstanding, issue a heartbeat command */
+       if (!phba->hb_outstanding) {
+               pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
+               if (!pmboxq) {
+                       mod_timer(&phba->hb_tmofunc,
+                               jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+                       return;
+               }
+               lpfc_heart_beat(phba, pmboxq);
+               pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl;
+               pmboxq->vport = phba->pport;
+               retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
+               if (retval != MBX_BUSY && retval != MBX_SUCCESS) {
+                       mempool_free(pmboxq, phba->mbox_mem_pool);
+                       mod_timer(&phba->hb_tmofunc,
+                               jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
+                       return;
+               }
+               mod_timer(&phba->hb_tmofunc,
+                       jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
+               phba->hb_outstanding = 1;
+               return;
+       } else {
+               /*
+                * If heart beat timeout called with hb_outstanding set we
+                * need to take the HBA offline.
+                */
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "%d:0459 Adapter heartbeat failure, taking "
+                       "this port offline.\n", phba->brd_no);
+               spin_lock_irq(&phba->hbalock);
+               psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+               spin_unlock_irq(&phba->hbalock);
+               lpfc_offline_prep(phba);
+               lpfc_offline(phba);
+               lpfc_unblock_mgmt_io(phba);
+               phba->link_state = LPFC_HBA_ERROR;
+               lpfc_hba_down_post(phba);
+       }
+ }
  /************************************************************************/
  /*                                                                      */
  /*    lpfc_handle_eratt                                                 */
  /*                                                                      */
  /************************************************************************/
  void
- lpfc_handle_eratt(struct lpfc_hba * phba)
+ lpfc_handle_eratt(struct lpfc_hba *phba)
  {
-       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_vport *vport = phba->pport;
+       struct lpfc_sli   *psli = &phba->sli;
        struct lpfc_sli_ring  *pring;
+       struct lpfc_vport *port_iterator;
        uint32_t event_data;
+       struct Scsi_Host  *shost;
        /* If the pci channel is offline, ignore possible errors,
         * since we cannot communicate with the pci card anyway. */
        if (pci_channel_offline(phba->pcidev))
                                "Data: x%x x%x x%x\n",
                                phba->brd_no, phba->work_hs,
                                phba->work_status[0], phba->work_status[1]);
-               spin_lock_irq(phba->host->host_lock);
-               phba->fc_flag |= FC_ESTABLISH_LINK;
+               list_for_each_entry(port_iterator, &phba->port_list,
+                                   listentry) {
+                       shost = lpfc_shost_from_vport(port_iterator);
+                       spin_lock_irq(shost->host_lock);
+                       port_iterator->fc_flag |= FC_ESTABLISH_LINK;
+                       spin_unlock_irq(shost->host_lock);
+               }
+               spin_lock_irq(&phba->hbalock);
                psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
-               spin_unlock_irq(phba->host->host_lock);
+               spin_unlock_irq(&phba->hbalock);
  
                /*
                * Firmware stops when it triggled erratt with HS_FFER6.
                                phba->work_status[0], phba->work_status[1]);
  
                event_data = FC_REG_DUMP_EVENT;
-               fc_host_post_vendor_event(phba->host, fc_get_event_number(),
+               shost = lpfc_shost_from_vport(vport);
+               fc_host_post_vendor_event(shost, fc_get_event_number(),
                                sizeof(event_data), (char *) &event_data,
                                SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
  
+               spin_lock_irq(&phba->hbalock);
                psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+               spin_unlock_irq(&phba->hbalock);
                lpfc_offline_prep(phba);
                lpfc_offline(phba);
                lpfc_unblock_mgmt_io(phba);
-               phba->hba_state = LPFC_HBA_ERROR;
+               phba->link_state = LPFC_HBA_ERROR;
                lpfc_hba_down_post(phba);
        }
  }
  /*                                                                      */
  /************************************************************************/
  void
- lpfc_handle_latt(struct lpfc_hba * phba)
+ lpfc_handle_latt(struct lpfc_hba *phba)
  {
-       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_vport *vport = phba->pport;
+       struct lpfc_sli   *psli = &phba->sli;
+       struct lpfc_vport *port_iterator;
        LPFC_MBOXQ_t *pmb;
        volatile uint32_t control;
        struct lpfc_dmabuf *mp;
        rc = -EIO;
  
        /* Cleanup any outstanding ELS commands */
-       lpfc_els_flush_cmd(phba);
+       list_for_each_entry(port_iterator, &phba->port_list, listentry)
+               lpfc_els_flush_cmd(port_iterator);
  
        psli->slistat.link_event++;
        lpfc_read_la(phba, pmb, mp);
        pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
+       pmb->vport = vport;
        rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
        if (rc == MBX_NOT_FINISHED)
                goto lpfc_handle_latt_free_mbuf;
  
        /* Clear Link Attention in HA REG */
-       spin_lock_irq(phba->host->host_lock);
+       spin_lock_irq(&phba->hbalock);
        writel(HA_LATT, phba->HAregaddr);
        readl(phba->HAregaddr); /* flush */
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
  
        return;
  
@@@ -614,7 -756,7 +756,7 @@@ lpfc_handle_latt_free_pmb
        mempool_free(pmb, phba->mbox_mem_pool);
  lpfc_handle_latt_err_exit:
        /* Enable Link attention interrupts */
-       spin_lock_irq(phba->host->host_lock);
+       spin_lock_irq(&phba->hbalock);
        psli->sli_flag |= LPFC_PROCESS_LA;
        control = readl(phba->HCregaddr);
        control |= HC_LAINT_ENA;
        /* Clear Link Attention in HA REG */
        writel(HA_LATT, phba->HAregaddr);
        readl(phba->HAregaddr); /* flush */
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
        lpfc_linkdown(phba);
-       phba->hba_state = LPFC_HBA_ERROR;
+       phba->link_state = LPFC_HBA_ERROR;
  
        /* The other case is an error from issue_mbox */
        if (rc == -ENOMEM)
-               lpfc_printf_log(phba,
-                               KERN_WARNING,
-                               LOG_MBOX,
+               lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
                                "%d:0300 READ_LA: no buffers\n",
                                phba->brd_no);
  
  /*                                                                      */
  /************************************************************************/
  static int
- lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
+ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
  {
        uint8_t lenlo, lenhi;
        int Length;
                return 0;
  
        /* Vital Product */
-       lpfc_printf_log(phba,
-                       KERN_INFO,
-                       LOG_INIT,
+       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                        "%d:0455 Vital Product Data: x%x x%x x%x x%x\n",
                        phba->brd_no,
                        (uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2],
  }
  
  static void
- lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
+ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
  {
        lpfc_vpd_t *vp;
        uint16_t dev_id = phba->pcidev->device;
  /*   Returns the number of buffers NOT posted.    */
  /**************************************************/
  int
- lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
+ lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt,
                 int type)
  {
        IOCB_t *icmd;
        /* While there are buffers to post */
        while (cnt > 0) {
                /* Allocate buffer for  command iocb */
-               spin_lock_irq(phba->host->host_lock);
                iocb = lpfc_sli_get_iocbq(phba);
-               spin_unlock_irq(phba->host->host_lock);
                if (iocb == NULL) {
                        pring->missbufcnt = cnt;
                        return cnt;
                                                &mp1->phys);
                if (mp1 == 0 || mp1->virt == 0) {
                        kfree(mp1);
-                       spin_lock_irq(phba->host->host_lock);
                        lpfc_sli_release_iocbq(phba, iocb);
-                       spin_unlock_irq(phba->host->host_lock);
                        pring->missbufcnt = cnt;
                        return cnt;
                }
                                kfree(mp2);
                                lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
                                kfree(mp1);
-                               spin_lock_irq(phba->host->host_lock);
                                lpfc_sli_release_iocbq(phba, iocb);
-                               spin_unlock_irq(phba->host->host_lock);
                                pring->missbufcnt = cnt;
                                return cnt;
                        }
                icmd->ulpCommand = CMD_QUE_RING_BUF64_CN;
                icmd->ulpLe = 1;
  
-               spin_lock_irq(phba->host->host_lock);
                if (lpfc_sli_issue_iocb(phba, pring, iocb, 0) == IOCB_ERROR) {
                        lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
                        kfree(mp1);
                        }
                        lpfc_sli_release_iocbq(phba, iocb);
                        pring->missbufcnt = cnt;
-                       spin_unlock_irq(phba->host->host_lock);
                        return cnt;
                }
-               spin_unlock_irq(phba->host->host_lock);
                lpfc_sli_ringpostbuf_put(phba, pring, mp1);
-               if (mp2) {
+               if (mp2)
                        lpfc_sli_ringpostbuf_put(phba, pring, mp2);
-               }
        }
        pring->missbufcnt = 0;
        return 0;
  /*                                                                      */
  /************************************************************************/
  static int
- lpfc_post_rcv_buf(struct lpfc_hba * phba)
+ lpfc_post_rcv_buf(struct lpfc_hba *phba)
  {
        struct lpfc_sli *psli = &phba->sli;
  
@@@ -1151,7 -1279,7 +1279,7 @@@ lpfc_hba_init(struct lpfc_hba *phba, ui
  {
        int t;
        uint32_t *HashWorking;
-       uint32_t *pwwnn = phba->wwnn;
+       uint32_t *pwwnn = (uint32_t *) phba->wwnn;
  
        HashWorking = kmalloc(80 * sizeof(uint32_t), GFP_KERNEL);
        if (!HashWorking)
  }
  
  static void
- lpfc_cleanup(struct lpfc_hba * phba)
+ lpfc_cleanup(struct lpfc_vport *vport)
  {
        struct lpfc_nodelist *ndlp, *next_ndlp;
  
        /* clean up phba - lpfc specific */
-       lpfc_can_disctmo(phba);
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
+       lpfc_can_disctmo(vport);
+       list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
                lpfc_nlp_put(ndlp);
-       INIT_LIST_HEAD(&phba->fc_nodes);
        return;
  }
  
  static void
  lpfc_establish_link_tmo(unsigned long ptr)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+       struct lpfc_hba   *phba = (struct lpfc_hba *) ptr;
+       struct lpfc_vport *vport = phba->pport;
        unsigned long iflag;
  
        /* Re-establishing Link, timer expired */
        lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
                        "%d:1300 Re-establishing Link, timer expired "
                        "Data: x%x x%x\n",
-                       phba->brd_no, phba->fc_flag, phba->hba_state);
-       spin_lock_irqsave(phba->host->host_lock, iflag);
-       phba->fc_flag &= ~FC_ESTABLISH_LINK;
-       spin_unlock_irqrestore(phba->host->host_lock, iflag);
+                       phba->brd_no, vport->fc_flag,
+                       vport->port_state);
+       list_for_each_entry(vport, &phba->port_list, listentry) {
+               struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+               spin_lock_irqsave(shost->host_lock, iflag);
+               vport->fc_flag &= ~FC_ESTABLISH_LINK;
+               spin_unlock_irqrestore(shost->host_lock, iflag);
+       }
  }
  
- static int
- lpfc_stop_timer(struct lpfc_hba * phba)
+ void
+ lpfc_stop_vport_timers(struct lpfc_vport *vport)
  {
-       struct lpfc_sli *psli = &phba->sli;
+       del_timer_sync(&vport->els_tmofunc);
+       del_timer_sync(&vport->fc_fdmitmo);
+       lpfc_can_disctmo(vport);
+       return;
+ }
+ static void
+ lpfc_stop_phba_timers(struct lpfc_hba *phba)
+ {
+       struct lpfc_vport *vport;
  
        del_timer_sync(&phba->fcp_poll_timer);
        del_timer_sync(&phba->fc_estabtmo);
-       del_timer_sync(&phba->fc_disctmo);
-       del_timer_sync(&phba->fc_fdmitmo);
-       del_timer_sync(&phba->els_tmofunc);
-       psli = &phba->sli;
-       del_timer_sync(&psli->mbox_tmo);
-       return(1);
+       list_for_each_entry(vport, &phba->port_list, listentry)
+               lpfc_stop_vport_timers(vport);
+       del_timer_sync(&phba->sli.mbox_tmo);
+       del_timer_sync(&phba->fabric_block_timer);
+       phba->hb_outstanding = 0;
+       del_timer_sync(&phba->hb_tmofunc);
+       return;
  }
  
  int
- lpfc_online(struct lpfc_hba * phba)
+ lpfc_online(struct lpfc_hba *phba)
  {
+       struct lpfc_vport *vport = phba->pport;
        if (!phba)
                return 0;
  
-       if (!(phba->fc_flag & FC_OFFLINE_MODE))
+       if (!(vport->fc_flag & FC_OFFLINE_MODE))
                return 0;
  
-       lpfc_printf_log(phba,
-                      KERN_WARNING,
-                      LOG_INIT,
+       lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
                       "%d:0458 Bring Adapter online\n",
                       phba->brd_no);
  
                return 1;
        }
  
-       spin_lock_irq(phba->host->host_lock);
-       phba->fc_flag &= ~FC_OFFLINE_MODE;
-       spin_unlock_irq(phba->host->host_lock);
+       list_for_each_entry(vport, &phba->port_list, listentry) {
+               struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+               spin_lock_irq(shost->host_lock);
+               vport->fc_flag &= ~FC_OFFLINE_MODE;
+               if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
+                       vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+               spin_unlock_irq(shost->host_lock);
+       }
  
        lpfc_unblock_mgmt_io(phba);
        return 0;
@@@ -1256,9 -1401,9 +1401,9 @@@ lpfc_block_mgmt_io(struct lpfc_hba * ph
  {
        unsigned long iflag;
  
-       spin_lock_irqsave(phba->host->host_lock, iflag);
-       phba->fc_flag |= FC_BLOCK_MGMT_IO;
-       spin_unlock_irqrestore(phba->host->host_lock, iflag);
+       spin_lock_irqsave(&phba->hbalock, iflag);
+       phba->sli.sli_flag |= LPFC_BLOCK_MGMT_IO;
+       spin_unlock_irqrestore(&phba->hbalock, iflag);
  }
  
  void
@@@ -1266,17 -1411,18 +1411,18 @@@ lpfc_unblock_mgmt_io(struct lpfc_hba * 
  {
        unsigned long iflag;
  
-       spin_lock_irqsave(phba->host->host_lock, iflag);
-       phba->fc_flag &= ~FC_BLOCK_MGMT_IO;
-       spin_unlock_irqrestore(phba->host->host_lock, iflag);
+       spin_lock_irqsave(&phba->hbalock, iflag);
+       phba->sli.sli_flag &= ~LPFC_BLOCK_MGMT_IO;
+       spin_unlock_irqrestore(&phba->hbalock, iflag);
  }
  
  void
  lpfc_offline_prep(struct lpfc_hba * phba)
  {
+       struct lpfc_vport *vport = phba->pport;
        struct lpfc_nodelist  *ndlp, *next_ndlp;
  
-       if (phba->fc_flag & FC_OFFLINE_MODE)
+       if (vport->fc_flag & FC_OFFLINE_MODE)
                return;
  
        lpfc_block_mgmt_io(phba);
        lpfc_linkdown(phba);
  
        /* Issue an unreg_login to all nodes */
-       list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
+       list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
                if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
-                       lpfc_unreg_rpi(phba, ndlp);
+                       lpfc_unreg_rpi(vport, ndlp);
  
        lpfc_sli_flush_mbox_queue(phba);
  }
  
  void
- lpfc_offline(struct lpfc_hba * phba)
+ lpfc_offline(struct lpfc_hba *phba)
  {
-       unsigned long iflag;
+       struct lpfc_vport *vport = phba->pport;
+       struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_vport *port_iterator;
  
-       if (phba->fc_flag & FC_OFFLINE_MODE)
+       if (vport->fc_flag & FC_OFFLINE_MODE)
                return;
  
        /* stop all timers associated with this hba */
-       lpfc_stop_timer(phba);
+       lpfc_stop_phba_timers(phba);
+       list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+               port_iterator->work_port_events = 0;
+       }
  
-       lpfc_printf_log(phba,
-                      KERN_WARNING,
-                      LOG_INIT,
+       lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
                       "%d:0460 Bring Adapter offline\n",
                       phba->brd_no);
  
        /* Bring down the SLI Layer and cleanup.  The HBA is offline
           now.  */
        lpfc_sli_hba_down(phba);
-       lpfc_cleanup(phba);
-       spin_lock_irqsave(phba->host->host_lock, iflag);
-       phba->work_hba_events = 0;
+       spin_lock_irq(&phba->hbalock);
        phba->work_ha = 0;
-       phba->fc_flag |= FC_OFFLINE_MODE;
-       spin_unlock_irqrestore(phba->host->host_lock, iflag);
+       vport->fc_flag |= FC_OFFLINE_MODE;
+       spin_unlock_irq(&phba->hbalock);
+       list_for_each_entry(port_iterator, &phba->port_list, listentry) {
+               shost = lpfc_shost_from_vport(port_iterator);
+               lpfc_cleanup(port_iterator);
+               spin_lock_irq(shost->host_lock);
+               vport->work_port_events = 0;
+               vport->fc_flag |= FC_OFFLINE_MODE;
+               spin_unlock_irq(shost->host_lock);
+       }
  }
  
  /******************************************************************************
  *
  ******************************************************************************/
  static int
- lpfc_scsi_free(struct lpfc_hba * phba)
+ lpfc_scsi_free(struct lpfc_hba *phba)
  {
        struct lpfc_scsi_buf *sb, *sb_next;
        struct lpfc_iocbq *io, *io_next;
  
-       spin_lock_irq(phba->host->host_lock);
+       spin_lock_irq(&phba->hbalock);
        /* Release all the lpfc_scsi_bufs maintained by this host. */
        list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
                list_del(&sb->list);
                pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
-                                                               sb->dma_handle);
+                             sb->dma_handle);
                kfree(sb);
                phba->total_scsi_bufs--;
        }
                phba->total_iocbq_bufs--;
        }
  
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
  
        return 0;
  }
  
- void lpfc_remove_device(struct lpfc_hba *phba)
- {
-       unsigned long iflag;
  
-       lpfc_free_sysfs_attr(phba);
-       spin_lock_irqsave(phba->host->host_lock, iflag);
-       phba->fc_flag |= FC_UNLOADING;
+ struct lpfc_vport *
+ lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport)
+ {
+       struct lpfc_vport *vport;
+       struct Scsi_Host  *shost;
+       int error = 0;
  
-       spin_unlock_irqrestore(phba->host->host_lock, iflag);
+       shost = scsi_host_alloc(&lpfc_template, sizeof(struct lpfc_vport));
+       if (!shost)
+               goto out;
  
-       fc_remove_host(phba->host);
-       scsi_remove_host(phba->host);
+       vport = (struct lpfc_vport *) shost->hostdata;
+       vport->phba = phba;
  
-       kthread_stop(phba->worker_thread);
+       vport->load_flag |= FC_LOADING;
+       vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
  
+       shost->unique_id = instance;
+       shost->max_id = LPFC_MAX_TARGET;
+       shost->max_lun = phba->cfg_max_luns;
+       shost->this_id = -1;
+       shost->max_cmd_len = 16;
        /*
-        * Bring down the SLI Layer. This step disable all interrupts,
-        * clears the rings, discards all mailbox commands, and resets
-        * the HBA.
+        * Set initial can_queue value since 0 is no longer supported and
+        * scsi_add_host will fail. This will be adjusted later based on the
+        * max xri value determined in hba setup.
         */
-       lpfc_sli_hba_down(phba);
-       lpfc_sli_brdrestart(phba);
+       shost->can_queue = phba->cfg_hba_queue_depth - 10;
+       if (fc_vport != NULL) {
+               shost->transportt = lpfc_vport_transport_template;
+               vport->port_type = LPFC_NPIV_PORT;
+       } else {
+               shost->transportt = lpfc_transport_template;
+               vport->port_type = LPFC_PHYSICAL_PORT;
+       }
  
-       /* Release the irq reservation */
-       free_irq(phba->pcidev->irq, phba);
-       pci_disable_msi(phba->pcidev);
+       /* Initialize all internally managed lists. */
+       INIT_LIST_HEAD(&vport->fc_nodes);
+       spin_lock_init(&vport->work_port_lock);
  
-       lpfc_cleanup(phba);
-       lpfc_stop_timer(phba);
-       phba->work_hba_events = 0;
+       init_timer(&vport->fc_disctmo);
+       vport->fc_disctmo.function = lpfc_disc_timeout;
+       vport->fc_disctmo.data = (unsigned long)vport;
  
-       /*
-        * Call scsi_free before mem_free since scsi bufs are released to their
-        * corresponding pools here.
-        */
-       lpfc_scsi_free(phba);
-       lpfc_mem_free(phba);
+       init_timer(&vport->fc_fdmitmo);
+       vport->fc_fdmitmo.function = lpfc_fdmi_tmo;
+       vport->fc_fdmitmo.data = (unsigned long)vport;
  
-       /* Free resources associated with SLI2 interface */
-       dma_free_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,
-                         phba->slim2p, phba->slim2p_mapping);
+       init_timer(&vport->els_tmofunc);
+       vport->els_tmofunc.function = lpfc_els_timeout;
+       vport->els_tmofunc.data = (unsigned long)vport;
  
-       /* unmap adapter SLIM and Control Registers */
-       iounmap(phba->ctrl_regs_memmap_p);
-       iounmap(phba->slim_memmap_p);
+       if (fc_vport != NULL) {
+               error = scsi_add_host(shost, &fc_vport->dev);
+       } else {
+               error = scsi_add_host(shost, &phba->pcidev->dev);
+       }
+       if (error)
+               goto out_put_shost;
  
-       pci_release_regions(phba->pcidev);
-       pci_disable_device(phba->pcidev);
+       list_add_tail(&vport->listentry, &phba->port_list);
+       return vport;
  
-       idr_remove(&lpfc_hba_index, phba->brd_no);
-       scsi_host_put(phba->host);
+ out_put_shost:
+       scsi_host_put(shost);
+ out:
+       return NULL;
  }
  
- void lpfc_scan_start(struct Scsi_Host *host)
+ void
+ destroy_port(struct lpfc_vport *vport)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+       struct lpfc_hba  *phba = vport->phba;
  
-       if (lpfc_alloc_sysfs_attr(phba))
-               goto error;
+       kfree(vport->vname);
  
-       phba->MBslimaddr = phba->slim_memmap_p;
-       phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
-       phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
-       phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
-       phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
+       lpfc_debugfs_terminate(vport);
+       fc_remove_host(shost);
+       scsi_remove_host(shost);
  
-       if (lpfc_sli_hba_setup(phba))
-               goto error;
+       spin_lock_irq(&phba->hbalock);
+       list_del_init(&vport->listentry);
+       spin_unlock_irq(&phba->hbalock);
  
-       /*
-        * hba setup may have changed the hba_queue_depth so we need to adjust
-        * the value of can_queue.
-        */
-       host->can_queue = phba->cfg_hba_queue_depth - 10;
+       lpfc_cleanup(vport);
        return;
+ }
+ int
+ lpfc_get_instance(void)
+ {
+       int instance = 0;
  
- error:
-       lpfc_remove_device(phba);
+       /* Assign an unused number */
+       if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
+               return -1;
+       if (idr_get_new(&lpfc_hba_index, NULL, &instance))
+               return -1;
+       return instance;
  }
  
+ /*
+  * Note: there is no scan_start function as adapter initialization
+  * will have asynchronously kicked off the link initialization.
+  */
  int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
  {
-       struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       int stat = 0;
  
-       if (!phba->host)
-               return 1;
-       if (time >= 30 * HZ)
+       spin_lock_irq(shost->host_lock);
+       if (vport->fc_flag & FC_UNLOADING) {
+               stat = 1;
+               goto finished;
+       }
+       if (time >= 30 * HZ) {
+               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "%d:0461 Scanning longer than 30 "
+                               "seconds.  Continuing initialization\n",
+                               phba->brd_no);
+               stat = 1;
+               goto finished;
+       }
+       if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) {
+               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "%d:0465 Link down longer than 15 "
+                               "seconds.  Continuing initialization\n",
+                               phba->brd_no);
+               stat = 1;
                goto finished;
+       }
  
-       if (phba->hba_state != LPFC_HBA_READY)
-               return 0;
-       if (phba->num_disc_nodes || phba->fc_prli_sent)
-               return 0;
-       if ((phba->fc_map_cnt == 0) && (time < 2 * HZ))
-               return 0;
-       if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)
-               return 0;
-       if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ))
-               return 0;
+       if (vport->port_state != LPFC_VPORT_READY)
+               goto finished;
+       if (vport->num_disc_nodes || vport->fc_prli_sent)
+               goto finished;
+       if (vport->fc_map_cnt == 0 && time < 2 * HZ)
+               goto finished;
+       if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0)
+               goto finished;
+       stat = 1;
  
  finished:
-       if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
-               spin_lock_irq(shost->host_lock);
-               lpfc_poll_start_timer(phba);
-               spin_unlock_irq(shost->host_lock);
-       }
+       spin_unlock_irq(shost->host_lock);
+       return stat;
+ }
  
+ void lpfc_host_attrib_init(struct Scsi_Host *shost)
+ {
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
        /*
-        * set fixed host attributes
-        * Must done after lpfc_sli_hba_setup()
+        * Set fixed host attributes.  Must done after lpfc_sli_hba_setup().
         */
  
-       fc_host_node_name(shost) = wwn_to_u64(phba->fc_nodename.u.wwn);
-       fc_host_port_name(shost) = wwn_to_u64(phba->fc_portname.u.wwn);
+       fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
+       fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
        fc_host_supported_classes(shost) = FC_COS_CLASS3;
  
        memset(fc_host_supported_fc4s(shost), 0,
-               sizeof(fc_host_supported_fc4s(shost)));
+              sizeof(fc_host_supported_fc4s(shost)));
        fc_host_supported_fc4s(shost)[2] = 1;
        fc_host_supported_fc4s(shost)[7] = 1;
  
-       lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
+       lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost),
+                                sizeof fc_host_symbolic_name(shost));
  
        fc_host_supported_speeds(shost) = 0;
        if (phba->lmt & LMT_10Gb)
                fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT;
  
        fc_host_maxframe_size(shost) =
-               ((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
-                (uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);
+               (((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
+               (uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
  
        /* This value is also unchanging */
        memset(fc_host_active_fc4s(shost), 0,
-               sizeof(fc_host_active_fc4s(shost)));
+              sizeof(fc_host_active_fc4s(shost)));
        fc_host_active_fc4s(shost)[2] = 1;
        fc_host_active_fc4s(shost)[7] = 1;
  
+       fc_host_max_npiv_vports(shost) = phba->max_vpi;
        spin_lock_irq(shost->host_lock);
-       phba->fc_flag &= ~FC_LOADING;
+       vport->fc_flag &= ~FC_LOADING;
        spin_unlock_irq(shost->host_lock);
-       return 1;
  }
  
  static int __devinit
  lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
  {
-       struct Scsi_Host *host;
-       struct lpfc_hba  *phba;
-       struct lpfc_sli  *psli;
+       struct lpfc_vport *vport = NULL;
+       struct lpfc_hba   *phba;
+       struct lpfc_sli   *psli;
        struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL;
+       struct Scsi_Host  *shost = NULL;
        unsigned long bar0map_len, bar2map_len;
-       int error = -ENODEV, retval;
+       int error = -ENODEV;
        int i;
        uint16_t iotag;
  
        if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
                goto out_disable_device;
  
-       host = scsi_host_alloc(&lpfc_template, sizeof (struct lpfc_hba));
-       if (!host)
+       phba = kzalloc(sizeof (struct lpfc_hba), GFP_KERNEL);
+       if (!phba)
                goto out_release_regions;
  
-       phba = (struct lpfc_hba*)host->hostdata;
-       memset(phba, 0, sizeof (struct lpfc_hba));
-       phba->host = host;
+       spin_lock_init(&phba->hbalock);
  
-       phba->fc_flag |= FC_LOADING;
        phba->pcidev = pdev;
  
        /* Assign an unused board number */
-       if (!idr_pre_get(&lpfc_hba_index, GFP_KERNEL))
-               goto out_put_host;
+       if ((phba->brd_no = lpfc_get_instance()) < 0)
+               goto out_free_phba;
  
-       error = idr_get_new(&lpfc_hba_index, NULL, &phba->brd_no);
-       if (error)
-               goto out_put_host;
-       host->unique_id = phba->brd_no;
+       INIT_LIST_HEAD(&phba->port_list);
+       INIT_LIST_HEAD(&phba->hbq_buffer_list);
+       /*
+        * Get all the module params for configuring this host and then
+        * establish the host.
+        */
+       lpfc_get_cfgparam(phba);
+       phba->max_vpi = LPFC_MAX_VPI;
  
        /* Initialize timers used by driver */
        init_timer(&phba->fc_estabtmo);
        phba->fc_estabtmo.function = lpfc_establish_link_tmo;
        phba->fc_estabtmo.data = (unsigned long)phba;
-       init_timer(&phba->fc_disctmo);
-       phba->fc_disctmo.function = lpfc_disc_timeout;
-       phba->fc_disctmo.data = (unsigned long)phba;
-       init_timer(&phba->fc_fdmitmo);
-       phba->fc_fdmitmo.function = lpfc_fdmi_tmo;
-       phba->fc_fdmitmo.data = (unsigned long)phba;
-       init_timer(&phba->els_tmofunc);
-       phba->els_tmofunc.function = lpfc_els_timeout;
-       phba->els_tmofunc.data = (unsigned long)phba;
+       init_timer(&phba->hb_tmofunc);
+       phba->hb_tmofunc.function = lpfc_hb_timeout;
+       phba->hb_tmofunc.data = (unsigned long)phba;
        psli = &phba->sli;
        init_timer(&psli->mbox_tmo);
        psli->mbox_tmo.function = lpfc_mbox_timeout;
-       psli->mbox_tmo.data = (unsigned long)phba;
+       psli->mbox_tmo.data = (unsigned long) phba;
        init_timer(&phba->fcp_poll_timer);
        phba->fcp_poll_timer.function = lpfc_poll_timeout;
-       phba->fcp_poll_timer.data = (unsigned long)phba;
-       /*
-        * Get all the module params for configuring this host and then
-        * establish the host parameters.
-        */
-       lpfc_get_cfgparam(phba);
-       host->max_id = LPFC_MAX_TARGET;
-       host->max_lun = phba->cfg_max_luns;
-       host->this_id = -1;
-       INIT_LIST_HEAD(&phba->fc_nodes);
+       phba->fcp_poll_timer.data = (unsigned long) phba;
+       init_timer(&phba->fabric_block_timer);
+       phba->fabric_block_timer.function = lpfc_fabric_block_timeout;
+       phba->fabric_block_timer.data = (unsigned long) phba;
  
        pci_set_master(pdev);
 -      retval = pci_set_mwi(pdev);
 -      if (retval)
 -              dev_printk(KERN_WARNING, &pdev->dev,
 -                         "Warning: pci_set_mwi returned %d\n", retval);
 +      pci_try_set_mwi(pdev);
  
        if (pci_set_dma_mask(phba->pcidev, DMA_64BIT_MASK) != 0)
                if (pci_set_dma_mask(phba->pcidev, DMA_32BIT_MASK) != 0)
  
        memset(phba->slim2p, 0, SLI2_SLIM_SIZE);
  
+       phba->hbqslimp.virt = dma_alloc_coherent(&phba->pcidev->dev,
+                                                lpfc_sli_hbq_size(),
+                                                &phba->hbqslimp.phys,
+                                                GFP_KERNEL);
+       if (!phba->hbqslimp.virt)
+               goto out_free_slim;
+       memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size());
        /* Initialize the SLI Layer to run with lpfc HBAs. */
        lpfc_sli_setup(phba);
        lpfc_sli_queue_setup(phba);
  
        error = lpfc_mem_alloc(phba);
        if (error)
-               goto out_free_slim;
+               goto out_free_hbqslimp;
  
        /* Initialize and populate the iocb list per host.  */
        INIT_LIST_HEAD(&phba->lpfc_iocb_list);
                        error = -ENOMEM;
                        goto out_free_iocbq;
                }
-               spin_lock_irq(phba->host->host_lock);
+               spin_lock_irq(&phba->hbalock);
                list_add(&iocbq_entry->list, &phba->lpfc_iocb_list);
                phba->total_iocbq_bufs++;
-               spin_unlock_irq(phba->host->host_lock);
+               spin_unlock_irq(&phba->hbalock);
        }
  
        /* Initialize HBA structure */
                goto out_free_iocbq;
        }
  
-       /*
-        * Set initial can_queue value since 0 is no longer supported and
-        * scsi_add_host will fail. This will be adjusted later based on the
-        * max xri value determined in hba setup.
-        */
-       host->can_queue = phba->cfg_hba_queue_depth - 10;
-       /* Tell the midlayer we support 16 byte commands */
-       host->max_cmd_len = 16;
        /* Initialize the list of scsi buffers used by driver for scsi IO. */
        spin_lock_init(&phba->scsi_buf_list_lock);
        INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
  
-       host->transportt = lpfc_transport_template;
-       pci_set_drvdata(pdev, host);
+       /* Initialize list of fabric iocbs */
+       INIT_LIST_HEAD(&phba->fabric_iocb_list);
+       vport = lpfc_create_port(phba, phba->brd_no, NULL);
+       if (!vport)
+               goto out_kthread_stop;
+       shost = lpfc_shost_from_vport(vport);
+       phba->pport = vport;
+       lpfc_debugfs_initialize(vport);
+       pci_set_drvdata(pdev, shost);
  
        if (phba->cfg_use_msi) {
                error = pci_enable_msi(phba->pcidev);
        }
  
        error = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED,
-                                                       LPFC_DRIVER_NAME, phba);
+                           LPFC_DRIVER_NAME, phba);
        if (error) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                        "%d:0451 Enable interrupt handler failed\n",
                        phba->brd_no);
-               goto out_kthread_stop;
+               goto out_disable_msi;
        }
  
-       error = scsi_add_host(host, &pdev->dev);
-       if (error)
+       phba->MBslimaddr = phba->slim_memmap_p;
+       phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
+       phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
+       phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
+       phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
+       if (lpfc_alloc_sysfs_attr(vport))
                goto out_free_irq;
  
-       scsi_scan_host(host);
+       if (lpfc_sli_hba_setup(phba))
+               goto out_remove_device;
+       /*
+        * hba setup may have changed the hba_queue_depth so we need to adjust
+        * the value of can_queue.
+        */
+       shost->can_queue = phba->cfg_hba_queue_depth - 10;
+       lpfc_host_attrib_init(shost);
+       if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+               spin_lock_irq(shost->host_lock);
+               lpfc_poll_start_timer(phba);
+               spin_unlock_irq(shost->host_lock);
+       }
+       scsi_scan_host(shost);
  
        return 0;
  
+ out_remove_device:
+       lpfc_free_sysfs_attr(vport);
+       spin_lock_irq(shost->host_lock);
+       vport->fc_flag |= FC_UNLOADING;
+       spin_unlock_irq(shost->host_lock);
  out_free_irq:
-       lpfc_stop_timer(phba);
-       phba->work_hba_events = 0;
+       lpfc_stop_phba_timers(phba);
+       phba->pport->work_port_events = 0;
        free_irq(phba->pcidev->irq, phba);
+ out_disable_msi:
        pci_disable_msi(phba->pcidev);
+       destroy_port(vport);
  out_kthread_stop:
        kthread_stop(phba->worker_thread);
  out_free_iocbq:
        list_for_each_entry_safe(iocbq_entry, iocbq_next,
                                                &phba->lpfc_iocb_list, list) {
-               spin_lock_irq(phba->host->host_lock);
                kfree(iocbq_entry);
                phba->total_iocbq_bufs--;
-               spin_unlock_irq(phba->host->host_lock);
        }
        lpfc_mem_free(phba);
+ out_free_hbqslimp:
+       dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
+                         phba->hbqslimp.phys);
  out_free_slim:
        dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE, phba->slim2p,
                                                        phba->slim2p_mapping);
@@@ -1741,27 -1974,85 +1971,85 @@@ out_iounmap_slim
        iounmap(phba->slim_memmap_p);
  out_idr_remove:
        idr_remove(&lpfc_hba_index, phba->brd_no);
- out_put_host:
-       phba->host = NULL;
-       scsi_host_put(host);
+ out_free_phba:
+       kfree(phba);
  out_release_regions:
        pci_release_regions(pdev);
  out_disable_device:
        pci_disable_device(pdev);
  out:
        pci_set_drvdata(pdev, NULL);
+       if (shost)
+               scsi_host_put(shost);
        return error;
  }
  
  static void __devexit
  lpfc_pci_remove_one(struct pci_dev *pdev)
  {
-       struct Scsi_Host   *host = pci_get_drvdata(pdev);
-       struct lpfc_hba    *phba = (struct lpfc_hba *)host->hostdata;
+       struct Scsi_Host  *shost = pci_get_drvdata(pdev);
+       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       struct lpfc_vport *port_iterator;
+       list_for_each_entry(port_iterator, &phba->port_list, listentry)
+               port_iterator->load_flag |= FC_UNLOADING;
+       kfree(vport->vname);
+       lpfc_free_sysfs_attr(vport);
+       fc_remove_host(shost);
+       scsi_remove_host(shost);
+       /*
+        * Bring down the SLI Layer. This step disable all interrupts,
+        * clears the rings, discards all mailbox commands, and resets
+        * the HBA.
+        */
+       lpfc_sli_hba_down(phba);
+       lpfc_sli_brdrestart(phba);
+       lpfc_stop_phba_timers(phba);
+       spin_lock_irq(&phba->hbalock);
+       list_del_init(&vport->listentry);
+       spin_unlock_irq(&phba->hbalock);
  
-       lpfc_remove_device(phba);
+       lpfc_debugfs_terminate(vport);
+       lpfc_cleanup(vport);
+       kthread_stop(phba->worker_thread);
+       /* Release the irq reservation */
+       free_irq(phba->pcidev->irq, phba);
+       pci_disable_msi(phba->pcidev);
  
        pci_set_drvdata(pdev, NULL);
+       scsi_host_put(shost);
+       /*
+        * Call scsi_free before mem_free since scsi bufs are released to their
+        * corresponding pools here.
+        */
+       lpfc_scsi_free(phba);
+       lpfc_mem_free(phba);
+       dma_free_coherent(&pdev->dev, lpfc_sli_hbq_size(), phba->hbqslimp.virt,
+                         phba->hbqslimp.phys);
+       /* Free resources associated with SLI2 interface */
+       dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
+                         phba->slim2p, phba->slim2p_mapping);
+       /* unmap adapter SLIM and Control Registers */
+       iounmap(phba->ctrl_regs_memmap_p);
+       iounmap(phba->slim_memmap_p);
+       idr_remove(&lpfc_hba_index, phba->brd_no);
+       kfree(phba);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
  }
  
  /**
@@@ -1819,10 -2110,13 +2107,13 @@@ static pci_ers_result_t lpfc_io_slot_re
        pci_set_master(pdev);
  
        /* Re-establishing Link */
-       spin_lock_irq(phba->host->host_lock);
-       phba->fc_flag |= FC_ESTABLISH_LINK;
+       spin_lock_irq(host->host_lock);
+       phba->pport->fc_flag |= FC_ESTABLISH_LINK;
+       spin_unlock_irq(host->host_lock);
+       spin_lock_irq(&phba->hbalock);
        psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
-       spin_unlock_irq(phba->host->host_lock);
+       spin_unlock_irq(&phba->hbalock);
  
  
        /* Take device offline; this will perform cleanup */
@@@ -1932,7 -2226,7 +2223,7 @@@ static struct pci_driver lpfc_driver = 
        .id_table       = lpfc_id_table,
        .probe          = lpfc_pci_probe_one,
        .remove         = __devexit_p(lpfc_pci_remove_one),
-       .err_handler = &lpfc_err_handler,
+       .err_handler    = &lpfc_err_handler,
  };
  
  static int __init
@@@ -1945,11 -2239,15 +2236,15 @@@ lpfc_init(void
  
        lpfc_transport_template =
                                fc_attach_transport(&lpfc_transport_functions);
-       if (!lpfc_transport_template)
+       lpfc_vport_transport_template =
+                       fc_attach_transport(&lpfc_vport_transport_functions);
+       if (!lpfc_transport_template || !lpfc_vport_transport_template)
                return -ENOMEM;
        error = pci_register_driver(&lpfc_driver);
-       if (error)
+       if (error) {
                fc_release_transport(lpfc_transport_template);
+               fc_release_transport(lpfc_vport_transport_template);
+       }
  
        return error;
  }
@@@ -1959,6 -2257,7 +2254,7 @@@ lpfc_exit(void
  {
        pci_unregister_driver(&lpfc_driver);
        fc_release_transport(lpfc_transport_template);
+       fc_release_transport(lpfc_vport_transport_template);
  }
  
  module_init(lpfc_init);
diff --combined drivers/scsi/nsp32.c
index 3e9765f0281d948669347b1ef6e309ce36122adb,8cc9e64bbdff4806e923ef66d07279b4864a0e42..7fed35372150afe68d619d61d4faa4a2a4588437
  #include <scsi/scsi_host.h>
  #include <scsi/scsi_ioctl.h>
  
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
- # include <linux/blk.h>
- #endif
  #include "nsp32.h"
  
  
@@@ -199,17 -195,9 +195,9 @@@ static int  __init    init_nsp32  (void
  static void __exit    exit_nsp32  (void);
  
  /* struct struct scsi_host_template */
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
  static int         nsp32_proc_info   (struct Scsi_Host *, char *, char **, off_t, int, int);
- #else
- static int         nsp32_proc_info   (char *, char **, off_t, int, int, int);
- #endif
  
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
  static int         nsp32_detect      (struct pci_dev *pdev);
- #else
- static int         nsp32_detect      (struct scsi_host_template *);
- #endif
  static int         nsp32_queuecommand(struct scsi_cmnd *,
                void (*done)(struct scsi_cmnd *));
  static const char *nsp32_info        (struct Scsi_Host *);
@@@ -296,15 -284,7 +284,7 @@@ static struct scsi_host_template nsp32_
        .eh_abort_handler               = nsp32_eh_abort,
        .eh_bus_reset_handler           = nsp32_eh_bus_reset,
        .eh_host_reset_handler          = nsp32_eh_host_reset,
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74))
-       .detect                         = nsp32_detect,
-       .release                        = nsp32_release,
- #endif
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
-       .use_new_eh_code                = 1,
- #else
  /*    .highmem_io                     = 1, */
- #endif
  };
  
  #include "nsp32_io.h"
@@@ -739,7 -719,7 +719,7 @@@ static int nsp32_selection_autoscsi(str
        command = 0;
        command |= (TRANSFER_GO | ALL_COUNTER_CLR);
        if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
-               if (SCpnt->request_bufflen > 0) {
+               if (scsi_bufflen(SCpnt) > 0) {
                        command |= BM_START;
                }
        } else if (data->trans_method & NSP32_TRANSFER_MMIO) {
@@@ -888,31 -868,28 +868,28 @@@ static int nsp32_reselection(struct scs
  static int nsp32_setup_sg_table(struct scsi_cmnd *SCpnt)
  {
        nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
-       struct scatterlist   *sgl;
+       struct scatterlist *sg;
        nsp32_sgtable *sgt = data->cur_lunt->sglun->sgt;
        int num, i;
        u32_le l;
  
-       if (SCpnt->request_bufflen == 0) {
-               return TRUE;
-       }
        if (sgt == NULL) {
                nsp32_dbg(NSP32_DEBUG_SGLIST, "SGT == null");
                return FALSE;
        }
  
-       if (SCpnt->use_sg) {
-               sgl = (struct scatterlist *)SCpnt->request_buffer;
-               num = pci_map_sg(data->Pci, sgl, SCpnt->use_sg,
-                                SCpnt->sc_data_direction);
-               for (i = 0; i < num; i++) {
+       num = scsi_dma_map(SCpnt);
+       if (!num)
+               return TRUE;
+       else if (num < 0)
+               return FALSE;
+       else {
+               scsi_for_each_sg(SCpnt, sg, num, i) {
                        /*
                         * Build nsp32_sglist, substitute sg dma addresses.
                         */
-                       sgt[i].addr = cpu_to_le32(sg_dma_address(sgl));
-                       sgt[i].len  = cpu_to_le32(sg_dma_len(sgl));
-                       sgl++;
+                       sgt[i].addr = cpu_to_le32(sg_dma_address(sg));
+                       sgt[i].len  = cpu_to_le32(sg_dma_len(sg));
  
                        if (le32_to_cpu(sgt[i].len) > 0x10000) {
                                nsp32_msg(KERN_ERR,
                /* set end mark */
                l = le32_to_cpu(sgt[num-1].len);
                sgt[num-1].len = cpu_to_le32(l | SGTEND);
-       } else {
-               SCpnt->SCp.have_data_in = pci_map_single(data->Pci,
-                       SCpnt->request_buffer, SCpnt->request_bufflen,
-                       SCpnt->sc_data_direction);
-               sgt[0].addr = cpu_to_le32(SCpnt->SCp.have_data_in);
-               sgt[0].len  = cpu_to_le32(SCpnt->request_bufflen | SGTEND); /* set end mark */
-               if (SCpnt->request_bufflen > 0x10000) {
-                       nsp32_msg(KERN_ERR,
-                                 "can't transfer over 64KB at a time, size=0x%lx", SCpnt->request_bufflen);
-                       return FALSE;
-               }
-               nsp32_dbg(NSP32_DEBUG_SGLIST, "single : addr 0x%lx len=0x%lx",
-                         le32_to_cpu(sgt[0].addr),
-                         le32_to_cpu(sgt[0].len ));
        }
  
        return TRUE;
@@@ -962,7 -922,7 +922,7 @@@ static int nsp32_queuecommand(struct sc
                  "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x "
                  "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x",
                  SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len,
-                 SCpnt->use_sg, SCpnt->request_buffer, SCpnt->request_bufflen);
+                 scsi_sg_count(SCpnt), scsi_sglist(SCpnt), scsi_bufflen(SCpnt));
  
        if (data->CurrentSC != NULL) {
                nsp32_msg(KERN_ERR, "Currentsc != NULL. Cancel this command request");
        data->CurrentSC      = SCpnt;
        SCpnt->SCp.Status    = CHECK_CONDITION;
        SCpnt->SCp.Message   = 0;
-       SCpnt->resid         = SCpnt->request_bufflen;
+       scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
  
-       SCpnt->SCp.ptr              = (char *) SCpnt->request_buffer;
-       SCpnt->SCp.this_residual    = SCpnt->request_bufflen;
+       SCpnt->SCp.ptr              = (char *)scsi_sglist(SCpnt);
+       SCpnt->SCp.this_residual    = scsi_bufflen(SCpnt);
        SCpnt->SCp.buffer           = NULL;
        SCpnt->SCp.buffers_residual = 0;
  
@@@ -1210,13 -1170,9 +1170,9 @@@ static irqreturn_t do_nsp32_isr(int irq
        unsigned long flags;
        int ret;
        int handled = 0;
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
        struct Scsi_Host *host = data->Host;
        spin_lock_irqsave(host->host_lock, flags);
- #else
-       spin_lock_irqsave(&io_request_lock, flags);
- #endif
  
        /*
         * IRQ check, then enable IRQ mask
                }
  
                if ((auto_stat & DATA_IN_PHASE) &&
-                   (SCpnt->resid > 0) &&
+                   (scsi_get_resid(SCpnt) > 0) &&
                    ((nsp32_read2(base, FIFO_REST_CNT) & FIFO_REST_MASK) != 0)) {
                        printk( "auto+fifo\n");
                        //nsp32_pio_read(SCpnt);
                        nsp32_dbg(NSP32_DEBUG_INTR, "SSACK=0x%lx", 
                                    nsp32_read4(base, SAVED_SACK_CNT));
  
-                       SCpnt->resid = 0; /* all data transfered! */
+                       scsi_set_resid(SCpnt, 0); /* all data transfered! */
                }
  
                /*
        nsp32_write2(base, IRQ_CONTROL, 0);
  
   out2:
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
        spin_unlock_irqrestore(host->host_lock, flags);
- #else
-       spin_unlock_irqrestore(&io_request_lock, flags);
- #endif
  
        nsp32_dbg(NSP32_DEBUG_INTR, "exit");
  
                        nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
                } \
        } while(0)
- static int nsp32_proc_info(
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
-       struct Scsi_Host *host,
- #endif
-       char             *buffer,
-       char            **start,
-       off_t             offset,
-       int               length,
- #if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
-       int               hostno,
- #endif
-       int               inout)
+ static int nsp32_proc_info(struct Scsi_Host *host, char *buffer, char **start,
+                          off_t offset, int length, int inout)
  {
        char             *pos = buffer;
        int               thislength;
        unsigned long     flags;
        nsp32_hw_data    *data;
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
        int               hostno;
- #else
-       struct Scsi_Host *host;
- #endif
        unsigned int      base;
        unsigned char     mode_reg;
        int               id, speed;
                return -EINVAL;
        }
  
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
        hostno = host->host_no;
- #else
-       /* search this HBA host */
-       host = scsi_host_hn_get(hostno);
-       if (host == NULL) {
-               return -ESRCH;
-       }
- #endif
        data = (nsp32_hw_data *)host->hostdata;
        base = host->io_port;
  
@@@ -1626,25 -1557,8 +1557,8 @@@ static void nsp32_scsi_done(struct scsi
        nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
        unsigned int   base = SCpnt->device->host->io_port;
  
-       /*
-        * unmap pci
-        */
-       if (SCpnt->request_bufflen == 0) {
-               goto skip;
-       }
+       scsi_dma_unmap(SCpnt);
  
-       if (SCpnt->use_sg) {
-               pci_unmap_sg(data->Pci,
-                            (struct scatterlist *)SCpnt->request_buffer,
-                            SCpnt->use_sg, SCpnt->sc_data_direction);
-       } else {
-               pci_unmap_single(data->Pci,
-                                (u32)SCpnt->SCp.have_data_in,
-                                SCpnt->request_bufflen,
-                                SCpnt->sc_data_direction);
-       }
-  skip:
        /*
         * clear TRANSFERCONTROL_BM_START
         */
@@@ -1800,7 -1714,7 +1714,7 @@@ static int nsp32_busfree_occur(struct s
                SCpnt->SCp.Message = 0;
                nsp32_dbg(NSP32_DEBUG_BUSFREE, 
                          "normal end stat=0x%x resid=0x%x\n",
-                         SCpnt->SCp.Status, SCpnt->resid);
+                         SCpnt->SCp.Status, scsi_get_resid(SCpnt));
                SCpnt->result = (DID_OK             << 16) |
                                (SCpnt->SCp.Message <<  8) |
                                (SCpnt->SCp.Status  <<  0);
@@@ -1844,7 -1758,7 +1758,7 @@@ static void nsp32_adjust_busfree(struc
        unsigned int          restlen, sentlen;
        u32_le                len, addr;
  
-       nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", SCpnt->resid);
+       nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", scsi_get_resid(SCpnt));
  
        /* adjust saved SACK count with 4 byte start address boundary */
        s_sacklen -= le32_to_cpu(sgt[old_entry].addr) & 3;
        return;
  
   last:
-       if (SCpnt->resid < sentlen) {
+       if (scsi_get_resid(SCpnt) < sentlen) {
                nsp32_msg(KERN_ERR, "resid underflow");
        }
  
-       SCpnt->resid -= sentlen;
-       nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", SCpnt->resid);
+       scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) - sentlen);
+       nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", scsi_get_resid(SCpnt));
  
        /* update hostdata and lun */
  
@@@ -2022,7 -1936,7 +1936,7 @@@ static void nsp32_restart_autoscsi(stru
        transfer = 0;
        transfer |= (TRANSFER_GO | ALL_COUNTER_CLR);
        if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
-               if (SCpnt->request_bufflen > 0) {
+               if (scsi_bufflen(SCpnt) > 0) {
                        transfer |= BM_START;
                }
        } else if (data->trans_method & NSP32_TRANSFER_MMIO) {
@@@ -2674,17 -2588,7 +2588,7 @@@ static void nsp32_sack_negate(nsp32_hw_
   *    0x900-0xbff: (map same 0x800-0x8ff I/O port image repeatedly)
   *    0xc00-0xfff: CardBus status registers
   */
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
- #define DETECT_OK 0
- #define DETECT_NG 1
- #define PCIDEV    pdev
  static int nsp32_detect(struct pci_dev *pdev)
- #else
- #define DETECT_OK 1
- #define DETECT_NG 0
- #define PCIDEV    (data->Pci)
- static int nsp32_detect(struct scsi_host_template *sht)
- #endif
  {
        struct Scsi_Host *host; /* registered host structure */
        struct resource  *res;
        /*
         * register this HBA as SCSI device
         */
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
        host = scsi_host_alloc(&nsp32_template, sizeof(nsp32_hw_data));
- #else
-       host = scsi_register(sht, sizeof(nsp32_hw_data));
- #endif
        if (host == NULL) {
                nsp32_msg (KERN_ERR, "failed to scsi register");
                goto err;
        host->unique_id = data->BaseAddress;
        host->n_io_port = data->NumAddress;
        host->base      = (unsigned long)data->MmioAddress;
- #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,63))
-       scsi_set_pci_device(host, PCIDEV);
- #endif
  
        data->Host      = host;
        spin_lock_init(&(data->Lock));
        /*
         * setup DMA 
         */
-       if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) {
+       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
                nsp32_msg (KERN_ERR, "failed to set PCI DMA mask");
                goto scsi_unregister;
        }
        /*
         * allocate autoparam DMA resource.
         */
-       data->autoparam = pci_alloc_consistent(PCIDEV, sizeof(nsp32_autoparam), &(data->auto_paddr));
+       data->autoparam = pci_alloc_consistent(pdev, sizeof(nsp32_autoparam), &(data->auto_paddr));
        if (data->autoparam == NULL) {
                nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
                goto scsi_unregister;
        /*
         * allocate scatter-gather DMA resource.
         */
-       data->sg_list = pci_alloc_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+       data->sg_list = pci_alloc_consistent(pdev, NSP32_SG_TABLE_SIZE,
                                             &(data->sg_paddr));
        if (data->sg_list == NULL) {
                nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
                goto free_irq;
          }
  
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
-       ret = scsi_add_host(host, &PCIDEV->dev);
+       ret = scsi_add_host(host, &pdev->dev);
        if (ret) {
                nsp32_msg(KERN_ERR, "failed to add scsi host");
                goto free_region;
        }
        scsi_scan_host(host);
- #endif
-       pci_set_drvdata(PCIDEV, host);
-       return DETECT_OK;
+       pci_set_drvdata(pdev, host);
+       return 0;
  
   free_region:
        release_region(host->io_port, host->n_io_port);
        free_irq(host->irq, data);
  
   free_sg_list:
-       pci_free_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+       pci_free_consistent(pdev, NSP32_SG_TABLE_SIZE,
                            data->sg_list, data->sg_paddr);
  
   free_autoparam:
-       pci_free_consistent(PCIDEV, sizeof(nsp32_autoparam),
+       pci_free_consistent(pdev, sizeof(nsp32_autoparam),
                            data->autoparam, data->auto_paddr);
        
   scsi_unregister:
        scsi_host_put(host);
  
   err:
-       return DETECT_NG;
+       return 1;
  }
- #undef DETECT_OK
- #undef DETECT_NG
- #undef PCIDEV
  
  static int nsp32_release(struct Scsi_Host *host)
  {
@@@ -3487,6 -3379,15 +3379,6 @@@ static int nsp32_resume(struct pci_dev 
        return 0;
  }
  
 -/* Enable wake event */
 -static int nsp32_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable)
 -{
 -      struct Scsi_Host *host = pci_get_drvdata(pdev);
 -
 -      nsp32_msg(KERN_INFO, "pci-enable_wake: stub, pdev=0x%p, enable=%d, slot=%s, host=0x%p", pdev, enable, pci_name(pdev), host);
 -
 -      return 0;
 -}
  #endif
  
  /************************************************************************
@@@ -3516,11 -3417,7 +3408,7 @@@ static int __devinit nsp32_probe(struc
  
        pci_set_master(pdev);
  
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
        ret = nsp32_detect(pdev);
- #else
-       ret = scsi_register_host(&nsp32_template);
- #endif
  
        nsp32_msg(KERN_INFO, "irq: %i mmio: %p+0x%lx slot: %s model: %s",
                  pdev->irq,
  
  static void __devexit nsp32_remove(struct pci_dev *pdev)
  {
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
        struct Scsi_Host *host = pci_get_drvdata(pdev);
- #endif
  
        nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
  
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
          scsi_remove_host(host);
  
        nsp32_release(host);
  
        scsi_host_put(host);
- #else
-       scsi_unregister_host(&nsp32_template);  
- #endif
  }
  
  static struct pci_driver nsp32_driver = {
        .name           = "nsp32",
        .id_table       = nsp32_pci_table,
  #ifdef CONFIG_PM
        .suspend        = nsp32_suspend, 
        .resume         = nsp32_resume, 
 -      .enable_wake    = nsp32_enable_wake,
  #endif
  };
  
index 942db9de785efb274ff10aa311e93d994e1fd885,b79c4dfc2a9c239c60a08e0a44896906dc0e8049..3eb2208675aef00d164bd6889aa6089f0d8cf1b9
@@@ -6,14 -6,16 +6,17 @@@
   */
  #include "qla_def.h"
  
+ #include <linux/kthread.h>
  #include <linux/vmalloc.h>
  
+ int qla24xx_vport_disable(struct fc_vport *, bool);
  /* SYSFS attributes --------------------------------------------------------- */
  
  static ssize_t
 -qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
 +                         struct bin_attribute *bin_attr,
 +                         char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@@ -32,9 -34,8 +35,9 @@@
  }
  
  static ssize_t
 -qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
 +                          struct bin_attribute *bin_attr,
 +                          char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@@ -75,6 -76,7 +78,6 @@@ static struct bin_attribute sysfs_fw_du
        .attr = {
                .name = "fw_dump",
                .mode = S_IRUSR | S_IWUSR,
 -              .owner = THIS_MODULE,
        },
        .size = 0,
        .read = qla2x00_sysfs_read_fw_dump,
@@@ -82,9 -84,8 +85,9 @@@
  };
  
  static ssize_t
 -qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_read_nvram(struct kobject *kobj,
 +                       struct bin_attribute *bin_attr,
 +                       char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
  }
  
  static ssize_t
 -qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_write_nvram(struct kobject *kobj,
 +                        struct bin_attribute *bin_attr,
 +                        char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@@ -152,6 -152,7 +155,6 @@@ static struct bin_attribute sysfs_nvram
        .attr = {
                .name = "nvram",
                .mode = S_IRUSR | S_IWUSR,
 -              .owner = THIS_MODULE,
        },
        .size = 512,
        .read = qla2x00_sysfs_read_nvram,
  };
  
  static ssize_t
 -qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_read_optrom(struct kobject *kobj,
 +                        struct bin_attribute *bin_attr,
 +                        char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
  }
  
  static ssize_t
 -qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_write_optrom(struct kobject *kobj,
 +                         struct bin_attribute *bin_attr,
 +                         char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@@ -202,6 -201,7 +205,6 @@@ static struct bin_attribute sysfs_optro
        .attr = {
                .name = "optrom",
                .mode = S_IRUSR | S_IWUSR,
 -              .owner = THIS_MODULE,
        },
        .size = OPTROM_SIZE_24XX,
        .read = qla2x00_sysfs_read_optrom,
  };
  
  static ssize_t
 -qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
 +                             struct bin_attribute *bin_attr,
 +                             char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@@ -283,15 -282,15 +286,15 @@@ static struct bin_attribute sysfs_optro
        .attr = {
                .name = "optrom_ctl",
                .mode = S_IWUSR,
 -              .owner = THIS_MODULE,
        },
        .size = 0,
        .write = qla2x00_sysfs_write_optrom_ctl,
  };
  
  static ssize_t
 -qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_read_vpd(struct kobject *kobj,
 +                     struct bin_attribute *bin_attr,
 +                     char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
  }
  
  static ssize_t
 -qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_write_vpd(struct kobject *kobj,
 +                      struct bin_attribute *bin_attr,
 +                      char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@@ -332,6 -330,7 +335,6 @@@ static struct bin_attribute sysfs_vpd_a
        .attr = {
                .name = "vpd",
                .mode = S_IRUSR | S_IWUSR,
 -              .owner = THIS_MODULE,
        },
        .size = 0,
        .read = qla2x00_sysfs_read_vpd,
  };
  
  static ssize_t
 -qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
 -    size_t count)
 +qla2x00_sysfs_read_sfp(struct kobject *kobj,
 +                     struct bin_attribute *bin_attr,
 +                     char *buf, loff_t off, size_t count)
  {
        struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
            struct device, kobj)));
@@@ -380,6 -378,7 +383,6 @@@ static struct bin_attribute sysfs_sfp_a
        .attr = {
                .name = "sfp",
                .mode = S_IRUSR | S_IWUSR,
 -              .owner = THIS_MODULE,
        },
        .size = SFP_DEV_SIZE * 2,
        .read = qla2x00_sysfs_read_sfp,
@@@ -963,6 -962,122 +966,122 @@@ qla2x00_get_host_port_state(struct Scsi
                fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
  }
  
+ static int
+ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
+ {
+       int     ret = 0;
+       scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+       scsi_qla_host_t *vha;
+       ret = qla24xx_vport_create_req_sanity_check(fc_vport);
+       if (ret) {
+               DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, "
+                   "status %x\n", ret));
+               return (ret);
+       }
+       vha = qla24xx_create_vhost(fc_vport);
+       if (vha == NULL) {
+               DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n",
+                   vha));
+               return FC_VPORT_FAILED;
+       }
+       if (disable) {
+               atomic_set(&vha->vp_state, VP_OFFLINE);
+               fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
+       } else
+               atomic_set(&vha->vp_state, VP_FAILED);
+       /* ready to create vport */
+       qla_printk(KERN_INFO, vha, "VP entry id %d assigned.\n", vha->vp_idx);
+       /* initialized vport states */
+       atomic_set(&vha->loop_state, LOOP_DOWN);
+       vha->vp_err_state=  VP_ERR_PORTDWN;
+       vha->vp_prev_err_state=  VP_ERR_UNKWN;
+       /* Check if physical ha port is Up */
+       if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
+           atomic_read(&ha->loop_state) == LOOP_DEAD) {
+               /* Don't retry or attempt login of this virtual port */
+               DEBUG15(printk ("scsi(%ld): pport loop_state is not UP.\n",
+                   vha->host_no));
+               atomic_set(&vha->loop_state, LOOP_DEAD);
+               if (!disable)
+                       fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
+       }
+       if (scsi_add_host(vha->host, &fc_vport->dev)) {
+               DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
+                       vha->host_no, vha->vp_idx));
+               goto vport_create_failed_2;
+       }
+       /* initialize attributes */
+       fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
+       fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
+       fc_host_supported_classes(vha->host) =
+               fc_host_supported_classes(ha->host);
+       fc_host_supported_speeds(vha->host) =
+               fc_host_supported_speeds(ha->host);
+       qla24xx_vport_disable(fc_vport, disable);
+       return 0;
+ vport_create_failed_2:
+       qla24xx_disable_vp(vha);
+       qla24xx_deallocate_vp_id(vha);
+       kfree(vha->port_name);
+       kfree(vha->node_name);
+       scsi_host_put(vha->host);
+       return FC_VPORT_FAILED;
+ }
+ int
+ qla24xx_vport_delete(struct fc_vport *fc_vport)
+ {
+       scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
+       scsi_qla_host_t *vha = fc_vport->dd_data;
+       qla24xx_disable_vp(vha);
+       qla24xx_deallocate_vp_id(vha);
+       down(&ha->vport_sem);
+       ha->cur_vport_count--;
+       clear_bit(vha->vp_idx, (unsigned long *)ha->vp_idx_map);
+       up(&ha->vport_sem);
+       kfree(vha->node_name);
+       kfree(vha->port_name);
+       if (vha->timer_active) {
+               qla2x00_vp_stop_timer(vha);
+               DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p "
+                   "has stopped\n",
+                   vha->host_no, vha->vp_idx, vha));
+         }
+       fc_remove_host(vha->host);
+       scsi_remove_host(vha->host);
+       scsi_host_put(vha->host);
+       return 0;
+ }
+ int
+ qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable)
+ {
+       scsi_qla_host_t *vha = fc_vport->dd_data;
+       if (disable)
+               qla24xx_disable_vp(vha);
+       else
+               qla24xx_enable_vp(vha);
+       return 0;
+ }
  struct fc_function_template qla2xxx_transport_functions = {
  
        .show_host_node_name = 1,
  
        .issue_fc_host_lip = qla2x00_issue_lip,
        .get_fc_host_stats = qla2x00_get_fc_host_stats,
+       .vport_create = qla24xx_vport_create,
+       .vport_disable = qla24xx_vport_disable,
+       .vport_delete = qla24xx_vport_delete,
+ };
+ struct fc_function_template qla2xxx_transport_vport_functions = {
+       .show_host_node_name = 1,
+       .show_host_port_name = 1,
+       .show_host_supported_classes = 1,
+       .get_host_port_id = qla2x00_get_host_port_id,
+       .show_host_port_id = 1,
+       .get_host_speed = qla2x00_get_host_speed,
+       .show_host_speed = 1,
+       .get_host_port_type = qla2x00_get_host_port_type,
+       .show_host_port_type = 1,
+       .get_host_symbolic_name = qla2x00_get_host_symbolic_name,
+       .show_host_symbolic_name = 1,
+       .set_host_system_hostname = qla2x00_set_host_system_hostname,
+       .show_host_system_hostname = 1,
+       .get_host_fabric_name = qla2x00_get_host_fabric_name,
+       .show_host_fabric_name = 1,
+       .get_host_port_state = qla2x00_get_host_port_state,
+       .show_host_port_state = 1,
+       .dd_fcrport_size = sizeof(struct fc_port *),
+       .show_rport_supported_classes = 1,
+       .get_starget_node_name = qla2x00_get_starget_node_name,
+       .show_starget_node_name = 1,
+       .get_starget_port_name = qla2x00_get_starget_port_name,
+       .show_starget_port_name = 1,
+       .get_starget_port_id  = qla2x00_get_starget_port_id,
+       .show_starget_port_id = 1,
+       .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
+       .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
+       .show_rport_dev_loss_tmo = 1,
+       .issue_fc_host_lip = qla2x00_issue_lip,
+       .get_fc_host_stats = qla2x00_get_fc_host_stats,
  };
  
  void
@@@ -1008,4 -1166,6 +1170,6 @@@ qla2x00_init_host_attr(scsi_qla_host_t 
        fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name);
        fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
        fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
+       fc_host_max_npiv_vports(ha->host) = MAX_NUM_VPORT_FABRIC;
+       fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count;
  }
index cf94f8636ba5af6b5504d5acb6995f0e9a7aaeae,bd95f7dc5cfce9a9279d71268952ad354f92b7f9..cc6ebb609e987447ef91154265039496b58458d0
@@@ -296,7 -296,7 +296,7 @@@ qla24xx_pci_config(scsi_qla_host_t *ha
        d &= ~PCI_ROM_ADDRESS_ENABLE;
        pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
  
 -      pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->chip_revision);
 +      ha->chip_revision = ha->pdev->revision;
  
        /* Get PCI bus information. */
        spin_lock_irqsave(&ha->hardware_lock, flags);
@@@ -899,6 -899,10 +899,10 @@@ qla2x00_setup_chip(scsi_qla_host_t *ha
                                    &ha->fw_subminor_version,
                                    &ha->fw_attributes, &ha->fw_memory_size);
                                qla2x00_resize_request_q(ha);
+                               ha->flags.npiv_supported = 0;
+                               if (IS_QLA24XX(ha) &&
+                                   (ha->fw_attributes & BIT_2))
+                                       ha->flags.npiv_supported = 1;
  
                                if (ql2xallocfwdump)
                                        qla2x00_alloc_fw_dump(ha);
@@@ -1101,6 -1105,8 +1105,8 @@@ qla2x00_init_rings(scsi_qla_host_t *ha
        int     rval;
        unsigned long flags = 0;
        int cnt;
+       struct mid_init_cb_24xx *mid_init_cb =
+           (struct mid_init_cb_24xx *) ha->init_cb;
  
        spin_lock_irqsave(&ha->hardware_lock, flags);
  
        ha->isp_ops.update_fw_options(ha);
  
        DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));
+       mid_init_cb->count = MAX_NUM_VPORT_FABRIC;
+       ha->max_npiv_vports = MAX_NUM_VPORT_FABRIC;
        rval = qla2x00_init_firmware(ha, ha->init_cb_size);
        if (rval) {
                DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n",
@@@ -1263,6 -1273,7 +1273,7 @@@ qla2x00_configure_hba(scsi_qla_host_t *
        int       rval;
        uint16_t      loop_id;
        uint16_t      topo;
+       uint16_t      sw_cap;
        uint8_t       al_pa;
        uint8_t       area;
        uint8_t       domain;
  
        /* Get host addresses. */
        rval = qla2x00_get_adapter_id(ha,
-           &loop_id, &al_pa, &area, &domain, &topo);
+           &loop_id, &al_pa, &area, &domain, &topo, &sw_cap);
        if (rval != QLA_SUCCESS) {
                if (LOOP_TRANSITION(ha) || atomic_read(&ha->loop_down_timer) ||
                    (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {
        /* initialize */
        ha->min_external_loopid = SNS_FIRST_LOOP_ID;
        ha->operating_mode = LOOP;
+       ha->switch_cap = 0;
  
        switch (topo) {
        case 0:
        case 1:
                DEBUG3(printk("scsi(%ld): HBA in FL topology.\n",
                    ha->host_no));
+               ha->switch_cap = sw_cap;
                ha->current_topology = ISP_CFG_FL;
                strcpy(connect_type, "(FL_Port)");
                break;
        case 3:
                DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n",
                    ha->host_no));
+               ha->switch_cap = sw_cap;
                ha->operating_mode = P2P;
                ha->current_topology = ISP_CFG_F;
                strcpy(connect_type, "(F_Port)");
@@@ -1743,7 -1757,6 +1757,6 @@@ qla2x00_rport_del(void *data
        spin_unlock_irqrestore(&fcport->rport_lock, flags);
        if (rport)
                fc_remote_port_delete(rport);
  }
  
  /**
@@@ -1765,6 -1778,7 +1778,7 @@@ qla2x00_alloc_fcport(scsi_qla_host_t *h
        /* Setup fcport template structure. */
        memset(fcport, 0, sizeof (fc_port_t));
        fcport->ha = ha;
+       fcport->vp_idx = ha->vp_idx;
        fcport->port_type = FCT_UNKNOWN;
        fcport->loop_id = FC_NO_LOOP_ID;
        atomic_set(&fcport->state, FCS_UNCONFIGURED);
@@@ -1911,6 -1925,7 +1925,7 @@@ qla2x00_configure_local_loop(scsi_qla_h
        char            *id_iter;
        uint16_t        loop_id;
        uint8_t         domain, area, al_pa;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        found_devs = 0;
        new_fcport = NULL;
        /*
         * Mark local devices that were present with FCF_DEVICE_LOST for now.
         */
-       list_for_each_entry(fcport, &ha->fcports, list) {
+       list_for_each_entry(fcport, &pha->fcports, list) {
+               if (fcport->vp_idx != ha->vp_idx)
+                       continue;
                if (atomic_read(&fcport->state) == FCS_ONLINE &&
                    fcport->port_type != FCT_BROADCAST &&
                    (fcport->flags & FCF_FABRIC_DEVICE) == 0) {
                new_fcport->d_id.b.area = area;
                new_fcport->d_id.b.al_pa = al_pa;
                new_fcport->loop_id = loop_id;
+               new_fcport->vp_idx = ha->vp_idx;
                rval2 = qla2x00_get_port_database(ha, new_fcport, 0);
                if (rval2 != QLA_SUCCESS) {
                        DEBUG2(printk("scsi(%ld): Failed to retrieve fcport "
                /* Check for matching device in port list. */
                found = 0;
                fcport = NULL;
-               list_for_each_entry(fcport, &ha->fcports, list) {
+               list_for_each_entry(fcport, &pha->fcports, list) {
+                       if (fcport->vp_idx != ha->vp_idx)
+                               continue;
                        if (memcmp(new_fcport->port_name, fcport->port_name,
                            WWN_SIZE))
                                continue;
                if (!found) {
                        /* New device, add to fcports list. */
                        new_fcport->flags &= ~FCF_PERSISTENT_BOUND;
-                       list_add_tail(&new_fcport->list, &ha->fcports);
+                       if (ha->parent) {
+                               new_fcport->ha = ha;
+                               new_fcport->vp_idx = ha->vp_idx;
+                               list_add_tail(&new_fcport->vp_fcport,
+                                   &ha->vp_fcports);
+                       }
+                       list_add_tail(&new_fcport->list, &pha->fcports);
  
                        /* Allocate a new replacement fcport. */
                        fcport = new_fcport;
@@@ -2199,11 -2227,13 +2227,13 @@@ qla2x00_reg_remote_port(scsi_qla_host_
  void
  qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
  {
+       scsi_qla_host_t *pha = to_qla_parent(ha);
        fcport->ha = ha;
        fcport->login_retry = 0;
-       fcport->port_login_retry_count = ha->port_down_retry_count *
+       fcport->port_login_retry_count = pha->port_down_retry_count *
            PORT_RETRY_TIME;
-       atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
+       atomic_set(&fcport->port_down_timer, pha->port_down_retry_count *
            PORT_RETRY_TIME);
        fcport->flags &= ~FCF_LOGIN_NEEDED;
  
@@@ -2234,6 -2264,7 +2264,7 @@@ qla2x00_configure_fabric(scsi_qla_host_
        uint16_t        mb[MAILBOX_REGISTER_COUNT];
        uint16_t        loop_id;
        LIST_HEAD(new_fcports);
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        /* If FL port exists, then SNS is present */
        if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
                 * Logout all previous fabric devices marked lost, except
                 * tape devices.
                 */
-               list_for_each_entry(fcport, &ha->fcports, list) {
+               list_for_each_entry(fcport, &pha->fcports, list) {
+                       if (fcport->vp_idx !=ha->vp_idx)
+                               continue;
                        if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
                                break;
  
                }
  
                /* Starting free loop ID. */
-               next_loopid = ha->min_external_loopid;
+               next_loopid = pha->min_external_loopid;
  
                /*
                 * Scan through our port list and login entries that need to be
                 * logged in.
                 */
-               list_for_each_entry(fcport, &ha->fcports, list) {
+               list_for_each_entry(fcport, &pha->fcports, list) {
+                       if (fcport->vp_idx != ha->vp_idx)
+                               continue;
                        if (atomic_read(&ha->loop_down_timer) ||
                            test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
                                break;
                                break;
                        }
  
-                       /* Remove device from the new list and add it to DB */
-                       list_move_tail(&fcport->list, &ha->fcports);
                        /* Login and update database */
                        qla2x00_fabric_dev_login(ha, fcport, &next_loopid);
+                       if (ha->parent) {
+                               fcport->ha = ha;
+                               fcport->vp_idx = ha->vp_idx;
+                               list_add_tail(&fcport->vp_fcport,
+                                   &ha->vp_fcports);
+                               list_move_tail(&fcport->list,
+                                   &ha->parent->fcports);
+                       } else
+                               list_move_tail(&fcport->list, &ha->fcports);
                }
        } while (0);
  
@@@ -2428,6 -2472,11 +2472,11 @@@ qla2x00_find_all_fabric_devs(scsi_qla_h
        int             swl_idx;
        int             first_dev, last_dev;
        port_id_t       wrap, nxt_d_id;
+       int             vp_index;
+       int             empty_vp_index;
+       int             found_vp;
+       scsi_qla_host_t *vha;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        rval = QLA_SUCCESS;
  
                return (QLA_MEMORY_ALLOC_FAILED);
        }
        new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
+       new_fcport->vp_idx = ha->vp_idx;
        /* Set start port ID scan at adapter ID. */
        first_dev = 1;
        last_dev = 0;
  
        /* Starting free loop ID. */
-       loop_id = ha->min_external_loopid;
+       loop_id = pha->min_external_loopid;
        for (; loop_id <= ha->last_loop_id; loop_id++) {
                if (qla2x00_is_reserved_id(ha, loop_id))
                        continue;
                        break;
                }
  
-               /* Bypass if host adapter. */
-               if (new_fcport->d_id.b24 == ha->d_id.b24)
+               /* Bypass if same physical adapter. */
+               if (new_fcport->d_id.b24 == pha->d_id.b24)
                        continue;
  
+               /* Bypass virtual ports of the same host. */
+               if (pha->num_vhosts) {
+                       vp_index = find_next_bit(
+                           (unsigned long *)pha->vp_idx_map,
+                           MAX_MULTI_ID_FABRIC + 1, 1);
+                       for (;vp_index <= MAX_MULTI_ID_FABRIC;
+                           vp_index = find_next_bit(
+                           (unsigned long *)pha->vp_idx_map,
+                           MAX_MULTI_ID_FABRIC + 1, vp_index + 1)) {
+                               empty_vp_index = 1;
+                               found_vp = 0;
+                               list_for_each_entry(vha, &pha->vp_list,
+                                   vp_list) {
+                                       if (vp_index == vha->vp_idx) {
+                                               empty_vp_index = 0;
+                                               found_vp = 1;
+                                               break;
+                                       }
+                               }
+                               if (empty_vp_index)
+                                       continue;
+                               if (found_vp &&
+                                   new_fcport->d_id.b24 == vha->d_id.b24)
+                                       break;
+                       }
+                       if (vp_index <= MAX_MULTI_ID_FABRIC)
+                               continue;
+               }
                /* Bypass if same domain and area of adapter. */
                if (((new_fcport->d_id.b24 & 0xffff00) ==
                    (ha->d_id.b24 & 0xffff00)) && ha->current_topology ==
  
                /* Locate matching device in database. */
                found = 0;
-               list_for_each_entry(fcport, &ha->fcports, list) {
+               list_for_each_entry(fcport, &pha->fcports, list) {
+                       if (new_fcport->vp_idx != fcport->vp_idx)
+                               continue;
                        if (memcmp(new_fcport->port_name, fcport->port_name,
                            WWN_SIZE))
                                continue;
                }
                new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
                new_fcport->d_id.b24 = nxt_d_id.b24;
+               new_fcport->vp_idx = ha->vp_idx;
        }
  
        kfree(swl);
@@@ -2637,6 -2721,7 +2721,7 @@@ qla2x00_find_new_loop_id(scsi_qla_host_
        int     found;
        fc_port_t *fcport;
        uint16_t first_loop_id;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        rval = QLA_SUCCESS;
  
                /* Check for loop ID being already in use. */
                found = 0;
                fcport = NULL;
-               list_for_each_entry(fcport, &ha->fcports, list) {
+               list_for_each_entry(fcport, &pha->fcports, list) {
                        if (fcport->loop_id == dev->loop_id && fcport != dev) {
                                /* ID possibly in use */
                                found++;
@@@ -2710,6 -2795,7 +2795,7 @@@ qla2x00_device_resync(scsi_qla_host_t *
        uint8_t rscn_out_iter;
        uint8_t format;
        port_id_t d_id;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        rval = QLA_RSCNS_HANDLED;
  
  
                rval = QLA_SUCCESS;
  
-               list_for_each_entry(fcport, &ha->fcports, list) {
+               list_for_each_entry(fcport, &pha->fcports, list) {
+                       if (fcport->vp_idx != ha->vp_idx)
+                               continue;
                        if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
                            (fcport->d_id.b24 & mask) != d_id.b24 ||
                            fcport->port_type == FCT_BROADCAST)
@@@ -3940,3 -4029,40 +4029,40 @@@ qla2x00_try_to_stop_firmware(scsi_qla_h
                ret = qla2x00_stop_firmware(ha);
        }
  }
+ int
+ qla24xx_configure_vhba(scsi_qla_host_t *ha)
+ {
+       int rval = QLA_SUCCESS;
+       uint16_t mb[MAILBOX_REGISTER_COUNT];
+       if (!ha->parent)
+               return -EINVAL;
+       rval = qla2x00_fw_ready(ha);
+       if (rval == QLA_SUCCESS) {
+               clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
+               qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
+       }
+       ha->flags.management_server_logged_in = 0;
+       /* Login to SNS first */
+       qla24xx_login_fabric(ha, NPH_SNS, 0xff, 0xff, 0xfc,
+           mb, BIT_1);
+       if (mb[0] != MBS_COMMAND_COMPLETE) {
+               DEBUG15(qla_printk(KERN_INFO, ha,
+                   "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "
+                   "mb[2]=%x mb[6]=%x mb[7]=%x\n", NPH_SNS,
+                   mb[0], mb[1], mb[2], mb[6], mb[7]));
+               return (QLA_FUNCTION_FAILED);
+       }
+       atomic_set(&ha->loop_down_timer, 0);
+       atomic_set(&ha->loop_state, LOOP_UP);
+       set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+       set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
+       rval = qla2x00_loop_resync(ha);
+       return rval;
+ }
index b98136adaaaebe4784040a05eebcdbd92a490b63,a8658b1d284f687e0bcca8bc4f79fe0451cd371c..b5a77b0c0deb6d5f7d3b7e878b986bc76f4cb400
@@@ -29,8 -29,7 +29,7 @@@ static struct kmem_cache *srb_cachep
  /*
   * Ioctl related information.
   */
- static int num_hosts;
+ int num_hosts;
  int ql2xlogintimeout = 20;
  module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
  MODULE_PARM_DESC(ql2xlogintimeout,
@@@ -112,7 -111,7 +111,7 @@@ static int qla2x00_device_reset(scsi_ql
  static int qla2x00_change_queue_depth(struct scsi_device *, int);
  static int qla2x00_change_queue_type(struct scsi_device *, int);
  
- static struct scsi_host_template qla2x00_driver_template = {
+ struct scsi_host_template qla2x00_driver_template = {
        .module                 = THIS_MODULE,
        .name                   = QLA2XXX_DRIVER_NAME,
        .queuecommand           = qla2x00_queuecommand,
        .shost_attrs            = qla2x00_host_attrs,
  };
  
- static struct scsi_host_template qla24xx_driver_template = {
+ struct scsi_host_template qla24xx_driver_template = {
        .module                 = THIS_MODULE,
        .name                   = QLA2XXX_DRIVER_NAME,
        .queuecommand           = qla24xx_queuecommand,
  };
  
  static struct scsi_transport_template *qla2xxx_transport_template = NULL;
+ struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
  
  /* TODO Convert to inlines
   *
   * Timer routines
   */
- #define       WATCH_INTERVAL          1       /* number of seconds */
  
static void qla2x00_timer(scsi_qla_host_t *);
+ void qla2x00_timer(scsi_qla_host_t *);
  
static __inline__ void qla2x00_start_timer(scsi_qla_host_t *,
+ __inline__ void qla2x00_start_timer(scsi_qla_host_t *,
      void *, unsigned long);
  static __inline__ void qla2x00_restart_timer(scsi_qla_host_t *, unsigned long);
static __inline__ void qla2x00_stop_timer(scsi_qla_host_t *);
+ __inline__ void qla2x00_stop_timer(scsi_qla_host_t *);
  
static inline void
__inline__ void
  qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval)
  {
        init_timer(&ha->timer);
@@@ -202,7 -201,7 +201,7 @@@ qla2x00_restart_timer(scsi_qla_host_t *
        mod_timer(&ha->timer, jiffies + interval * HZ);
  }
  
static __inline__ void
+ __inline__ void
  qla2x00_stop_timer(scsi_qla_host_t *ha)
  {
        del_timer_sync(&ha->timer);
@@@ -213,8 -212,8 +212,8 @@@ static int qla2x00_do_dpc(void *data)
  
  static void qla2x00_rst_aen(scsi_qla_host_t *);
  
static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
static void qla2x00_mem_free(scsi_qla_host_t *ha);
+ uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
+ void qla2x00_mem_free(scsi_qla_host_t *ha);
  static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
  static void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
  static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *);
@@@ -438,6 -437,7 +437,7 @@@ qla24xx_queuecommand(struct scsi_cmnd *
        struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
        srb_t *sp;
        int rval;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        rval = fc_remote_port_chkready(rport);
        if (rval) {
  
        if (atomic_read(&fcport->state) != FCS_ONLINE) {
                if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
-                   atomic_read(&ha->loop_state) == LOOP_DEAD) {
+                   atomic_read(&pha->loop_state) == LOOP_DEAD) {
                        cmd->result = DID_NO_CONNECT << 16;
                        goto qc24_fail_command;
                }
  
        spin_unlock_irq(ha->host->host_lock);
  
-       sp = qla2x00_get_new_sp(ha, fcport, cmd, done);
+       sp = qla2x00_get_new_sp(pha, fcport, cmd, done);
        if (!sp)
                goto qc24_host_busy_lock;
  
        return 0;
  
  qc24_host_busy_free_sp:
-       qla2x00_sp_free_dma(ha, sp);
-       mempool_free(sp, ha->srb_mempool);
+       qla2x00_sp_free_dma(pha, sp);
+       mempool_free(sp, pha->srb_mempool);
  
  qc24_host_busy_lock:
        spin_lock_irq(ha->host->host_lock);
@@@ -548,16 -548,17 +548,17 @@@ qla2x00_wait_for_hba_online(scsi_qla_ho
  {
        int             return_status;
        unsigned long   wait_online;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
-       while (((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) ||
-           test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
-           test_bit(ISP_ABORT_RETRY, &ha->dpc_flags) ||
-           ha->dpc_active) && time_before(jiffies, wait_online)) {
+       while (((test_bit(ISP_ABORT_NEEDED, &pha->dpc_flags)) ||
+           test_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags) ||
+           test_bit(ISP_ABORT_RETRY, &pha->dpc_flags) ||
+           pha->dpc_active) && time_before(jiffies, wait_online)) {
  
                msleep(1000);
        }
-       if (ha->flags.online)
+       if (pha->flags.online)
                return_status = QLA_SUCCESS;
        else
                return_status = QLA_FUNCTION_FAILED;
@@@ -588,14 -589,15 +589,15 @@@ qla2x00_wait_for_loop_ready(scsi_qla_ho
  {
        int      return_status = QLA_SUCCESS;
        unsigned long loop_timeout ;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        /* wait for 5 min at the max for loop to be ready */
        loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ);
  
-       while ((!atomic_read(&ha->loop_down_timer) &&
-           atomic_read(&ha->loop_state) == LOOP_DOWN) ||
-           atomic_read(&ha->loop_state) != LOOP_READY) {
-               if (atomic_read(&ha->loop_state) == LOOP_DEAD) {
+       while ((!atomic_read(&pha->loop_down_timer) &&
+           atomic_read(&pha->loop_state) == LOOP_DOWN) ||
+           atomic_read(&pha->loop_state) != LOOP_READY) {
+               if (atomic_read(&pha->loop_state) == LOOP_DEAD) {
                        return_status = QLA_FUNCTION_FAILED;
                        break;
                }
@@@ -650,6 -652,7 +652,7 @@@ qla2xxx_eh_abort(struct scsi_cmnd *cmd
        unsigned long serial;
        unsigned long flags;
        int wait = 0;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        qla2x00_block_error_handler(cmd);
  
        serial = cmd->serial_number;
  
        /* Check active list for command command. */
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock_irqsave(&pha->hardware_lock, flags);
        for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
-               sp = ha->outstanding_cmds[i];
+               sp = pha->outstanding_cmds[i];
  
                if (sp == NULL)
                        continue;
                    __func__, ha->host_no, sp, serial));
                DEBUG3(qla2x00_print_scsi_cmd(cmd));
  
-               spin_unlock_irqrestore(&ha->hardware_lock, flags);
+               spin_unlock_irqrestore(&pha->hardware_lock, flags);
                if (ha->isp_ops.abort_command(ha, sp)) {
                        DEBUG2(printk("%s(%ld): abort_command "
                            "mbx failed.\n", __func__, ha->host_no));
                            "mbx success.\n", __func__, ha->host_no));
                        wait = 1;
                }
-               spin_lock_irqsave(&ha->hardware_lock, flags);
+               spin_lock_irqsave(&pha->hardware_lock, flags);
  
                break;
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irqrestore(&pha->hardware_lock, flags);
  
        /* Wait for the command to be returned. */
        if (wait) {
@@@ -731,6 -734,7 +734,7 @@@ qla2x00_eh_wait_for_pending_target_comm
        srb_t           *sp;
        struct scsi_cmnd *cmd;
        unsigned long flags;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        status = 0;
  
         * array
         */
        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-               spin_lock_irqsave(&ha->hardware_lock, flags);
-               sp = ha->outstanding_cmds[cnt];
+               spin_lock_irqsave(&pha->hardware_lock, flags);
+               sp = pha->outstanding_cmds[cnt];
                if (sp) {
                        cmd = sp->cmd;
-                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-                       if (cmd->device->id == t) {
+                       spin_unlock_irqrestore(&pha->hardware_lock, flags);
+                       if (cmd->device->id == t &&
+                           ha->vp_idx == sp->ha->vp_idx) {
                                if (!qla2x00_eh_wait_on_command(ha, cmd)) {
                                        status = 1;
                                        break;
                                }
                        }
                } else {
-                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+                       spin_unlock_irqrestore(&pha->hardware_lock, flags);
                }
        }
        return (status);
@@@ -782,14 -787,12 +787,12 @@@ qla2xxx_eh_device_reset(struct scsi_cmn
  {
        scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-       int ret;
+       int ret = FAILED;
        unsigned int id, lun;
        unsigned long serial;
  
        qla2x00_block_error_handler(cmd);
  
-       ret = FAILED;
        id = cmd->device->id;
        lun = cmd->device->lun;
        serial = cmd->serial_number;
@@@ -912,15 -915,14 +915,14 @@@ static in
  qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
  {
        scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
+       scsi_qla_host_t *pha = to_qla_parent(ha);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-       int ret;
+       int ret = FAILED;
        unsigned int id, lun;
        unsigned long serial;
  
        qla2x00_block_error_handler(cmd);
  
-       ret = FAILED;
        id = cmd->device->id;
        lun = cmd->device->lun;
        serial = cmd->serial_number;
                goto eh_bus_reset_done;
  
        /* Flush outstanding commands. */
-       if (!qla2x00_eh_wait_for_pending_commands(ha))
+       if (!qla2x00_eh_wait_for_pending_commands(pha))
                ret = FAILED;
  
  eh_bus_reset_done:
@@@ -974,14 -976,13 +976,13 @@@ qla2xxx_eh_host_reset(struct scsi_cmnd 
  {
        scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-       int ret;
+       int ret = FAILED;
        unsigned int id, lun;
        unsigned long serial;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        qla2x00_block_error_handler(cmd);
  
-       ret = FAILED;
        id = cmd->device->id;
        lun = cmd->device->lun;
        serial = cmd->serial_number;
         * while dpc is stuck for the mailbox to complete.
         */
        qla2x00_wait_for_loop_ready(ha);
-       set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
-       if (qla2x00_abort_isp(ha)) {
-               clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
+       set_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
+       if (qla2x00_abort_isp(pha)) {
+               clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
                /* failed. schedule dpc to try */
-               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+               set_bit(ISP_ABORT_NEEDED, &pha->dpc_flags);
  
                if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
                        goto eh_host_reset_lock;
        }
-       clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);
+       clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
  
        /* Waiting for our command in done_queue to be returned to OS.*/
-       if (qla2x00_eh_wait_for_pending_commands(ha))
+       if (qla2x00_eh_wait_for_pending_commands(pha))
                ret = SUCCESS;
  
+       if (ha->parent)
+               qla2x00_vp_abort_isp(ha);
  eh_host_reset_lock:
        qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
            (ret == FAILED) ? "failed" : "succeded");
@@@ -1435,6 -1439,7 +1439,7 @@@ qla2x00_probe_one(struct pci_dev *pdev
        ha->host = host;
        ha->host_no = host->host_no;
        sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
+       ha->parent = NULL;
  
        /* Set ISP-type information. */
        qla2x00_set_isp_flags(ha);
  
        ha->prev_topology = 0;
        ha->init_cb_size = sizeof(init_cb_t);
-       ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
+       ha->mgmt_svr_loop_id = MANAGEMENT_SERVER + ha->vp_idx;
        ha->link_data_rate = PORT_SPEED_UNKNOWN;
        ha->optrom_size = OPTROM_SIZE_2300;
  
                ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
                ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
                ha->last_loop_id = SNS_LAST_LOOP_ID_2300;
-               ha->init_cb_size = sizeof(struct init_cb_24xx);
-               ha->mgmt_svr_loop_id = 10;
+               ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
+               ha->mgmt_svr_loop_id = 10 + ha->vp_idx;
                ha->isp_ops.pci_config = qla24xx_pci_config;
                ha->isp_ops.reset_chip = qla24xx_reset_chip;
                ha->isp_ops.chip_diag = qla24xx_chip_diag;
        ha->instance = num_hosts;
  
        init_MUTEX(&ha->mbx_cmd_sem);
+       init_MUTEX(&ha->vport_sem);
        init_MUTEX_LOCKED(&ha->mbx_intr_sem);
  
        INIT_LIST_HEAD(&ha->list);
        INIT_LIST_HEAD(&ha->fcports);
+       INIT_LIST_HEAD(&ha->vp_list);
+       set_bit(0, (unsigned long *) ha->vp_idx_map);
  
        qla2x00_config_dma_addressing(ha);
        if (qla2x00_mem_alloc(ha)) {
@@@ -1789,7 -1798,8 +1798,8 @@@ qla2x00_schedule_rport_del(struct scsi_
  void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,
      int do_login, int defer)
  {
-       if (atomic_read(&fcport->state) == FCS_ONLINE)
+       if (atomic_read(&fcport->state) == FCS_ONLINE &&
+           ha->vp_idx == fcport->vp_idx)
                qla2x00_schedule_rport_del(ha, fcport, defer);
  
        /*
  qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
  {
        fc_port_t *fcport;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
-       list_for_each_entry(fcport, &ha->fcports, list) {
-               if (fcport->port_type != FCT_TARGET)
+       list_for_each_entry(fcport, &pha->fcports, list) {
+               if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx)
                        continue;
                /*
                 * No point in marking the device as lost, if the device is
                 * already DEAD.
                 */
                if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
                        continue;
-               if (atomic_read(&fcport->state) == FCS_ONLINE)
-                       qla2x00_schedule_rport_del(ha, fcport, defer);
+               if (atomic_read(&fcport->state) == FCS_ONLINE) {
+                       if (defer)
+                               qla2x00_schedule_rport_del(ha, fcport, defer);
+                       else if (ha->vp_idx == fcport->vp_idx)
+                               qla2x00_schedule_rport_del(ha, fcport, defer);
+               }
                atomic_set(&fcport->state, FCS_DEVICE_LOST);
        }
  
  *      0  = success.
  *      1  = failure.
  */
static uint8_t
+ uint8_t
  qla2x00_mem_alloc(scsi_qla_host_t *ha)
  {
        char    name[16];
                        continue;
                }
  
-               snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME,
-                   ha->host_no);
-               ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev,
-                   DMA_POOL_SIZE, 8, 0);
-               if (ha->s_dma_pool == NULL) {
+               /* get consistent memory allocated for init control block */
+               ha->init_cb = dma_alloc_coherent(&ha->pdev->dev,
+                   ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL);
+               if (ha->init_cb == NULL) {
                        qla_printk(KERN_WARNING, ha,
-                           "Memory Allocation failed - s_dma_pool\n");
+                           "Memory Allocation failed - init_cb\n");
  
                        qla2x00_mem_free(ha);
                        msleep(100);
  
                        continue;
                }
+               memset(ha->init_cb, 0, ha->init_cb_size);
  
-               /* get consistent memory allocated for init control block */
-               ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
-                   &ha->init_cb_dma);
-               if (ha->init_cb == NULL) {
+               snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME,
+                   ha->host_no);
+               ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev,
+                   DMA_POOL_SIZE, 8, 0);
+               if (ha->s_dma_pool == NULL) {
                        qla_printk(KERN_WARNING, ha,
-                           "Memory Allocation failed - init_cb\n");
+                           "Memory Allocation failed - s_dma_pool\n");
  
                        qla2x00_mem_free(ha);
                        msleep(100);
  
                        continue;
                }
-               memset(ha->init_cb, 0, ha->init_cb_size);
  
                if (qla2x00_allocate_sp_pool(ha)) {
                        qla_printk(KERN_WARNING, ha,
  * Input:
  *      ha = adapter block pointer.
  */
static void
+ void
  qla2x00_mem_free(scsi_qla_host_t *ha)
  {
        struct list_head        *fcpl, *fcptemp;
        if (ha->ms_iocb)
                dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
  
-       if (ha->init_cb)
-               dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma);
        if (ha->s_dma_pool)
                dma_pool_destroy(ha->s_dma_pool);
  
+       if (ha->init_cb)
+               dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
+                   ha->init_cb, ha->init_cb_dma);
        if (ha->gid_list)
                dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
                    ha->gid_list_dma);
@@@ -2199,6 -2214,7 +2214,7 @@@ qla2x00_free_sp_pool( scsi_qla_host_t *
  static int
  qla2x00_do_dpc(void *data)
  {
+       int             rval;
        scsi_qla_host_t *ha;
        fc_port_t       *fcport;
        uint8_t         status;
                        if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE,
                            &ha->dpc_flags))) {
  
-                               qla2x00_loop_resync(ha);
+                               rval = qla2x00_loop_resync(ha);
  
                                clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);
                        }
                if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags))
                        ha->isp_ops.beacon_blink(ha);
  
+               qla2x00_do_dpc_all_vps(ha);
                ha->dpc_active = 0;
        } /* End of while(1) */
  
@@@ -2426,13 -2444,7 +2444,7 @@@ qla2x00_sp_free_dma(scsi_qla_host_t *ha
        struct scsi_cmnd *cmd = sp->cmd;
  
        if (sp->flags & SRB_DMA_VALID) {
-               if (cmd->use_sg) {
-                       dma_unmap_sg(&ha->pdev->dev, cmd->request_buffer,
-                           cmd->use_sg, cmd->sc_data_direction);
-               } else if (cmd->request_bufflen) {
-                       dma_unmap_single(&ha->pdev->dev, sp->dma_handle,
-                           cmd->request_bufflen, cmd->sc_data_direction);
-               }
+               scsi_dma_unmap(cmd);
                sp->flags &= ~SRB_DMA_VALID;
        }
        CMD_SP(cmd) = NULL;
@@@ -2458,7 -2470,7 +2470,7 @@@ qla2x00_sp_compl(scsi_qla_host_t *ha, s
  *
  * Context: Interrupt
  ***************************************************************************/
static void
+ void
  qla2x00_timer(scsi_qla_host_t *ha)
  {
        unsigned long   cpu_flags = 0;
        int             index;
        srb_t           *sp;
        int             t;
+       scsi_qla_host_t *pha = to_qla_parent(ha);
  
        /*
         * Ports - Port down timer.
                                atomic_set(&ha->loop_state, LOOP_DEAD);
  
                        /* Schedule an ISP abort to return any tape commands. */
-                       spin_lock_irqsave(&ha->hardware_lock, cpu_flags);
-                       for (index = 1; index < MAX_OUTSTANDING_COMMANDS;
-                           index++) {
-                               fc_port_t *sfcp;
+                       /* NPIV - scan physical port only */
+                       if (!ha->parent) {
+                               spin_lock_irqsave(&ha->hardware_lock,
+                                   cpu_flags);
+                               for (index = 1;
+                                   index < MAX_OUTSTANDING_COMMANDS;
+                                   index++) {
+                                       fc_port_t *sfcp;
+                                       sp = ha->outstanding_cmds[index];
+                                       if (!sp)
+                                               continue;
+                                       sfcp = sp->fcport;
+                                       if (!(sfcp->flags & FCF_TAPE_PRESENT))
+                                               continue;
  
-                               sp = ha->outstanding_cmds[index];
-                               if (!sp)
-                                       continue;
-                               sfcp = sp->fcport;
-                               if (!(sfcp->flags & FCF_TAPE_PRESENT))
-                                       continue;
-                               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-                               break;
+                                       set_bit(ISP_ABORT_NEEDED,
+                                           &ha->dpc_flags);
+                                       break;
+                               }
+                               spin_unlock_irqrestore(&ha->hardware_lock,
+                                   cpu_flags);
                        }
-                       spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags);
                        set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags);
                        start_dpc++;
                }
            test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
            test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
            test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
+           test_bit(VP_DPC_NEEDED, &ha->dpc_flags) ||
            test_bit(RELOGIN_NEEDED, &ha->dpc_flags)))
-               qla2xxx_wake_dpc(ha);
+               qla2xxx_wake_dpc(pha);
  
        qla2x00_restart_timer(ha, WATCH_INTERVAL);
  }
@@@ -2590,7 -2610,7 +2610,7 @@@ qla2x00_down_timeout(struct semaphore *
                        return 0;
                if (msleep_interruptible(step))
                        break;
 -      } while (--iterations >= 0);
 +      } while (--iterations > 0);
  
        return -ETIMEDOUT;
  }
@@@ -2717,14 -2737,24 +2737,24 @@@ qla2x00_module_init(void
  
        qla2xxx_transport_template =
            fc_attach_transport(&qla2xxx_transport_functions);
-       if (!qla2xxx_transport_template)
+       if (!qla2xxx_transport_template) {
+               kmem_cache_destroy(srb_cachep);
                return -ENODEV;
+       }
+       qla2xxx_transport_vport_template =
+           fc_attach_transport(&qla2xxx_transport_vport_functions);
+       if (!qla2xxx_transport_vport_template) {
+               kmem_cache_destroy(srb_cachep);
+               fc_release_transport(qla2xxx_transport_template);
+               return -ENODEV;
+       }
  
        printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
        ret = pci_register_driver(&qla2xxx_pci_driver);
        if (ret) {
                kmem_cache_destroy(srb_cachep);
                fc_release_transport(qla2xxx_transport_template);
+               fc_release_transport(qla2xxx_transport_vport_template);
        }
        return ret;
  }
@@@ -2739,6 -2769,7 +2769,7 @@@ qla2x00_module_exit(void
        qla2x00_release_firmware();
        kmem_cache_destroy(srb_cachep);
        fc_release_transport(qla2xxx_transport_template);
+       fc_release_transport(qla2xxx_transport_vport_template);
  }
  
  module_init(qla2x00_module_init);
diff --combined drivers/scsi/scsi_scan.c
index 662577fbe7a87ddd93a66e37e66bbedbeb64e73d,0827df2ebb6ddd1d8a622baa554971f0046d0312..a86e62f4b3ba86b934cdaaecc7f7213d1ef45d68
@@@ -184,15 -184,6 +184,15 @@@ int scsi_complete_async_scans(void
  /* Only exported for the benefit of scsi_wait_scan */
  EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
  
 +#ifndef MODULE
 +/*
 + * For async scanning we need to wait for all the scans to complete before
 + * trying to mount the root fs.  Otherwise non-modular drivers may not be ready
 + * yet.
 + */
 +late_initcall(scsi_complete_async_scans);
 +#endif
 +
  /**
   * scsi_unlock_floptical - unlock device via a special MODE SENSE command
   * @sdev:     scsi device to send command to
@@@ -703,16 -694,14 +703,14 @@@ static int scsi_probe_lun(struct scsi_d
  
  /**
   * scsi_add_lun - allocate and fully initialze a scsi_device
-  * @sdevscan: holds information to be stored in the new scsi_device
-  * @sdevnew:  store the address of the newly allocated scsi_device
+  * @sdev:     holds information to be stored in the new scsi_device
   * @inq_result:       holds the result of a previous INQUIRY to the LUN
   * @bflags:   black/white list flag
+  * @async:    1 if this device is being scanned asynchronously
   *
   * Description:
-  *     Allocate and initialize a scsi_device matching sdevscan. Optionally
-  *     set fields based on values in *@bflags. If @sdevnew is not
-  *     NULL, store the address of the new scsi_device in *@sdevnew (needed
-  *     when scanning a particular LUN).
+  *     Initialize the scsi_device @sdev.  Optionally set fields based
+  *     on values in *@bflags.
   *
   * Return:
   *     SCSI_SCAN_NO_RESPONSE: could not allocate or setup a scsi_device
@@@ -752,25 -741,15 +750,15 @@@ static int scsi_add_lun(struct scsi_dev
        sdev->rev = (char *) (sdev->inquiry + 32);
  
        if (*bflags & BLIST_ISROM) {
-               /*
-                * It would be better to modify sdev->type, and set
-                * sdev->removable; this can now be done since
-                * print_inquiry has gone away.
-                */
-               inq_result[0] = TYPE_ROM;
-               inq_result[1] |= 0x80;  /* removable */
-       } else if (*bflags & BLIST_NO_ULD_ATTACH)
-               sdev->no_uld_attach = 1;
+               sdev->type = TYPE_ROM;
+               sdev->removable = 1;
+       } else {
+               sdev->type = (inq_result[0] & 0x1f);
+               sdev->removable = (inq_result[1] & 0x80) >> 7;
+       }
  
-       switch (sdev->type = (inq_result[0] & 0x1f)) {
+       switch (sdev->type) {
        case TYPE_RBC:
-               /* RBC devices can return SCSI-3 compliance and yet
-                * still not support REPORT LUNS, so make them act as
-                * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
-                * specifically set */
-               if ((*bflags & BLIST_REPORTLUN2) == 0)
-                       *bflags |= BLIST_NOREPORTLUN;
-               /* fall through */
        case TYPE_TAPE:
        case TYPE_DISK:
        case TYPE_PRINTER:
                sdev->writeable = 1;
                break;
        case TYPE_ROM:
-               /* MMC devices can return SCSI-3 compliance and yet
-                * still not support REPORT LUNS, so make them act as
-                * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
-                * specifically set */
-               if ((*bflags & BLIST_REPORTLUN2) == 0)
-                       *bflags |= BLIST_NOREPORTLUN;
-               /* fall through */
        case TYPE_WORM:
                sdev->writeable = 0;
                break;
                printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type);
        }
  
+       if (sdev->type == TYPE_RBC || sdev->type == TYPE_ROM) {
+               /* RBC and MMC devices can return SCSI-3 compliance and yet
+                * still not support REPORT LUNS, so make them act as
+                * BLIST_NOREPORTLUN unless BLIST_REPORTLUN2 is
+                * specifically set */
+               if ((*bflags & BLIST_REPORTLUN2) == 0)
+                       *bflags |= BLIST_NOREPORTLUN;
+       }
        /*
         * For a peripheral qualifier (PQ) value of 1 (001b), the SCSI
         * spec says: The device server is capable of supporting the
         */ 
  
        sdev->inq_periph_qual = (inq_result[0] >> 5) & 7;
-       sdev->removable = (0x80 & inq_result[1]) >> 7;
        sdev->lockable = sdev->removable;
        sdev->soft_reset = (inq_result[7] & 1) && ((inq_result[3] & 7) == 2);
  
-       if (sdev->scsi_level >= SCSI_3 || (sdev->inquiry_len > 56 &&
-               inq_result[56] & 0x04))
+       if (sdev->scsi_level >= SCSI_3 ||
+                       (sdev->inquiry_len > 56 && inq_result[56] & 0x04))
                sdev->ppr = 1;
        if (inq_result[7] & 0x60)
                sdev->wdtr = 1;
                        sdev->inq_periph_qual, inq_result[2] & 0x07,
                        (inq_result[3] & 0x0f) == 1 ? " CCS" : "");
  
-       /*
-        * End sysfs code.
-        */
        if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) &&
            !(*bflags & BLIST_NOTQ))
                sdev->tagged_supported = 1;
        /*
         * Some devices (Texel CD ROM drives) have handshaking problems
         * when used with the Seagate controllers. borken is initialized
        if ((*bflags & BLIST_BORKEN) == 0)
                sdev->borken = 0;
  
+       if (*bflags & BLIST_NO_ULD_ATTACH)
+               sdev->no_uld_attach = 1;
        /*
         * Apparently some really broken devices (contrary to the SCSI
         * standards) need to be selected without asserting ATN
        if (*bflags & BLIST_SINGLELUN)
                sdev->single_lun = 1;
  
        sdev->use_10_for_rw = 1;
  
        if (*bflags & BLIST_MS_SKIP_PAGE_08)
@@@ -1213,7 -1192,7 +1201,7 @@@ static void scsi_sequential_lun_scan(st
   *     Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns
   *     the integer: 0x0b030a04
   **/
static int scsilun_to_int(struct scsi_lun *scsilun)
+ int scsilun_to_int(struct scsi_lun *scsilun)
  {
        int i;
        unsigned int lun;
                              scsilun->scsi_lun[i + 1]) << (i * 8));
        return lun;
  }
+ EXPORT_SYMBOL(scsilun_to_int);
  
  /**
   * int_to_scsilun: reverts an int into a scsi_lun