]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 18 Apr 2008 18:25:31 +0000 (11:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 18 Apr 2008 18:25:31 +0000 (11:25 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (137 commits)
  [SCSI] iscsi: bidi support for iscsi_tcp
  [SCSI] iscsi: bidi support at the generic libiscsi level
  [SCSI] iscsi: extended cdb support
  [SCSI] zfcp: Fix error handling for blocked unit for send FCP command
  [SCSI] zfcp: Remove zfcp_erp_wait from slave destory handler to fix deadlock
  [SCSI] zfcp: fix 31 bit compile warnings
  [SCSI] bsg: no need to set BSG_F_BLOCK bit in bsg_complete_all_commands
  [SCSI] bsg: remove minor in struct bsg_device
  [SCSI] bsg: use better helper list functions
  [SCSI] bsg: replace kobject_get with blk_get_queue
  [SCSI] bsg: takes a ref to struct device in fops->open
  [SCSI] qla1280: remove version check
  [SCSI] libsas: fix endianness bug in sas_ata
  [SCSI] zfcp: fix compiler warning caused by poking inside new semaphore (linux-next)
  [SCSI] aacraid: Do not describe check_reset parameter with its value
  [SCSI] aacraid: Fix down_interruptible() to check the return value
  [SCSI] sun3_scsi_vme: add MODULE_LICENSE
  [SCSI] st: rename flush_write_buffer()
  [SCSI] tgt: use KMEM_CACHE macro
  [SCSI] initio: fix big endian problems for auto request sense
  ...

133 files changed:
Documentation/scsi/st.txt
arch/ia64/hp/sim/simscsi.c
block/bsg.c
drivers/ata/libata-scsi.c
drivers/base/transport_class.c
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_ccw.c
drivers/s390/scsi/zfcp_dbf.c
drivers/s390/scsi/zfcp_dbf.h [new file with mode: 0644]
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs_adapter.c
drivers/s390/scsi/zfcp_sysfs_port.c
drivers/s390/scsi/zfcp_sysfs_unit.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-xxxx.c
drivers/scsi/BusLogic.c
drivers/scsi/BusLogic.h
drivers/scsi/FlashPoint.c
drivers/scsi/Kconfig
drivers/scsi/a2091.c
drivers/scsi/a3000.c
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/commsup.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
drivers/scsi/aic94xx/aic94xx.h
drivers/scsi/aic94xx/aic94xx_dev.c
drivers/scsi/aic94xx/aic94xx_dump.c
drivers/scsi/aic94xx/aic94xx_dump.h
drivers/scsi/aic94xx/aic94xx_hwi.c
drivers/scsi/aic94xx/aic94xx_hwi.h
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/aic94xx/aic94xx_reg.c
drivers/scsi/aic94xx/aic94xx_scb.c
drivers/scsi/aic94xx/aic94xx_sds.c
drivers/scsi/aic94xx/aic94xx_seq.c
drivers/scsi/aic94xx/aic94xx_seq.h
drivers/scsi/aic94xx/aic94xx_task.c
drivers/scsi/aic94xx/aic94xx_tmf.c
drivers/scsi/arm/acornscsi.c
drivers/scsi/arm/cumana_1.c
drivers/scsi/ch.c
drivers/scsi/dc395x.c
drivers/scsi/eata_pio.c
drivers/scsi/gdth.c
drivers/scsi/gdth.h
drivers/scsi/gvp11.c
drivers/scsi/hosts.c
drivers/scsi/hptiop.c
drivers/scsi/initio.c
drivers/scsi/ips.c
drivers/scsi/iscsi_tcp.c
drivers/scsi/libiscsi.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/lpfc/lpfc_vport.c
drivers/scsi/mac_scsi.c
drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/mvme147.c
drivers/scsi/ps3rom.c
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/Kconfig
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_dbg.h
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_dfs.c
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_settings.h
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/qla4xxx/ql4_fw.h
drivers/scsi/qla4xxx/ql4_glbl.h
drivers/scsi/qla4xxx/ql4_iocb.c
drivers/scsi/qla4xxx/ql4_isr.c
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/raid_class.c
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_debug.h [deleted file]
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_tgt_lib.c
drivers/scsi/sgiwd93.c
drivers/scsi/st.c
drivers/scsi/st.h
drivers/scsi/st_options.h
drivers/scsi/stex.c
drivers/scsi/sun3_scsi_vme.c
drivers/scsi/wd33c93.c
include/linux/attribute_container.h
include/linux/mtio.h
include/linux/scatterlist.h
include/linux/transport_class.h
include/scsi/iscsi_proto.h
include/scsi/libsas.h
include/scsi/sas_ata.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_eh.h
include/scsi/scsi_host.h
lib/scatterlist.c

index b7be95b5bd24f1a53431ef0d45ddb85b2832c3a9..40752602c0504b65c5210765924be22026e79934 100644 (file)
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
 The driver is currently maintained by Kai Mäkisara (email
 Kai.Makisara@kolumbus.fi)
 
-Last modified: Mon Mar  7 21:14:44 2005 by kai.makisara
+Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara
 
 
 BASICS
@@ -133,6 +133,11 @@ the defaults set by the user. The value -1 means the default is not set. The
 file 'dev' contains the device numbers corresponding to this device. The links
 'device' and 'driver' point to the SCSI device and driver entries.
 
+Each directory also contains the entry 'options' which shows the currently
+enabled driver and mode options. The value in the file is a bit mask where the
+bit definitions are the same as those used with MTSETDRVBUFFER in setting the
+options.
+
 A link named 'tape' is made from the SCSI device directory to the class
 directory corresponding to the mode 0 auto-rewind device (e.g., st0). 
 
@@ -372,6 +377,11 @@ MTSETDRVBUFFER
             MT_ST_SYSV sets the SYSV semantics (mode)
             MT_ST_NOWAIT enables immediate mode (i.e., don't wait for
                the command to finish) for some commands (e.g., rewind)
+            MT_ST_SILI enables setting the SILI bit in SCSI commands when
+               reading in variable block mode to enhance performance when
+               reading blocks shorter than the byte count; set this only
+               if you are sure that the drive supports SILI and the HBA
+               correctly returns transfer residuals
             MT_ST_DEBUGGING debugging (global; debugging must be
                compiled into the driver)
        MT_ST_SETBOOLEANS
index 7661bb065fa570a4a61036acf551d5feacda94ef..3a078ad3aa44e4a91ebfb256ca49ba674a35a3da 100644 (file)
@@ -201,22 +201,6 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
        simscsi_sg_readwrite(sc, mode, offset);
 }
 
-static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len)
-{
-
-       int i;
-       unsigned thislen;
-       struct scatterlist *slp;
-
-       scsi_for_each_sg(sc, slp, scsi_sg_count(sc), i) {
-               if (!len)
-                       break;
-               thislen = min(len, slp->length);
-               memcpy(sg_virt(slp), buf, thislen);
-               len -= thislen;
-       }
-}
-
 static int
 simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 {
@@ -258,7 +242,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
                        buf[6] = 0;     /* reserved */
                        buf[7] = 0;     /* various flags */
                        memcpy(buf + 8, "HP      SIMULATED DISK  0.00",  28);
-                       simscsi_fillresult(sc, buf, 36);
+                       scsi_sg_copy_from_buffer(sc, buf, 36);
                        sc->result = GOOD;
                        break;
 
@@ -306,14 +290,15 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
                        buf[5] = 0;
                        buf[6] = 2;
                        buf[7] = 0;
-                       simscsi_fillresult(sc, buf, 8);
+                       scsi_sg_copy_from_buffer(sc, buf, 8);
                        sc->result = GOOD;
                        break;
 
                      case MODE_SENSE:
                      case MODE_SENSE_10:
                        /* sd.c uses this to determine whether disk does write-caching. */
-                       simscsi_fillresult(sc, (char *)empty_zero_page, scsi_bufflen(sc));
+                       scsi_sg_copy_from_buffer(sc, (char *)empty_zero_page,
+                                                PAGE_SIZE);
                        sc->result = GOOD;
                        break;
 
index 8917c5174dc2646c5ad8d4d67eb67529a98783f5..302ac1f5af391b7058aad198615cdf1fee29931d 100644 (file)
@@ -37,7 +37,6 @@ struct bsg_device {
        struct list_head done_list;
        struct hlist_node dev_list;
        atomic_t ref_count;
-       int minor;
        int queued_cmds;
        int done_cmds;
        wait_queue_head_t wq_done;
@@ -368,7 +367,7 @@ static struct bsg_command *bsg_next_done_cmd(struct bsg_device *bd)
 
        spin_lock_irq(&bd->lock);
        if (bd->done_cmds) {
-               bc = list_entry(bd->done_list.next, struct bsg_command, list);
+               bc = list_first_entry(&bd->done_list, struct bsg_command, list);
                list_del(&bc->list);
                bd->done_cmds--;
        }
@@ -468,8 +467,6 @@ static int bsg_complete_all_commands(struct bsg_device *bd)
 
        dprintk("%s: entered\n", bd->name);
 
-       set_bit(BSG_F_BLOCK, &bd->flags);
-
        /*
         * wait for all commands to complete
         */
@@ -705,6 +702,7 @@ static struct bsg_device *bsg_alloc_device(void)
 static int bsg_put_device(struct bsg_device *bd)
 {
        int ret = 0;
+       struct device *dev = bd->queue->bsg_dev.dev;
 
        mutex_lock(&bsg_mutex);
 
@@ -730,6 +728,7 @@ static int bsg_put_device(struct bsg_device *bd)
        kfree(bd);
 out:
        mutex_unlock(&bsg_mutex);
+       put_device(dev);
        return ret;
 }
 
@@ -738,22 +737,26 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
                                         struct file *file)
 {
        struct bsg_device *bd;
+       int ret;
 #ifdef BSG_DEBUG
        unsigned char buf[32];
 #endif
+       ret = blk_get_queue(rq);
+       if (ret)
+               return ERR_PTR(-ENXIO);
 
        bd = bsg_alloc_device();
-       if (!bd)
+       if (!bd) {
+               blk_put_queue(rq);
                return ERR_PTR(-ENOMEM);
+       }
 
        bd->queue = rq;
-       kobject_get(&rq->kobj);
        bsg_set_block(bd, file);
 
        atomic_set(&bd->ref_count, 1);
-       bd->minor = iminor(inode);
        mutex_lock(&bsg_mutex);
-       hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(bd->minor));
+       hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode)));
 
        strncpy(bd->name, rq->bsg_dev.class_dev->class_id, sizeof(bd->name) - 1);
        dprintk("bound to <%s>, max queue %d\n",
@@ -763,23 +766,21 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
        return bd;
 }
 
-static struct bsg_device *__bsg_get_device(int minor)
+static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)
 {
-       struct bsg_device *bd = NULL;
+       struct bsg_device *bd;
        struct hlist_node *entry;
 
        mutex_lock(&bsg_mutex);
 
-       hlist_for_each(entry, bsg_dev_idx_hash(minor)) {
-               bd = hlist_entry(entry, struct bsg_device, dev_list);
-               if (bd->minor == minor) {
+       hlist_for_each_entry(bd, entry, bsg_dev_idx_hash(minor), dev_list) {
+               if (bd->queue == q) {
                        atomic_inc(&bd->ref_count);
-                       break;
+                       goto found;
                }
-
-               bd = NULL;
        }
-
+       bd = NULL;
+found:
        mutex_unlock(&bsg_mutex);
        return bd;
 }
@@ -789,21 +790,27 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
        struct bsg_device *bd;
        struct bsg_class_device *bcd;
 
-       bd = __bsg_get_device(iminor(inode));
-       if (bd)
-               return bd;
-
        /*
         * find the class device
         */
        mutex_lock(&bsg_mutex);
        bcd = idr_find(&bsg_minor_idr, iminor(inode));
+       if (bcd)
+               get_device(bcd->dev);
        mutex_unlock(&bsg_mutex);
 
        if (!bcd)
                return ERR_PTR(-ENODEV);
 
-       return bsg_add_device(inode, bcd->queue, file);
+       bd = __bsg_get_device(iminor(inode), bcd->queue);
+       if (bd)
+               return bd;
+
+       bd = bsg_add_device(inode, bcd->queue, file);
+       if (IS_ERR(bd))
+               put_device(bcd->dev);
+
+       return bd;
 }
 
 static int bsg_open(struct inode *inode, struct file *file)
@@ -942,7 +949,6 @@ void bsg_unregister_queue(struct request_queue *q)
        class_device_unregister(bcd->class_dev);
        put_device(bcd->dev);
        bcd->class_dev = NULL;
-       bcd->dev = NULL;
        mutex_unlock(&bsg_mutex);
 }
 EXPORT_SYMBOL_GPL(bsg_unregister_queue);
index c16e3cea1d28b2e941773f95bfc8368e86b774de..f3c69a8c1103a0af3ac48e99694ff2e364603258 100644 (file)
@@ -2332,11 +2332,7 @@ void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
 {
        cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
-       cmd->sense_buffer[0] = 0x70;    /* fixed format, current */
-       cmd->sense_buffer[2] = sk;
-       cmd->sense_buffer[7] = 18 - 8;  /* additional sense length */
-       cmd->sense_buffer[12] = asc;
-       cmd->sense_buffer[13] = ascq;
+       scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
 }
 
 /**
index 40bca48abc12dcfa18de9e92c8e4327fb1bf6845..cabd0edf21569c3ea1cd2f3da9c77bfd5007936c 100644 (file)
@@ -108,7 +108,8 @@ EXPORT_SYMBOL_GPL(anon_transport_class_register);
  */
 void anon_transport_class_unregister(struct anon_transport_class *atc)
 {
-       attribute_container_unregister(&atc->container);
+       if (unlikely(attribute_container_unregister(&atc->container)))
+               BUG();
 }
 EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
 
index c6be6eba7dc360d82c63e0892d5da4008742f906..db3c892f87fb50aafc6f53ac5aaaaf016ee2860f 100644 (file)
@@ -79,7 +79,7 @@ MODULE_VERSION(my_VERSION);
 /*
  *  cmd line parameters
  */
-static int mpt_msi_enable;
+static int mpt_msi_enable = -1;
 module_param(mpt_msi_enable, int, 0);
 MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
 
@@ -1686,6 +1686,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                ioc->bus_type = SAS;
        }
 
+       if (ioc->bus_type == SAS && mpt_msi_enable == -1)
+               ioc->msi_enable = 1;
+       else
+               ioc->msi_enable = mpt_msi_enable;
+
        if (ioc->errata_flag_1064)
                pci_disable_io_access(pdev);
 
@@ -1831,7 +1836,7 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state)
        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
        free_irq(ioc->pci_irq, ioc);
-       if (mpt_msi_enable)
+       if (ioc->msi_enable)
                pci_disable_msi(ioc->pcidev);
        ioc->pci_irq = -1;
        pci_save_state(pdev);
@@ -2057,15 +2062,17 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
        if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
                ioc->pci_irq = -1;
                if (ioc->pcidev->irq) {
-                       if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
+                       if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
                                printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
                                    ioc->name);
+                       else
+                               ioc->msi_enable = 0;
                        rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
                            IRQF_SHARED, ioc->name, ioc);
                        if (rc < 0) {
                                printk(MYIOC_s_ERR_FMT "Unable to allocate "
                                    "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
-                               if (mpt_msi_enable)
+                               if (ioc->msi_enable)
                                        pci_disable_msi(ioc->pcidev);
                                return -EBUSY;
                        }
@@ -2173,7 +2180,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                /*
                 * Initalize link list for inactive raid volumes.
                 */
-               init_MUTEX(&ioc->raid_data.inactive_list_mutex);
+               mutex_init(&ioc->raid_data.inactive_list_mutex);
                INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
 
                if (ioc->bus_type == SAS) {
@@ -2261,7 +2268,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
  out:
        if ((ret != 0) && irq_allocated) {
                free_irq(ioc->pci_irq, ioc);
-               if (mpt_msi_enable)
+               if (ioc->msi_enable)
                        pci_disable_msi(ioc->pcidev);
        }
        return ret;
@@ -2443,7 +2450,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
 
        if (ioc->pci_irq != -1) {
                free_irq(ioc->pci_irq, ioc);
-               if (mpt_msi_enable)
+               if (ioc->msi_enable)
                        pci_disable_msi(ioc->pcidev);
                ioc->pci_irq = -1;
        }
@@ -5159,13 +5166,13 @@ mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
        if (list_empty(&ioc->raid_data.inactive_list))
                return;
 
-       down(&ioc->raid_data.inactive_list_mutex);
+       mutex_lock(&ioc->raid_data.inactive_list_mutex);
        list_for_each_entry_safe(component_info, pNext,
            &ioc->raid_data.inactive_list, list) {
                list_del(&component_info->list);
                kfree(component_info);
        }
-       up(&ioc->raid_data.inactive_list_mutex);
+       mutex_unlock(&ioc->raid_data.inactive_list_mutex);
 }
 
 /**
@@ -5224,7 +5231,7 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
        if (!handle_inactive_volumes)
                goto out;
 
-       down(&ioc->raid_data.inactive_list_mutex);
+       mutex_lock(&ioc->raid_data.inactive_list_mutex);
        for (i = 0; i < buffer->NumPhysDisks; i++) {
                if(mpt_raid_phys_disk_pg0(ioc,
                    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
@@ -5244,7 +5251,7 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
                list_add_tail(&component_info->list,
                    &ioc->raid_data.inactive_list);
        }
-       up(&ioc->raid_data.inactive_list_mutex);
+       mutex_unlock(&ioc->raid_data.inactive_list_mutex);
 
  out:
        if (buffer)
index caadc68c3000c3a9e34fa9eb77e37443a93117b5..a8f617447d22081a6640866f7080b1699e29b854 100644 (file)
@@ -51,6 +51,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/mutex.h>
 
 #include "lsi/mpi_type.h"
 #include "lsi/mpi.h"           /* Fusion MPI(nterface) basic defs */
@@ -531,7 +532,7 @@ struct inactive_raid_component_info {
 typedef        struct _RaidCfgData {
        IOCPage2_t      *pIocPg2;               /* table of Raid Volumes */
        IOCPage3_t      *pIocPg3;               /* table of physical disks */
-       struct semaphore        inactive_list_mutex;
+       struct mutex    inactive_list_mutex;
        struct list_head        inactive_list; /* link list for physical
                                                disk that belong in
                                                inactive volumes */
@@ -630,6 +631,7 @@ typedef struct _MPT_ADAPTER
        int                      mtrr_reg;
        struct pci_dev          *pcidev;        /* struct pci_dev pointer */
        int                     bars;           /* bitmask of BAR's that must be configured */
+       int                     msi_enable;
        u8                      __iomem *memmap;        /* mmap address */
        struct Scsi_Host        *sh;            /* Scsi Host pointer */
        SpiCfgData              spi_data;       /* Scsi config. data */
@@ -693,7 +695,6 @@ typedef struct _MPT_ADAPTER
        struct mutex             sas_discovery_mutex;
        u8                       sas_discovery_runtime;
        u8                       sas_discovery_ignore_events;
-       u16                      handle;
        int                      sas_index; /* index refrencing */
        MPT_SAS_MGMT             sas_mgmt;
        struct work_struct       sas_persist_task;
index 78734e25edd515bcc863fbcae3216c6447e045eb..468480771f1304ff5e86b838c3eb3b08b53ebdae 100644 (file)
@@ -230,6 +230,20 @@ static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
        return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
 }
 
+static struct mptsas_portinfo *
+mptsas_get_hba_portinfo(MPT_ADAPTER *ioc)
+{
+       struct list_head        *head = &ioc->sas_topology;
+       struct mptsas_portinfo  *pi = NULL;
+
+       /* always the first entry on sas_topology list */
+
+       if (!list_empty(head))
+               pi = list_entry(head->next, struct mptsas_portinfo, list);
+
+       return pi;
+}
+
 /*
  * mptsas_find_portinfo_by_handle
  *
@@ -1290,7 +1304,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
                struct mptsas_portinfo *port_info;
 
                mutex_lock(&ioc->sas_topology_mutex);
-               port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
+               port_info = mptsas_get_hba_portinfo(ioc);
                if (port_info && port_info->phy_info)
                        sas_address =
                                port_info->phy_info[0].phy->identify.sas_address;
@@ -2028,8 +2042,7 @@ static int mptsas_probe_one_phy(struct device *dev,
                        int i;
 
                        mutex_lock(&ioc->sas_topology_mutex);
-                       port_info = mptsas_find_portinfo_by_handle(ioc,
-                                                                  ioc->handle);
+                       port_info = mptsas_get_hba_portinfo(ioc);
                        mutex_unlock(&ioc->sas_topology_mutex);
 
                        for (i = 0; i < port_info->num_phys; i++)
@@ -2099,8 +2112,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
 
        mptsas_sas_io_unit_pg1(ioc);
        mutex_lock(&ioc->sas_topology_mutex);
-       ioc->handle = hba->phy_info[0].handle;
-       port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
+       port_info = mptsas_get_hba_portinfo(ioc);
        if (!port_info) {
                port_info = hba;
                list_add_tail(&port_info->list, &ioc->sas_topology);
index c207bda6723b9454aa42875db9397d218e0ff00e..89c63147a15dcb734c429695c31bfd0240fb3dbc 100644 (file)
@@ -2304,14 +2304,14 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
        if (list_empty(&ioc->raid_data.inactive_list))
                goto out;
 
-       down(&ioc->raid_data.inactive_list_mutex);
+       mutex_lock(&ioc->raid_data.inactive_list_mutex);
        list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
            list) {
                if ((component_info->d.PhysDiskID == id) &&
                    (component_info->d.PhysDiskBus == channel))
                        rc = 1;
        }
-       up(&ioc->raid_data.inactive_list_mutex);
+       mutex_unlock(&ioc->raid_data.inactive_list_mutex);
 
  out:
        return rc;
@@ -2341,14 +2341,14 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
        if (list_empty(&ioc->raid_data.inactive_list))
                goto out;
 
-       down(&ioc->raid_data.inactive_list_mutex);
+       mutex_lock(&ioc->raid_data.inactive_list_mutex);
        list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
            list) {
                if ((component_info->d.PhysDiskID == id) &&
                    (component_info->d.PhysDiskBus == channel))
                        rc = component_info->d.PhysDiskNum;
        }
-       up(&ioc->raid_data.inactive_list_mutex);
+       mutex_unlock(&ioc->raid_data.inactive_list_mutex);
 
  out:
        return rc;
index 874b55ed00a3473f44a71227e69c33fa70eba04e..8c7e2b778ef1a18fc012c7f80a7429c01c5f4d2f 100644 (file)
@@ -1030,10 +1030,10 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 
        /* initialize debug locks */
 
-       spin_lock_init(&adapter->erp_dbf_lock);
        spin_lock_init(&adapter->hba_dbf_lock);
        spin_lock_init(&adapter->san_dbf_lock);
        spin_lock_init(&adapter->scsi_dbf_lock);
+       spin_lock_init(&adapter->rec_dbf_lock);
 
        retval = zfcp_adapter_debug_register(adapter);
        if (retval)
@@ -1325,10 +1325,10 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_FC
 
-static void
-zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
-                          struct fsf_status_read_buffer *status_buffer)
+static void zfcp_fsf_incoming_els_rscn(struct zfcp_fsf_req *fsf_req)
 {
+       struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
+       struct zfcp_adapter *adapter = fsf_req->adapter;
        struct fcp_rscn_head *fcp_rscn_head;
        struct fcp_rscn_element *fcp_rscn_element;
        struct zfcp_port *port;
@@ -1375,7 +1375,8 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
                                ZFCP_LOG_INFO("incoming RSCN, trying to open "
                                              "port 0x%016Lx\n", port->wwpn);
                                zfcp_erp_port_reopen(port,
-                                                    ZFCP_STATUS_COMMON_ERP_FAILED);
+                                                    ZFCP_STATUS_COMMON_ERP_FAILED,
+                                                    82, fsf_req);
                                continue;
                        }
 
@@ -1406,10 +1407,10 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
        }
 }
 
-static void
-zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
-                           struct fsf_status_read_buffer *status_buffer)
+static void zfcp_fsf_incoming_els_plogi(struct zfcp_fsf_req *fsf_req)
 {
+       struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
+       struct zfcp_adapter *adapter = fsf_req->adapter;
        struct fsf_plogi *els_plogi;
        struct zfcp_port *port;
        unsigned long flags;
@@ -1428,14 +1429,14 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
                               status_buffer->d_id,
                               zfcp_get_busid_by_adapter(adapter));
        } else {
-               zfcp_erp_port_forced_reopen(port, 0);
+               zfcp_erp_port_forced_reopen(port, 0, 83, fsf_req);
        }
 }
 
-static void
-zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
-                          struct fsf_status_read_buffer *status_buffer)
+static void zfcp_fsf_incoming_els_logo(struct zfcp_fsf_req *fsf_req)
 {
+       struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
+       struct zfcp_adapter *adapter = fsf_req->adapter;
        struct fcp_logo *els_logo = (struct fcp_logo *) status_buffer->payload;
        struct zfcp_port *port;
        unsigned long flags;
@@ -1453,7 +1454,7 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
                               status_buffer->d_id,
                               zfcp_get_busid_by_adapter(adapter));
        } else {
-               zfcp_erp_port_forced_reopen(port, 0);
+               zfcp_erp_port_forced_reopen(port, 0, 84, fsf_req);
        }
 }
 
@@ -1480,12 +1481,12 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req)
 
        zfcp_san_dbf_event_incoming_els(fsf_req);
        if (els_type == LS_PLOGI)
-               zfcp_fsf_incoming_els_plogi(adapter, status_buffer);
+               zfcp_fsf_incoming_els_plogi(fsf_req);
        else if (els_type == LS_LOGO)
-               zfcp_fsf_incoming_els_logo(adapter, status_buffer);
+               zfcp_fsf_incoming_els_logo(fsf_req);
        else if ((els_type & 0xffff0000) == LS_RSCN)
                /* we are only concerned with the command, not the length */
-               zfcp_fsf_incoming_els_rscn(adapter, status_buffer);
+               zfcp_fsf_incoming_els_rscn(fsf_req);
        else
                zfcp_fsf_incoming_els_unknown(adapter, status_buffer);
 }
index edc5015e920d8fbc9c0f5c0fb3e457433d1e2f89..66d3b88844b0f8a52a9df4a9227e33ec7c3b006b 100644 (file)
@@ -170,9 +170,10 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
        BUG_ON(!zfcp_reqlist_isempty(adapter));
        adapter->req_no = 0;
 
-       zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
-                                      ZFCP_SET);
-       zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
+       zfcp_erp_modify_adapter_status(adapter, 10, NULL,
+                                      ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+       zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85,
+                               NULL);
        zfcp_erp_wait(adapter);
        goto out;
 
@@ -197,7 +198,7 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 
        down(&zfcp_data.config_sema);
        adapter = dev_get_drvdata(&ccw_device->dev);
-       zfcp_erp_adapter_shutdown(adapter, 0);
+       zfcp_erp_adapter_shutdown(adapter, 0, 86, NULL);
        zfcp_erp_wait(adapter);
        zfcp_erp_thread_kill(adapter);
        up(&zfcp_data.config_sema);
@@ -223,24 +224,21 @@ zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
        case CIO_GONE:
                ZFCP_LOG_NORMAL("adapter %s: device gone\n",
                                zfcp_get_busid_by_adapter(adapter));
-               debug_text_event(adapter->erp_dbf,1,"dev_gone");
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL);
                break;
        case CIO_NO_PATH:
                ZFCP_LOG_NORMAL("adapter %s: no path\n",
                                zfcp_get_busid_by_adapter(adapter));
-               debug_text_event(adapter->erp_dbf,1,"no_path");
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL);
                break;
        case CIO_OPER:
                ZFCP_LOG_NORMAL("adapter %s: operational again\n",
                                zfcp_get_busid_by_adapter(adapter));
-               debug_text_event(adapter->erp_dbf,1,"dev_oper");
-               zfcp_erp_modify_adapter_status(adapter,
+               zfcp_erp_modify_adapter_status(adapter, 11, NULL,
                                               ZFCP_STATUS_COMMON_RUNNING,
                                               ZFCP_SET);
-               zfcp_erp_adapter_reopen(adapter,
-                                       ZFCP_STATUS_COMMON_ERP_FAILED);
+               zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
+                                       89, NULL);
                break;
        }
        zfcp_erp_wait(adapter);
@@ -272,7 +270,7 @@ zfcp_ccw_shutdown(struct ccw_device *cdev)
 
        down(&zfcp_data.config_sema);
        adapter = dev_get_drvdata(&cdev->dev);
-       zfcp_erp_adapter_shutdown(adapter, 0);
+       zfcp_erp_adapter_shutdown(adapter, 0, 90, NULL);
        zfcp_erp_wait(adapter);
        up(&zfcp_data.config_sema);
 }
index 701046c9bb330ef8dc1ca6d0a76516755a5687ea..37b85c67b11dcb2404d0f59eafa021d096f47588 100644 (file)
@@ -31,123 +31,128 @@ MODULE_PARM_DESC(dbfsize,
 
 #define ZFCP_LOG_AREA                  ZFCP_LOG_AREA_OTHER
 
-static int
-zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
+static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len,
+                            int level, char *from, int from_len)
+{
+       int offset;
+       struct zfcp_dbf_dump *dump = to;
+       int room = to_len - sizeof(*dump);
+
+       for (offset = 0; offset < from_len; offset += dump->size) {
+               memset(to, 0, to_len);
+               strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
+               dump->total_size = from_len;
+               dump->offset = offset;
+               dump->size = min(from_len - offset, room);
+               memcpy(dump->data, from + offset, dump->size);
+               debug_event(dbf, level, dump, dump->size);
+       }
+}
+
+/* FIXME: this duplicate this code in s390 debug feature */
+static void zfcp_dbf_timestamp(unsigned long long stck, struct timespec *time)
 {
        unsigned long long sec;
-       struct timespec dbftime;
-       int len = 0;
 
        stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
        sec = stck >> 12;
        do_div(sec, 1000000);
-       dbftime.tv_sec = sec;
+       time->tv_sec = sec;
        stck -= (sec * 1000000) << 12;
-       dbftime.tv_nsec = ((stck * 1000) >> 12);
-       len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n",
-                      label, dbftime.tv_sec, dbftime.tv_nsec);
-
-       return len;
+       time->tv_nsec = ((stck * 1000) >> 12);
 }
 
-static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag)
+static void zfcp_dbf_tag(char **p, const char *label, const char *tag)
 {
-       int len = 0, i;
+       int i;
 
-       len += sprintf(out_buf + len, "%-24s", label);
+       *p += sprintf(*p, "%-24s", label);
        for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++)
-               len += sprintf(out_buf + len, "%c", tag[i]);
-       len += sprintf(out_buf + len, "\n");
+               *p += sprintf(*p, "%c", tag[i]);
+       *p += sprintf(*p, "\n");
+}
 
-       return len;
+static void zfcp_dbf_outs(char **buf, const char *s1, const char *s2)
+{
+       *buf += sprintf(*buf, "%-24s%s\n", s1, s2);
 }
 
-static int
-zfcp_dbf_view(char *out_buf, const char *label, const char *format, ...)
+static void zfcp_dbf_out(char **buf, const char *s, const char *format, ...)
 {
        va_list arg;
-       int len = 0;
 
-       len += sprintf(out_buf + len, "%-24s", label);
+       *buf += sprintf(*buf, "%-24s", s);
        va_start(arg, format);
-       len += vsprintf(out_buf + len, format, arg);
+       *buf += vsprintf(*buf, format, arg);
        va_end(arg);
-       len += sprintf(out_buf + len, "\n");
-
-       return len;
+       *buf += sprintf(*buf, "\n");
 }
 
-static int
-zfcp_dbf_view_dump(char *out_buf, const char *label,
-                  char *buffer, int buflen, int offset, int total_size)
+static void zfcp_dbf_outd(char **p, const char *label, char *buffer,
+                         int buflen, int offset, int total_size)
 {
-       int len = 0;
-
-       if (offset == 0)
-               len += sprintf(out_buf + len, "%-24s  ", label);
-
+       if (!offset)
+               *p += sprintf(*p, "%-24s  ", label);
        while (buflen--) {
                if (offset > 0) {
                        if ((offset % 32) == 0)
-                               len += sprintf(out_buf + len, "\n%-24c  ", ' ');
+                               *p += sprintf(*p, "\n%-24c  ", ' ');
                        else if ((offset % 4) == 0)
-                               len += sprintf(out_buf + len, " ");
+                               *p += sprintf(*p, " ");
                }
-               len += sprintf(out_buf + len, "%02x", *buffer++);
+               *p += sprintf(*p, "%02x", *buffer++);
                if (++offset == total_size) {
-                       len += sprintf(out_buf + len, "\n");
+                       *p += sprintf(*p, "\n");
                        break;
                }
        }
-
-       if (total_size == 0)
-               len += sprintf(out_buf + len, "\n");
-
-       return len;
+       if (!total_size)
+               *p += sprintf(*p, "\n");
 }
 
-static int
-zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
-                    debug_entry_t * entry, char *out_buf)
+static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view,
+                               int area, debug_entry_t *entry, char *out_buf)
 {
        struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry);
-       int len = 0;
+       struct timespec t;
+       char *p = out_buf;
 
        if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) {
-               len += zfcp_dbf_stck(out_buf + len, "timestamp",
-                                    entry->id.stck);
-               len += zfcp_dbf_view(out_buf + len, "cpu", "%02i",
-                                    entry->id.fields.cpuid);
-       } else {
-               len += zfcp_dbf_view_dump(out_buf + len, NULL,
-                                         dump->data,
-                                         dump->size,
-                                         dump->offset, dump->total_size);
+               zfcp_dbf_timestamp(entry->id.stck, &t);
+               zfcp_dbf_out(&p, "timestamp", "%011lu:%06lu",
+                            t.tv_sec, t.tv_nsec);
+               zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid);
+       } else  {
+               zfcp_dbf_outd(&p, NULL, dump->data, dump->size, dump->offset,
+                             dump->total_size);
                if ((dump->offset + dump->size) == dump->total_size)
-                       len += sprintf(out_buf + len, "\n");
+                       p += sprintf(p, "\n");
        }
-
-       return len;
+       return p - out_buf;
 }
 
+/**
+ * zfcp_hba_dbf_event_fsf_response - trace event for request completion
+ * @fsf_req: request that has been completed
+ */
 void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_adapter *adapter = fsf_req->adapter;
        struct fsf_qtcb *qtcb = fsf_req->qtcb;
        union fsf_prot_status_qual *prot_status_qual =
-           &qtcb->prefix.prot_status_qual;
+                                       &qtcb->prefix.prot_status_qual;
        union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual;
        struct scsi_cmnd *scsi_cmnd;
        struct zfcp_port *port;
        struct zfcp_unit *unit;
        struct zfcp_send_els *send_els;
        struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
-       struct zfcp_hba_dbf_record_response *response = &rec->type.response;
+       struct zfcp_hba_dbf_record_response *response = &rec->u.response;
        int level;
        unsigned long flags;
 
        spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
-       memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+       memset(rec, 0, sizeof(*rec));
        strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE);
 
        if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
@@ -161,6 +166,9 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
                   (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) {
                strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE);
                level = 4;
+       } else if (qtcb->header.log_length) {
+               strncpy(rec->tag2, "qtcb", ZFCP_DBF_TAG_SIZE);
+               level = 5;
        } else {
                strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE);
                level = 6;
@@ -188,11 +196,9 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
                if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
                        break;
                scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
-               if (scsi_cmnd != NULL) {
-                       response->data.send_fcp.scsi_cmnd
-                           = (unsigned long)scsi_cmnd;
-                       response->data.send_fcp.scsi_serial
-                           = scsi_cmnd->serial_number;
+               if (scsi_cmnd) {
+                       response->u.fcp.cmnd = (unsigned long)scsi_cmnd;
+                       response->u.fcp.serial = scsi_cmnd->serial_number;
                }
                break;
 
@@ -200,25 +206,25 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
        case FSF_QTCB_CLOSE_PORT:
        case FSF_QTCB_CLOSE_PHYSICAL_PORT:
                port = (struct zfcp_port *)fsf_req->data;
-               response->data.port.wwpn = port->wwpn;
-               response->data.port.d_id = port->d_id;
-               response->data.port.port_handle = qtcb->header.port_handle;
+               response->u.port.wwpn = port->wwpn;
+               response->u.port.d_id = port->d_id;
+               response->u.port.port_handle = qtcb->header.port_handle;
                break;
 
        case FSF_QTCB_OPEN_LUN:
        case FSF_QTCB_CLOSE_LUN:
                unit = (struct zfcp_unit *)fsf_req->data;
                port = unit->port;
-               response->data.unit.wwpn = port->wwpn;
-               response->data.unit.fcp_lun = unit->fcp_lun;
-               response->data.unit.port_handle = qtcb->header.port_handle;
-               response->data.unit.lun_handle = qtcb->header.lun_handle;
+               response->u.unit.wwpn = port->wwpn;
+               response->u.unit.fcp_lun = unit->fcp_lun;
+               response->u.unit.port_handle = qtcb->header.port_handle;
+               response->u.unit.lun_handle = qtcb->header.lun_handle;
                break;
 
        case FSF_QTCB_SEND_ELS:
                send_els = (struct zfcp_send_els *)fsf_req->data;
-               response->data.send_els.d_id = qtcb->bottom.support.d_id;
-               response->data.send_els.ls_code = send_els->ls_code >> 24;
+               response->u.els.d_id = qtcb->bottom.support.d_id;
+               response->u.els.ls_code = send_els->ls_code >> 24;
                break;
 
        case FSF_QTCB_ABORT_FCP_CMND:
@@ -230,39 +236,54 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
                break;
        }
 
-       debug_event(adapter->hba_dbf, level,
-                   rec, sizeof(struct zfcp_hba_dbf_record));
+       debug_event(adapter->hba_dbf, level, rec, sizeof(*rec));
+
+       /* have fcp channel microcode fixed to use as little as possible */
+       if (fsf_req->fsf_command != FSF_QTCB_FCP_CMND) {
+               /* adjust length skipping trailing zeros */
+               char *buf = (char *)qtcb + qtcb->header.log_start;
+               int len = qtcb->header.log_length;
+               for (; len && !buf[len - 1]; len--);
+               zfcp_dbf_hexdump(adapter->hba_dbf, rec, sizeof(*rec), level,
+                                buf, len);
+       }
+
        spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
 }
 
-void
-zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
-                            struct fsf_status_read_buffer *status_buffer)
+/**
+ * zfcp_hba_dbf_event_fsf_unsol - trace event for an unsolicited status buffer
+ * @tag: tag indicating which kind of unsolicited status has been received
+ * @adapter: adapter that has issued the unsolicited status buffer
+ * @status_buffer: buffer containing payload of unsolicited status
+ */
+void zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
+                                 struct fsf_status_read_buffer *status_buffer)
 {
        struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
        unsigned long flags;
 
        spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
-       memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+       memset(rec, 0, sizeof(*rec));
        strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE);
        strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE);
 
-       rec->type.status.failed = adapter->status_read_failed;
+       rec->u.status.failed = adapter->status_read_failed;
        if (status_buffer != NULL) {
-               rec->type.status.status_type = status_buffer->status_type;
-               rec->type.status.status_subtype = status_buffer->status_subtype;
-               memcpy(&rec->type.status.queue_designator,
+               rec->u.status.status_type = status_buffer->status_type;
+               rec->u.status.status_subtype = status_buffer->status_subtype;
+               memcpy(&rec->u.status.queue_designator,
                       &status_buffer->queue_designator,
                       sizeof(struct fsf_queue_designator));
 
                switch (status_buffer->status_type) {
                case FSF_STATUS_READ_SENSE_DATA_AVAIL:
-                       rec->type.status.payload_size =
+                       rec->u.status.payload_size =
                            ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL;
                        break;
 
                case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
-                       rec->type.status.payload_size =
+                       rec->u.status.payload_size =
                            ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD;
                        break;
 
@@ -270,119 +291,101 @@ zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
                        switch (status_buffer->status_subtype) {
                        case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
                        case FSF_STATUS_READ_SUB_FDISC_FAILED:
-                               rec->type.status.payload_size =
+                               rec->u.status.payload_size =
                                        sizeof(struct fsf_link_down_info);
                        }
                        break;
 
                case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
-                       rec->type.status.payload_size =
+                       rec->u.status.payload_size =
                            ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT;
                        break;
                }
-               memcpy(&rec->type.status.payload,
-                      &status_buffer->payload, rec->type.status.payload_size);
+               memcpy(&rec->u.status.payload,
+                      &status_buffer->payload, rec->u.status.payload_size);
        }
 
-       debug_event(adapter->hba_dbf, 2,
-                   rec, sizeof(struct zfcp_hba_dbf_record));
+       debug_event(adapter->hba_dbf, 2, rec, sizeof(*rec));
        spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
 }
 
-void
-zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
-                       unsigned int qdio_error, unsigned int siga_error,
-                       int sbal_index, int sbal_count)
+/**
+ * zfcp_hba_dbf_event_qdio - trace event for QDIO related failure
+ * @adapter: adapter affected by this QDIO related event
+ * @status: as passed by qdio module
+ * @qdio_error: as passed by qdio module
+ * @siga_error: as passed by qdio module
+ * @sbal_index: first buffer with error condition, as passed by qdio module
+ * @sbal_count: number of buffers affected, as passed by qdio module
+ */
+void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
+                            unsigned int qdio_error, unsigned int siga_error,
+                            int sbal_index, int sbal_count)
 {
-       struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+       struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
        unsigned long flags;
 
        spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
-       memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
-       strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE);
-       rec->type.qdio.status = status;
-       rec->type.qdio.qdio_error = qdio_error;
-       rec->type.qdio.siga_error = siga_error;
-       rec->type.qdio.sbal_index = sbal_index;
-       rec->type.qdio.sbal_count = sbal_count;
-       debug_event(adapter->hba_dbf, 0,
-                   rec, sizeof(struct zfcp_hba_dbf_record));
+       memset(r, 0, sizeof(*r));
+       strncpy(r->tag, "qdio", ZFCP_DBF_TAG_SIZE);
+       r->u.qdio.status = status;
+       r->u.qdio.qdio_error = qdio_error;
+       r->u.qdio.siga_error = siga_error;
+       r->u.qdio.sbal_index = sbal_index;
+       r->u.qdio.sbal_count = sbal_count;
+       debug_event(adapter->hba_dbf, 0, r, sizeof(*r));
        spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
 }
 
-static int
-zfcp_hba_dbf_view_response(char *out_buf,
-                          struct zfcp_hba_dbf_record_response *rec)
-{
-       int len = 0;
-
-       len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x",
-                            rec->fsf_command);
-       len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
-                            rec->fsf_reqid);
-       len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
-                            rec->fsf_seqno);
-       len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
-       len += zfcp_dbf_view(out_buf + len, "fsf_prot_status", "0x%08x",
-                            rec->fsf_prot_status);
-       len += zfcp_dbf_view(out_buf + len, "fsf_status", "0x%08x",
-                            rec->fsf_status);
-       len += zfcp_dbf_view_dump(out_buf + len, "fsf_prot_status_qual",
-                                 rec->fsf_prot_status_qual,
-                                 FSF_PROT_STATUS_QUAL_SIZE,
-                                 0, FSF_PROT_STATUS_QUAL_SIZE);
-       len += zfcp_dbf_view_dump(out_buf + len, "fsf_status_qual",
-                                 rec->fsf_status_qual,
-                                 FSF_STATUS_QUALIFIER_SIZE,
-                                 0, FSF_STATUS_QUALIFIER_SIZE);
-       len += zfcp_dbf_view(out_buf + len, "fsf_req_status", "0x%08x",
-                            rec->fsf_req_status);
-       len += zfcp_dbf_view(out_buf + len, "sbal_first", "0x%02x",
-                            rec->sbal_first);
-       len += zfcp_dbf_view(out_buf + len, "sbal_curr", "0x%02x",
-                            rec->sbal_curr);
-       len += zfcp_dbf_view(out_buf + len, "sbal_last", "0x%02x",
-                            rec->sbal_last);
-       len += zfcp_dbf_view(out_buf + len, "pool", "0x%02x", rec->pool);
-
-       switch (rec->fsf_command) {
+static void zfcp_hba_dbf_view_response(char **p,
+                                      struct zfcp_hba_dbf_record_response *r)
+{
+       struct timespec t;
+
+       zfcp_dbf_out(p, "fsf_command", "0x%08x", r->fsf_command);
+       zfcp_dbf_out(p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
+       zfcp_dbf_out(p, "fsf_seqno", "0x%08x", r->fsf_seqno);
+       zfcp_dbf_timestamp(r->fsf_issued, &t);
+       zfcp_dbf_out(p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
+       zfcp_dbf_out(p, "fsf_prot_status", "0x%08x", r->fsf_prot_status);
+       zfcp_dbf_out(p, "fsf_status", "0x%08x", r->fsf_status);
+       zfcp_dbf_outd(p, "fsf_prot_status_qual", r->fsf_prot_status_qual,
+                     FSF_PROT_STATUS_QUAL_SIZE, 0, FSF_PROT_STATUS_QUAL_SIZE);
+       zfcp_dbf_outd(p, "fsf_status_qual", r->fsf_status_qual,
+                     FSF_STATUS_QUALIFIER_SIZE, 0, FSF_STATUS_QUALIFIER_SIZE);
+       zfcp_dbf_out(p, "fsf_req_status", "0x%08x", r->fsf_req_status);
+       zfcp_dbf_out(p, "sbal_first", "0x%02x", r->sbal_first);
+       zfcp_dbf_out(p, "sbal_curr", "0x%02x", r->sbal_curr);
+       zfcp_dbf_out(p, "sbal_last", "0x%02x", r->sbal_last);
+       zfcp_dbf_out(p, "pool", "0x%02x", r->pool);
+
+       switch (r->fsf_command) {
        case FSF_QTCB_FCP_CMND:
-               if (rec->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
+               if (r->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
                        break;
-               len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
-                                    rec->data.send_fcp.scsi_cmnd);
-               len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
-                                    rec->data.send_fcp.scsi_serial);
+               zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
+               zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
                break;
 
        case FSF_QTCB_OPEN_PORT_WITH_DID:
        case FSF_QTCB_CLOSE_PORT:
        case FSF_QTCB_CLOSE_PHYSICAL_PORT:
-               len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
-                                    rec->data.port.wwpn);
-               len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
-                                    rec->data.port.d_id);
-               len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
-                                    rec->data.port.port_handle);
+               zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.port.wwpn);
+               zfcp_dbf_out(p, "d_id", "0x%06x", r->u.port.d_id);
+               zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.port.port_handle);
                break;
 
        case FSF_QTCB_OPEN_LUN:
        case FSF_QTCB_CLOSE_LUN:
-               len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
-                                    rec->data.unit.wwpn);
-               len += zfcp_dbf_view(out_buf + len, "fcp_lun", "0x%016Lx",
-                                    rec->data.unit.fcp_lun);
-               len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
-                                    rec->data.unit.port_handle);
-               len += zfcp_dbf_view(out_buf + len, "lun_handle", "0x%08x",
-                                    rec->data.unit.lun_handle);
+               zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.unit.wwpn);
+               zfcp_dbf_out(p, "fcp_lun", "0x%016Lx", r->u.unit.fcp_lun);
+               zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.unit.port_handle);
+               zfcp_dbf_out(p, "lun_handle", "0x%08x", r->u.unit.lun_handle);
                break;
 
        case FSF_QTCB_SEND_ELS:
-               len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
-                                    rec->data.send_els.d_id);
-               len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
-                                    rec->data.send_els.ls_code);
+               zfcp_dbf_out(p, "d_id", "0x%06x", r->u.els.d_id);
+               zfcp_dbf_out(p, "ls_code", "0x%02x", r->u.els.ls_code);
                break;
 
        case FSF_QTCB_ABORT_FCP_CMND:
@@ -393,74 +396,52 @@ zfcp_hba_dbf_view_response(char *out_buf,
        case FSF_QTCB_UPLOAD_CONTROL_FILE:
                break;
        }
-
-       return len;
 }
 
-static int
-zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
+static void zfcp_hba_dbf_view_status(char **p,
+                                    struct zfcp_hba_dbf_record_status *r)
 {
-       int len = 0;
-
-       len += zfcp_dbf_view(out_buf + len, "failed", "0x%02x", rec->failed);
-       len += zfcp_dbf_view(out_buf + len, "status_type", "0x%08x",
-                            rec->status_type);
-       len += zfcp_dbf_view(out_buf + len, "status_subtype", "0x%08x",
-                            rec->status_subtype);
-       len += zfcp_dbf_view_dump(out_buf + len, "queue_designator",
-                                 (char *)&rec->queue_designator,
-                                 sizeof(struct fsf_queue_designator),
-                                 0, sizeof(struct fsf_queue_designator));
-       len += zfcp_dbf_view_dump(out_buf + len, "payload",
-                                 (char *)&rec->payload,
-                                 rec->payload_size, 0, rec->payload_size);
-
-       return len;
+       zfcp_dbf_out(p, "failed", "0x%02x", r->failed);
+       zfcp_dbf_out(p, "status_type", "0x%08x", r->status_type);
+       zfcp_dbf_out(p, "status_subtype", "0x%08x", r->status_subtype);
+       zfcp_dbf_outd(p, "queue_designator", (char *)&r->queue_designator,
+                     sizeof(struct fsf_queue_designator), 0,
+                     sizeof(struct fsf_queue_designator));
+       zfcp_dbf_outd(p, "payload", (char *)&r->payload, r->payload_size, 0,
+                     r->payload_size);
 }
 
-static int
-zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec)
+static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r)
 {
-       int len = 0;
-
-       len += zfcp_dbf_view(out_buf + len, "status", "0x%08x", rec->status);
-       len += zfcp_dbf_view(out_buf + len, "qdio_error", "0x%08x",
-                            rec->qdio_error);
-       len += zfcp_dbf_view(out_buf + len, "siga_error", "0x%08x",
-                            rec->siga_error);
-       len += zfcp_dbf_view(out_buf + len, "sbal_index", "0x%02x",
-                            rec->sbal_index);
-       len += zfcp_dbf_view(out_buf + len, "sbal_count", "0x%02x",
-                            rec->sbal_count);
-
-       return len;
+       zfcp_dbf_out(p, "status", "0x%08x", r->status);
+       zfcp_dbf_out(p, "qdio_error", "0x%08x", r->qdio_error);
+       zfcp_dbf_out(p, "siga_error", "0x%08x", r->siga_error);
+       zfcp_dbf_out(p, "sbal_index", "0x%02x", r->sbal_index);
+       zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count);
 }
 
-static int
-zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view,
-                        char *out_buf, const char *in_buf)
+static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
+                                   char *out_buf, const char *in_buf)
 {
-       struct zfcp_hba_dbf_record *rec = (struct zfcp_hba_dbf_record *)in_buf;
-       int len = 0;
+       struct zfcp_hba_dbf_record *r = (struct zfcp_hba_dbf_record *)in_buf;
+       char *p = out_buf;
 
-       if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+       if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
                return 0;
 
-       len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
-       if (isalpha(rec->tag2[0]))
-               len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
-       if (strncmp(rec->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
-               len += zfcp_hba_dbf_view_response(out_buf + len,
-                                                 &rec->type.response);
-       else if (strncmp(rec->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
-               len += zfcp_hba_dbf_view_status(out_buf + len,
-                                               &rec->type.status);
-       else if (strncmp(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
-               len += zfcp_hba_dbf_view_qdio(out_buf + len, &rec->type.qdio);
+       zfcp_dbf_tag(&p, "tag", r->tag);
+       if (isalpha(r->tag2[0]))
+               zfcp_dbf_tag(&p, "tag2", r->tag2);
 
-       len += sprintf(out_buf + len, "\n");
+       if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
+               zfcp_hba_dbf_view_response(&p, &r->u.response);
+       else if (strncmp(r->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
+               zfcp_hba_dbf_view_status(&p, &r->u.status);
+       else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
+               zfcp_hba_dbf_view_qdio(&p, &r->u.qdio);
 
-       return len;
+       p += sprintf(p, "\n");
+       return p - out_buf;
 }
 
 static struct debug_view zfcp_hba_dbf_view = {
@@ -472,219 +453,570 @@ static struct debug_view zfcp_hba_dbf_view = {
        NULL
 };
 
-static void
-_zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
-                             u32 s_id, u32 d_id, void *buffer, int buflen)
+static const char *zfcp_rec_dbf_tags[] = {
+       [ZFCP_REC_DBF_ID_THREAD] = "thread",
+       [ZFCP_REC_DBF_ID_TARGET] = "target",
+       [ZFCP_REC_DBF_ID_TRIGGER] = "trigger",
+       [ZFCP_REC_DBF_ID_ACTION] = "action",
+};
+
+static const char *zfcp_rec_dbf_ids[] = {
+       [1]     = "new",
+       [2]     = "ready",
+       [3]     = "kill",
+       [4]     = "down sleep",
+       [5]     = "down wakeup",
+       [6]     = "down sleep ecd",
+       [7]     = "down wakeup ecd",
+       [8]     = "down sleep epd",
+       [9]     = "down wakeup epd",
+       [10]    = "online",
+       [11]    = "operational",
+       [12]    = "scsi slave destroy",
+       [13]    = "propagate failed adapter",
+       [14]    = "propagate failed port",
+       [15]    = "block adapter",
+       [16]    = "unblock adapter",
+       [17]    = "block port",
+       [18]    = "unblock port",
+       [19]    = "block unit",
+       [20]    = "unblock unit",
+       [21]    = "unit recovery failed",
+       [22]    = "port recovery failed",
+       [23]    = "adapter recovery failed",
+       [24]    = "qdio queues down",
+       [25]    = "p2p failed",
+       [26]    = "nameserver lookup failed",
+       [27]    = "nameserver port failed",
+       [28]    = "link up",
+       [29]    = "link down",
+       [30]    = "link up status read",
+       [31]    = "open port failed",
+       [32]    = "open port failed",
+       [33]    = "close port",
+       [34]    = "open unit failed",
+       [35]    = "exclusive open unit failed",
+       [36]    = "shared open unit failed",
+       [37]    = "link down",
+       [38]    = "link down status read no link",
+       [39]    = "link down status read fdisc login",
+       [40]    = "link down status read firmware update",
+       [41]    = "link down status read unknown reason",
+       [42]    = "link down ecd incomplete",
+       [43]    = "link down epd incomplete",
+       [44]    = "sysfs adapter recovery",
+       [45]    = "sysfs port recovery",
+       [46]    = "sysfs unit recovery",
+       [47]    = "port boxed abort",
+       [48]    = "unit boxed abort",
+       [49]    = "port boxed ct",
+       [50]    = "port boxed close physical",
+       [51]    = "port boxed open unit",
+       [52]    = "port boxed close unit",
+       [53]    = "port boxed fcp",
+       [54]    = "unit boxed fcp",
+       [55]    = "port access denied ct",
+       [56]    = "port access denied els",
+       [57]    = "port access denied open port",
+       [58]    = "port access denied close physical",
+       [59]    = "unit access denied open unit",
+       [60]    = "shared unit access denied open unit",
+       [61]    = "unit access denied fcp",
+       [62]    = "request timeout",
+       [63]    = "adisc link test reject or timeout",
+       [64]    = "adisc link test d_id changed",
+       [65]    = "adisc link test failed",
+       [66]    = "recovery out of memory",
+       [67]    = "adapter recovery repeated after state change",
+       [68]    = "port recovery repeated after state change",
+       [69]    = "unit recovery repeated after state change",
+       [70]    = "port recovery follow-up after successful adapter recovery",
+       [71]    = "adapter recovery escalation after failed adapter recovery",
+       [72]    = "port recovery follow-up after successful physical port "
+                 "recovery",
+       [73]    = "adapter recovery escalation after failed physical port "
+                 "recovery",
+       [74]    = "unit recovery follow-up after successful port recovery",
+       [75]    = "physical port recovery escalation after failed port "
+                 "recovery",
+       [76]    = "port recovery escalation after failed unit recovery",
+       [77]    = "recovery opening nameserver port",
+       [78]    = "duplicate request id",
+       [79]    = "link down",
+       [80]    = "exclusive read-only unit access unsupported",
+       [81]    = "shared read-write unit access unsupported",
+       [82]    = "incoming rscn",
+       [83]    = "incoming plogi",
+       [84]    = "incoming logo",
+       [85]    = "online",
+       [86]    = "offline",
+       [87]    = "ccw device gone",
+       [88]    = "ccw device no path",
+       [89]    = "ccw device operational",
+       [90]    = "ccw device shutdown",
+       [91]    = "sysfs port addition",
+       [92]    = "sysfs port removal",
+       [93]    = "sysfs adapter recovery",
+       [94]    = "sysfs unit addition",
+       [95]    = "sysfs unit removal",
+       [96]    = "sysfs port recovery",
+       [97]    = "sysfs unit recovery",
+       [98]    = "sequence number mismatch",
+       [99]    = "link up",
+       [100]   = "error state",
+       [101]   = "status read physical port closed",
+       [102]   = "link up status read",
+       [103]   = "too many failed status read buffers",
+       [104]   = "port handle not valid abort",
+       [105]   = "lun handle not valid abort",
+       [106]   = "port handle not valid ct",
+       [107]   = "port handle not valid close port",
+       [108]   = "port handle not valid close physical port",
+       [109]   = "port handle not valid open unit",
+       [110]   = "port handle not valid close unit",
+       [111]   = "lun handle not valid close unit",
+       [112]   = "port handle not valid fcp",
+       [113]   = "lun handle not valid fcp",
+       [114]   = "handle mismatch fcp",
+       [115]   = "lun not valid fcp",
+       [116]   = "qdio send failed",
+       [117]   = "version mismatch",
+       [118]   = "incompatible qtcb type",
+       [119]   = "unknown protocol status",
+       [120]   = "unknown fsf command",
+       [121]   = "no recommendation for status qualifier",
+       [122]   = "status read physical port closed in error",
+       [123]   = "fc service class not supported ct",
+       [124]   = "fc service class not supported els",
+       [125]   = "need newer zfcp",
+       [126]   = "need newer microcode",
+       [127]   = "arbitrated loop not supported",
+       [128]   = "unknown topology",
+       [129]   = "qtcb size mismatch",
+       [130]   = "unknown fsf status ecd",
+       [131]   = "fcp request too big",
+       [132]   = "fc service class not supported fcp",
+       [133]   = "data direction not valid fcp",
+       [134]   = "command length not valid fcp",
+       [135]   = "status read act update",
+       [136]   = "status read cfdc update",
+       [137]   = "hbaapi port open",
+       [138]   = "hbaapi unit open",
+       [139]   = "hbaapi unit shutdown",
+       [140]   = "qdio error",
+       [141]   = "scsi host reset",
+       [142]   = "dismissing fsf request for recovery action",
+       [143]   = "recovery action timed out",
+       [144]   = "recovery action gone",
+       [145]   = "recovery action being processed",
+       [146]   = "recovery action ready for next step",
+};
+
+static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
+                                   char *buf, const char *_rec)
+{
+       struct zfcp_rec_dbf_record *r = (struct zfcp_rec_dbf_record *)_rec;
+       char *p = buf;
+
+       zfcp_dbf_outs(&p, "tag", zfcp_rec_dbf_tags[r->id]);
+       zfcp_dbf_outs(&p, "hint", zfcp_rec_dbf_ids[r->id2]);
+       zfcp_dbf_out(&p, "id", "%d", r->id2);
+       switch (r->id) {
+       case ZFCP_REC_DBF_ID_THREAD:
+               zfcp_dbf_out(&p, "total", "%d", r->u.thread.total);
+               zfcp_dbf_out(&p, "ready", "%d", r->u.thread.ready);
+               zfcp_dbf_out(&p, "running", "%d", r->u.thread.running);
+               break;
+       case ZFCP_REC_DBF_ID_TARGET:
+               zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.target.ref);
+               zfcp_dbf_out(&p, "status", "0x%08x", r->u.target.status);
+               zfcp_dbf_out(&p, "erp_count", "%d", r->u.target.erp_count);
+               zfcp_dbf_out(&p, "d_id", "0x%06x", r->u.target.d_id);
+               zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.target.wwpn);
+               zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.target.fcp_lun);
+               break;
+       case ZFCP_REC_DBF_ID_TRIGGER:
+               zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.trigger.ref);
+               zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.trigger.action);
+               zfcp_dbf_out(&p, "requested", "%d", r->u.trigger.want);
+               zfcp_dbf_out(&p, "executed", "%d", r->u.trigger.need);
+               zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.trigger.wwpn);
+               zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.trigger.fcp_lun);
+               zfcp_dbf_out(&p, "adapter_status", "0x%08x", r->u.trigger.as);
+               zfcp_dbf_out(&p, "port_status", "0x%08x", r->u.trigger.ps);
+               zfcp_dbf_out(&p, "unit_status", "0x%08x", r->u.trigger.us);
+               break;
+       case ZFCP_REC_DBF_ID_ACTION:
+               zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action);
+               zfcp_dbf_out(&p, "fsf_req", "0x%016Lx", r->u.action.fsf_req);
+               zfcp_dbf_out(&p, "status", "0x%08Lx", r->u.action.status);
+               zfcp_dbf_out(&p, "step", "0x%08Lx", r->u.action.step);
+               break;
+       }
+       p += sprintf(p, "\n");
+       return p - buf;
+}
+
+static struct debug_view zfcp_rec_dbf_view = {
+       "structured",
+       NULL,
+       &zfcp_dbf_view_header,
+       &zfcp_rec_dbf_view_format,
+       NULL,
+       NULL
+};
+
+/**
+ * zfcp_rec_dbf_event_thread - trace event related to recovery thread operation
+ * @id2: identifier for event
+ * @adapter: adapter
+ * @lock: non-zero value indicates that erp_lock has not yet been acquired
+ */
+void zfcp_rec_dbf_event_thread(u8 id2, struct zfcp_adapter *adapter, int lock)
+{
+       struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+       unsigned long flags = 0;
+       struct list_head *entry;
+       unsigned ready = 0, running = 0, total;
+
+       if (lock)
+               read_lock_irqsave(&adapter->erp_lock, flags);
+       list_for_each(entry, &adapter->erp_ready_head)
+               ready++;
+       list_for_each(entry, &adapter->erp_running_head)
+               running++;
+       total = adapter->erp_total_count;
+       if (lock)
+               read_unlock_irqrestore(&adapter->erp_lock, flags);
+
+       spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+       memset(r, 0, sizeof(*r));
+       r->id = ZFCP_REC_DBF_ID_THREAD;
+       r->id2 = id2;
+       r->u.thread.total = total;
+       r->u.thread.ready = ready;
+       r->u.thread.running = running;
+       debug_event(adapter->rec_dbf, 5, r, sizeof(*r));
+       spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+}
+
+static void zfcp_rec_dbf_event_target(u8 id2, void *ref,
+                                     struct zfcp_adapter *adapter,
+                                     atomic_t *status, atomic_t *erp_count,
+                                     u64 wwpn, u32 d_id, u64 fcp_lun)
+{
+       struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+       memset(r, 0, sizeof(*r));
+       r->id = ZFCP_REC_DBF_ID_TARGET;
+       r->id2 = id2;
+       r->u.target.ref = (unsigned long)ref;
+       r->u.target.status = atomic_read(status);
+       r->u.target.wwpn = wwpn;
+       r->u.target.d_id = d_id;
+       r->u.target.fcp_lun = fcp_lun;
+       r->u.target.erp_count = atomic_read(erp_count);
+       debug_event(adapter->rec_dbf, 3, r, sizeof(*r));
+       spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+}
+
+/**
+ * zfcp_rec_dbf_event_adapter - trace event for adapter state change
+ * @id: identifier for trigger of state change
+ * @ref: additional reference (e.g. request)
+ * @adapter: adapter
+ */
+void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *adapter)
+{
+       zfcp_rec_dbf_event_target(id, ref, adapter, &adapter->status,
+                                 &adapter->erp_counter, 0, 0, 0);
+}
+
+/**
+ * zfcp_rec_dbf_event_port - trace event for port state change
+ * @id: identifier for trigger of state change
+ * @ref: additional reference (e.g. request)
+ * @port: port
+ */
+void zfcp_rec_dbf_event_port(u8 id, void *ref, struct zfcp_port *port)
 {
-       struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data;
-       struct zfcp_port *port = send_ct->port;
        struct zfcp_adapter *adapter = port->adapter;
-       struct ct_hdr *header = (struct ct_hdr *)buffer;
-       struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
-       struct zfcp_san_dbf_record_ct *ct = &rec->type.ct;
+
+       zfcp_rec_dbf_event_target(id, ref, adapter, &port->status,
+                                 &port->erp_counter, port->wwpn, port->d_id,
+                                 0);
+}
+
+/**
+ * zfcp_rec_dbf_event_unit - trace event for unit state change
+ * @id: identifier for trigger of state change
+ * @ref: additional reference (e.g. request)
+ * @unit: unit
+ */
+void zfcp_rec_dbf_event_unit(u8 id, void *ref, struct zfcp_unit *unit)
+{
+       struct zfcp_port *port = unit->port;
+       struct zfcp_adapter *adapter = port->adapter;
+
+       zfcp_rec_dbf_event_target(id, ref, adapter, &unit->status,
+                                 &unit->erp_counter, port->wwpn, port->d_id,
+                                 unit->fcp_lun);
+}
+
+/**
+ * zfcp_rec_dbf_event_trigger - trace event for triggered error recovery
+ * @id2: identifier for error recovery trigger
+ * @ref: additional reference (e.g. request)
+ * @want: originally requested error recovery action
+ * @need: error recovery action actually initiated
+ * @action: address of error recovery action struct
+ * @adapter: adapter
+ * @port: port
+ * @unit: unit
+ */
+void zfcp_rec_dbf_event_trigger(u8 id2, void *ref, u8 want, u8 need,
+                               void *action, struct zfcp_adapter *adapter,
+                               struct zfcp_port *port, struct zfcp_unit *unit)
+{
+       struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->san_dbf_lock, flags);
-       memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
-       strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
-       rec->fsf_reqid = (unsigned long)fsf_req;
-       rec->fsf_seqno = fsf_req->seq_no;
-       rec->s_id = s_id;
-       rec->d_id = d_id;
-       if (strncmp(tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
-               ct->type.request.cmd_req_code = header->cmd_rsp_code;
-               ct->type.request.revision = header->revision;
-               ct->type.request.gs_type = header->gs_type;
-               ct->type.request.gs_subtype = header->gs_subtype;
-               ct->type.request.options = header->options;
-               ct->type.request.max_res_size = header->max_res_size;
-       } else if (strncmp(tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
-               ct->type.response.cmd_rsp_code = header->cmd_rsp_code;
-               ct->type.response.revision = header->revision;
-               ct->type.response.reason_code = header->reason_code;
-               ct->type.response.reason_code_expl = header->reason_code_expl;
-               ct->type.response.vendor_unique = header->vendor_unique;
+       spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+       memset(r, 0, sizeof(*r));
+       r->id = ZFCP_REC_DBF_ID_TRIGGER;
+       r->id2 = id2;
+       r->u.trigger.ref = (unsigned long)ref;
+       r->u.trigger.want = want;
+       r->u.trigger.need = need;
+       r->u.trigger.action = (unsigned long)action;
+       r->u.trigger.as = atomic_read(&adapter->status);
+       if (port) {
+               r->u.trigger.ps = atomic_read(&port->status);
+               r->u.trigger.wwpn = port->wwpn;
        }
-       ct->payload_size =
-           min(buflen - (int)sizeof(struct ct_hdr), ZFCP_DBF_CT_PAYLOAD);
-       memcpy(ct->payload, buffer + sizeof(struct ct_hdr), ct->payload_size);
-       debug_event(adapter->san_dbf, 3,
-                   rec, sizeof(struct zfcp_san_dbf_record));
-       spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+       if (unit) {
+               r->u.trigger.us = atomic_read(&unit->status);
+               r->u.trigger.fcp_lun = unit->fcp_lun;
+       }
+       debug_event(adapter->rec_dbf, action ? 1 : 4, r, sizeof(*r));
+       spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
 }
 
+/**
+ * zfcp_rec_dbf_event_action - trace event showing progress of recovery action
+ * @id2: identifier
+ * @erp_action: error recovery action struct pointer
+ */
+void zfcp_rec_dbf_event_action(u8 id2, struct zfcp_erp_action *erp_action)
+{
+       struct zfcp_adapter *adapter = erp_action->adapter;
+       struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+       memset(r, 0, sizeof(*r));
+       r->id = ZFCP_REC_DBF_ID_ACTION;
+       r->id2 = id2;
+       r->u.action.action = (unsigned long)erp_action;
+       r->u.action.status = erp_action->status;
+       r->u.action.step = erp_action->step;
+       r->u.action.fsf_req = (unsigned long)erp_action->fsf_req;
+       debug_event(adapter->rec_dbf, 4, r, sizeof(*r));
+       spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+}
+
+/**
+ * zfcp_san_dbf_event_ct_request - trace event for issued CT request
+ * @fsf_req: request containing issued CT data
+ */
 void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
        struct zfcp_port *port = ct->port;
        struct zfcp_adapter *adapter = port->adapter;
+       struct ct_hdr *hdr = zfcp_sg_to_address(ct->req);
+       struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
+       struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req;
+       unsigned long flags;
 
-       _zfcp_san_dbf_event_common_ct("octc", fsf_req,
-                                     fc_host_port_id(adapter->scsi_host),
-                                     port->d_id, zfcp_sg_to_address(ct->req),
-                                     ct->req->length);
+       spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+       memset(r, 0, sizeof(*r));
+       strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE);
+       r->fsf_reqid = (unsigned long)fsf_req;
+       r->fsf_seqno = fsf_req->seq_no;
+       r->s_id = fc_host_port_id(adapter->scsi_host);
+       r->d_id = port->d_id;
+       oct->cmd_req_code = hdr->cmd_rsp_code;
+       oct->revision = hdr->revision;
+       oct->gs_type = hdr->gs_type;
+       oct->gs_subtype = hdr->gs_subtype;
+       oct->options = hdr->options;
+       oct->max_res_size = hdr->max_res_size;
+       oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr),
+                      ZFCP_DBF_CT_PAYLOAD);
+       memcpy(oct->payload, (void *)hdr + sizeof(struct ct_hdr), oct->len);
+       debug_event(adapter->san_dbf, 3, r, sizeof(*r));
+       spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
 }
 
+/**
+ * zfcp_san_dbf_event_ct_response - trace event for completion of CT request
+ * @fsf_req: request containing CT response
+ */
 void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
        struct zfcp_port *port = ct->port;
        struct zfcp_adapter *adapter = port->adapter;
+       struct ct_hdr *hdr = zfcp_sg_to_address(ct->resp);
+       struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
+       struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp;
+       unsigned long flags;
 
-       _zfcp_san_dbf_event_common_ct("rctc", fsf_req, port->d_id,
-                                     fc_host_port_id(adapter->scsi_host),
-                                     zfcp_sg_to_address(ct->resp),
-                                     ct->resp->length);
+       spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+       memset(r, 0, sizeof(*r));
+       strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE);
+       r->fsf_reqid = (unsigned long)fsf_req;
+       r->fsf_seqno = fsf_req->seq_no;
+       r->s_id = port->d_id;
+       r->d_id = fc_host_port_id(adapter->scsi_host);
+       rct->cmd_rsp_code = hdr->cmd_rsp_code;
+       rct->revision = hdr->revision;
+       rct->reason_code = hdr->reason_code;
+       rct->expl = hdr->reason_code_expl;
+       rct->vendor_unique = hdr->vendor_unique;
+       rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
+                      ZFCP_DBF_CT_PAYLOAD);
+       memcpy(rct->payload, (void *)hdr + sizeof(struct ct_hdr), rct->len);
+       debug_event(adapter->san_dbf, 3, r, sizeof(*r));
+       spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
 }
 
-static void
-_zfcp_san_dbf_event_common_els(const char *tag, int level,
-                              struct zfcp_fsf_req *fsf_req, u32 s_id,
-                              u32 d_id, u8 ls_code, void *buffer, int buflen)
+static void zfcp_san_dbf_event_els(const char *tag, int level,
+                                  struct zfcp_fsf_req *fsf_req, u32 s_id,
+                                  u32 d_id, u8 ls_code, void *buffer,
+                                  int buflen)
 {
        struct zfcp_adapter *adapter = fsf_req->adapter;
        struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
-       struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
        unsigned long flags;
-       int offset = 0;
 
        spin_lock_irqsave(&adapter->san_dbf_lock, flags);
-       do {
-               memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
-               if (offset == 0) {
-                       strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
-                       rec->fsf_reqid = (unsigned long)fsf_req;
-                       rec->fsf_seqno = fsf_req->seq_no;
-                       rec->s_id = s_id;
-                       rec->d_id = d_id;
-                       rec->type.els.ls_code = ls_code;
-                       buflen = min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD);
-                       rec->type.els.payload_size = buflen;
-                       memcpy(rec->type.els.payload,
-                              buffer, min(buflen, ZFCP_DBF_ELS_PAYLOAD));
-                       offset += min(buflen, ZFCP_DBF_ELS_PAYLOAD);
-               } else {
-                       strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
-                       dump->total_size = buflen;
-                       dump->offset = offset;
-                       dump->size = min(buflen - offset,
-                                        (int)sizeof(struct zfcp_san_dbf_record)
-                                        - (int)sizeof(struct zfcp_dbf_dump));
-                       memcpy(dump->data, buffer + offset, dump->size);
-                       offset += dump->size;
-               }
-               debug_event(adapter->san_dbf, level,
-                           rec, sizeof(struct zfcp_san_dbf_record));
-       } while (offset < buflen);
+       memset(rec, 0, sizeof(*rec));
+       strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+       rec->fsf_reqid = (unsigned long)fsf_req;
+       rec->fsf_seqno = fsf_req->seq_no;
+       rec->s_id = s_id;
+       rec->d_id = d_id;
+       rec->u.els.ls_code = ls_code;
+       debug_event(adapter->san_dbf, level, rec, sizeof(*rec));
+       zfcp_dbf_hexdump(adapter->san_dbf, rec, sizeof(*rec), level,
+                        buffer, min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD));
        spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
 }
 
+/**
+ * zfcp_san_dbf_event_els_request - trace event for issued ELS
+ * @fsf_req: request containing issued ELS
+ */
 void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
 
-       _zfcp_san_dbf_event_common_els("oels", 2, fsf_req,
-                                      fc_host_port_id(els->adapter->scsi_host),
-                                      els->d_id,
-                                      *(u8 *) zfcp_sg_to_address(els->req),
-                                      zfcp_sg_to_address(els->req),
-                                      els->req->length);
+       zfcp_san_dbf_event_els("oels", 2, fsf_req,
+                              fc_host_port_id(els->adapter->scsi_host),
+                              els->d_id, *(u8 *) zfcp_sg_to_address(els->req),
+                              zfcp_sg_to_address(els->req), els->req->length);
 }
 
+/**
+ * zfcp_san_dbf_event_els_response - trace event for completed ELS
+ * @fsf_req: request containing ELS response
+ */
 void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
 
-       _zfcp_san_dbf_event_common_els("rels", 2, fsf_req, els->d_id,
-                                      fc_host_port_id(els->adapter->scsi_host),
-                                      *(u8 *) zfcp_sg_to_address(els->req),
-                                      zfcp_sg_to_address(els->resp),
-                                      els->resp->length);
+       zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id,
+                              fc_host_port_id(els->adapter->scsi_host),
+                              *(u8 *)zfcp_sg_to_address(els->req),
+                              zfcp_sg_to_address(els->resp),
+                              els->resp->length);
 }
 
+/**
+ * zfcp_san_dbf_event_incoming_els - trace event for incomig ELS
+ * @fsf_req: request containing unsolicited status buffer with incoming ELS
+ */
 void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_adapter *adapter = fsf_req->adapter;
-       struct fsf_status_read_buffer *status_buffer =
-           (struct fsf_status_read_buffer *)fsf_req->data;
-       int length = (int)status_buffer->length -
-           (int)((void *)&status_buffer->payload - (void *)status_buffer);
-
-       _zfcp_san_dbf_event_common_els("iels", 1, fsf_req, status_buffer->d_id,
-                                      fc_host_port_id(adapter->scsi_host),
-                                      *(u8 *) status_buffer->payload,
-                                      (void *)status_buffer->payload, length);
+       struct fsf_status_read_buffer *buf =
+                       (struct fsf_status_read_buffer *)fsf_req->data;
+       int length = (int)buf->length -
+                    (int)((void *)&buf->payload - (void *)buf);
+
+       zfcp_san_dbf_event_els("iels", 1, fsf_req, buf->d_id,
+                              fc_host_port_id(adapter->scsi_host),
+                              *(u8 *)buf->payload, (void *)buf->payload,
+                              length);
 }
 
-static int
-zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view,
-                        char *out_buf, const char *in_buf)
+static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
+                                   char *out_buf, const char *in_buf)
 {
-       struct zfcp_san_dbf_record *rec = (struct zfcp_san_dbf_record *)in_buf;
+       struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf;
        char *buffer = NULL;
        int buflen = 0, total = 0;
-       int len = 0;
+       char *p = out_buf;
 
-       if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+       if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
                return 0;
 
-       len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
-       len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
-                            rec->fsf_reqid);
-       len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
-                            rec->fsf_seqno);
-       len += zfcp_dbf_view(out_buf + len, "s_id", "0x%06x", rec->s_id);
-       len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", rec->d_id);
-
-       if (strncmp(rec->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
-               len += zfcp_dbf_view(out_buf + len, "cmd_req_code", "0x%04x",
-                                    rec->type.ct.type.request.cmd_req_code);
-               len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
-                                    rec->type.ct.type.request.revision);
-               len += zfcp_dbf_view(out_buf + len, "gs_type", "0x%02x",
-                                    rec->type.ct.type.request.gs_type);
-               len += zfcp_dbf_view(out_buf + len, "gs_subtype", "0x%02x",
-                                    rec->type.ct.type.request.gs_subtype);
-               len += zfcp_dbf_view(out_buf + len, "options", "0x%02x",
-                                    rec->type.ct.type.request.options);
-               len += zfcp_dbf_view(out_buf + len, "max_res_size", "0x%04x",
-                                    rec->type.ct.type.request.max_res_size);
-               total = rec->type.ct.payload_size;
-               buffer = rec->type.ct.payload;
+       zfcp_dbf_tag(&p, "tag", r->tag);
+       zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
+       zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
+       zfcp_dbf_out(&p, "s_id", "0x%06x", r->s_id);
+       zfcp_dbf_out(&p, "d_id", "0x%06x", r->d_id);
+
+       if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
+               struct zfcp_san_dbf_record_ct_request *ct = &r->u.ct_req;
+               zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code);
+               zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
+               zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type);
+               zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype);
+               zfcp_dbf_out(&p, "options", "0x%02x", ct->options);
+               zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
+               total = ct->len;
+               buffer = ct->payload;
                buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
-       } else if (strncmp(rec->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
-               len += zfcp_dbf_view(out_buf + len, "cmd_rsp_code", "0x%04x",
-                                    rec->type.ct.type.response.cmd_rsp_code);
-               len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
-                                    rec->type.ct.type.response.revision);
-               len += zfcp_dbf_view(out_buf + len, "reason_code", "0x%02x",
-                                    rec->type.ct.type.response.reason_code);
-               len +=
-                   zfcp_dbf_view(out_buf + len, "reason_code_expl", "0x%02x",
-                                 rec->type.ct.type.response.reason_code_expl);
-               len +=
-                   zfcp_dbf_view(out_buf + len, "vendor_unique", "0x%02x",
-                                 rec->type.ct.type.response.vendor_unique);
-               total = rec->type.ct.payload_size;
-               buffer = rec->type.ct.payload;
+       } else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
+               struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp;
+               zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code);
+               zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
+               zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code);
+               zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl);
+               zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique);
+               total = ct->len;
+               buffer = ct->payload;
                buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
-       } else if (strncmp(rec->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
-                  strncmp(rec->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
-                  strncmp(rec->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
-               len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
-                                    rec->type.els.ls_code);
-               total = rec->type.els.payload_size;
-               buffer = rec->type.els.payload;
+       } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
+                  strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
+                  strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
+               struct zfcp_san_dbf_record_els *els = &r->u.els;
+               zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code);
+               total = els->len;
+               buffer = els->payload;
                buflen = min(total, ZFCP_DBF_ELS_PAYLOAD);
        }
 
-       len += zfcp_dbf_view_dump(out_buf + len, "payload",
-                                 buffer, buflen, 0, total);
-
+       zfcp_dbf_outd(&p, "payload", buffer, buflen, 0, total);
        if (buflen == total)
-               len += sprintf(out_buf + len, "\n");
+               p += sprintf(p, "\n");
 
-       return len;
+       return p - out_buf;
 }
 
 static struct debug_view zfcp_san_dbf_view = {
@@ -696,12 +1028,11 @@ static struct debug_view zfcp_san_dbf_view = {
        NULL
 };
 
-static void
-_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
-                           struct zfcp_adapter *adapter,
-                           struct scsi_cmnd *scsi_cmnd,
-                           struct zfcp_fsf_req *fsf_req,
-                           unsigned long old_req_id)
+static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
+                               struct zfcp_adapter *adapter,
+                               struct scsi_cmnd *scsi_cmnd,
+                               struct zfcp_fsf_req *fsf_req,
+                               unsigned long old_req_id)
 {
        struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
        struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
@@ -712,7 +1043,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
 
        spin_lock_irqsave(&adapter->scsi_dbf_lock, flags);
        do {
-               memset(rec, 0, sizeof(struct zfcp_scsi_dbf_record));
+               memset(rec, 0, sizeof(*rec));
                if (offset == 0) {
                        strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
                        strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
@@ -738,20 +1069,16 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
                                fcp_sns_info =
                                    zfcp_get_fcp_sns_info_ptr(fcp_rsp);
 
-                               rec->type.fcp.rsp_validity =
-                                   fcp_rsp->validity.value;
-                               rec->type.fcp.rsp_scsi_status =
-                                   fcp_rsp->scsi_status;
-                               rec->type.fcp.rsp_resid = fcp_rsp->fcp_resid;
+                               rec->rsp_validity = fcp_rsp->validity.value;
+                               rec->rsp_scsi_status = fcp_rsp->scsi_status;
+                               rec->rsp_resid = fcp_rsp->fcp_resid;
                                if (fcp_rsp->validity.bits.fcp_rsp_len_valid)
-                                       rec->type.fcp.rsp_code =
-                                           *(fcp_rsp_info + 3);
+                                       rec->rsp_code = *(fcp_rsp_info + 3);
                                if (fcp_rsp->validity.bits.fcp_sns_len_valid) {
                                        buflen = min((int)fcp_rsp->fcp_sns_len,
                                                     ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
-                                       rec->type.fcp.sns_info_len = buflen;
-                                       memcpy(rec->type.fcp.sns_info,
-                                              fcp_sns_info,
+                                       rec->sns_info_len = buflen;
+                                       memcpy(rec->sns_info, fcp_sns_info,
                                               min(buflen,
                                                   ZFCP_DBF_SCSI_FCP_SNS_INFO));
                                        offset += min(buflen,
@@ -762,7 +1089,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
                                rec->fsf_seqno = fsf_req->seq_no;
                                rec->fsf_issued = fsf_req->issued;
                        }
-                       rec->type.old_fsf_reqid = old_req_id;
+                       rec->old_fsf_reqid = old_req_id;
                } else {
                        strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
                        dump->total_size = buflen;
@@ -774,108 +1101,101 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
                        memcpy(dump->data, fcp_sns_info + offset, dump->size);
                        offset += dump->size;
                }
-               debug_event(adapter->scsi_dbf, level,
-                           rec, sizeof(struct zfcp_scsi_dbf_record));
+               debug_event(adapter->scsi_dbf, level, rec, sizeof(*rec));
        } while (offset < buflen);
        spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
 }
 
-void
-zfcp_scsi_dbf_event_result(const char *tag, int level,
-                          struct zfcp_adapter *adapter,
-                          struct scsi_cmnd *scsi_cmnd,
-                          struct zfcp_fsf_req *fsf_req)
+/**
+ * zfcp_scsi_dbf_event_result - trace event for SCSI command completion
+ * @tag: tag indicating success or failure of SCSI command
+ * @level: trace level applicable for this event
+ * @adapter: adapter that has been used to issue the SCSI command
+ * @scsi_cmnd: SCSI command pointer
+ * @fsf_req: request used to issue SCSI command (might be NULL)
+ */
+void zfcp_scsi_dbf_event_result(const char *tag, int level,
+                               struct zfcp_adapter *adapter,
+                               struct scsi_cmnd *scsi_cmnd,
+                               struct zfcp_fsf_req *fsf_req)
 {
-       _zfcp_scsi_dbf_event_common("rslt", tag, level,
-                       adapter, scsi_cmnd, fsf_req, 0);
+       zfcp_scsi_dbf_event("rslt", tag, level, adapter, scsi_cmnd, fsf_req, 0);
 }
 
-void
-zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
-                         struct scsi_cmnd *scsi_cmnd,
-                         struct zfcp_fsf_req *new_fsf_req,
-                         unsigned long old_req_id)
+/**
+ * zfcp_scsi_dbf_event_abort - trace event for SCSI command abort
+ * @tag: tag indicating success or failure of abort operation
+ * @adapter: adapter thas has been used to issue SCSI command to be aborted
+ * @scsi_cmnd: SCSI command to be aborted
+ * @new_fsf_req: request containing abort (might be NULL)
+ * @old_req_id: identifier of request containg SCSI command to be aborted
+ */
+void zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
+                              struct scsi_cmnd *scsi_cmnd,
+                              struct zfcp_fsf_req *new_fsf_req,
+                              unsigned long old_req_id)
 {
-       _zfcp_scsi_dbf_event_common("abrt", tag, 1,
-                       adapter, scsi_cmnd, new_fsf_req, old_req_id);
+       zfcp_scsi_dbf_event("abrt", tag, 1, adapter, scsi_cmnd, new_fsf_req,
+                           old_req_id);
 }
 
-void
-zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
-                            struct scsi_cmnd *scsi_cmnd)
+/**
+ * zfcp_scsi_dbf_event_devreset - trace event for Logical Unit or Target Reset
+ * @tag: tag indicating success or failure of reset operation
+ * @flag: indicates type of reset (Target Reset, Logical Unit Reset)
+ * @unit: unit that needs reset
+ * @scsi_cmnd: SCSI command which caused this error recovery
+ */
+void zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag,
+                                 struct zfcp_unit *unit,
+                                 struct scsi_cmnd *scsi_cmnd)
 {
-       struct zfcp_adapter *adapter = unit->port->adapter;
-
-       _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
-                       tag, 1, adapter, scsi_cmnd, NULL, 0);
+       zfcp_scsi_dbf_event(flag == FCP_TARGET_RESET ? "trst" : "lrst", tag, 1,
+                           unit->port->adapter, scsi_cmnd, NULL, 0);
 }
 
-static int
-zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
-                         char *out_buf, const char *in_buf)
+static int zfcp_scsi_dbf_view_format(debug_info_t *id, struct debug_view *view,
+                                    char *out_buf, const char *in_buf)
 {
-       struct zfcp_scsi_dbf_record *rec =
-           (struct zfcp_scsi_dbf_record *)in_buf;
-       int len = 0;
+       struct zfcp_scsi_dbf_record *r = (struct zfcp_scsi_dbf_record *)in_buf;
+       struct timespec t;
+       char *p = out_buf;
 
-       if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+       if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
                return 0;
 
-       len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
-       len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
-       len += zfcp_dbf_view(out_buf + len, "scsi_id", "0x%08x", rec->scsi_id);
-       len += zfcp_dbf_view(out_buf + len, "scsi_lun", "0x%08x",
-                            rec->scsi_lun);
-       len += zfcp_dbf_view(out_buf + len, "scsi_result", "0x%08x",
-                            rec->scsi_result);
-       len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
-                            rec->scsi_cmnd);
-       len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
-                            rec->scsi_serial);
-       len += zfcp_dbf_view_dump(out_buf + len, "scsi_opcode",
-                                 rec->scsi_opcode,
-                                 ZFCP_DBF_SCSI_OPCODE,
-                                 0, ZFCP_DBF_SCSI_OPCODE);
-       len += zfcp_dbf_view(out_buf + len, "scsi_retries", "0x%02x",
-                            rec->scsi_retries);
-       len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
-                            rec->scsi_allowed);
-       if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
-               len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx",
-                                    rec->type.old_fsf_reqid);
-       }
-       len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
-                            rec->fsf_reqid);
-       len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
-                            rec->fsf_seqno);
-       len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
-       if (strncmp(rec->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
-               len +=
-                   zfcp_dbf_view(out_buf + len, "fcp_rsp_validity", "0x%02x",
-                                 rec->type.fcp.rsp_validity);
-               len +=
-                   zfcp_dbf_view(out_buf + len, "fcp_rsp_scsi_status",
-                                 "0x%02x", rec->type.fcp.rsp_scsi_status);
-               len +=
-                   zfcp_dbf_view(out_buf + len, "fcp_rsp_resid", "0x%08x",
-                                 rec->type.fcp.rsp_resid);
-               len +=
-                   zfcp_dbf_view(out_buf + len, "fcp_rsp_code", "0x%08x",
-                                 rec->type.fcp.rsp_code);
-               len +=
-                   zfcp_dbf_view(out_buf + len, "fcp_sns_info_len", "0x%08x",
-                                 rec->type.fcp.sns_info_len);
-               len +=
-                   zfcp_dbf_view_dump(out_buf + len, "fcp_sns_info",
-                                      rec->type.fcp.sns_info,
-                                      min((int)rec->type.fcp.sns_info_len,
-                                          ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
-                                      rec->type.fcp.sns_info_len);
+       zfcp_dbf_tag(&p, "tag", r->tag);
+       zfcp_dbf_tag(&p, "tag2", r->tag2);
+       zfcp_dbf_out(&p, "scsi_id", "0x%08x", r->scsi_id);
+       zfcp_dbf_out(&p, "scsi_lun", "0x%08x", r->scsi_lun);
+       zfcp_dbf_out(&p, "scsi_result", "0x%08x", r->scsi_result);
+       zfcp_dbf_out(&p, "scsi_cmnd", "0x%0Lx", r->scsi_cmnd);
+       zfcp_dbf_out(&p, "scsi_serial", "0x%016Lx", r->scsi_serial);
+       zfcp_dbf_outd(&p, "scsi_opcode", r->scsi_opcode, ZFCP_DBF_SCSI_OPCODE,
+                     0, ZFCP_DBF_SCSI_OPCODE);
+       zfcp_dbf_out(&p, "scsi_retries", "0x%02x", r->scsi_retries);
+       zfcp_dbf_out(&p, "scsi_allowed", "0x%02x", r->scsi_allowed);
+       if (strncmp(r->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0)
+               zfcp_dbf_out(&p, "old_fsf_reqid", "0x%0Lx", r->old_fsf_reqid);
+       zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
+       zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
+       zfcp_dbf_timestamp(r->fsf_issued, &t);
+       zfcp_dbf_out(&p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
+
+       if (strncmp(r->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
+               zfcp_dbf_out(&p, "fcp_rsp_validity", "0x%02x", r->rsp_validity);
+               zfcp_dbf_out(&p, "fcp_rsp_scsi_status", "0x%02x",
+                            r->rsp_scsi_status);
+               zfcp_dbf_out(&p, "fcp_rsp_resid", "0x%08x", r->rsp_resid);
+               zfcp_dbf_out(&p, "fcp_rsp_code", "0x%08x", r->rsp_code);
+               zfcp_dbf_out(&p, "fcp_sns_info_len", "0x%08x", r->sns_info_len);
+               zfcp_dbf_outd(&p, "fcp_sns_info", r->sns_info,
+                             min((int)r->sns_info_len,
+                             ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
+                             r->sns_info_len);
        }
-
-       len += sprintf(out_buf + len, "\n");
-
-       return len;
+       p += sprintf(p, "\n");
+       return p - out_buf;
 }
 
 static struct debug_view zfcp_scsi_dbf_view = {
@@ -897,13 +1217,14 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
        char dbf_name[DEBUG_MAX_NAME_LEN];
 
        /* debug feature area which records recovery activity */
-       sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
-       adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
-                                         sizeof(struct zfcp_erp_dbf_record));
-       if (!adapter->erp_dbf)
+       sprintf(dbf_name, "zfcp_%s_rec", zfcp_get_busid_by_adapter(adapter));
+       adapter->rec_dbf = debug_register(dbf_name, dbfsize, 1,
+                                         sizeof(struct zfcp_rec_dbf_record));
+       if (!adapter->rec_dbf)
                goto failed;
-       debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
-       debug_set_level(adapter->erp_dbf, 3);
+       debug_register_view(adapter->rec_dbf, &debug_hex_ascii_view);
+       debug_register_view(adapter->rec_dbf, &zfcp_rec_dbf_view);
+       debug_set_level(adapter->rec_dbf, 3);
 
        /* debug feature area which records HBA (FSF and QDIO) conditions */
        sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
@@ -952,11 +1273,11 @@ void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
        debug_unregister(adapter->scsi_dbf);
        debug_unregister(adapter->san_dbf);
        debug_unregister(adapter->hba_dbf);
-       debug_unregister(adapter->erp_dbf);
+       debug_unregister(adapter->rec_dbf);
        adapter->scsi_dbf = NULL;
        adapter->san_dbf = NULL;
        adapter->hba_dbf = NULL;
-       adapter->erp_dbf = NULL;
+       adapter->rec_dbf = NULL;
 }
 
 #undef ZFCP_LOG_AREA
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
new file mode 100644 (file)
index 0000000..54c34e4
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
+ *
+ * Copyright IBM Corp. 2008, 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef ZFCP_DBF_H
+#define ZFCP_DBF_H
+
+#include "zfcp_fsf.h"
+
+#define ZFCP_DBF_TAG_SIZE      4
+
+struct zfcp_dbf_dump {
+       u8 tag[ZFCP_DBF_TAG_SIZE];
+       u32 total_size;         /* size of total dump data */
+       u32 offset;             /* how much data has being already dumped */
+       u32 size;               /* how much data comes with this record */
+       u8 data[];              /* dump data */
+} __attribute__ ((packed));
+
+struct zfcp_rec_dbf_record_thread {
+       u32 total;
+       u32 ready;
+       u32 running;
+} __attribute__ ((packed));
+
+struct zfcp_rec_dbf_record_target {
+       u64 ref;
+       u32 status;
+       u32 d_id;
+       u64 wwpn;
+       u64 fcp_lun;
+       u32 erp_count;
+} __attribute__ ((packed));
+
+struct zfcp_rec_dbf_record_trigger {
+       u8 want;
+       u8 need;
+       u32 as;
+       u32 ps;
+       u32 us;
+       u64 ref;
+       u64 action;
+       u64 wwpn;
+       u64 fcp_lun;
+} __attribute__ ((packed));
+
+struct zfcp_rec_dbf_record_action {
+       u32 status;
+       u32 step;
+       u64 action;
+       u64 fsf_req;
+} __attribute__ ((packed));
+
+struct zfcp_rec_dbf_record {
+       u8 id;
+       u8 id2;
+       union {
+               struct zfcp_rec_dbf_record_action action;
+               struct zfcp_rec_dbf_record_thread thread;
+               struct zfcp_rec_dbf_record_target target;
+               struct zfcp_rec_dbf_record_trigger trigger;
+       } u;
+} __attribute__ ((packed));
+
+enum {
+       ZFCP_REC_DBF_ID_ACTION,
+       ZFCP_REC_DBF_ID_THREAD,
+       ZFCP_REC_DBF_ID_TARGET,
+       ZFCP_REC_DBF_ID_TRIGGER,
+};
+
+struct zfcp_hba_dbf_record_response {
+       u32 fsf_command;
+       u64 fsf_reqid;
+       u32 fsf_seqno;
+       u64 fsf_issued;
+       u32 fsf_prot_status;
+       u32 fsf_status;
+       u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
+       u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
+       u32 fsf_req_status;
+       u8 sbal_first;
+       u8 sbal_curr;
+       u8 sbal_last;
+       u8 pool;
+       u64 erp_action;
+       union {
+               struct {
+                       u64 cmnd;
+                       u64 serial;
+               } fcp;
+               struct {
+                       u64 wwpn;
+                       u32 d_id;
+                       u32 port_handle;
+               } port;
+               struct {
+                       u64 wwpn;
+                       u64 fcp_lun;
+                       u32 port_handle;
+                       u32 lun_handle;
+               } unit;
+               struct {
+                       u32 d_id;
+                       u8 ls_code;
+               } els;
+       } u;
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record_status {
+       u8 failed;
+       u32 status_type;
+       u32 status_subtype;
+       struct fsf_queue_designator
+        queue_designator;
+       u32 payload_size;
+#define ZFCP_DBF_UNSOL_PAYLOAD                         80
+#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL                32
+#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD     56
+#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT    2 * sizeof(u32)
+       u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record_qdio {
+       u32 status;
+       u32 qdio_error;
+       u32 siga_error;
+       u8 sbal_index;
+       u8 sbal_count;
+} __attribute__ ((packed));
+
+struct zfcp_hba_dbf_record {
+       u8 tag[ZFCP_DBF_TAG_SIZE];
+       u8 tag2[ZFCP_DBF_TAG_SIZE];
+       union {
+               struct zfcp_hba_dbf_record_response response;
+               struct zfcp_hba_dbf_record_status status;
+               struct zfcp_hba_dbf_record_qdio qdio;
+       } u;
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record_ct_request {
+       u16 cmd_req_code;
+       u8 revision;
+       u8 gs_type;
+       u8 gs_subtype;
+       u8 options;
+       u16 max_res_size;
+       u32 len;
+#define ZFCP_DBF_CT_PAYLOAD    24
+       u8 payload[ZFCP_DBF_CT_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record_ct_response {
+       u16 cmd_rsp_code;
+       u8 revision;
+       u8 reason_code;
+       u8 expl;
+       u8 vendor_unique;
+       u32 len;
+       u8 payload[ZFCP_DBF_CT_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record_els {
+       u8 ls_code;
+       u32 len;
+#define ZFCP_DBF_ELS_PAYLOAD   32
+#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
+       u8 payload[ZFCP_DBF_ELS_PAYLOAD];
+} __attribute__ ((packed));
+
+struct zfcp_san_dbf_record {
+       u8 tag[ZFCP_DBF_TAG_SIZE];
+       u64 fsf_reqid;
+       u32 fsf_seqno;
+       u32 s_id;
+       u32 d_id;
+       union {
+               struct zfcp_san_dbf_record_ct_request ct_req;
+               struct zfcp_san_dbf_record_ct_response ct_resp;
+               struct zfcp_san_dbf_record_els els;
+       } u;
+} __attribute__ ((packed));
+
+struct zfcp_scsi_dbf_record {
+       u8 tag[ZFCP_DBF_TAG_SIZE];
+       u8 tag2[ZFCP_DBF_TAG_SIZE];
+       u32 scsi_id;
+       u32 scsi_lun;
+       u32 scsi_result;
+       u64 scsi_cmnd;
+       u64 scsi_serial;
+#define ZFCP_DBF_SCSI_OPCODE   16
+       u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
+       u8 scsi_retries;
+       u8 scsi_allowed;
+       u64 fsf_reqid;
+       u32 fsf_seqno;
+       u64 fsf_issued;
+       u64 old_fsf_reqid;
+       u8 rsp_validity;
+       u8 rsp_scsi_status;
+       u32 rsp_resid;
+       u8 rsp_code;
+#define ZFCP_DBF_SCSI_FCP_SNS_INFO     16
+#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256
+       u32 sns_info_len;
+       u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
+} __attribute__ ((packed));
+
+#endif /* ZFCP_DBF_H */
index 45a7cd98c140c97bc4debbe1c9c37a97ad4da433..bda8c77b22daf6160235f3199b93c9953c4b4d51 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/qdio.h>
 #include <asm/debug.h>
 #include <asm/ebcdic.h>
+#include "zfcp_dbf.h"
 #include "zfcp_fsf.h"
 
 
@@ -261,167 +262,6 @@ struct fcp_logo {
         wwn_t nport_wwpn;
 } __attribute__((packed));
 
-/*
- * DBF stuff
- */
-#define ZFCP_DBF_TAG_SIZE      4
-
-struct zfcp_dbf_dump {
-       u8 tag[ZFCP_DBF_TAG_SIZE];
-       u32 total_size;         /* size of total dump data */
-       u32 offset;             /* how much data has being already dumped */
-       u32 size;               /* how much data comes with this record */
-       u8 data[];              /* dump data */
-} __attribute__ ((packed));
-
-/* FIXME: to be inflated when reworking the erp dbf */
-struct zfcp_erp_dbf_record {
-       u8 dummy[16];
-} __attribute__ ((packed));
-
-struct zfcp_hba_dbf_record_response {
-       u32 fsf_command;
-       u64 fsf_reqid;
-       u32 fsf_seqno;
-       u64 fsf_issued;
-       u32 fsf_prot_status;
-       u32 fsf_status;
-       u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
-       u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
-       u32 fsf_req_status;
-       u8 sbal_first;
-       u8 sbal_curr;
-       u8 sbal_last;
-       u8 pool;
-       u64 erp_action;
-       union {
-               struct {
-                       u64 scsi_cmnd;
-                       u64 scsi_serial;
-               } send_fcp;
-               struct {
-                       u64 wwpn;
-                       u32 d_id;
-                       u32 port_handle;
-               } port;
-               struct {
-                       u64 wwpn;
-                       u64 fcp_lun;
-                       u32 port_handle;
-                       u32 lun_handle;
-               } unit;
-               struct {
-                       u32 d_id;
-                       u8 ls_code;
-               } send_els;
-       } data;
-} __attribute__ ((packed));
-
-struct zfcp_hba_dbf_record_status {
-       u8 failed;
-       u32 status_type;
-       u32 status_subtype;
-       struct fsf_queue_designator
-        queue_designator;
-       u32 payload_size;
-#define ZFCP_DBF_UNSOL_PAYLOAD                         80
-#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL                32
-#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD     56
-#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT    2 * sizeof(u32)
-       u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
-} __attribute__ ((packed));
-
-struct zfcp_hba_dbf_record_qdio {
-       u32 status;
-       u32 qdio_error;
-       u32 siga_error;
-       u8 sbal_index;
-       u8 sbal_count;
-} __attribute__ ((packed));
-
-struct zfcp_hba_dbf_record {
-       u8 tag[ZFCP_DBF_TAG_SIZE];
-       u8 tag2[ZFCP_DBF_TAG_SIZE];
-       union {
-               struct zfcp_hba_dbf_record_response response;
-               struct zfcp_hba_dbf_record_status status;
-               struct zfcp_hba_dbf_record_qdio qdio;
-       } type;
-} __attribute__ ((packed));
-
-struct zfcp_san_dbf_record_ct {
-       union {
-               struct {
-                       u16 cmd_req_code;
-                       u8 revision;
-                       u8 gs_type;
-                       u8 gs_subtype;
-                       u8 options;
-                       u16 max_res_size;
-               } request;
-               struct {
-                       u16 cmd_rsp_code;
-                       u8 revision;
-                       u8 reason_code;
-                       u8 reason_code_expl;
-                       u8 vendor_unique;
-               } response;
-       } type;
-       u32 payload_size;
-#define ZFCP_DBF_CT_PAYLOAD    24
-       u8 payload[ZFCP_DBF_CT_PAYLOAD];
-} __attribute__ ((packed));
-
-struct zfcp_san_dbf_record_els {
-       u8 ls_code;
-       u32 payload_size;
-#define ZFCP_DBF_ELS_PAYLOAD   32
-#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
-       u8 payload[ZFCP_DBF_ELS_PAYLOAD];
-} __attribute__ ((packed));
-
-struct zfcp_san_dbf_record {
-       u8 tag[ZFCP_DBF_TAG_SIZE];
-       u64 fsf_reqid;
-       u32 fsf_seqno;
-       u32 s_id;
-       u32 d_id;
-       union {
-               struct zfcp_san_dbf_record_ct ct;
-               struct zfcp_san_dbf_record_els els;
-       } type;
-} __attribute__ ((packed));
-
-struct zfcp_scsi_dbf_record {
-       u8 tag[ZFCP_DBF_TAG_SIZE];
-       u8 tag2[ZFCP_DBF_TAG_SIZE];
-       u32 scsi_id;
-       u32 scsi_lun;
-       u32 scsi_result;
-       u64 scsi_cmnd;
-       u64 scsi_serial;
-#define ZFCP_DBF_SCSI_OPCODE   16
-       u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
-       u8 scsi_retries;
-       u8 scsi_allowed;
-       u64 fsf_reqid;
-       u32 fsf_seqno;
-       u64 fsf_issued;
-       union {
-               u64 old_fsf_reqid;
-               struct {
-                       u8 rsp_validity;
-                       u8 rsp_scsi_status;
-                       u32 rsp_resid;
-                       u8 rsp_code;
-#define ZFCP_DBF_SCSI_FCP_SNS_INFO     16
-#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256
-                       u32 sns_info_len;
-                       u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
-               } fcp;
-       } type;
-} __attribute__ ((packed));
-
 /*
  * FC-FS stuff
  */
@@ -634,7 +474,6 @@ do { \
                 ZFCP_STATUS_PORT_NO_SCSI_ID)
 
 /* logical unit status */
-#define ZFCP_STATUS_UNIT_NOTSUPPUNITRESET      0x00000001
 #define ZFCP_STATUS_UNIT_TEMPORARY             0x00000002
 #define ZFCP_STATUS_UNIT_SHARED                        0x00000004
 #define ZFCP_STATUS_UNIT_READONLY              0x00000008
@@ -917,15 +756,15 @@ struct zfcp_adapter {
        u32                     erp_low_mem_count; /* nr of erp actions waiting
                                                      for memory */
        struct zfcp_port        *nameserver_port;  /* adapter's nameserver */
-       debug_info_t            *erp_dbf;
+       debug_info_t            *rec_dbf;
        debug_info_t            *hba_dbf;
        debug_info_t            *san_dbf;          /* debug feature areas */
        debug_info_t            *scsi_dbf;
-       spinlock_t              erp_dbf_lock;
+       spinlock_t              rec_dbf_lock;
        spinlock_t              hba_dbf_lock;
        spinlock_t              san_dbf_lock;
        spinlock_t              scsi_dbf_lock;
-       struct zfcp_erp_dbf_record      erp_dbf_buf;
+       struct zfcp_rec_dbf_record      rec_dbf_buf;
        struct zfcp_hba_dbf_record      hba_dbf_buf;
        struct zfcp_san_dbf_record      san_dbf_buf;
        struct zfcp_scsi_dbf_record     scsi_dbf_buf;
index 2dc8110ebf74d7a5e5e3a37bcbb6e1883e1523c6..805484658dd9ab618211316c161149850b6f9caf 100644 (file)
 static int zfcp_erp_adisc(struct zfcp_port *);
 static void zfcp_erp_adisc_handler(unsigned long);
 
-static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
-static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int);
-static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int);
-static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int);
-
-static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int);
-static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int);
+static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int, u8,
+                                           void *);
+static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int, u8,
+                                               void *);
+static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int, u8, void *);
+static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int, u8, void *);
+
+static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int, u8,
+                                            void *);
+static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int, u8,
+                                            void *);
 
 static void zfcp_erp_adapter_block(struct zfcp_adapter *, int);
 static void zfcp_erp_adapter_unblock(struct zfcp_adapter *);
@@ -97,7 +101,8 @@ static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *);
 static void zfcp_erp_action_dismiss(struct zfcp_erp_action *);
 
 static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *,
-                                  struct zfcp_port *, struct zfcp_unit *);
+                                  struct zfcp_port *, struct zfcp_unit *,
+                                  u8 id, void *ref);
 static int zfcp_erp_action_dequeue(struct zfcp_erp_action *);
 static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *,
                                    struct zfcp_port *, struct zfcp_unit *,
@@ -128,11 +133,9 @@ static void zfcp_close_qdio(struct zfcp_adapter *adapter)
        atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
        write_unlock_irq(&req_queue->queue_lock);
 
-       debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
        while (qdio_shutdown(adapter->ccw_device,
                             QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
                ssleep(1);
-       debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
 
        /* cleanup used outbound sbals */
        count = atomic_read(&req_queue->free_count);
@@ -163,7 +166,7 @@ static void zfcp_close_fsf(struct zfcp_adapter *adapter)
        /* reset FSF request sequence number */
        adapter->fsf_req_seq_no = 0;
        /* all ports and units are closed */
-       zfcp_erp_modify_adapter_status(adapter,
+       zfcp_erp_modify_adapter_status(adapter, 24, NULL,
                                       ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
 }
 
@@ -179,7 +182,8 @@ static void zfcp_close_fsf(struct zfcp_adapter *adapter)
 static void zfcp_fsf_request_timeout_handler(unsigned long data)
 {
        struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
-       zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
+       zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 62,
+                               NULL);
 }
 
 void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
@@ -200,12 +204,11 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
  * returns:    0       - initiated action successfully
  *             <0      - failed to initiate action
  */
-static int
-zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
+static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter,
+                                           int clear_mask, u8 id, void *ref)
 {
        int retval;
 
-       debug_text_event(adapter->erp_dbf, 5, "a_ro");
        ZFCP_LOG_DEBUG("reopen adapter %s\n",
                       zfcp_get_busid_by_adapter(adapter));
 
@@ -214,14 +217,13 @@ zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
        if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) {
                ZFCP_LOG_DEBUG("skipped reopen of failed adapter %s\n",
                               zfcp_get_busid_by_adapter(adapter));
-               debug_text_event(adapter->erp_dbf, 5, "a_ro_f");
                /* ensure propagation of failed status to new devices */
-               zfcp_erp_adapter_failed(adapter);
+               zfcp_erp_adapter_failed(adapter, 13, NULL);
                retval = -EIO;
                goto out;
        }
        retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
-                                        adapter, NULL, NULL);
+                                        adapter, NULL, NULL, id, ref);
 
  out:
        return retval;
@@ -236,56 +238,56 @@ zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
  * returns:    0       - initiated action successfully
  *             <0      - failed to initiate action
  */
-int
-zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask)
+int zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask,
+                           u8 id, void *ref)
 {
        int retval;
        unsigned long flags;
 
        read_lock_irqsave(&zfcp_data.config_lock, flags);
        write_lock(&adapter->erp_lock);
-       retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask);
+       retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask, id, ref);
        write_unlock(&adapter->erp_lock);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 
        return retval;
 }
 
-int
-zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask)
+int zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask,
+                             u8 id, void *ref)
 {
        int retval;
 
        retval = zfcp_erp_adapter_reopen(adapter,
                                         ZFCP_STATUS_COMMON_RUNNING |
                                         ZFCP_STATUS_COMMON_ERP_FAILED |
-                                        clear_mask);
+                                        clear_mask, id, ref);
 
        return retval;
 }
 
-int
-zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask)
+int zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask, u8 id,
+                          void *ref)
 {
        int retval;
 
        retval = zfcp_erp_port_reopen(port,
                                      ZFCP_STATUS_COMMON_RUNNING |
                                      ZFCP_STATUS_COMMON_ERP_FAILED |
-                                     clear_mask);
+                                     clear_mask, id, ref);
 
        return retval;
 }
 
-int
-zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
+int zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask, u8 id,
+                          void *ref)
 {
        int retval;
 
        retval = zfcp_erp_unit_reopen(unit,
                                      ZFCP_STATUS_COMMON_RUNNING |
                                      ZFCP_STATUS_COMMON_ERP_FAILED |
-                                     clear_mask);
+                                     clear_mask, id, ref);
 
        return retval;
 }
@@ -399,8 +401,7 @@ zfcp_erp_adisc_handler(unsigned long data)
                                "force physical port reopen "
                                "(adapter %s, port d_id=0x%06x)\n",
                                zfcp_get_busid_by_adapter(adapter), d_id);
-               debug_text_event(adapter->erp_dbf, 3, "forcreop");
-               if (zfcp_erp_port_forced_reopen(port, 0))
+               if (zfcp_erp_port_forced_reopen(port, 0, 63, NULL))
                        ZFCP_LOG_NORMAL("failed reopen of port "
                                        "(adapter %s, wwpn=0x%016Lx)\n",
                                        zfcp_get_busid_by_port(port),
@@ -427,7 +428,7 @@ zfcp_erp_adisc_handler(unsigned long data)
                                "adisc_resp_wwpn=0x%016Lx)\n",
                                zfcp_get_busid_by_port(port),
                                port->wwpn, (wwn_t) adisc->wwpn);
-               if (zfcp_erp_port_reopen(port, 0))
+               if (zfcp_erp_port_reopen(port, 0, 64, NULL))
                        ZFCP_LOG_NORMAL("failed reopen of port "
                                        "(adapter %s, wwpn=0x%016Lx)\n",
                                        zfcp_get_busid_by_port(port),
@@ -461,7 +462,7 @@ zfcp_test_link(struct zfcp_port *port)
                ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
                                "on adapter %s\n ", port->wwpn,
                                zfcp_get_busid_by_port(port));
-               retval = zfcp_erp_port_forced_reopen(port, 0);
+               retval = zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
                if (retval != 0) {
                        ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx "
                                        "on adapter %s failed\n", port->wwpn,
@@ -484,14 +485,11 @@ zfcp_test_link(struct zfcp_port *port)
  * returns:    0       - initiated action successfully
  *             <0      - failed to initiate action
  */
-static int
-zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
+static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port,
+                                               int clear_mask, u8 id,
+                                               void *ref)
 {
        int retval;
-       struct zfcp_adapter *adapter = port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 5, "pf_ro");
-       debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
 
        ZFCP_LOG_DEBUG("forced reopen of port 0x%016Lx on adapter %s\n",
                       port->wwpn, zfcp_get_busid_by_port(port));
@@ -502,14 +500,12 @@ zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
                ZFCP_LOG_DEBUG("skipped forced reopen of failed port 0x%016Lx "
                               "on adapter %s\n", port->wwpn,
                               zfcp_get_busid_by_port(port));
-               debug_text_event(adapter->erp_dbf, 5, "pf_ro_f");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                retval = -EIO;
                goto out;
        }
 
        retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
-                                        port->adapter, port, NULL);
+                                        port->adapter, port, NULL, id, ref);
 
  out:
        return retval;
@@ -524,8 +520,8 @@ zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
  * returns:    0       - initiated action successfully
  *             <0      - failed to initiate action
  */
-int
-zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
+int zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask, u8 id,
+                               void *ref)
 {
        int retval;
        unsigned long flags;
@@ -534,7 +530,8 @@ zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
        adapter = port->adapter;
        read_lock_irqsave(&zfcp_data.config_lock, flags);
        write_lock(&adapter->erp_lock);
-       retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask);
+       retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask, id,
+                                                     ref);
        write_unlock(&adapter->erp_lock);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 
@@ -551,14 +548,10 @@ zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
  * returns:    0       - initiated action successfully
  *             <0      - failed to initiate action
  */
-static int
-zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
+static int zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask,
+                                        u8 id, void *ref)
 {
        int retval;
-       struct zfcp_adapter *adapter = port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 5, "p_ro");
-       debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
 
        ZFCP_LOG_DEBUG("reopen of port 0x%016Lx on adapter %s\n",
                       port->wwpn, zfcp_get_busid_by_port(port));
@@ -569,16 +562,14 @@ zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
                ZFCP_LOG_DEBUG("skipped reopen of failed port 0x%016Lx "
                               "on adapter %s\n", port->wwpn,
                               zfcp_get_busid_by_port(port));
-               debug_text_event(adapter->erp_dbf, 5, "p_ro_f");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                /* ensure propagation of failed status to new devices */
-               zfcp_erp_port_failed(port);
+               zfcp_erp_port_failed(port, 14, NULL);
                retval = -EIO;
                goto out;
        }
 
        retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
-                                        port->adapter, port, NULL);
+                                        port->adapter, port, NULL, id, ref);
 
  out:
        return retval;
@@ -594,8 +585,8 @@ zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
  * correct locking. An error recovery task is initiated to do the reopen.
  * To wait for the completion of the reopen zfcp_erp_wait should be used.
  */
-int
-zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
+int zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask, u8 id,
+                        void *ref)
 {
        int retval;
        unsigned long flags;
@@ -603,7 +594,7 @@ zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
 
        read_lock_irqsave(&zfcp_data.config_lock, flags);
        write_lock(&adapter->erp_lock);
-       retval = zfcp_erp_port_reopen_internal(port, clear_mask);
+       retval = zfcp_erp_port_reopen_internal(port, clear_mask, id, ref);
        write_unlock(&adapter->erp_lock);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 
@@ -620,14 +611,12 @@ zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
  * returns:    0       - initiated action successfully
  *             <0      - failed to initiate action
  */
-static int
-zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
+static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask,
+                                        u8 id, void *ref)
 {
        int retval;
        struct zfcp_adapter *adapter = unit->port->adapter;
 
-       debug_text_event(adapter->erp_dbf, 5, "u_ro");
-       debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
        ZFCP_LOG_DEBUG("reopen of unit 0x%016Lx on port 0x%016Lx "
                       "on adapter %s\n", unit->fcp_lun,
                       unit->port->wwpn, zfcp_get_busid_by_unit(unit));
@@ -639,15 +628,12 @@ zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
                               "on port 0x%016Lx on adapter %s\n",
                               unit->fcp_lun, unit->port->wwpn,
                               zfcp_get_busid_by_unit(unit));
-               debug_text_event(adapter->erp_dbf, 5, "u_ro_f");
-               debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
-                           sizeof (fcp_lun_t));
                retval = -EIO;
                goto out;
        }
 
        retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
-                                        unit->port->adapter, unit->port, unit);
+                                        adapter, unit->port, unit, id, ref);
  out:
        return retval;
 }
@@ -662,8 +648,8 @@ zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
  * locking. An error recovery task is initiated to do the reopen.
  * To wait for the completion of the reopen zfcp_erp_wait should be used.
  */
-int
-zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
+int zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask, u8 id,
+                        void *ref)
 {
        int retval;
        unsigned long flags;
@@ -675,7 +661,7 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
 
        read_lock_irqsave(&zfcp_data.config_lock, flags);
        write_lock(&adapter->erp_lock);
-       retval = zfcp_erp_unit_reopen_internal(unit, clear_mask);
+       retval = zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref);
        write_unlock(&adapter->erp_lock);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 
@@ -687,19 +673,43 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
  */
 static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask)
 {
-       debug_text_event(adapter->erp_dbf, 6, "a_bl");
-       zfcp_erp_modify_adapter_status(adapter,
+       zfcp_erp_modify_adapter_status(adapter, 15, NULL,
                                       ZFCP_STATUS_COMMON_UNBLOCKED |
                                       clear_mask, ZFCP_CLEAR);
 }
 
+/* FIXME: isn't really atomic */
+/*
+ * returns the mask which has not been set so far, i.e.
+ * 0 if no bit has been changed, !0 if some bit has been changed
+ */
+static int atomic_test_and_set_mask(unsigned long mask, atomic_t *v)
+{
+       int changed_bits = (atomic_read(v) /*XOR*/^ mask) & mask;
+       atomic_set_mask(mask, v);
+       return changed_bits;
+}
+
+/* FIXME: isn't really atomic */
+/*
+ * returns the mask which has not been cleared so far, i.e.
+ * 0 if no bit has been changed, !0 if some bit has been changed
+ */
+static int atomic_test_and_clear_mask(unsigned long mask, atomic_t *v)
+{
+       int changed_bits = atomic_read(v) & mask;
+       atomic_clear_mask(mask, v);
+       return changed_bits;
+}
+
 /**
  * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests
  */
 static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
 {
-       debug_text_event(adapter->erp_dbf, 6, "a_ubl");
-       atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
+       if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
+                                    &adapter->status))
+               zfcp_rec_dbf_event_adapter(16, NULL, adapter);
 }
 
 /*
@@ -714,11 +724,7 @@ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
 static void
 zfcp_erp_port_block(struct zfcp_port *port, int clear_mask)
 {
-       struct zfcp_adapter *adapter = port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 6, "p_bl");
-       debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
-       zfcp_erp_modify_port_status(port,
+       zfcp_erp_modify_port_status(port, 17, NULL,
                                    ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
                                    ZFCP_CLEAR);
 }
@@ -733,11 +739,9 @@ zfcp_erp_port_block(struct zfcp_port *port, int clear_mask)
 static void
 zfcp_erp_port_unblock(struct zfcp_port *port)
 {
-       struct zfcp_adapter *adapter = port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 6, "p_ubl");
-       debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
-       atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
+       if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
+                                    &port->status))
+               zfcp_rec_dbf_event_port(18, NULL, port);
 }
 
 /*
@@ -752,11 +756,7 @@ zfcp_erp_port_unblock(struct zfcp_port *port)
 static void
 zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
 {
-       struct zfcp_adapter *adapter = unit->port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 6, "u_bl");
-       debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
-       zfcp_erp_modify_unit_status(unit,
+       zfcp_erp_modify_unit_status(unit, 19, NULL,
                                    ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
                                    ZFCP_CLEAR);
 }
@@ -771,11 +771,9 @@ zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
 static void
 zfcp_erp_unit_unblock(struct zfcp_unit *unit)
 {
-       struct zfcp_adapter *adapter = unit->port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 6, "u_ubl");
-       debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
-       atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
+       if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
+                                    &unit->status))
+               zfcp_rec_dbf_event_unit(20, NULL, unit);
 }
 
 static void
@@ -783,11 +781,9 @@ zfcp_erp_action_ready(struct zfcp_erp_action *erp_action)
 {
        struct zfcp_adapter *adapter = erp_action->adapter;
 
-       debug_text_event(adapter->erp_dbf, 4, "a_ar");
-       debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int));
-
        zfcp_erp_action_to_ready(erp_action);
        up(&adapter->erp_ready_sem);
+       zfcp_rec_dbf_event_thread(2, adapter, 0);
 }
 
 /*
@@ -849,18 +845,15 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
                if (zfcp_reqlist_find_safe(adapter, erp_action->fsf_req) &&
                    erp_action->fsf_req->erp_action == erp_action) {
                        /* fsf_req still exists */
-                       debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
-                       debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
-                                   sizeof (unsigned long));
                        /* dismiss fsf_req of timed out/dismissed erp_action */
                        if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
                                                  ZFCP_STATUS_ERP_TIMEDOUT)) {
-                               debug_text_event(adapter->erp_dbf, 3,
-                                                "a_ca_disreq");
                                erp_action->fsf_req->status |=
                                        ZFCP_STATUS_FSFREQ_DISMISSED;
+                               zfcp_rec_dbf_event_action(142, erp_action);
                        }
                        if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+                               zfcp_rec_dbf_event_action(143, erp_action);
                                ZFCP_LOG_NORMAL("error: erp step timed out "
                                                "(action=%d, fsf_req=%p)\n ",
                                                erp_action->action,
@@ -879,7 +872,6 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
                                erp_action->fsf_req = NULL;
                        }
                } else {
-                       debug_text_event(adapter->erp_dbf, 3, "a_ca_gonereq");
                        /*
                         * even if this fsf_req has gone, forget about
                         * association between erp_action and fsf_req
@@ -887,8 +879,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
                        erp_action->fsf_req = NULL;
                }
                spin_unlock(&adapter->req_list_lock);
-       } else
-               debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
+       }
 }
 
 /**
@@ -900,19 +891,11 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
 static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
                                          unsigned long set_mask)
 {
-       struct zfcp_adapter *adapter = erp_action->adapter;
-
        if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
-               debug_text_event(adapter->erp_dbf, 2, "a_asyh_ex");
-               debug_event(adapter->erp_dbf, 2, &erp_action->action,
-                           sizeof (int));
                erp_action->status |= set_mask;
                zfcp_erp_action_ready(erp_action);
        } else {
                /* action is ready or gone - nothing to do */
-               debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone");
-               debug_event(adapter->erp_dbf, 3, &erp_action->action,
-                           sizeof (int));
        }
 }
 
@@ -939,10 +922,6 @@ static void
 zfcp_erp_memwait_handler(unsigned long data)
 {
        struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-
-       debug_text_event(adapter->erp_dbf, 2, "a_mwh");
-       debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
 
        zfcp_erp_async_handler(erp_action, 0);
 }
@@ -955,10 +934,6 @@ zfcp_erp_memwait_handler(unsigned long data)
 static void zfcp_erp_timeout_handler(unsigned long data)
 {
        struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-
-       debug_text_event(adapter->erp_dbf, 2, "a_th");
-       debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
 
        zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT);
 }
@@ -973,11 +948,6 @@ static void zfcp_erp_timeout_handler(unsigned long data)
  */
 static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action)
 {
-       struct zfcp_adapter *adapter = erp_action->adapter;
-
-       debug_text_event(adapter->erp_dbf, 2, "a_adis");
-       debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
-
        erp_action->status |= ZFCP_STATUS_ERP_DISMISSED;
        if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING)
                zfcp_erp_action_ready(erp_action);
@@ -995,12 +965,10 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
                ZFCP_LOG_NORMAL("error: creation of erp thread failed for "
                                "adapter %s\n",
                                zfcp_get_busid_by_adapter(adapter));
-               debug_text_event(adapter->erp_dbf, 5, "a_thset_fail");
        } else {
                wait_event(adapter->erp_thread_wqh,
                           atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
                                            &adapter->status));
-               debug_text_event(adapter->erp_dbf, 5, "a_thset_ok");
        }
 
        return (retval < 0);
@@ -1027,6 +995,7 @@ zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
 
        atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
        up(&adapter->erp_ready_sem);
+       zfcp_rec_dbf_event_thread(2, adapter, 1);
 
        wait_event(adapter->erp_thread_wqh,
                   !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
@@ -1035,8 +1004,6 @@ zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
        atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
                          &adapter->status);
 
-       debug_text_event(adapter->erp_dbf, 5, "a_thki_ok");
-
        return retval;
 }
 
@@ -1059,7 +1026,6 @@ zfcp_erp_thread(void *data)
        /* Block all signals */
        siginitsetinv(&current->blocked, 0);
        atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
-       debug_text_event(adapter->erp_dbf, 5, "a_th_run");
        wake_up(&adapter->erp_thread_wqh);
 
        while (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
@@ -1084,12 +1050,12 @@ zfcp_erp_thread(void *data)
                 * no action in 'ready' queue to be processed and
                 * thread is not to be killed
                 */
+               zfcp_rec_dbf_event_thread(4, adapter, 1);
                down_interruptible(&adapter->erp_ready_sem);
-               debug_text_event(adapter->erp_dbf, 5, "a_th_woken");
+               zfcp_rec_dbf_event_thread(5, adapter, 1);
        }
 
        atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
-       debug_text_event(adapter->erp_dbf, 5, "a_th_stop");
        wake_up(&adapter->erp_thread_wqh);
 
        return 0;
@@ -1125,7 +1091,6 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
        /* dequeue dismissed action and leave, if required */
        retval = zfcp_erp_strategy_check_action(erp_action, retval);
        if (retval == ZFCP_ERP_DISMISSED) {
-               debug_text_event(adapter->erp_dbf, 4, "a_st_dis1");
                goto unlock;
        }
 
@@ -1176,20 +1141,17 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
                   element was timed out.
                 */
                if (adapter->erp_total_count == adapter->erp_low_mem_count) {
-                       debug_text_event(adapter->erp_dbf, 3, "a_st_lowmem");
                        ZFCP_LOG_NORMAL("error: no mempool elements available, "
                                        "restarting I/O on adapter %s "
                                        "to free mempool\n",
                                        zfcp_get_busid_by_adapter(adapter));
-                       zfcp_erp_adapter_reopen_internal(adapter, 0);
+                       zfcp_erp_adapter_reopen_internal(adapter, 0, 66, NULL);
                } else {
-               debug_text_event(adapter->erp_dbf, 2, "a_st_memw");
                retval = zfcp_erp_strategy_memwait(erp_action);
                }
                goto unlock;
        case ZFCP_ERP_CONTINUES:
                /* leave since this action runs asynchronously */
-               debug_text_event(adapter->erp_dbf, 6, "a_st_cont");
                if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
                        --adapter->erp_low_mem_count;
                        erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
@@ -1218,7 +1180,6 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
         * action is repeated in order to process state change
         */
        if (retval == ZFCP_ERP_EXIT) {
-               debug_text_event(adapter->erp_dbf, 2, "a_st_exit");
                goto unlock;
        }
 
@@ -1244,8 +1205,6 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
        if (retval != ZFCP_ERP_DISMISSED)
                zfcp_erp_strategy_check_queues(adapter);
 
-       debug_text_event(adapter->erp_dbf, 6, "a_st_done");
-
        return retval;
 }
 
@@ -1260,17 +1219,12 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
 static int
 zfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval)
 {
-       struct zfcp_adapter *adapter = erp_action->adapter;
-
        zfcp_erp_strategy_check_fsfreq(erp_action);
 
-       debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int));
        if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
-               debug_text_event(adapter->erp_dbf, 3, "a_stcd_dis");
                zfcp_erp_action_dequeue(erp_action);
                retval = ZFCP_ERP_DISMISSED;
-       } else
-               debug_text_event(adapter->erp_dbf, 5, "a_stcd_nodis");
+       }
 
        return retval;
 }
@@ -1279,7 +1233,6 @@ static int
 zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
 {
        int retval = ZFCP_ERP_FAILED;
-       struct zfcp_adapter *adapter = erp_action->adapter;
 
        /*
         * try to execute/continue action as far as possible,
@@ -1309,9 +1262,6 @@ zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
                break;
 
        default:
-               debug_text_exception(adapter->erp_dbf, 1, "a_stda_bug");
-               debug_event(adapter->erp_dbf, 1, &erp_action->action,
-                           sizeof (int));
                ZFCP_LOG_NORMAL("bug: unknown erp action requested on "
                                "adapter %s (action=%d)\n",
                                zfcp_get_busid_by_adapter(erp_action->adapter),
@@ -1333,10 +1283,7 @@ static int
 zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
 {
        int retval = ZFCP_ERP_CONTINUES;
-       struct zfcp_adapter *adapter = erp_action->adapter;
 
-       debug_text_event(adapter->erp_dbf, 6, "a_mwinit");
-       debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int));
        init_timer(&erp_action->timer);
        erp_action->timer.function = zfcp_erp_memwait_handler;
        erp_action->timer.data = (unsigned long) erp_action;
@@ -1353,13 +1300,12 @@ zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
  *
  */
 void
-zfcp_erp_adapter_failed(struct zfcp_adapter *adapter)
+zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref)
 {
-       zfcp_erp_modify_adapter_status(adapter,
+       zfcp_erp_modify_adapter_status(adapter, id, ref,
                                       ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
        ZFCP_LOG_NORMAL("adapter erp failed on adapter %s\n",
                        zfcp_get_busid_by_adapter(adapter));
-       debug_text_event(adapter->erp_dbf, 2, "a_afail");
 }
 
 /*
@@ -1369,9 +1315,9 @@ zfcp_erp_adapter_failed(struct zfcp_adapter *adapter)
  *
  */
 void
-zfcp_erp_port_failed(struct zfcp_port *port)
+zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref)
 {
-       zfcp_erp_modify_port_status(port,
+       zfcp_erp_modify_port_status(port, id, ref,
                                    ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
 
        if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
@@ -1381,9 +1327,6 @@ zfcp_erp_port_failed(struct zfcp_port *port)
        else
                ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n",
                                zfcp_get_busid_by_port(port), port->wwpn);
-
-       debug_text_event(port->adapter->erp_dbf, 2, "p_pfail");
-       debug_event(port->adapter->erp_dbf, 2, &port->wwpn, sizeof (wwn_t));
 }
 
 /*
@@ -1393,17 +1336,14 @@ zfcp_erp_port_failed(struct zfcp_port *port)
  *
  */
 void
-zfcp_erp_unit_failed(struct zfcp_unit *unit)
+zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref)
 {
-       zfcp_erp_modify_unit_status(unit,
+       zfcp_erp_modify_unit_status(unit, id, ref,
                                    ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
 
        ZFCP_LOG_NORMAL("unit erp failed on unit 0x%016Lx on port 0x%016Lx "
                        " on adapter %s\n", unit->fcp_lun,
                        unit->port->wwpn, zfcp_get_busid_by_unit(unit));
-       debug_text_event(unit->port->adapter->erp_dbf, 2, "u_ufail");
-       debug_event(unit->port->adapter->erp_dbf, 2,
-                   &unit->fcp_lun, sizeof (fcp_lun_t));
 }
 
 /*
@@ -1427,10 +1367,6 @@ zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result)
        struct zfcp_port *port = erp_action->port;
        struct zfcp_unit *unit = erp_action->unit;
 
-       debug_text_event(adapter->erp_dbf, 5, "a_stct_norm");
-       debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int));
-       debug_event(adapter->erp_dbf, 5, &result, sizeof (int));
-
        switch (erp_action->action) {
 
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
@@ -1457,15 +1393,14 @@ zfcp_erp_strategy_statechange(int action,
                              struct zfcp_port *port,
                              struct zfcp_unit *unit, int retval)
 {
-       debug_text_event(adapter->erp_dbf, 3, "a_stsc");
-       debug_event(adapter->erp_dbf, 3, &action, sizeof (int));
-
        switch (action) {
 
        case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
                if (zfcp_erp_strategy_statechange_detected(&adapter->status,
                                                           status)) {
-                       zfcp_erp_adapter_reopen_internal(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
+                       zfcp_erp_adapter_reopen_internal(adapter,
+                                               ZFCP_STATUS_COMMON_ERP_FAILED,
+                                               67, NULL);
                        retval = ZFCP_ERP_EXIT;
                }
                break;
@@ -1474,7 +1409,9 @@ zfcp_erp_strategy_statechange(int action,
        case ZFCP_ERP_ACTION_REOPEN_PORT:
                if (zfcp_erp_strategy_statechange_detected(&port->status,
                                                           status)) {
-                       zfcp_erp_port_reopen_internal(port, ZFCP_STATUS_COMMON_ERP_FAILED);
+                       zfcp_erp_port_reopen_internal(port,
+                                               ZFCP_STATUS_COMMON_ERP_FAILED,
+                                               68, NULL);
                        retval = ZFCP_ERP_EXIT;
                }
                break;
@@ -1482,7 +1419,9 @@ zfcp_erp_strategy_statechange(int action,
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
                if (zfcp_erp_strategy_statechange_detected(&unit->status,
                                                           status)) {
-                       zfcp_erp_unit_reopen_internal(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
+                       zfcp_erp_unit_reopen_internal(unit,
+                                               ZFCP_STATUS_COMMON_ERP_FAILED,
+                                               69, NULL);
                        retval = ZFCP_ERP_EXIT;
                }
                break;
@@ -1506,10 +1445,6 @@ zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status)
 static int
 zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
 {
-       debug_text_event(unit->port->adapter->erp_dbf, 5, "u_stct");
-       debug_event(unit->port->adapter->erp_dbf, 5, &unit->fcp_lun,
-                   sizeof (fcp_lun_t));
-
        switch (result) {
        case ZFCP_ERP_SUCCEEDED :
                atomic_set(&unit->erp_counter, 0);
@@ -1518,7 +1453,7 @@ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
        case ZFCP_ERP_FAILED :
                atomic_inc(&unit->erp_counter);
                if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS)
-                       zfcp_erp_unit_failed(unit);
+                       zfcp_erp_unit_failed(unit, 21, NULL);
                break;
        case ZFCP_ERP_EXIT :
                /* nothing */
@@ -1536,9 +1471,6 @@ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
 static int
 zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
 {
-       debug_text_event(port->adapter->erp_dbf, 5, "p_stct");
-       debug_event(port->adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
-
        switch (result) {
        case ZFCP_ERP_SUCCEEDED :
                atomic_set(&port->erp_counter, 0);
@@ -1547,7 +1479,7 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
        case ZFCP_ERP_FAILED :
                atomic_inc(&port->erp_counter);
                if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS)
-                       zfcp_erp_port_failed(port);
+                       zfcp_erp_port_failed(port, 22, NULL);
                break;
        case ZFCP_ERP_EXIT :
                /* nothing */
@@ -1565,8 +1497,6 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
 static int
 zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
 {
-       debug_text_event(adapter->erp_dbf, 5, "a_stct");
-
        switch (result) {
        case ZFCP_ERP_SUCCEEDED :
                atomic_set(&adapter->erp_counter, 0);
@@ -1575,7 +1505,7 @@ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
        case ZFCP_ERP_FAILED :
                atomic_inc(&adapter->erp_counter);
                if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS)
-                       zfcp_erp_adapter_failed(adapter);
+                       zfcp_erp_adapter_failed(adapter, 23, NULL);
                break;
        case ZFCP_ERP_EXIT :
                /* nothing */
@@ -1658,37 +1588,34 @@ zfcp_erp_strategy_followup_actions(int action,
                                   struct zfcp_port *port,
                                   struct zfcp_unit *unit, int status)
 {
-       debug_text_event(adapter->erp_dbf, 5, "a_stfol");
-       debug_event(adapter->erp_dbf, 5, &action, sizeof (int));
-
        /* initiate follow-up actions depending on success of finished action */
        switch (action) {
 
        case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
                if (status == ZFCP_ERP_SUCCEEDED)
-                       zfcp_erp_port_reopen_all_internal(adapter, 0);
+                       zfcp_erp_port_reopen_all_internal(adapter, 0, 70, NULL);
                else
-                       zfcp_erp_adapter_reopen_internal(adapter, 0);
+                       zfcp_erp_adapter_reopen_internal(adapter, 0, 71, NULL);
                break;
 
        case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
                if (status == ZFCP_ERP_SUCCEEDED)
-                       zfcp_erp_port_reopen_internal(port, 0);
+                       zfcp_erp_port_reopen_internal(port, 0, 72, NULL);
                else
-                       zfcp_erp_adapter_reopen_internal(adapter, 0);
+                       zfcp_erp_adapter_reopen_internal(adapter, 0, 73, NULL);
                break;
 
        case ZFCP_ERP_ACTION_REOPEN_PORT:
                if (status == ZFCP_ERP_SUCCEEDED)
-                       zfcp_erp_unit_reopen_all_internal(port, 0);
+                       zfcp_erp_unit_reopen_all_internal(port, 0, 74, NULL);
                else
-                       zfcp_erp_port_forced_reopen_internal(port, 0);
+                       zfcp_erp_port_forced_reopen_internal(port, 0, 75, NULL);
                break;
 
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
                /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */
                if (status != ZFCP_ERP_SUCCEEDED)
-                       zfcp_erp_port_reopen_internal(unit->port, 0);
+                       zfcp_erp_port_reopen_internal(unit->port, 0, 76, NULL);
                break;
        }
 
@@ -1704,12 +1631,10 @@ zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter)
        read_lock(&adapter->erp_lock);
        if (list_empty(&adapter->erp_ready_head) &&
            list_empty(&adapter->erp_running_head)) {
-                       debug_text_event(adapter->erp_dbf, 4, "a_cq_wake");
                        atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
                                          &adapter->status);
                        wake_up(&adapter->erp_done_wqh);
-       } else
-               debug_text_event(adapter->erp_dbf, 5, "a_cq_notempty");
+       }
        read_unlock(&adapter->erp_lock);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 
@@ -1733,29 +1658,27 @@ zfcp_erp_wait(struct zfcp_adapter *adapter)
        return retval;
 }
 
-void
-zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter,
-                              u32 mask, int set_or_clear)
+void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id,
+                                   void *ref, u32 mask, int set_or_clear)
 {
        struct zfcp_port *port;
-       u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+       u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS;
 
        if (set_or_clear == ZFCP_SET) {
-               atomic_set_mask(mask, &adapter->status);
-               debug_text_event(adapter->erp_dbf, 3, "a_mod_as_s");
+               changed = atomic_test_and_set_mask(mask, &adapter->status);
        } else {
-               atomic_clear_mask(mask, &adapter->status);
+               changed = atomic_test_and_clear_mask(mask, &adapter->status);
                if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
                        atomic_set(&adapter->erp_counter, 0);
-               debug_text_event(adapter->erp_dbf, 3, "a_mod_as_c");
        }
-       debug_event(adapter->erp_dbf, 3, &mask, sizeof (u32));
+       if (changed)
+               zfcp_rec_dbf_event_adapter(id, ref, adapter);
 
        /* Deal with all underlying devices, only pass common_mask */
        if (common_mask)
                list_for_each_entry(port, &adapter->port_list_head, list)
-                   zfcp_erp_modify_port_status(port, common_mask,
-                                               set_or_clear);
+                       zfcp_erp_modify_port_status(port, id, ref, common_mask,
+                                                   set_or_clear);
 }
 
 /*
@@ -1764,29 +1687,27 @@ zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter,
  * purpose:    sets the port and all underlying devices to ERP_FAILED
  *
  */
-void
-zfcp_erp_modify_port_status(struct zfcp_port *port, u32 mask, int set_or_clear)
+void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref,
+                                u32 mask, int set_or_clear)
 {
        struct zfcp_unit *unit;
-       u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+       u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS;
 
        if (set_or_clear == ZFCP_SET) {
-               atomic_set_mask(mask, &port->status);
-               debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_s");
+               changed = atomic_test_and_set_mask(mask, &port->status);
        } else {
-               atomic_clear_mask(mask, &port->status);
+               changed = atomic_test_and_clear_mask(mask, &port->status);
                if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
                        atomic_set(&port->erp_counter, 0);
-               debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_c");
        }
-       debug_event(port->adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t));
-       debug_event(port->adapter->erp_dbf, 3, &mask, sizeof (u32));
+       if (changed)
+               zfcp_rec_dbf_event_port(id, ref, port);
 
        /* Modify status of all underlying devices, only pass common mask */
        if (common_mask)
                list_for_each_entry(unit, &port->unit_list_head, list)
-                   zfcp_erp_modify_unit_status(unit, common_mask,
-                                               set_or_clear);
+                       zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
+                                                   set_or_clear);
 }
 
 /*
@@ -1795,22 +1716,21 @@ zfcp_erp_modify_port_status(struct zfcp_port *port, u32 mask, int set_or_clear)
  * purpose:    sets the unit to ERP_FAILED
  *
  */
-void
-zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear)
+void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref,
+                                u32 mask, int set_or_clear)
 {
+       u32 changed;
+
        if (set_or_clear == ZFCP_SET) {
-               atomic_set_mask(mask, &unit->status);
-               debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_s");
+               changed = atomic_test_and_set_mask(mask, &unit->status);
        } else {
-               atomic_clear_mask(mask, &unit->status);
+               changed = atomic_test_and_clear_mask(mask, &unit->status);
                if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
                        atomic_set(&unit->erp_counter, 0);
                }
-               debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_c");
        }
-       debug_event(unit->port->adapter->erp_dbf, 3, &unit->fcp_lun,
-                   sizeof (fcp_lun_t));
-       debug_event(unit->port->adapter->erp_dbf, 3, &mask, sizeof (u32));
+       if (changed)
+               zfcp_rec_dbf_event_unit(id, ref, unit);
 }
 
 /*
@@ -1822,30 +1742,32 @@ zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear)
  * returns:    0       - initiated action successfully
  *             <0      - failed to initiate action
  */
-int
-zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask)
+int zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask,
+                            u8 id, void *ref)
 {
        int retval;
        unsigned long flags;
 
        read_lock_irqsave(&zfcp_data.config_lock, flags);
        write_lock(&adapter->erp_lock);
-       retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask);
+       retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask, id,
+                                                  ref);
        write_unlock(&adapter->erp_lock);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 
        return retval;
 }
 
-static int
-zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
+static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter,
+                                            int clear_mask, u8 id, void *ref)
 {
        int retval = 0;
        struct zfcp_port *port;
 
        list_for_each_entry(port, &adapter->port_list_head, list)
                if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
-                       zfcp_erp_port_reopen_internal(port, clear_mask);
+                       zfcp_erp_port_reopen_internal(port, clear_mask, id,
+                                                     ref);
 
        return retval;
 }
@@ -1857,14 +1779,14 @@ zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
  *
  * returns:    FIXME
  */
-static int
-zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, int clear_mask)
+static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port,
+                                            int clear_mask, u8 id, void *ref)
 {
        int retval = 0;
        struct zfcp_unit *unit;
 
        list_for_each_entry(unit, &port->unit_list_head, list)
-           zfcp_erp_unit_reopen_internal(unit, clear_mask);
+               zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref);
 
        return retval;
 }
@@ -1892,10 +1814,6 @@ zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action)
        else
                retval = zfcp_erp_adapter_strategy_open(erp_action);
 
-       debug_text_event(adapter->erp_dbf, 3, "a_ast/ret");
-       debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
-       debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
-
        if (retval == ZFCP_ERP_FAILED) {
                ZFCP_LOG_INFO("Waiting to allow the adapter %s "
                              "to recover itself\n",
@@ -2021,7 +1939,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
                              zfcp_get_busid_by_adapter(adapter));
                goto failed_qdio_establish;
        }
-       debug_text_event(adapter->erp_dbf, 3, "qdio_est");
 
        if (qdio_activate(adapter->ccw_device, 0) != 0) {
                ZFCP_LOG_INFO("error: activation of QDIO queues failed "
@@ -2029,7 +1946,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
                              zfcp_get_busid_by_adapter(adapter));
                goto failed_qdio_activate;
        }
-       debug_text_event(adapter->erp_dbf, 3, "qdio_act");
 
        /*
         * put buffers into response queue,
@@ -2077,11 +1993,9 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
        /* NOP */
 
  failed_qdio_activate:
-       debug_text_event(adapter->erp_dbf, 3, "qdio_down1a");
        while (qdio_shutdown(adapter->ccw_device,
                             QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
                ssleep(1);
-       debug_text_event(adapter->erp_dbf, 3, "qdio_down1b");
 
  failed_qdio_establish:
  failed_sanity:
@@ -2127,14 +2041,12 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
                write_unlock_irq(&adapter->erp_lock);
                if (zfcp_fsf_exchange_config_data(erp_action)) {
                        retval = ZFCP_ERP_FAILED;
-                       debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
                        ZFCP_LOG_INFO("error:  initiation of exchange of "
                                      "configuration data failed for "
                                      "adapter %s\n",
                                      zfcp_get_busid_by_adapter(adapter));
                        break;
                }
-               debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");
                ZFCP_LOG_DEBUG("Xchange underway\n");
 
                /*
@@ -2150,7 +2062,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
                 * _must_ be the one belonging to the 'exchange config
                 * data' request.
                 */
+               zfcp_rec_dbf_event_thread(6, adapter, 1);
                down(&adapter->erp_ready_sem);
+               zfcp_rec_dbf_event_thread(7, adapter, 1);
                if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
                        ZFCP_LOG_INFO("error: exchange of configuration data "
                                      "for adapter %s timed out\n",
@@ -2198,16 +2112,15 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
 
        ret = zfcp_fsf_exchange_port_data(erp_action);
        if (ret == -EOPNOTSUPP) {
-               debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
                return ZFCP_ERP_SUCCEEDED;
        } else if (ret) {
-               debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
                return ZFCP_ERP_FAILED;
        }
-       debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
 
        ret = ZFCP_ERP_SUCCEEDED;
+       zfcp_rec_dbf_event_thread(8, adapter, 1);
        down(&adapter->erp_ready_sem);
+       zfcp_rec_dbf_event_thread(9, adapter, 1);
        if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
                ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
                              "%s)\n", zfcp_get_busid_by_adapter(adapter));
@@ -2261,7 +2174,6 @@ zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
 {
        int retval = ZFCP_ERP_FAILED;
        struct zfcp_port *port = erp_action->port;
-       struct zfcp_adapter *adapter = erp_action->adapter;
 
        switch (erp_action->step) {
 
@@ -2298,11 +2210,6 @@ zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
                break;
        }
 
-       debug_text_event(adapter->erp_dbf, 3, "p_pfst/ret");
-       debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t));
-       debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
-       debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
-
        return retval;
 }
 
@@ -2320,7 +2227,6 @@ zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
 {
        int retval = ZFCP_ERP_FAILED;
        struct zfcp_port *port = erp_action->port;
-       struct zfcp_adapter *adapter = erp_action->adapter;
 
        switch (erp_action->step) {
 
@@ -2353,11 +2259,6 @@ zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
                retval = zfcp_erp_port_strategy_open(erp_action);
 
  out:
-       debug_text_event(adapter->erp_dbf, 3, "p_pst/ret");
-       debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t));
-       debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
-       debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
-
        return retval;
 }
 
@@ -2395,7 +2296,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
                                                port->wwpn,
                                                zfcp_get_busid_by_adapter(adapter),
                                                adapter->peer_wwpn);
-                               zfcp_erp_port_failed(port);
+                               zfcp_erp_port_failed(port, 25, NULL);
                                retval = ZFCP_ERP_FAILED;
                                break;
                        }
@@ -2421,8 +2322,8 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
                        /* nameserver port may live again */
                        atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING,
                                        &adapter->nameserver_port->status);
-                       if (zfcp_erp_port_reopen(adapter->nameserver_port, 0)
-                           >= 0) {
+                       if (zfcp_erp_port_reopen(adapter->nameserver_port, 0,
+                                                77, erp_action) >= 0) {
                                erp_action->step =
                                        ZFCP_ERP_STEP_NAMESERVER_OPEN;
                                retval = ZFCP_ERP_CONTINUES;
@@ -2453,7 +2354,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
                                               "for port 0x%016Lx "
                                               "(misconfigured WWPN?)\n",
                                               port->wwpn);
-                               zfcp_erp_port_failed(port);
+                               zfcp_erp_port_failed(port, 26, NULL);
                                retval = ZFCP_ERP_EXIT;
                        } else {
                                ZFCP_LOG_DEBUG("nameserver look-up failed for "
@@ -2549,17 +2450,12 @@ zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action
        read_lock_irqsave(&adapter->erp_lock, flags);
        list_for_each_entry_safe(erp_action, tmp, &adapter->erp_running_head,
                                 list) {
-               debug_text_event(adapter->erp_dbf, 4, "p_pstnsw_n");
-               debug_event(adapter->erp_dbf, 4, &erp_action->port->wwpn,
-                           sizeof (wwn_t));
                if (erp_action->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) {
-                       debug_text_event(adapter->erp_dbf, 3, "p_pstnsw_w");
-                       debug_event(adapter->erp_dbf, 3,
-                                   &erp_action->port->wwpn, sizeof (wwn_t));
                        if (atomic_test_mask(
                                    ZFCP_STATUS_COMMON_ERP_FAILED,
                                    &adapter->nameserver_port->status))
-                               zfcp_erp_port_failed(erp_action->port);
+                               zfcp_erp_port_failed(erp_action->port, 27,
+                                                    NULL);
                        zfcp_erp_action_ready(erp_action);
                }
        }
@@ -2580,26 +2476,18 @@ static int
 zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action)
 {
        int retval;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-       struct zfcp_port *port = erp_action->port;
 
        retval = zfcp_fsf_close_physical_port(erp_action);
        if (retval == -ENOMEM) {
-               debug_text_event(adapter->erp_dbf, 5, "o_pfstc_nomem");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                retval = ZFCP_ERP_NOMEM;
                goto out;
        }
        erp_action->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING;
        if (retval != 0) {
-               debug_text_event(adapter->erp_dbf, 5, "o_pfstc_cpf");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                /* could not send 'open', fail */
                retval = ZFCP_ERP_FAILED;
                goto out;
        }
-       debug_text_event(adapter->erp_dbf, 6, "o_pfstc_cpok");
-       debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
        retval = ZFCP_ERP_CONTINUES;
  out:
        return retval;
@@ -2609,10 +2497,6 @@ static int
 zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
 {
        int retval = 0;
-       struct zfcp_adapter *adapter = port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 5, "p_pstclst");
-       debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
 
        atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
                          ZFCP_STATUS_COMMON_CLOSING |
@@ -2636,26 +2520,18 @@ static int
 zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
 {
        int retval;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-       struct zfcp_port *port = erp_action->port;
 
        retval = zfcp_fsf_close_port(erp_action);
        if (retval == -ENOMEM) {
-               debug_text_event(adapter->erp_dbf, 5, "p_pstc_nomem");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                retval = ZFCP_ERP_NOMEM;
                goto out;
        }
        erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING;
        if (retval != 0) {
-               debug_text_event(adapter->erp_dbf, 5, "p_pstc_cpf");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                /* could not send 'close', fail */
                retval = ZFCP_ERP_FAILED;
                goto out;
        }
-       debug_text_event(adapter->erp_dbf, 6, "p_pstc_cpok");
-       debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
        retval = ZFCP_ERP_CONTINUES;
  out:
        return retval;
@@ -2673,26 +2549,18 @@ static int
 zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
 {
        int retval;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-       struct zfcp_port *port = erp_action->port;
 
        retval = zfcp_fsf_open_port(erp_action);
        if (retval == -ENOMEM) {
-               debug_text_event(adapter->erp_dbf, 5, "p_psto_nomem");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                retval = ZFCP_ERP_NOMEM;
                goto out;
        }
        erp_action->step = ZFCP_ERP_STEP_PORT_OPENING;
        if (retval != 0) {
-               debug_text_event(adapter->erp_dbf, 5, "p_psto_opf");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                /* could not send 'open', fail */
                retval = ZFCP_ERP_FAILED;
                goto out;
        }
-       debug_text_event(adapter->erp_dbf, 6, "p_psto_opok");
-       debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
        retval = ZFCP_ERP_CONTINUES;
  out:
        return retval;
@@ -2710,26 +2578,18 @@ static int
 zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action)
 {
        int retval;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-       struct zfcp_port *port = erp_action->port;
 
        retval = zfcp_ns_gid_pn_request(erp_action);
        if (retval == -ENOMEM) {
-               debug_text_event(adapter->erp_dbf, 5, "p_pstn_nomem");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                retval = ZFCP_ERP_NOMEM;
                goto out;
        }
        erp_action->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
        if (retval != 0) {
-               debug_text_event(adapter->erp_dbf, 5, "p_pstn_ref");
-               debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
                /* could not send nameserver request, fail */
                retval = ZFCP_ERP_FAILED;
                goto out;
        }
-       debug_text_event(adapter->erp_dbf, 6, "p_pstn_reok");
-       debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
        retval = ZFCP_ERP_CONTINUES;
  out:
        return retval;
@@ -2750,7 +2610,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
 {
        int retval = ZFCP_ERP_FAILED;
        struct zfcp_unit *unit = erp_action->unit;
-       struct zfcp_adapter *adapter = erp_action->adapter;
 
        switch (erp_action->step) {
 
@@ -2797,10 +2656,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
                break;
        }
 
-       debug_text_event(adapter->erp_dbf, 3, "u_ust/ret");
-       debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof (fcp_lun_t));
-       debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
-       debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
        return retval;
 }
 
@@ -2808,10 +2663,6 @@ static int
 zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
 {
        int retval = 0;
-       struct zfcp_adapter *adapter = unit->port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 5, "u_ustclst");
-       debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
 
        atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
                          ZFCP_STATUS_COMMON_CLOSING |
@@ -2835,28 +2686,18 @@ static int
 zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
 {
        int retval;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-       struct zfcp_unit *unit = erp_action->unit;
 
        retval = zfcp_fsf_close_unit(erp_action);
        if (retval == -ENOMEM) {
-               debug_text_event(adapter->erp_dbf, 5, "u_ustc_nomem");
-               debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
-                           sizeof (fcp_lun_t));
                retval = ZFCP_ERP_NOMEM;
                goto out;
        }
        erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING;
        if (retval != 0) {
-               debug_text_event(adapter->erp_dbf, 5, "u_ustc_cuf");
-               debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
-                           sizeof (fcp_lun_t));
                /* could not send 'close', fail */
                retval = ZFCP_ERP_FAILED;
                goto out;
        }
-       debug_text_event(adapter->erp_dbf, 6, "u_ustc_cuok");
-       debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
        retval = ZFCP_ERP_CONTINUES;
 
  out:
@@ -2875,28 +2716,18 @@ static int
 zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
 {
        int retval;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-       struct zfcp_unit *unit = erp_action->unit;
 
        retval = zfcp_fsf_open_unit(erp_action);
        if (retval == -ENOMEM) {
-               debug_text_event(adapter->erp_dbf, 5, "u_usto_nomem");
-               debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
-                           sizeof (fcp_lun_t));
                retval = ZFCP_ERP_NOMEM;
                goto out;
        }
        erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING;
        if (retval != 0) {
-               debug_text_event(adapter->erp_dbf, 5, "u_usto_ouf");
-               debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
-                           sizeof (fcp_lun_t));
                /* could not send 'open', fail */
                retval = ZFCP_ERP_FAILED;
                goto out;
        }
-       debug_text_event(adapter->erp_dbf, 6, "u_usto_ouok");
-       debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
        retval = ZFCP_ERP_CONTINUES;
  out:
        return retval;
@@ -2918,14 +2749,12 @@ void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req)
  *
  * returns:
  */
-static int
-zfcp_erp_action_enqueue(int action,
-                       struct zfcp_adapter *adapter,
-                       struct zfcp_port *port, struct zfcp_unit *unit)
+static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
+                                  struct zfcp_port *port,
+                                  struct zfcp_unit *unit, u8 id, void *ref)
 {
-       int retval = 1;
+       int retval = 1, need = want;
        struct zfcp_erp_action *erp_action = NULL;
-       int stronger_action = 0;
        u32 status = 0;
 
        /*
@@ -2944,17 +2773,11 @@ zfcp_erp_action_enqueue(int action,
                              &adapter->status))
                return -EIO;
 
-       debug_event(adapter->erp_dbf, 4, &action, sizeof (int));
        /* check whether we really need this */
-       switch (action) {
+       switch (want) {
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
                if (atomic_test_mask
                    (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) {
-                       debug_text_event(adapter->erp_dbf, 4, "u_actenq_drp");
-                       debug_event(adapter->erp_dbf, 4, &port->wwpn,
-                                   sizeof (wwn_t));
-                       debug_event(adapter->erp_dbf, 4, &unit->fcp_lun,
-                                   sizeof (fcp_lun_t));
                        goto out;
                }
                if (!atomic_test_mask
@@ -2964,18 +2787,13 @@ zfcp_erp_action_enqueue(int action,
                        goto out;
                }
                if (!atomic_test_mask
-                   (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) {
-                       stronger_action = ZFCP_ERP_ACTION_REOPEN_PORT;
-                       unit = NULL;
-               }
+                   (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
+                       need = ZFCP_ERP_ACTION_REOPEN_PORT;
                /* fall through !!! */
 
        case ZFCP_ERP_ACTION_REOPEN_PORT:
                if (atomic_test_mask
                    (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) {
-                       debug_text_event(adapter->erp_dbf, 4, "p_actenq_drp");
-                       debug_event(adapter->erp_dbf, 4, &port->wwpn,
-                                   sizeof (wwn_t));
                        goto out;
                }
                /* fall through !!! */
@@ -2987,15 +2805,9 @@ zfcp_erp_action_enqueue(int action,
                            ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) {
                                ZFCP_LOG_INFO("dropped erp action %i (port "
                                              "0x%016Lx, action in use: %i)\n",
-                                             action, port->wwpn,
+                                             want, port->wwpn,
                                              port->erp_action.action);
-                               debug_text_event(adapter->erp_dbf, 4,
-                                                "pf_actenq_drp");
-                       } else
-                               debug_text_event(adapter->erp_dbf, 4,
-                                                "pf_actenq_drpcp");
-                       debug_event(adapter->erp_dbf, 4, &port->wwpn,
-                                   sizeof (wwn_t));
+                       }
                        goto out;
                }
                if (!atomic_test_mask
@@ -3005,46 +2817,36 @@ zfcp_erp_action_enqueue(int action,
                        goto out;
                }
                if (!atomic_test_mask
-                   (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) {
-                       stronger_action = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
-                       port = NULL;
-               }
+                   (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
+                       need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
                /* fall through !!! */
 
        case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
                if (atomic_test_mask
                    (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) {
-                       debug_text_event(adapter->erp_dbf, 4, "a_actenq_drp");
                        goto out;
                }
                break;
 
        default:
-               debug_text_exception(adapter->erp_dbf, 1, "a_actenq_bug");
-               debug_event(adapter->erp_dbf, 1, &action, sizeof (int));
                ZFCP_LOG_NORMAL("bug: unknown erp action requested "
                                "on adapter %s (action=%d)\n",
-                               zfcp_get_busid_by_adapter(adapter), action);
+                               zfcp_get_busid_by_adapter(adapter), want);
                goto out;
        }
 
        /* check whether we need something stronger first */
-       if (stronger_action) {
-               debug_text_event(adapter->erp_dbf, 4, "a_actenq_str");
-               debug_event(adapter->erp_dbf, 4, &stronger_action,
-                           sizeof (int));
+       if (need) {
                ZFCP_LOG_DEBUG("stronger erp action %d needed before "
                               "erp action %d on adapter %s\n",
-                              stronger_action, action,
-                              zfcp_get_busid_by_adapter(adapter));
-               action = stronger_action;
+                              need, want, zfcp_get_busid_by_adapter(adapter));
        }
 
        /* mark adapter to have some error recovery pending */
        atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
 
        /* setup error recovery action */
-       switch (action) {
+       switch (need) {
 
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
                zfcp_unit_get(unit);
@@ -3077,13 +2879,11 @@ zfcp_erp_action_enqueue(int action,
                break;
        }
 
-       debug_text_event(adapter->erp_dbf, 4, "a_actenq");
-
        memset(erp_action, 0, sizeof (struct zfcp_erp_action));
        erp_action->adapter = adapter;
        erp_action->port = port;
        erp_action->unit = unit;
-       erp_action->action = action;
+       erp_action->action = need;
        erp_action->status = status;
 
        ++adapter->erp_total_count;
@@ -3091,8 +2891,11 @@ zfcp_erp_action_enqueue(int action,
        /* finally put it into 'ready' queue and kick erp thread */
        list_add_tail(&erp_action->list, &adapter->erp_ready_head);
        up(&adapter->erp_ready_sem);
+       zfcp_rec_dbf_event_thread(1, adapter, 0);
        retval = 0;
  out:
+       zfcp_rec_dbf_event_trigger(id, ref, want, need, erp_action,
+                                  adapter, port, unit);
        return retval;
 }
 
@@ -3108,9 +2911,9 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
                erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
        }
 
-       debug_text_event(adapter->erp_dbf, 4, "a_actdeq");
-       debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int));
        list_del(&erp_action->list);
+       zfcp_rec_dbf_event_action(144, erp_action);
+
        switch (erp_action->action) {
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
                atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
@@ -3215,7 +3018,6 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
 {
        struct zfcp_port *port;
 
-       debug_text_event(adapter->erp_dbf, 5, "a_actab");
        if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status))
                zfcp_erp_action_dismiss(&adapter->erp_action);
        else
@@ -3226,10 +3028,7 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
 static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 {
        struct zfcp_unit *unit;
-       struct zfcp_adapter *adapter = port->adapter;
 
-       debug_text_event(adapter->erp_dbf, 5, "p_actab");
-       debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
        if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status))
                zfcp_erp_action_dismiss(&port->erp_action);
        else
@@ -3239,92 +3038,60 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 
 static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
 {
-       struct zfcp_adapter *adapter = unit->port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 5, "u_actab");
-       debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
        if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status))
                zfcp_erp_action_dismiss(&unit->erp_action);
 }
 
 static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
 {
-       struct zfcp_adapter *adapter = erp_action->adapter;
-
-       debug_text_event(adapter->erp_dbf, 6, "a_toru");
-       debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int));
        list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
+       zfcp_rec_dbf_event_action(145, erp_action);
 }
 
 static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
 {
-       struct zfcp_adapter *adapter = erp_action->adapter;
-
-       debug_text_event(adapter->erp_dbf, 6, "a_tore");
-       debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int));
        list_move(&erp_action->list, &erp_action->adapter->erp_ready_head);
+       zfcp_rec_dbf_event_action(146, erp_action);
 }
 
-void
-zfcp_erp_port_boxed(struct zfcp_port *port)
+void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref)
 {
-       struct zfcp_adapter *adapter = port->adapter;
        unsigned long flags;
 
-       debug_text_event(adapter->erp_dbf, 3, "p_access_boxed");
-       debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
        read_lock_irqsave(&zfcp_data.config_lock, flags);
-       zfcp_erp_modify_port_status(port,
-                       ZFCP_STATUS_COMMON_ACCESS_BOXED,
-                       ZFCP_SET);
+       zfcp_erp_modify_port_status(port, id, ref,
+                                   ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
-       zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
+       zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
 }
 
-void
-zfcp_erp_unit_boxed(struct zfcp_unit *unit)
+void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref)
 {
-       struct zfcp_adapter *adapter = unit->port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 3, "u_access_boxed");
-       debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
-       zfcp_erp_modify_unit_status(unit,
-                       ZFCP_STATUS_COMMON_ACCESS_BOXED,
-                       ZFCP_SET);
-       zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
+       zfcp_erp_modify_unit_status(unit, id, ref,
+                                   ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
+       zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
 }
 
-void
-zfcp_erp_port_access_denied(struct zfcp_port *port)
+void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref)
 {
-       struct zfcp_adapter *adapter = port->adapter;
        unsigned long flags;
 
-       debug_text_event(adapter->erp_dbf, 3, "p_access_denied");
-       debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
        read_lock_irqsave(&zfcp_data.config_lock, flags);
-       zfcp_erp_modify_port_status(port,
-                       ZFCP_STATUS_COMMON_ERP_FAILED |
-                       ZFCP_STATUS_COMMON_ACCESS_DENIED,
-                       ZFCP_SET);
+       zfcp_erp_modify_port_status(port, id, ref,
+                                   ZFCP_STATUS_COMMON_ERP_FAILED |
+                                   ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 }
 
-void
-zfcp_erp_unit_access_denied(struct zfcp_unit *unit)
+void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref)
 {
-       struct zfcp_adapter *adapter = unit->port->adapter;
-
-       debug_text_event(adapter->erp_dbf, 3, "u_access_denied");
-       debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
-       zfcp_erp_modify_unit_status(unit,
-                       ZFCP_STATUS_COMMON_ERP_FAILED |
-                       ZFCP_STATUS_COMMON_ACCESS_DENIED,
-                       ZFCP_SET);
+       zfcp_erp_modify_unit_status(unit, id, ref,
+                                   ZFCP_STATUS_COMMON_ERP_FAILED |
+                                   ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
 }
 
-void
-zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
+void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id,
+                                    void *ref)
 {
        struct zfcp_port *port;
        unsigned long flags;
@@ -3332,54 +3099,43 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
        if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
                return;
 
-       debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
-       debug_event(adapter->erp_dbf, 3, zfcp_get_busid_by_adapter(adapter), 8);
-
        read_lock_irqsave(&zfcp_data.config_lock, flags);
        if (adapter->nameserver_port)
-               zfcp_erp_port_access_changed(adapter->nameserver_port);
+               zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref);
        list_for_each_entry(port, &adapter->port_list_head, list)
                if (port != adapter->nameserver_port)
-                       zfcp_erp_port_access_changed(port);
+                       zfcp_erp_port_access_changed(port, id, ref);
        read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 }
 
-void
-zfcp_erp_port_access_changed(struct zfcp_port *port)
+void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, void *ref)
 {
        struct zfcp_adapter *adapter = port->adapter;
        struct zfcp_unit *unit;
 
-       debug_text_event(adapter->erp_dbf, 3, "p_access_recover");
-       debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
-
        if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
                              &port->status) &&
            !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
                              &port->status)) {
                if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
                        list_for_each_entry(unit, &port->unit_list_head, list)
-                               zfcp_erp_unit_access_changed(unit);
+                               zfcp_erp_unit_access_changed(unit, id, ref);
                return;
        }
 
        ZFCP_LOG_NORMAL("reopen of port 0x%016Lx on adapter %s "
                        "(due to ACT update)\n",
                        port->wwpn, zfcp_get_busid_by_adapter(adapter));
-       if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
+       if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref))
                ZFCP_LOG_NORMAL("failed reopen of port"
                                "(adapter %s, wwpn=0x%016Lx)\n",
                                zfcp_get_busid_by_adapter(adapter), port->wwpn);
 }
 
-void
-zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
+void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, void *ref)
 {
        struct zfcp_adapter *adapter = unit->port->adapter;
 
-       debug_text_event(adapter->erp_dbf, 3, "u_access_recover");
-       debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
-
        if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
                              &unit->status) &&
            !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
@@ -3390,7 +3146,7 @@ zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
                        " on adapter %s (due to ACT update)\n",
                        unit->fcp_lun, unit->port->wwpn,
                        zfcp_get_busid_by_adapter(adapter));
-       if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
+       if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref))
                ZFCP_LOG_NORMAL("failed reopen of unit (adapter %s, "
                                "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
                                zfcp_get_busid_by_adapter(adapter),
index 06b1079b7f3d8e53dbe0961e40a02b20df2cb5ba..6abf178fda5df2a4fc641215e381999eb1248238 100644 (file)
@@ -131,22 +131,25 @@ extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, int);
 extern struct fc_function_template zfcp_transport_functions;
 
 /******************************** ERP ****************************************/
-extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int);
-extern int  zfcp_erp_adapter_reopen(struct zfcp_adapter *, int);
-extern int  zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int);
-extern void zfcp_erp_adapter_failed(struct zfcp_adapter *);
-
-extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int);
-extern int  zfcp_erp_port_reopen(struct zfcp_port *, int);
-extern int  zfcp_erp_port_shutdown(struct zfcp_port *, int);
-extern int  zfcp_erp_port_forced_reopen(struct zfcp_port *, int);
-extern void zfcp_erp_port_failed(struct zfcp_port *);
-extern int  zfcp_erp_port_reopen_all(struct zfcp_adapter *, int);
-
-extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u32, int);
-extern int  zfcp_erp_unit_reopen(struct zfcp_unit *, int);
-extern int  zfcp_erp_unit_shutdown(struct zfcp_unit *, int);
-extern void zfcp_erp_unit_failed(struct zfcp_unit *);
+extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u8, void *,
+                                          u32, int);
+extern int  zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, u8, void *);
+extern int  zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, u8, void *);
+extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, u8, void *);
+
+extern void zfcp_erp_modify_port_status(struct zfcp_port *, u8, void *, u32,
+                                       int);
+extern int  zfcp_erp_port_reopen(struct zfcp_port *, int, u8, void *);
+extern int  zfcp_erp_port_shutdown(struct zfcp_port *, int, u8, void *);
+extern int  zfcp_erp_port_forced_reopen(struct zfcp_port *, int, u8, void *);
+extern void zfcp_erp_port_failed(struct zfcp_port *, u8, void *);
+extern int  zfcp_erp_port_reopen_all(struct zfcp_adapter *, int, u8, void *);
+
+extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u8, void *, u32,
+                                       int);
+extern int  zfcp_erp_unit_reopen(struct zfcp_unit *, int, u8, void *);
+extern int  zfcp_erp_unit_shutdown(struct zfcp_unit *, int, u8, void *);
+extern void zfcp_erp_unit_failed(struct zfcp_unit *, u8, void *);
 
 extern int  zfcp_erp_thread_setup(struct zfcp_adapter *);
 extern int  zfcp_erp_thread_kill(struct zfcp_adapter *);
@@ -155,15 +158,25 @@ extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
 
 extern int  zfcp_test_link(struct zfcp_port *);
 
-extern void zfcp_erp_port_boxed(struct zfcp_port *);
-extern void zfcp_erp_unit_boxed(struct zfcp_unit *);
-extern void zfcp_erp_port_access_denied(struct zfcp_port *);
-extern void zfcp_erp_unit_access_denied(struct zfcp_unit *);
-extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *);
-extern void zfcp_erp_port_access_changed(struct zfcp_port *);
-extern void zfcp_erp_unit_access_changed(struct zfcp_unit *);
+extern void zfcp_erp_port_boxed(struct zfcp_port *, u8 id, void *ref);
+extern void zfcp_erp_unit_boxed(struct zfcp_unit *, u8 id, void *ref);
+extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8 id, void *ref);
+extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8 id, void *ref);
+extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *);
+extern void zfcp_erp_port_access_changed(struct zfcp_port *, u8, void *);
+extern void zfcp_erp_unit_access_changed(struct zfcp_unit *, u8, void *);
 
 /******************************** AUX ****************************************/
+extern void zfcp_rec_dbf_event_thread(u8 id, struct zfcp_adapter *adapter,
+                                     int lock);
+extern void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *);
+extern void zfcp_rec_dbf_event_port(u8 id, void *ref, struct zfcp_port *port);
+extern void zfcp_rec_dbf_event_unit(u8 id, void *ref, struct zfcp_unit *unit);
+extern void zfcp_rec_dbf_event_trigger(u8 id, void *ref, u8 want, u8 need,
+                                      void *action, struct zfcp_adapter *,
+                                      struct zfcp_port *, struct zfcp_unit *);
+extern void zfcp_rec_dbf_event_action(u8 id, struct zfcp_erp_action *);
+
 extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *);
 extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *,
                                         struct fsf_status_read_buffer *);
index 0dff05840ee2e1ffcdb222cdb3805c01054fbd65..7c3f02816e95c35b8ed6005c9f0c7d7fa2f9fa21 100644 (file)
@@ -46,7 +46,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *);
 static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *);
 static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
 static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
-static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *,
+static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *, u8,
        struct fsf_link_down_info *);
 static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
 
@@ -284,37 +284,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                goto skip_protstatus;
        }
 
-       /* log additional information provided by FSF (if any) */
-       if (likely(qtcb->header.log_length)) {
-               /* do not trust them ;-) */
-               if (unlikely(qtcb->header.log_start >
-                            sizeof(struct fsf_qtcb))) {
-                       ZFCP_LOG_NORMAL
-                           ("bug: ULP (FSF logging) log data starts "
-                            "beyond end of packet header. Ignored. "
-                            "(start=%i, size=%li)\n",
-                            qtcb->header.log_start,
-                            sizeof(struct fsf_qtcb));
-                       goto forget_log;
-               }
-               if (unlikely((size_t) (qtcb->header.log_start +
-                                      qtcb->header.log_length) >
-                            sizeof(struct fsf_qtcb))) {
-                       ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
-                                       "beyond end of packet header. Ignored. "
-                                       "(start=%i, length=%i, size=%li)\n",
-                                       qtcb->header.log_start,
-                                       qtcb->header.log_length,
-                                       sizeof(struct fsf_qtcb));
-                       goto forget_log;
-               }
-               ZFCP_LOG_TRACE("ULP log data: \n");
-               ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
-                             (char *) qtcb + qtcb->header.log_start,
-                             qtcb->header.log_length);
-       }
- forget_log:
-
        /* evaluate FSF Protocol Status */
        switch (qtcb->prefix.prot_status) {
 
@@ -329,7 +298,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                zfcp_get_busid_by_adapter(adapter),
                                prot_status_qual->version_error.fsf_version,
                                ZFCP_QTCB_VERSION);
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 117, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -340,7 +309,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                qtcb->prefix.req_seq_no,
                                zfcp_get_busid_by_adapter(adapter),
                                prot_status_qual->sequence_error.exp_req_seq_no);
-               zfcp_erp_adapter_reopen(adapter, 0);
+               zfcp_erp_adapter_reopen(adapter, 0, 98, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
@@ -351,7 +320,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                "that used on adapter %s. "
                                "Stopping all operations on this adapter.\n",
                                zfcp_get_busid_by_adapter(adapter));
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 118, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -368,14 +337,15 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                *(unsigned long long*)
                                (&qtcb->bottom.support.req_handle),
                                        zfcp_get_busid_by_adapter(adapter));
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 78, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
        case FSF_PROT_LINK_DOWN:
-               zfcp_fsf_link_down_info_eval(adapter,
+               zfcp_fsf_link_down_info_eval(fsf_req, 37,
                                             &prot_status_qual->link_down_info);
-               zfcp_erp_adapter_reopen(adapter, 0);
+               /* FIXME: reopening adapter now? better wait for link up */
+               zfcp_erp_adapter_reopen(adapter, 0, 79, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -385,12 +355,13 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                              "Re-starting operations on this adapter.\n",
                              zfcp_get_busid_by_adapter(adapter));
                /* All ports should be marked as ready to run again */
-               zfcp_erp_modify_adapter_status(adapter,
+               zfcp_erp_modify_adapter_status(adapter, 28, NULL,
                                               ZFCP_STATUS_COMMON_RUNNING,
                                               ZFCP_SET);
                zfcp_erp_adapter_reopen(adapter,
                                        ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
-                                       | ZFCP_STATUS_COMMON_ERP_FAILED);
+                                       | ZFCP_STATUS_COMMON_ERP_FAILED,
+                                       99, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -400,7 +371,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                "Restarting all operations on this "
                                "adapter.\n",
                                zfcp_get_busid_by_adapter(adapter));
-               zfcp_erp_adapter_reopen(adapter, 0);
+               zfcp_erp_adapter_reopen(adapter, 0, 100, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
@@ -413,7 +384,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                                "(debug info 0x%x).\n",
                                zfcp_get_busid_by_adapter(adapter),
                                qtcb->prefix.prot_status);
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 119, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
        }
 
@@ -452,7 +423,7 @@ zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req)
                                "(debug info 0x%x).\n",
                                zfcp_get_busid_by_adapter(fsf_req->adapter),
                                fsf_req->qtcb->header.fsf_command);
-               zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
+               zfcp_erp_adapter_shutdown(fsf_req->adapter, 0, 120, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -506,7 +477,7 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
                                "problem on the adapter %s "
                                "Stopping all operations on this adapter. ",
                                zfcp_get_busid_by_adapter(fsf_req->adapter));
-               zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
+               zfcp_erp_adapter_shutdown(fsf_req->adapter, 0, 121, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        case FSF_SQ_ULP_PROGRAMMING_ERROR:
@@ -537,9 +508,11 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
  * zfcp_fsf_link_down_info_eval - evaluate link down information block
  */
 static void
-zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
+zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *fsf_req, u8 id,
                             struct fsf_link_down_info *link_down)
 {
+       struct zfcp_adapter *adapter = fsf_req->adapter;
+
        if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
                             &adapter->status))
                return;
@@ -630,7 +603,7 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
                                link_down->vendor_specific_code);
 
  out:
-       zfcp_erp_adapter_failed(adapter);
+       zfcp_erp_adapter_failed(adapter, id, fsf_req);
 }
 
 /*
@@ -824,19 +797,14 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
        switch (status_buffer->status_subtype) {
 
        case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT:
-               debug_text_event(adapter->erp_dbf, 3, "unsol_pc_phys:");
-               zfcp_erp_port_reopen(port, 0);
+               zfcp_erp_port_reopen(port, 0, 101, fsf_req);
                break;
 
        case FSF_STATUS_READ_SUB_ERROR_PORT:
-               debug_text_event(adapter->erp_dbf, 1, "unsol_pc_err:");
-               zfcp_erp_port_shutdown(port, 0);
+               zfcp_erp_port_shutdown(port, 0, 122, fsf_req);
                break;
 
        default:
-               debug_text_event(adapter->erp_dbf, 0, "unsol_unk_sub:");
-               debug_exception(adapter->erp_dbf, 0,
-                               &status_buffer->status_subtype, sizeof (u32));
                ZFCP_LOG_NORMAL("bug: Undefined status subtype received "
                                "for a reopen indication on port with "
                                "d_id 0x%06x on the adapter %s. "
@@ -928,7 +896,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
                case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
                        ZFCP_LOG_INFO("Physical link to adapter %s is down\n",
                                      zfcp_get_busid_by_adapter(adapter));
-                       zfcp_fsf_link_down_info_eval(adapter,
+                       zfcp_fsf_link_down_info_eval(fsf_req, 38,
                                (struct fsf_link_down_info *)
                                &status_buffer->payload);
                        break;
@@ -936,7 +904,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
                        ZFCP_LOG_INFO("Local link to adapter %s is down "
                                      "due to failed FDISC login\n",
                                      zfcp_get_busid_by_adapter(adapter));
-                       zfcp_fsf_link_down_info_eval(adapter,
+                       zfcp_fsf_link_down_info_eval(fsf_req, 39,
                                (struct fsf_link_down_info *)
                                &status_buffer->payload);
                        break;
@@ -944,13 +912,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
                        ZFCP_LOG_INFO("Local link to adapter %s is down "
                                      "due to firmware update on adapter\n",
                                      zfcp_get_busid_by_adapter(adapter));
-                       zfcp_fsf_link_down_info_eval(adapter, NULL);
+                       zfcp_fsf_link_down_info_eval(fsf_req, 40, NULL);
                        break;
                default:
                        ZFCP_LOG_INFO("Local link to adapter %s is down "
                                      "due to unknown reason\n",
                                      zfcp_get_busid_by_adapter(adapter));
-                       zfcp_fsf_link_down_info_eval(adapter, NULL);
+                       zfcp_fsf_link_down_info_eval(fsf_req, 41, NULL);
                };
                break;
 
@@ -959,12 +927,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
                                "Restarting operations on this adapter\n",
                                zfcp_get_busid_by_adapter(adapter));
                /* All ports should be marked as ready to run again */
-               zfcp_erp_modify_adapter_status(adapter,
+               zfcp_erp_modify_adapter_status(adapter, 30, NULL,
                                               ZFCP_STATUS_COMMON_RUNNING,
                                               ZFCP_SET);
                zfcp_erp_adapter_reopen(adapter,
                                        ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
-                                       | ZFCP_STATUS_COMMON_ERP_FAILED);
+                                       | ZFCP_STATUS_COMMON_ERP_FAILED,
+                                       102, fsf_req);
                break;
 
        case FSF_STATUS_READ_NOTIFICATION_LOST:
@@ -998,13 +967,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
 
                if (status_buffer->status_subtype &
                    FSF_STATUS_READ_SUB_ACT_UPDATED)
-                       zfcp_erp_adapter_access_changed(adapter);
+                       zfcp_erp_adapter_access_changed(adapter, 135, fsf_req);
                break;
 
        case FSF_STATUS_READ_CFDC_UPDATED:
                ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
                              zfcp_get_busid_by_adapter(adapter));
-               zfcp_erp_adapter_access_changed(adapter);
+               zfcp_erp_adapter_access_changed(adapter, 136, fsf_req);
                break;
 
        case FSF_STATUS_READ_CFDC_HARDENED:
@@ -1025,7 +994,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
                break;
 
        case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
-               debug_text_event(adapter->erp_dbf, 2, "unsol_features:");
                ZFCP_LOG_INFO("List of supported features on adapter %s has "
                              "been changed from 0x%08X to 0x%08X\n",
                              zfcp_get_busid_by_adapter(adapter),
@@ -1073,7 +1041,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
                        ZFCP_LOG_INFO("restart adapter %s due to status read "
                                      "buffer shortage\n",
                                      zfcp_get_busid_by_adapter(adapter));
-                       zfcp_erp_adapter_reopen(adapter, 0);
+                       zfcp_erp_adapter_reopen(adapter, 0, 103, fsf_req);
                }
        }
  out:
@@ -1174,8 +1142,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
 
        case FSF_PORT_HANDLE_NOT_VALID:
                if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) {
-                       debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
-                                        "fsf_s_phand_nv0");
                        /*
                         * In this case a command that was sent prior to a port
                         * reopen was aborted (handles are different). This is
@@ -1194,17 +1160,14 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
                                      fsf_status_qual,
                                      sizeof (union fsf_status_qual));
                        /* Let's hope this sorts out the mess */
-                       debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_s_phand_nv1");
-                       zfcp_erp_adapter_reopen(unit->port->adapter, 0);
+                       zfcp_erp_adapter_reopen(unit->port->adapter, 0, 104,
+                                               new_fsf_req);
                        new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                }
                break;
 
        case FSF_LUN_HANDLE_NOT_VALID:
                if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) {
-                       debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
-                                        "fsf_s_lhand_nv0");
                        /*
                         * In this case a command that was sent prior to a unit
                         * reopen was aborted (handles are different).
@@ -1226,17 +1189,13 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
                                      fsf_status_qual,
                                      sizeof (union fsf_status_qual));
                        /* Let's hope this sorts out the mess */
-                       debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_s_lhand_nv1");
-                       zfcp_erp_port_reopen(unit->port, 0);
+                       zfcp_erp_port_reopen(unit->port, 0, 105, new_fsf_req);
                        new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                }
                break;
 
        case FSF_FCP_COMMAND_DOES_NOT_EXIST:
                retval = 0;
-               debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
-                                "fsf_s_no_exist");
                new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
                break;
 
@@ -1244,9 +1203,7 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
                ZFCP_LOG_INFO("Remote port 0x%016Lx on adapter %s needs to "
                              "be reopened\n", unit->port->wwpn,
                              zfcp_get_busid_by_unit(unit));
-               debug_text_event(new_fsf_req->adapter->erp_dbf, 2,
-                                "fsf_s_pboxed");
-               zfcp_erp_port_boxed(unit->port);
+               zfcp_erp_port_boxed(unit->port, 47, new_fsf_req);
                new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
                    | ZFCP_STATUS_FSFREQ_RETRY;
                break;
@@ -1257,8 +1214,7 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
                         "to be reopened\n",
                         unit->fcp_lun, unit->port->wwpn,
                         zfcp_get_busid_by_unit(unit));
-                debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
-               zfcp_erp_unit_boxed(unit);
+               zfcp_erp_unit_boxed(unit, 48, new_fsf_req);
                 new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
                         | ZFCP_STATUS_FSFREQ_RETRY;
                 break;
@@ -1266,26 +1222,17 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (new_fsf_req->qtcb->header.fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ltest");
                        zfcp_test_link(unit->port);
                        new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        /* SCSI stack will escalate */
-                       debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ulp");
                        new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                default:
                        ZFCP_LOG_NORMAL
                            ("bug: Wrong status qualifier 0x%x arrived.\n",
                             new_fsf_req->qtcb->header.fsf_status_qual.word[0]);
-                       debug_text_event(new_fsf_req->adapter->erp_dbf, 0,
-                                        "fsf_sq_inval:");
-                       debug_exception(new_fsf_req->adapter->erp_dbf, 0,
-                                       &new_fsf_req->qtcb->header.
-                                       fsf_status_qual.word[0], sizeof (u32));
                        break;
                }
                break;
@@ -1299,11 +1246,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
                ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
                                "(debug info 0x%x)\n",
                                new_fsf_req->qtcb->header.fsf_status);
-               debug_text_event(new_fsf_req->adapter->erp_dbf, 0,
-                                "fsf_s_inval:");
-               debug_exception(new_fsf_req->adapter->erp_dbf, 0,
-                               &new_fsf_req->qtcb->header.fsf_status,
-                               sizeof (u32));
                break;
        }
  skip_fsfstatus:
@@ -1506,8 +1448,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
                              zfcp_get_busid_by_port(port),
                              ZFCP_FC_SERVICE_CLASS_DEFAULT);
                /* stop operation for this adapter */
-               debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 123, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -1515,13 +1456,11 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
                 switch (header->fsf_status_qual.word[0]){
                 case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
                        /* reopening link to port */
-                       debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
                        zfcp_test_link(port);
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                 case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        /* ERP strategy will escalate */
-                       debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                 default:
@@ -1549,8 +1488,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
                                break;
                        }
                }
-               debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
-               zfcp_erp_port_access_denied(port);
+               zfcp_erp_port_access_denied(port, 55, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -1562,7 +1500,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
                              (char *) &header->fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(adapter->erp_dbf, 1, "fsf_s_gcom_rej");
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -1575,8 +1512,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
                              (char *) &header->fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv");
-               zfcp_erp_adapter_reopen(adapter, 0);
+               zfcp_erp_adapter_reopen(adapter, 0, 106, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -1584,8 +1520,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_INFO("port needs to be reopened "
                              "(adapter %s, port d_id=0x%06x)\n",
                              zfcp_get_busid_by_port(port), port->d_id);
-               debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
-               zfcp_erp_port_boxed(port);
+               zfcp_erp_port_boxed(port, 49, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
                    | ZFCP_STATUS_FSFREQ_RETRY;
                break;
@@ -1624,9 +1559,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
        default:
                ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
                                "(debug info 0x%x)\n", header->fsf_status);
-               debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:");
-               debug_exception(adapter->erp_dbf, 0,
-                               &header->fsf_status_qual.word[0], sizeof (u32));
                break;
        }
 
@@ -1810,21 +1742,18 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
                              zfcp_get_busid_by_adapter(adapter),
                              ZFCP_FC_SERVICE_CLASS_DEFAULT);
                /* stop operation for this adapter */
-               debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 124, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (header->fsf_status_qual.word[0]){
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
                        if (port && (send_els->ls_code != ZFCP_LS_ADISC))
                                zfcp_test_link(port);
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
-                       debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        retval =
                          zfcp_handle_els_rjt(header->fsf_status_qual.word[1],
@@ -1832,7 +1761,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
                                              &header->fsf_status_qual.word[2]);
                        break;
                case FSF_SQ_RETRY_IF_POSSIBLE:
-                       debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry");
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                default:
@@ -1909,9 +1837,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
                                break;
                        }
                }
-               debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
                if (port != NULL)
-                       zfcp_erp_port_access_denied(port);
+                       zfcp_erp_port_access_denied(port, 56, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -1921,9 +1848,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
                        "(adapter: %s, fsf_status=0x%08x)\n",
                        zfcp_get_busid_by_adapter(adapter),
                        header->fsf_status);
-               debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval");
-               debug_exception(adapter->erp_dbf, 0,
-                       &header->fsf_status_qual.word[0], sizeof(u32));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        }
@@ -2132,8 +2056,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
                                "versions in comparison to this device "
                                "driver (try updated device driver)\n",
                                zfcp_get_busid_by_adapter(adapter));
-               debug_text_event(adapter->erp_dbf, 0, "low_qtcb_ver");
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 125, fsf_req);
                return -EIO;
        }
        if (ZFCP_QTCB_VERSION > bottom->high_qtcb_version) {
@@ -2142,8 +2065,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
                                "versions than this device driver uses"
                                "(consider a microcode upgrade)\n",
                                zfcp_get_busid_by_adapter(adapter));
-               debug_text_event(adapter->erp_dbf, 0, "high_qtcb_ver");
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 126, fsf_req);
                return -EIO;
        }
        return 0;
@@ -2183,17 +2105,13 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                                        adapter->peer_wwnn,
                                        adapter->peer_wwpn,
                                        adapter->peer_d_id);
-                       debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                       "top-p-to-p");
                        break;
                case FC_PORTTYPE_NLPORT:
                        ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
                                        "topology detected at adapter %s "
                                        "unsupported, shutting down adapter\n",
                                        zfcp_get_busid_by_adapter(adapter));
-                       debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                        "top-al");
-                       zfcp_erp_adapter_shutdown(adapter, 0);
+                       zfcp_erp_adapter_shutdown(adapter, 0, 127, fsf_req);
                        return -EIO;
                case FC_PORTTYPE_NPORT:
                        ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
@@ -2208,9 +2126,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                                        "of a type known to the zfcp "
                                        "driver, shutting down adapter\n",
                                        zfcp_get_busid_by_adapter(adapter));
-                       debug_text_exception(fsf_req->adapter->erp_dbf, 0,
-                                            "unknown-topo");
-                       zfcp_erp_adapter_shutdown(adapter, 0);
+                       zfcp_erp_adapter_shutdown(adapter, 0, 128, fsf_req);
                        return -EIO;
                }
                bottom = &qtcb->bottom.config;
@@ -2222,33 +2138,24 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                                        bottom->max_qtcb_size,
                                        zfcp_get_busid_by_adapter(adapter),
                                        sizeof(struct fsf_qtcb));
-                       debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                        "qtcb-size");
-                       debug_event(fsf_req->adapter->erp_dbf, 0,
-                                   &bottom->max_qtcb_size, sizeof (u32));
-                       zfcp_erp_adapter_shutdown(adapter, 0);
+                       zfcp_erp_adapter_shutdown(adapter, 0, 129, fsf_req);
                        return -EIO;
                }
                atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
                                &adapter->status);
                break;
        case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
-               debug_text_event(adapter->erp_dbf, 0, "xchg-inco");
-
                if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0))
                        return -EIO;
 
                atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
                                &adapter->status);
 
-               zfcp_fsf_link_down_info_eval(adapter,
+               zfcp_fsf_link_down_info_eval(fsf_req, 42,
                        &qtcb->header.fsf_status_qual.link_down_info);
                break;
        default:
-               debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
-               debug_event(fsf_req->adapter->erp_dbf, 0,
-                           &fsf_req->qtcb->header.fsf_status, sizeof(u32));
-               zfcp_erp_adapter_shutdown(adapter, 0);
+               zfcp_erp_adapter_shutdown(adapter, 0, 130, fsf_req);
                return -EIO;
        }
        return 0;
@@ -2424,13 +2331,9 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
        case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
                zfcp_fsf_exchange_port_evaluate(fsf_req, 0);
                atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
-               zfcp_fsf_link_down_info_eval(adapter,
+               zfcp_fsf_link_down_info_eval(fsf_req, 43,
                        &qtcb->header.fsf_status_qual.link_down_info);
                 break;
-        default:
-               debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
-               debug_event(adapter->erp_dbf, 0,
-                           &fsf_req->qtcb->header.fsf_status, sizeof(u32));
        }
 }
 
@@ -2528,8 +2431,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_NORMAL("bug: remote port 0x%016Lx on adapter %s "
                                "is already open.\n",
                                port->wwpn, zfcp_get_busid_by_port(port));
-               debug_text_exception(fsf_req->adapter->erp_dbf, 0,
-                                    "fsf_s_popen");
                /*
                 * This is a bug, however operation should continue normally
                 * if it is simply ignored
@@ -2553,8 +2454,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
                                break;
                        }
                }
-               debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
-               zfcp_erp_port_access_denied(port);
+               zfcp_erp_port_access_denied(port, 57, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -2563,24 +2463,18 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
                              "The remote port 0x%016Lx on adapter %s "
                              "could not be opened. Disabling it.\n",
                              port->wwpn, zfcp_get_busid_by_port(port));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                "fsf_s_max_ports");
-               zfcp_erp_port_failed(port);
+               zfcp_erp_port_failed(port, 31, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (header->fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ltest");
                        /* ERP strategy will escalate */
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        /* ERP strategy will escalate */
-                       debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ulp");
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                case FSF_SQ_NO_RETRY_POSSIBLE:
@@ -2589,21 +2483,13 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
                                        "Disabling it.\n",
                                        port->wwpn,
                                        zfcp_get_busid_by_port(port));
-                       debug_text_exception(fsf_req->adapter->erp_dbf, 0,
-                                            "fsf_sq_no_retry");
-                       zfcp_erp_port_failed(port);
+                       zfcp_erp_port_failed(port, 32, fsf_req);
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                default:
                        ZFCP_LOG_NORMAL
                            ("bug: Wrong status qualifier 0x%x arrived.\n",
                             header->fsf_status_qual.word[0]);
-                       debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                        "fsf_sq_inval:");
-                       debug_exception(
-                               fsf_req->adapter->erp_dbf, 0,
-                               &header->fsf_status_qual.word[0],
-                               sizeof (u32));
                        break;
                }
                break;
@@ -2646,17 +2532,12 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
                                        "warning: insufficient length of "
                                        "PLOGI payload (%i)\n",
                                        fsf_req->qtcb->bottom.support.els1_length);
-                               debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                                "fsf_s_short_plogi:");
                                /* skip sanity check and assume wwpn is ok */
                        } else {
                                if (plogi->serv_param.wwpn != port->wwpn) {
                                        ZFCP_LOG_INFO("warning: d_id of port "
                                                      "0x%016Lx changed during "
                                                      "open\n", port->wwpn);
-                                       debug_text_event(
-                                               fsf_req->adapter->erp_dbf, 0,
-                                               "fsf_s_did_change:");
                                        atomic_clear_mask(
                                                ZFCP_STATUS_PORT_DID_DID,
                                                &port->status);
@@ -2681,9 +2562,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
                                "(debug info 0x%x)\n",
                                header->fsf_status);
-               debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
-               debug_exception(fsf_req->adapter->erp_dbf, 0,
-                               &header->fsf_status, sizeof (u32));
                break;
        }
 
@@ -2787,9 +2665,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                              (char *) &fsf_req->qtcb->header.fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                "fsf_s_phand_nv");
-               zfcp_erp_adapter_reopen(port->adapter, 0);
+               zfcp_erp_adapter_reopen(port->adapter, 0, 107, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -2804,7 +2680,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_TRACE("remote port 0x016%Lx on adapter %s closed, "
                               "port handle 0x%x\n", port->wwpn,
                               zfcp_get_busid_by_port(port), port->handle);
-               zfcp_erp_modify_port_status(port,
+               zfcp_erp_modify_port_status(port, 33, fsf_req,
                                            ZFCP_STATUS_COMMON_OPEN,
                                            ZFCP_CLEAR);
                retval = 0;
@@ -2814,10 +2690,6 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
                                "(debug info 0x%x)\n",
                                fsf_req->qtcb->header.fsf_status);
-               debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
-               debug_exception(fsf_req->adapter->erp_dbf, 0,
-                               &fsf_req->qtcb->header.fsf_status,
-                               sizeof (u32));
                break;
        }
 
@@ -2930,9 +2802,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                              (char *) &header->fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                "fsf_s_phand_nv");
-               zfcp_erp_adapter_reopen(port->adapter, 0);
+               zfcp_erp_adapter_reopen(port->adapter, 0, 108, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -2953,8 +2823,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
                                break;
                        }
                }
-               debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
-               zfcp_erp_port_access_denied(port);
+               zfcp_erp_port_access_denied(port, 58, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -2964,35 +2833,32 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
                               "to close it physically.\n",
                               port->wwpn,
                               zfcp_get_busid_by_port(port));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_pboxed");
-               zfcp_erp_port_boxed(port);
+               zfcp_erp_port_boxed(port, 50, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
                        ZFCP_STATUS_FSFREQ_RETRY;
+
+               /* can't use generic zfcp_erp_modify_port_status because
+                * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
+               atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
+               list_for_each_entry(unit, &port->unit_list_head, list)
+                       atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
+                                         &unit->status);
                break;
 
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (header->fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ltest");
                        /* This will now be escalated by ERP */
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        /* ERP strategy will escalate */
-                       debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ulp");
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                default:
                        ZFCP_LOG_NORMAL
                            ("bug: Wrong status qualifier 0x%x arrived.\n",
                             header->fsf_status_qual.word[0]);
-                       debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                        "fsf_sq_inval:");
-                       debug_exception(
-                               fsf_req->adapter->erp_dbf, 0,
-                               &header->fsf_status_qual.word[0], sizeof (u32));
                        break;
                }
                break;
@@ -3015,9 +2881,6 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
                                "(debug info 0x%x)\n",
                                header->fsf_status);
-               debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
-               debug_exception(fsf_req->adapter->erp_dbf, 0,
-                               &header->fsf_status, sizeof (u32));
                break;
        }
 
@@ -3149,8 +3012,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                              (char *) &header->fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(adapter->erp_dbf, 1, "fsf_s_ph_nv");
-               zfcp_erp_adapter_reopen(unit->port->adapter, 0);
+               zfcp_erp_adapter_reopen(unit->port->adapter, 0, 109, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3159,8 +3021,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                                "remote port 0x%016Lx on adapter %s twice.\n",
                                unit->fcp_lun,
                                unit->port->wwpn, zfcp_get_busid_by_unit(unit));
-               debug_text_exception(adapter->erp_dbf, 0,
-                                    "fsf_s_uopen");
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3182,8 +3042,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                                break;
                        }
                }
-               debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
-               zfcp_erp_unit_access_denied(unit);
+               zfcp_erp_unit_access_denied(unit, 59, fsf_req);
                atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
                 atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -3193,8 +3052,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
                               "needs to be reopened\n",
                               unit->port->wwpn, zfcp_get_busid_by_unit(unit));
-               debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
-               zfcp_erp_port_boxed(unit->port);
+               zfcp_erp_port_boxed(unit->port, 51, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
                        ZFCP_STATUS_FSFREQ_RETRY;
                break;
@@ -3234,9 +3092,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                              (char *) &header->fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(adapter->erp_dbf, 2,
-                                "fsf_s_l_sh_vio");
-               zfcp_erp_unit_access_denied(unit);
+               zfcp_erp_unit_access_denied(unit, 60, fsf_req);
                atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
                atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -3250,9 +3106,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                              unit->fcp_lun,
                              unit->port->wwpn,
                              zfcp_get_busid_by_unit(unit));
-               debug_text_event(adapter->erp_dbf, 1,
-                                "fsf_s_max_units");
-               zfcp_erp_unit_failed(unit);
+               zfcp_erp_unit_failed(unit, 34, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3260,26 +3114,17 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                switch (header->fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
                        /* Re-establish link to port */
-                       debug_text_event(adapter->erp_dbf, 1,
-                                        "fsf_sq_ltest");
                        zfcp_test_link(unit->port);
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        /* ERP strategy will escalate */
-                       debug_text_event(adapter->erp_dbf, 1,
-                                        "fsf_sq_ulp");
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                default:
                        ZFCP_LOG_NORMAL
                            ("bug: Wrong status qualifier 0x%x arrived.\n",
                             header->fsf_status_qual.word[0]);
-                       debug_text_event(adapter->erp_dbf, 0,
-                                        "fsf_sq_inval:");
-                       debug_exception(adapter->erp_dbf, 0,
-                                       &header->fsf_status_qual.word[0],
-                               sizeof (u32));
                }
                break;
 
@@ -3331,15 +3176,15 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                        if (exclusive && !readwrite) {
                                ZFCP_LOG_NORMAL("exclusive access of read-only "
                                                "unit not supported\n");
-                               zfcp_erp_unit_failed(unit);
+                               zfcp_erp_unit_failed(unit, 35, fsf_req);
                                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-                               zfcp_erp_unit_shutdown(unit, 0);
+                               zfcp_erp_unit_shutdown(unit, 0, 80, fsf_req);
                        } else if (!exclusive && readwrite) {
                                ZFCP_LOG_NORMAL("shared access of read-write "
                                                "unit not supported\n");
-                               zfcp_erp_unit_failed(unit);
+                               zfcp_erp_unit_failed(unit, 36, fsf_req);
                                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-                               zfcp_erp_unit_shutdown(unit, 0);
+                               zfcp_erp_unit_shutdown(unit, 0, 81, fsf_req);
                        }
                }
 
@@ -3350,9 +3195,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
                                "(debug info 0x%x)\n",
                                header->fsf_status);
-               debug_text_event(adapter->erp_dbf, 0, "fsf_s_inval:");
-               debug_exception(adapter->erp_dbf, 0,
-                               &header->fsf_status, sizeof (u32));
                break;
        }
 
@@ -3465,9 +3307,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                              (char *) &fsf_req->qtcb->header.fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                "fsf_s_phand_nv");
-               zfcp_erp_adapter_reopen(unit->port->adapter, 0);
+               zfcp_erp_adapter_reopen(unit->port->adapter, 0, 110, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3483,9 +3323,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                              (char *) &fsf_req->qtcb->header.fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                "fsf_s_lhand_nv");
-               zfcp_erp_port_reopen(unit->port, 0);
+               zfcp_erp_port_reopen(unit->port, 0, 111, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3494,8 +3332,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
                               "needs to be reopened\n",
                               unit->port->wwpn,
                               zfcp_get_busid_by_unit(unit));
-               debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
-               zfcp_erp_port_boxed(unit->port);
+               zfcp_erp_port_boxed(unit->port, 52, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
                        ZFCP_STATUS_FSFREQ_RETRY;
                break;
@@ -3504,27 +3341,17 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
                switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
                        /* re-establish link to port */
-                       debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ltest");
                        zfcp_test_link(unit->port);
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        /* ERP strategy will escalate */
-                       debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ulp");
                        fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                        break;
                default:
                        ZFCP_LOG_NORMAL
                            ("bug: Wrong status qualifier 0x%x arrived.\n",
                             fsf_req->qtcb->header.fsf_status_qual.word[0]);
-                       debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                        "fsf_sq_inval:");
-                       debug_exception(
-                               fsf_req->adapter->erp_dbf, 0,
-                               &fsf_req->qtcb->header.fsf_status_qual.word[0],
-                               sizeof (u32));
                        break;
                }
                break;
@@ -3545,10 +3372,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
                                "(debug info 0x%x)\n",
                                fsf_req->qtcb->header.fsf_status);
-               debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
-               debug_exception(fsf_req->adapter->erp_dbf, 0,
-                               &fsf_req->qtcb->header.fsf_status,
-                               sizeof (u32));
                break;
        }
 
@@ -3703,7 +3526,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
                                        zfcp_get_busid_by_unit(unit),
                                        unit->port->wwpn,
                                        unit->fcp_lun);
-                       zfcp_erp_unit_shutdown(unit, 0);
+                       zfcp_erp_unit_shutdown(unit, 0, 131, fsf_req);
                        retval = -EINVAL;
                }
                goto no_fit;
@@ -3739,8 +3562,8 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
  send_failed:
  no_fit:
  failed_scsi_cmnd:
- unit_blocked:
        zfcp_unit_put(unit);
+ unit_blocked:
        zfcp_fsf_req_free(fsf_req);
        fsf_req = NULL;
        scsi_cmnd->host_scribble = NULL;
@@ -3861,9 +3684,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                              (char *) &header->fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                "fsf_s_phand_nv");
-               zfcp_erp_adapter_reopen(unit->port->adapter, 0);
+               zfcp_erp_adapter_reopen(unit->port->adapter, 0, 112, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3879,9 +3700,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
                              (char *) &header->fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                "fsf_s_uhand_nv");
-               zfcp_erp_port_reopen(unit->port, 0);
+               zfcp_erp_port_reopen(unit->port, 0, 113, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3897,9 +3716,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
                              (char *) &header->fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                "fsf_s_hand_mis");
-               zfcp_erp_adapter_reopen(unit->port->adapter, 0);
+               zfcp_erp_adapter_reopen(unit->port->adapter, 0, 114, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3909,9 +3726,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                              zfcp_get_busid_by_unit(unit),
                              ZFCP_FC_SERVICE_CLASS_DEFAULT);
                /* stop operation for this adapter */
-               debug_text_exception(fsf_req->adapter->erp_dbf, 0,
-                                    "fsf_s_class_nsup");
-               zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
+               zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 132, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3927,9 +3742,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
                              (char *) &header->fsf_status_qual,
                              sizeof (union fsf_status_qual));
-               debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                "fsf_s_fcp_lun_nv");
-               zfcp_erp_port_reopen(unit->port, 0);
+               zfcp_erp_port_reopen(unit->port, 0, 115, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3951,8 +3764,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                                break;
                        }
                }
-               debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
-               zfcp_erp_unit_access_denied(unit);
+               zfcp_erp_unit_access_denied(unit, 61, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3965,9 +3777,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                              zfcp_get_busid_by_unit(unit),
                              fsf_req->qtcb->bottom.io.data_direction);
                /* stop operation for this adapter */
-               debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                "fsf_s_dir_ind_nv");
-               zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
+               zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 133, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3980,9 +3790,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                     zfcp_get_busid_by_unit(unit),
                     fsf_req->qtcb->bottom.io.fcp_cmnd_length);
                /* stop operation for this adapter */
-               debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                "fsf_s_cmd_len_nv");
-               zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
+               zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 134, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
 
@@ -3990,8 +3798,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
                               "needs to be reopened\n",
                               unit->port->wwpn, zfcp_get_busid_by_unit(unit));
-               debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
-               zfcp_erp_port_boxed(unit->port);
+               zfcp_erp_port_boxed(unit->port, 53, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
                        ZFCP_STATUS_FSFREQ_RETRY;
                break;
@@ -4001,8 +3808,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                                "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
                                zfcp_get_busid_by_unit(unit),
                                unit->port->wwpn, unit->fcp_lun);
-               debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
-               zfcp_erp_unit_boxed(unit);
+               zfcp_erp_unit_boxed(unit, 54, fsf_req);
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
                        | ZFCP_STATUS_FSFREQ_RETRY;
                break;
@@ -4011,25 +3817,16 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
                switch (header->fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
                        /* re-establish link to port */
-                       debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ltest");
                        zfcp_test_link(unit->port);
                        break;
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        /* FIXME(hw) need proper specs for proper action */
                        /* let scsi stack deal with retries and escalation */
-                       debug_text_event(fsf_req->adapter->erp_dbf, 1,
-                                        "fsf_sq_ulp");
                        break;
                default:
                        ZFCP_LOG_NORMAL
                            ("Unknown status qualifier 0x%x arrived.\n",
                             header->fsf_status_qual.word[0]);
-                       debug_text_event(fsf_req->adapter->erp_dbf, 0,
-                                        "fsf_sq_inval:");
-                       debug_exception(fsf_req->adapter->erp_dbf, 0,
-                                       &header->fsf_status_qual.word[0],
-                                       sizeof(u32));
                        break;
                }
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -4040,12 +3837,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
 
        case FSF_FCP_RSP_AVAILABLE:
                break;
-
-       default:
-               debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
-               debug_exception(fsf_req->adapter->erp_dbf, 0,
-                               &header->fsf_status, sizeof(u32));
-               break;
        }
 
  skip_fsfstatus:
@@ -4625,9 +4416,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
                        "was presented on the adapter %s\n",
                        header->fsf_status,
                        zfcp_get_busid_by_adapter(adapter));
-               debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval");
-               debug_exception(fsf_req->adapter->erp_dbf, 0,
-                       &header->fsf_status_qual.word[0], sizeof(u32));
                fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                retval = -EINVAL;
                break;
@@ -4817,7 +4605,6 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
        volatile struct qdio_buffer_element *sbale;
        int inc_seq_no;
        int new_distance_from_int;
-       u64 dbg_tmp[2];
        int retval = 0;
 
        adapter = fsf_req->adapter;
@@ -4867,10 +4654,6 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
                         QDIO_FLAG_SYNC_OUTPUT,
                         0, fsf_req->sbal_first, fsf_req->sbal_number, NULL);
 
-       dbg_tmp[0] = (unsigned long) sbale[0].addr;
-       dbg_tmp[1] = (u64) retval;
-       debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
-
        if (unlikely(retval)) {
                /* Queues are down..... */
                retval = -EIO;
@@ -4885,7 +4668,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
                req_queue->free_index -= fsf_req->sbal_number;
                req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q;
                req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */
-               zfcp_erp_adapter_reopen(adapter, 0);
+               zfcp_erp_adapter_reopen(adapter, 0, 116, fsf_req);
        } else {
                req_queue->distance_from_int = new_distance_from_int;
                /*
index 22fdc17e0d0e82aae92cbb1bdccbee6ee18f5edf..8ca5f074c68734ba07a11229087a390c49e8a2f3 100644 (file)
@@ -175,8 +175,9 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
                 * which is set again in case we have missed by a mile.
                 */
                zfcp_erp_adapter_reopen(adapter,
-                                      ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
-                                      ZFCP_STATUS_COMMON_ERP_FAILED);
+                                       ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
+                                       ZFCP_STATUS_COMMON_ERP_FAILED, 140,
+                                       NULL);
        }
        return retval;
 }
@@ -239,8 +240,6 @@ static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
        struct zfcp_fsf_req *fsf_req;
        unsigned long flags;
 
-       debug_long_event(adapter->erp_dbf, 4, req_id);
-
        spin_lock_irqsave(&adapter->req_list_lock, flags);
        fsf_req = zfcp_reqlist_find(adapter, req_id);
 
index b9daf5c058628720b82c03797ed323878d541a48..f81850624eedc5b5ca0e33119275e4964acaaebb 100644 (file)
@@ -31,6 +31,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *,
                                  void (*done) (struct scsi_cmnd *));
 static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *);
 static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *);
+static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *);
 static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
 static int zfcp_task_management_function(struct zfcp_unit *, u8,
                                         struct scsi_cmnd *);
@@ -51,6 +52,7 @@ struct zfcp_data zfcp_data = {
                .queuecommand           = zfcp_scsi_queuecommand,
                .eh_abort_handler       = zfcp_scsi_eh_abort_handler,
                .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
+               .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
                .eh_host_reset_handler  = zfcp_scsi_eh_host_reset_handler,
                .can_queue              = 4096,
                .this_id                = -1,
@@ -179,11 +181,10 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
        struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
 
        if (unit) {
-               zfcp_erp_wait(unit->port->adapter);
                atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
                sdpnt->hostdata = NULL;
                unit->device = NULL;
-               zfcp_erp_unit_failed(unit);
+               zfcp_erp_unit_failed(unit, 12, NULL);
                zfcp_unit_put(unit);
        } else
                ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at "
@@ -442,58 +443,32 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        return retval;
 }
 
-static int
-zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
+static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
 {
        int retval;
-       struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
+       struct zfcp_unit *unit = scpnt->device->hostdata;
 
        if (!unit) {
-               ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
-               retval = SUCCESS;
-               goto out;
+               WARN_ON(1);
+               return SUCCESS;
        }
-       ZFCP_LOG_NORMAL("resetting unit 0x%016Lx on port 0x%016Lx, adapter %s\n",
-                       unit->fcp_lun, unit->port->wwpn,
-                       zfcp_get_busid_by_adapter(unit->port->adapter));
+       retval = zfcp_task_management_function(unit,
+                                              FCP_LOGICAL_UNIT_RESET,
+                                              scpnt);
+       return retval ? FAILED : SUCCESS;
+}
 
-       /*
-        * If we do not know whether the unit supports 'logical unit reset'
-        * then try 'logical unit reset' and proceed with 'target reset'
-        * if 'logical unit reset' fails.
-        * If the unit is known not to support 'logical unit reset' then
-        * skip 'logical unit reset' and try 'target reset' immediately.
-        */
-       if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,
-                             &unit->status)) {
-               retval = zfcp_task_management_function(unit,
-                                                      FCP_LOGICAL_UNIT_RESET,
-                                                      scpnt);
-               if (retval) {
-                       ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit);
-                       if (retval == -ENOTSUPP)
-                               atomic_set_mask
-                                   (ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,
-                                    &unit->status);
-                       /* fall through and try 'target reset' next */
-               } else {
-                       ZFCP_LOG_DEBUG("unit reset succeeded (unit=%p)\n",
-                                      unit);
-                       /* avoid 'target reset' */
-                       retval = SUCCESS;
-                       goto out;
-               }
+static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
+{
+       int retval;
+       struct zfcp_unit *unit = scpnt->device->hostdata;
+
+       if (!unit) {
+               WARN_ON(1);
+               return SUCCESS;
        }
        retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt);
-       if (retval) {
-               ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit);
-               retval = FAILED;
-       } else {
-               ZFCP_LOG_DEBUG("target reset succeeded (unit=%p)\n", unit);
-               retval = SUCCESS;
-       }
- out:
-       return retval;
+       return retval ? FAILED : SUCCESS;
 }
 
 static int
@@ -553,7 +528,7 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
                unit->fcp_lun, unit->port->wwpn,
                zfcp_get_busid_by_adapter(unit->port->adapter));
 
-       zfcp_erp_adapter_reopen(adapter, 0);
+       zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt);
        zfcp_erp_wait(adapter);
 
        return SUCCESS;
index 705c6d4428f3d25a0292f93cc1479e2b17dbd16d..ccbba4dd3a77aabfcb7a3c5ee8d89c98289501e6 100644 (file)
@@ -89,7 +89,7 @@ zfcp_sysfs_port_add_store(struct device *dev, struct device_attribute *attr, con
 
        retval = 0;
 
-       zfcp_erp_port_reopen(port, 0);
+       zfcp_erp_port_reopen(port, 0, 91, NULL);
        zfcp_erp_wait(port->adapter);
        zfcp_port_put(port);
  out:
@@ -147,7 +147,7 @@ zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr,
                goto out;
        }
 
-       zfcp_erp_port_shutdown(port, 0);
+       zfcp_erp_port_shutdown(port, 0, 92, NULL);
        zfcp_erp_wait(adapter);
        zfcp_port_put(port);
        zfcp_port_dequeue(port);
@@ -191,9 +191,10 @@ zfcp_sysfs_adapter_failed_store(struct device *dev, struct device_attribute *att
                goto out;
        }
 
-       zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
-                                      ZFCP_SET);
-       zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
+       zfcp_erp_modify_adapter_status(adapter, 44, NULL,
+                                      ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+       zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 93,
+                               NULL);
        zfcp_erp_wait(adapter);
  out:
        up(&zfcp_data.config_sema);
index 1320c0591431efe8a292c09549ccdc051cc51241..703c1b5cb6029738394474cfae2c49f9a546a4c2 100644 (file)
@@ -94,7 +94,7 @@ zfcp_sysfs_unit_add_store(struct device *dev, struct device_attribute *attr, con
 
        retval = 0;
 
-       zfcp_erp_unit_reopen(unit, 0);
+       zfcp_erp_unit_reopen(unit, 0, 94, NULL);
        zfcp_erp_wait(unit->port->adapter);
        zfcp_unit_put(unit);
  out:
@@ -150,7 +150,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr,
                goto out;
        }
 
-       zfcp_erp_unit_shutdown(unit, 0);
+       zfcp_erp_unit_shutdown(unit, 0, 95, NULL);
        zfcp_erp_wait(unit->port->adapter);
        zfcp_unit_put(unit);
        zfcp_unit_dequeue(unit);
@@ -193,8 +193,9 @@ zfcp_sysfs_port_failed_store(struct device *dev, struct device_attribute *attr,
                goto out;
        }
 
-       zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
-       zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
+       zfcp_erp_modify_port_status(port, 45, NULL,
+                                   ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+       zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, 96, NULL);
        zfcp_erp_wait(port->adapter);
  out:
        up(&zfcp_data.config_sema);
index 63f75ee95c338e588e005228d2b2b18aee204862..80fb2c2cf48ae6bdb162be9f25000e6ef988ed9d 100644 (file)
@@ -94,8 +94,9 @@ zfcp_sysfs_unit_failed_store(struct device *dev, struct device_attribute *attr,
                goto out;
        }
 
-       zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
-       zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
+       zfcp_erp_modify_unit_status(unit, 46, NULL,
+                                   ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+       zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, 97, NULL);
        zfcp_erp_wait(unit->port->adapter);
  out:
        up(&zfcp_data.config_sema);
index b4912d1cee2aa164e81a82ffaefd9e01d991b2b0..51c3ebf1c7d11ecfe93bb1a68c15839e373508ea 100644 (file)
@@ -1838,12 +1838,11 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
                if (scsi_sg_count(srb)) {
                        if ((scsi_sg_count(srb) == 1) &&
                            (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
-                               if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) {
-                                       struct scatterlist *sg = scsi_sglist(srb);
-                                       char *buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
-                                       memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
-                                       kunmap_atomic(buf - sg->offset, KM_IRQ0);
-                               }
+                               if (srb->sc_data_direction == DMA_TO_DEVICE ||
+                                   srb->sc_data_direction == DMA_BIDIRECTIONAL)
+                                       scsi_sg_copy_to_buffer(srb,
+                                                              tw_dev->generic_buffer_virt[request_id],
+                                                              TW_SECTOR_SIZE);
                                command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
                                command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
                        } else {
@@ -1915,13 +1914,11 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
            (cmd->sc_data_direction == DMA_FROM_DEVICE ||
             cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
                if (scsi_sg_count(cmd) == 1) {
-                       struct scatterlist *sg = scsi_sglist(tw_dev->srb[request_id]);
-                       char *buf;
-                       unsigned long flags = 0;
+                       unsigned long flags;
+                       void *buf = tw_dev->generic_buffer_virt[request_id];
+
                        local_irq_save(flags);
-                       buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
-                       memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
-                       kunmap_atomic(buf - sg->offset, KM_IRQ0);
+                       scsi_sg_copy_from_buffer(cmd, buf, TW_SECTOR_SIZE);
                        local_irq_restore(flags);
                }
        }
@@ -2028,8 +2025,6 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
        }
        tw_dev = (TW_Device_Extension *)host->hostdata;
 
-       memset(tw_dev, 0, sizeof(TW_Device_Extension));
-
        /* Save values to device extension */
        tw_dev->host = host;
        tw_dev->tw_pci_dev = pdev;
index d09532162217b5f04376845546bbced6ada5b05a..adb98a297210f08b8f8b3d3d4003e7aae7dabb35 100644 (file)
@@ -1463,18 +1463,10 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
                                 void *data, unsigned int len)
 {
        struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-       void *buf;
-       unsigned int transfer_len;
-       unsigned long flags = 0;
-       struct scatterlist *sg = scsi_sglist(cmd);
+       unsigned long flags;
 
        local_irq_save(flags);
-       buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
-       transfer_len = min(sg->length, len);
-
-       memcpy(buf, data, transfer_len);
-
-       kunmap_atomic(buf - sg->offset, KM_IRQ0);
+       scsi_sg_copy_from_buffer(cmd, data, len);
        local_irq_restore(flags);
 }
 
@@ -2294,8 +2286,6 @@ static int __devinit tw_probe(struct pci_dev *pdev, const struct pci_device_id *
        }
        tw_dev = (TW_Device_Extension *)host->hostdata;
 
-       memset(tw_dev, 0, sizeof(TW_Device_Extension));
-
        /* Save values to device extension */
        tw_dev->host = host;
        tw_dev->tw_pci_dev = pdev;
index 4d3ebb1af49022e9777a6472f368d96e1a6dec45..2d689af2466419a70d51afddad85572db31dc507 100644 (file)
@@ -896,7 +896,7 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda
                IRQ_Channel = PCI_Device->irq;
                IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
                PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
+#ifdef CONFIG_SCSI_FLASHPOINT
                if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
                        BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0);
                        BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
@@ -1006,6 +1006,9 @@ static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter
 }
 
 
+#else
+#define BusLogic_InitializeProbeInfoList(adapter) \
+               BusLogic_InitializeProbeInfoListISA(adapter)
 #endif                         /* CONFIG_PCI */
 
 
index bfbfb5c3a8f65281a42db90626925ce94da92f4f..73f237a1ed94f6e81ca686ba58a280e54e7056be 100644 (file)
 #define PACKED __attribute__((packed))
 #endif
 
-/*
-  FlashPoint support is only available for the Intel x86 Architecture with
-  CONFIG_PCI set.
-*/
-
-#ifndef __i386__
-#undef CONFIG_SCSI_OMIT_FLASHPOINT
-#define CONFIG_SCSI_OMIT_FLASHPOINT
-#endif
-
-#ifndef CONFIG_PCI
-#undef CONFIG_SCSI_OMIT_FLASHPOINT
-#define CONFIG_SCSI_OMIT_FLASHPOINT
-#define BusLogic_InitializeProbeInfoListISA BusLogic_InitializeProbeInfoList
-#endif
-
-
 /*
   Define the maximum number of BusLogic Host Adapters supported by this driver.
 */
@@ -178,7 +161,7 @@ static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddres
   Define macros for testing the Host Adapter Type.
 */
 
-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
+#ifdef CONFIG_SCSI_FLASHPOINT
 
 #define BusLogic_MultiMasterHostAdapterP(HostAdapter) \
   (HostAdapter->HostAdapterType == BusLogic_MultiMaster)
@@ -871,7 +854,7 @@ struct BusLogic_CCB {
        void (*CallbackFunction) (struct BusLogic_CCB *);       /* Bytes 40-43 */
        u32 BaseAddress;        /* Bytes 44-47 */
        enum BusLogic_CompletionCode CompletionCode;    /* Byte 48 */
-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
+#ifdef CONFIG_SCSI_FLASHPOINT
        unsigned char:8;        /* Byte 49 */
        unsigned short OS_Flags;        /* Bytes 50-51 */
        unsigned char Private[48];      /* Bytes 52-99 */
index 1c9078191d9ecb4f76819007e4569bda09061bb4..b374e457e5e2ded4401697ce2e63e88252376f41 100644 (file)
@@ -16,7 +16,7 @@
 */
 
 
-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
+#ifdef CONFIG_SCSI_FLASHPOINT
 
 #define MAX_CARDS      8
 #undef BUSTYPE_PCI
@@ -7626,7 +7626,7 @@ FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
 #define FlashPoint_InterruptPending        FlashPoint__InterruptPending
 #define FlashPoint_HandleInterrupt         FlashPoint__HandleInterrupt
 
-#else                          /* CONFIG_SCSI_OMIT_FLASHPOINT */
+#else                          /* !CONFIG_SCSI_FLASHPOINT */
 
 /*
   Define prototypes for the FlashPoint SCCB Manager Functions.
@@ -7641,4 +7641,4 @@ extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
 extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
 extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
 
-#endif                         /* CONFIG_SCSI_OMIT_FLASHPOINT */
+#endif                         /* CONFIG_SCSI_FLASHPOINT */
index b9d374082b6572f136aff58dddf54e4b65e541fe..7f78e3ea517d7e9afa272af07d017c8ae26758bf 100644 (file)
@@ -588,18 +588,20 @@ config SCSI_BUSLOGIC
          <http://www.tldp.org/docs.html#howto>, and the files
          <file:Documentation/scsi/BusLogic.txt> and
          <file:Documentation/scsi/FlashPoint.txt> for more information.
+         Note that support for FlashPoint is only available for 32-bit
+         x86 configurations.
 
          To compile this driver as a module, choose M here: the
          module will be called BusLogic.
 
-config SCSI_OMIT_FLASHPOINT
-       bool "Omit FlashPoint support"
-       depends on SCSI_BUSLOGIC
+config SCSI_FLASHPOINT
+       bool "FlashPoint support"
+       depends on SCSI_BUSLOGIC && PCI && X86_32
        help
-         This option allows you to omit the FlashPoint support from the
+         This option allows you to add FlashPoint support to the
          BusLogic SCSI driver. The FlashPoint SCCB Manager code is
-         substantial, so users of MultiMaster Host Adapters may wish to omit
-         it.
+         substantial, so users of MultiMaster Host Adapters may not
+         wish to include it.
 
 config SCSI_DMX3191D
        tristate "DMX3191D SCSI support"
index 5ac3a3e8dfafcb57020edf4855690f0961550703..07d572feceed47d0ab56ae92dec83c3ae71564c3 100644 (file)
@@ -179,6 +179,9 @@ int __init a2091_detect(struct scsi_host_template *tpnt)
        DMA(instance)->DAWR = DAWR_A2091;
        regs.SASR = &(DMA(instance)->SASR);
        regs.SCMD = &(DMA(instance)->SCMD);
+       HDATA(instance)->no_sync = 0xff;
+       HDATA(instance)->fast = 0;
+       HDATA(instance)->dma_mode = CTRL_DMA;
        wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
        request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, "A2091 SCSI",
                    instance);
index 3aeec963940bd7e386c0f2e0cc22939df31dd06f..8b449d8acacdb4f249cfa80480a94c9e8cff4cc3 100644 (file)
@@ -178,6 +178,9 @@ int __init a3000_detect(struct scsi_host_template *tpnt)
     DMA(a3000_host)->DAWR = DAWR_A3000;
     regs.SASR = &(DMA(a3000_host)->SASR);
     regs.SCMD = &(DMA(a3000_host)->SCMD);
+    HDATA(a3000_host)->no_sync = 0xff;
+    HDATA(a3000_host)->fast = 0;
+    HDATA(a3000_host)->dma_mode = CTRL_DMA;
     wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15);
     if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI",
                    a3000_intr))
index c05092fd3a9dff7bfb3197639d0b5908b6a3d5b0..369fcf78f39612303787a8c1c3fdb5598f79d982 100644 (file)
@@ -205,7 +205,7 @@ MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health"
 
 int aac_check_reset = 1;
 module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(aac_check_reset, "If adapter fails health check, reset the"
+MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the"
        " adapter. a value of -1 forces the reset to adapters programmed to"
        " ignore it.");
 
@@ -379,24 +379,6 @@ int aac_get_containers(struct aac_dev *dev)
        return status;
 }
 
-static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
-{
-       void *buf;
-       int transfer_len;
-       struct scatterlist *sg = scsi_sglist(scsicmd);
-
-       buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
-       transfer_len = min(sg->length, len + offset);
-
-       transfer_len -= offset;
-       if (buf && transfer_len > 0)
-               memcpy(buf + offset, data, transfer_len);
-
-       flush_kernel_dcache_page(kmap_atomic_to_page(buf - sg->offset));
-       kunmap_atomic(buf - sg->offset, KM_IRQ0);
-
-}
-
 static void get_container_name_callback(void *context, struct fib * fibptr)
 {
        struct aac_get_name_resp * get_name_reply;
@@ -419,14 +401,17 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
                while (*sp == ' ')
                        ++sp;
                if (*sp) {
+                       struct inquiry_data inq;
                        char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
                        int count = sizeof(d);
                        char *dp = d;
                        do {
                                *dp++ = (*sp) ? *sp++ : ' ';
                        } while (--count > 0);
-                       aac_internal_transfer(scsicmd, d,
-                         offsetof(struct inquiry_data, inqd_pid), sizeof(d));
+
+                       scsi_sg_copy_to_buffer(scsicmd, &inq, sizeof(inq));
+                       memcpy(inq.inqd_pid, d, sizeof(d));
+                       scsi_sg_copy_from_buffer(scsicmd, &inq, sizeof(inq));
                }
        }
 
@@ -811,7 +796,7 @@ static void get_container_serial_callback(void *context, struct fib * fibptr)
                sp[2] = 0;
                sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
                  le32_to_cpu(get_serial_reply->uid));
-               aac_internal_transfer(scsicmd, sp, 0, sizeof(sp));
+               scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp));
        }
 
        scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
@@ -1986,8 +1971,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                                arr[4] = 0x0;
                                arr[5] = 0x80;
                                arr[1] = scsicmd->cmnd[2];
-                               aac_internal_transfer(scsicmd, &inq_data, 0,
-                                 sizeof(inq_data));
+                               scsi_sg_copy_from_buffer(scsicmd, &inq_data,
+                                                        sizeof(inq_data));
                                scsicmd->result = DID_OK << 16 |
                                  COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                        } else if (scsicmd->cmnd[2] == 0x80) {
@@ -1995,8 +1980,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                                arr[3] = setinqserial(dev, &arr[4],
                                  scmd_id(scsicmd));
                                arr[1] = scsicmd->cmnd[2];
-                               aac_internal_transfer(scsicmd, &inq_data, 0,
-                                 sizeof(inq_data));
+                               scsi_sg_copy_from_buffer(scsicmd, &inq_data,
+                                                        sizeof(inq_data));
                                return aac_get_container_serial(scsicmd);
                        } else {
                                /* vpd page not implemented */
@@ -2027,7 +2012,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                if (cid == host->this_id) {
                        setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
                        inq_data.inqd_pdt = INQD_PDT_PROC;      /* Processor device */
-                       aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
+                       scsi_sg_copy_from_buffer(scsicmd, &inq_data,
+                                                sizeof(inq_data));
                        scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                        scsicmd->scsi_done(scsicmd);
                        return 0;
@@ -2036,7 +2022,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                        return -1;
                setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
                inq_data.inqd_pdt = INQD_PDT_DA;        /* Direct/random access device */
-               aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
+               scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
                return aac_get_container_name(scsicmd);
        }
        case SERVICE_ACTION_IN:
@@ -2047,6 +2033,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
        {
                u64 capacity;
                char cp[13];
+               unsigned int alloc_len;
 
                dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));
                capacity = fsa_dev_ptr[cid].size - 1;
@@ -2063,18 +2050,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                cp[10] = 2;
                cp[11] = 0;
                cp[12] = 0;
-               aac_internal_transfer(scsicmd, cp, 0,
-                 min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
-               if (sizeof(cp) < scsicmd->cmnd[13]) {
-                       unsigned int len, offset = sizeof(cp);
 
-                       memset(cp, 0, offset);
-                       do {
-                               len = min_t(size_t, scsicmd->cmnd[13] - offset,
-                                               sizeof(cp));
-                               aac_internal_transfer(scsicmd, cp, offset, len);
-                       } while ((offset += len) < scsicmd->cmnd[13]);
-               }
+               alloc_len = ((scsicmd->cmnd[10] << 24)
+                            + (scsicmd->cmnd[11] << 16)
+                            + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]);
+
+               alloc_len = min_t(size_t, alloc_len, sizeof(cp));
+               scsi_sg_copy_from_buffer(scsicmd, cp, alloc_len);
+               if (alloc_len < scsi_bufflen(scsicmd))
+                       scsi_set_resid(scsicmd,
+                                      scsi_bufflen(scsicmd) - alloc_len);
 
                /* Do not cache partition table for arrays */
                scsicmd->device->removable = 1;
@@ -2104,7 +2089,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                cp[5] = 0;
                cp[6] = 2;
                cp[7] = 0;
-               aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
+               scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp));
                /* Do not cache partition table for arrays */
                scsicmd->device->removable = 1;
 
@@ -2139,7 +2124,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                        if (mode_buf_length > scsicmd->cmnd[4])
                                mode_buf_length = scsicmd->cmnd[4];
                }
-               aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
+               scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
                scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                scsicmd->scsi_done(scsicmd);
 
@@ -2174,7 +2159,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                        if (mode_buf_length > scsicmd->cmnd[8])
                                mode_buf_length = scsicmd->cmnd[8];
                }
-               aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
+               scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
 
                scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
                scsicmd->scsi_done(scsicmd);
index 47434499e82bc3704e74252d0913e52bd5ed1e6e..23a8e9f8dcb4666126e28a22ac86c1c60f045537 100644 (file)
@@ -515,10 +515,12 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                                }
                                udelay(5);
                        }
-               } else
-                       (void)down_interruptible(&fibptr->event_wait);
+               } else if (down_interruptible(&fibptr->event_wait) == 0) {
+                       fibptr->done = 2;
+                       up(&fibptr->event_wait);
+               }
                spin_lock_irqsave(&fibptr->event_lock, flags);
-               if (fibptr->done == 0) {
+               if ((fibptr->done == 0) || (fibptr->done == 2)) {
                        fibptr->done = 2; /* Tell interrupt we aborted */
                        spin_unlock_irqrestore(&fibptr->event_lock, flags);
                        return -EINTR;
@@ -594,7 +596,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
        if (le32_to_cpu(*q->headers.consumer) >= q->entries)
                *q->headers.consumer = cpu_to_le32(1);
        else
-               *q->headers.consumer = cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1);
+               le32_add_cpu(q->headers.consumer, 1);
 
        if (wasfull) {
                switch (qid) {
index 72fccd9f40df544e0686f8ea2681c34efb7bb448..0081aa357c8b09c7f5f939d76c4bddfd2b8de65f 100644 (file)
@@ -1413,6 +1413,10 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
        unsigned long flags;
        int nseg;
 
+       nseg = scsi_dma_map(cmd);
+       if (nseg < 0)
+               return SCSI_MLQUEUE_HOST_BUSY;
+
        ahd_lock(ahd, &flags);
 
        /*
@@ -1430,6 +1434,7 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
        if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
                ahd->flags |= AHD_RESOURCE_SHORTAGE;
                ahd_unlock(ahd, &flags);
+               scsi_dma_unmap(cmd);
                return SCSI_MLQUEUE_HOST_BUSY;
        }
 
@@ -1485,8 +1490,6 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
        ahd_set_sense_residual(scb, 0);
        scb->sg_count = 0;
 
-       nseg = scsi_dma_map(cmd);
-       BUG_ON(nseg < 0);
        if (nseg > 0) {
                void *sg = scb->sg_list;
                struct scatterlist *cur_seg;
index 282aff6f852e85bb5b9bae950e2da1f423e5df34..42ad48e09f022ae4409338a225a818c111527611 100644 (file)
@@ -1398,12 +1398,18 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
                        return SCSI_MLQUEUE_DEVICE_BUSY;
        }
 
+       nseg = scsi_dma_map(cmd);
+       if (nseg < 0)
+               return SCSI_MLQUEUE_HOST_BUSY;
+
        /*
         * Get an scb to use.
         */
        scb = ahc_get_scb(ahc);
-       if (!scb)
+       if (!scb) {
+               scsi_dma_unmap(cmd);
                return SCSI_MLQUEUE_HOST_BUSY;
+       }
 
        scb->io_ctx = cmd;
        scb->platform_data->dev = dev;
@@ -1464,8 +1470,6 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
        ahc_set_sense_residual(scb, 0);
        scb->sg_count = 0;
 
-       nseg = scsi_dma_map(cmd);
-       BUG_ON(nseg < 0);
        if (nseg > 0) {
                struct  ahc_dma_seg *sg;
                struct  scatterlist *cur_seg;
index 6066998ed5624388ccb2f5802094a0cb848a9c5f..702e2dbd11fb5b2feecfc701b52520fa76aade15 100644 (file)
@@ -1837,7 +1837,7 @@ type_check(symbol_t *symbol, expression_t *expression, int opcode)
        int and_op;
 
        and_op = FALSE;
-       if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ)
+       if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || opcode == AIC_OP_JZ)
                and_op = TRUE;
 
        /*
index eb8efdcefe482e0bf8997b566a72db30d76027ba..2ef459e9cda1a190213ae59fc2b64126f50c8923 100644 (file)
@@ -58,7 +58,6 @@
 
 extern struct kmem_cache *asd_dma_token_cache;
 extern struct kmem_cache *asd_ascb_cache;
-extern char sas_addr_str[2*SAS_ADDR_SIZE + 1];
 
 static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
 {
@@ -68,21 +67,6 @@ static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
        *p = '\0';
 }
 
-static inline void asd_destringify_sas_addr(u8 *sas_addr, const char *p)
-{
-       int i;
-       for (i = 0; i < SAS_ADDR_SIZE; i++) {
-               u8 h, l;
-               if (!*p)
-                       break;
-               h = isdigit(*p) ? *p-'0' : *p-'A'+10;
-               p++;
-               l = isdigit(*p) ? *p-'0' : *p-'A'+10;
-               p++;
-               sas_addr[i] = (h<<4) | l;
-       }
-}
-
 struct asd_ha_struct;
 struct asd_ascb;
 
index 72042cae7768551a68e597c4a1734ec1eb9f74f1..2e2ddec9c0b6321436c05c750713898c3dca3080 100644 (file)
@@ -35,7 +35,7 @@
 #define SET_DDB(_ddb, _ha) set_bit(_ddb, (_ha)->hw_prof.ddb_bitmap)
 #define CLEAR_DDB(_ddb, _ha) clear_bit(_ddb, (_ha)->hw_prof.ddb_bitmap)
 
-static inline int asd_get_ddb(struct asd_ha_struct *asd_ha)
+static int asd_get_ddb(struct asd_ha_struct *asd_ha)
 {
        int ddb, i;
 
@@ -71,7 +71,7 @@ out:
 #define NCQ_DATA_SCB_PTR offsetof(struct asd_ddb_stp_sata_target_port, ncq_data_scb_ptr)
 #define ITNL_TIMEOUT    offsetof(struct asd_ddb_ssp_smp_target_port, itnl_timeout)
 
-static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
+static void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
 {
        if (!ddb || ddb >= 0xFFFF)
                return;
@@ -79,7 +79,7 @@ static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
        CLEAR_DDB(ddb, asd_ha);
 }
 
-static inline void asd_set_ddb_type(struct domain_device *dev)
+static void asd_set_ddb_type(struct domain_device *dev)
 {
        struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
        int ddb = (int) (unsigned long) dev->lldd_dev;
@@ -109,7 +109,7 @@ static int asd_init_sata_tag_ddb(struct domain_device *dev)
        return 0;
 }
 
-static inline int asd_init_sata(struct domain_device *dev)
+static int asd_init_sata(struct domain_device *dev)
 {
        struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
        int ddb = (int) (unsigned long) dev->lldd_dev;
index 3d8c4ff1f2efe225628f6d082b47c4bf84d1374f..67eeba3bdb06b899dae6339980301b27aa9c9110 100644 (file)
@@ -738,6 +738,8 @@ static void asd_dump_lseq_state(struct asd_ha_struct *asd_ha, int lseq)
        PRINT_LMIP_dword(asd_ha, lseq, DEV_PRES_TIMER_TERM_TS);
 }
 
+#if 0
+
 /**
  * asd_dump_ddb_site -- dump a CSEQ DDB site
  * @asd_ha: pointer to host adapter structure
@@ -880,6 +882,8 @@ void asd_dump_scb_sites(struct asd_ha_struct *asd_ha)
        }
 }
 
+#endif  /*  0  */
+
 /**
  * ads_dump_seq_state -- dump CSEQ and LSEQ states
  * @asd_ha: pointer to host adapter structure
@@ -922,7 +926,9 @@ void asd_dump_frame_rcvd(struct asd_phy *phy,
        spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
 }
 
-static inline void asd_dump_scb(struct asd_ascb *ascb, int ind)
+#if 0
+
+static void asd_dump_scb(struct asd_ascb *ascb, int ind)
 {
        asd_printk("scb%d: vaddr: 0x%p, dma_handle: 0x%llx, next: 0x%llx, "
                   "index:%d, opcode:0x%02x\n",
@@ -956,4 +962,6 @@ void asd_dump_scb_list(struct asd_ascb *ascb, int num)
        }
 }
 
+#endif  /*  0  */
+
 #endif /* ASD_DEBUG */
index 0c388e7da6bbc78177b6da1dd047b557bb84f818..191a753d42a7a7783e606ef19f9443a2124f41ac 100644 (file)
 
 #ifdef ASD_DEBUG
 
-void asd_dump_ddb_0(struct asd_ha_struct *asd_ha);
-void asd_dump_target_ddb(struct asd_ha_struct *asd_ha, u16 site_no);
-void asd_dump_scb_sites(struct asd_ha_struct *asd_ha);
 void asd_dump_seq_state(struct asd_ha_struct *asd_ha, u8 lseq_mask);
 void asd_dump_frame_rcvd(struct asd_phy *phy,
                         struct done_list_struct *dl);
-void asd_dump_scb_list(struct asd_ascb *ascb, int num);
 #else /* ASD_DEBUG */
 
-static inline void asd_dump_ddb_0(struct asd_ha_struct *asd_ha) { }
-static inline void asd_dump_target_ddb(struct asd_ha_struct *asd_ha,
-                                    u16 site_no) { }
-static inline void asd_dump_scb_sites(struct asd_ha_struct *asd_ha) { }
 static inline void asd_dump_seq_state(struct asd_ha_struct *asd_ha,
                                      u8 lseq_mask) { }
 static inline void asd_dump_frame_rcvd(struct asd_phy *phy,
                                       struct done_list_struct *dl) { }
-static inline void asd_dump_scb_list(struct asd_ascb *ascb, int num) { }
 #endif /* ASD_DEBUG */
 
 #endif /* _AIC94XX_DUMP_H_ */
index 098b5f39cd31b3a2da7954e8488e265de442fdf0..83a78222896dfa171136dbb0bd6e04fc836a4f87 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/firmware.h>
 
 #include "aic94xx.h"
 #include "aic94xx_reg.h"
@@ -38,16 +39,14 @@ u32 MBAR0_SWB_SIZE;
 
 /* ---------- Initialization ---------- */
 
-static void asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
+static int asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
 {
-       extern char sas_addr_str[];
-       /* If the user has specified a WWN it overrides other settings
-        */
-       if (sas_addr_str[0] != '\0')
-               asd_destringify_sas_addr(asd_ha->hw_prof.sas_addr,
-                                        sas_addr_str);
-       else if (asd_ha->hw_prof.sas_addr[0] != 0)
-               asd_stringify_sas_addr(sas_addr_str, asd_ha->hw_prof.sas_addr);
+       /* adapter came with a sas address */
+       if (asd_ha->hw_prof.sas_addr[0])
+               return 0;
+
+       return sas_request_addr(asd_ha->sas_ha.core.shost,
+                               asd_ha->hw_prof.sas_addr);
 }
 
 static void asd_propagate_sas_addr(struct asd_ha_struct *asd_ha)
@@ -251,7 +250,7 @@ static int asd_init_scbs(struct asd_ha_struct *asd_ha)
        return 0;
 }
 
-static inline void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha)
+static void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha)
 {
        asd_ha->hw_prof.max_scbs = asd_get_cmdctx_size(asd_ha)/ASD_SCB_SIZE;
        asd_ha->hw_prof.max_ddbs = asd_get_devctx_size(asd_ha)/ASD_DDB_SIZE;
@@ -657,8 +656,7 @@ int asd_init_hw(struct asd_ha_struct *asd_ha)
 
        asd_init_ctxmem(asd_ha);
 
-       asd_get_user_sas_addr(asd_ha);
-       if (!asd_ha->hw_prof.sas_addr[0]) {
+       if (asd_get_user_sas_addr(asd_ha)) {
                asd_printk("No SAS Address provided for %s\n",
                           pci_name(asd_ha->pcidev));
                err = -ENODEV;
@@ -773,7 +771,7 @@ static void asd_dl_tasklet_handler(unsigned long data)
  * asd_process_donelist_isr -- schedule processing of done list entries
  * @asd_ha: pointer to host adapter structure
  */
-static inline void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
+static void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
 {
        tasklet_schedule(&asd_ha->seq.dl_tasklet);
 }
@@ -782,7 +780,7 @@ static inline void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
  * asd_com_sas_isr -- process device communication interrupt (COMINT)
  * @asd_ha: pointer to host adapter structure
  */
-static inline void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
+static void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
 {
        u32 comstat = asd_read_reg_dword(asd_ha, COMSTAT);
 
@@ -821,7 +819,7 @@ static inline void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
        asd_chip_reset(asd_ha);
 }
 
-static inline void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
+static void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
 {
        static const char *halt_code[256] = {
                "UNEXPECTED_INTERRUPT0",
@@ -908,7 +906,7 @@ static inline void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
  * asd_dch_sas_isr -- process device channel interrupt (DEVINT)
  * @asd_ha: pointer to host adapter structure
  */
-static inline void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
+static void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
 {
        u32 dchstatus = asd_read_reg_dword(asd_ha, DCHSTATUS);
 
@@ -923,7 +921,7 @@ static inline void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
  * ads_rbi_exsi_isr -- process external system interface interrupt (INITERR)
  * @asd_ha: pointer to host adapter structure
  */
-static inline void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
+static void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
 {
        u32 stat0r = asd_read_reg_dword(asd_ha, ASISTAT0R);
 
@@ -971,7 +969,7 @@ static inline void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
  *
  * Asserted on PCIX errors: target abort, etc.
  */
-static inline void asd_hst_pcix_isr(struct asd_ha_struct *asd_ha)
+static void asd_hst_pcix_isr(struct asd_ha_struct *asd_ha)
 {
        u16 status;
        u32 pcix_status;
@@ -1044,8 +1042,8 @@ irqreturn_t asd_hw_isr(int irq, void *dev_id)
 
 /* ---------- SCB handling ---------- */
 
-static inline struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
-                                             gfp_t gfp_flags)
+static struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
+                                      gfp_t gfp_flags)
 {
        extern struct kmem_cache *asd_ascb_cache;
        struct asd_seq_data *seq = &asd_ha->seq;
@@ -1144,8 +1142,8 @@ struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
  *
  * LOCKING: called with the pending list lock held.
  */
-static inline void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
-                                    struct asd_ascb *ascb)
+static void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
+                             struct asd_ascb *ascb)
 {
        struct asd_seq_data *seq = &asd_ha->seq;
        struct asd_ascb *last = list_entry(ascb->list.prev,
@@ -1171,7 +1169,7 @@ static inline void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
  * intended to be called from asd_post_ascb_list(), just prior to
  * posting the SCBs to the sequencer.
  */
-static inline void asd_start_scb_timers(struct list_head *list)
+static void asd_start_scb_timers(struct list_head *list)
 {
        struct asd_ascb *ascb;
        list_for_each_entry(ascb, list, list) {
index abc757559c1af2911584f3e14be97c69159d923c..8c1c28239e9307bfd5f30aadad0f2ba852d961c8 100644 (file)
@@ -391,8 +391,6 @@ void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc);
 void asd_control_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
 void asd_turn_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
 int  asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask);
-void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
-                                     u8 subfunc);
 
 void asd_ascb_timedout(unsigned long data);
 int  asd_chip_hardrst(struct asd_ha_struct *asd_ha);
index 88d1e731b65e15b04e5e1a71f281ba1d2035a8d7..90f5e0a6f2e3f77fbe024850a3de235589bb1ccb 100644 (file)
@@ -56,8 +56,6 @@ MODULE_PARM_DESC(collector, "\n"
        "\tThe aic94xx SAS LLDD supports both modes.\n"
        "\tDefault: 0 (Direct Mode).\n");
 
-char sas_addr_str[2*SAS_ADDR_SIZE + 1] = "";
-
 static struct scsi_transport_template *aic94xx_transport_template;
 static int asd_scan_finished(struct Scsi_Host *, unsigned long);
 static void asd_scan_start(struct Scsi_Host *);
@@ -547,7 +545,7 @@ static struct asd_pcidev_struct {
        },
 };
 
-static inline int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
+static int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
 {
        asd_ha->scb_pool = dma_pool_create(ASD_DRIVER_NAME "_scb_pool",
                                           &asd_ha->pcidev->dev,
@@ -565,7 +563,7 @@ static inline int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
  * asd_free_edbs -- free empty data buffers
  * asd_ha: pointer to host adapter structure
  */
-static inline void asd_free_edbs(struct asd_ha_struct *asd_ha)
+static void asd_free_edbs(struct asd_ha_struct *asd_ha)
 {
        struct asd_seq_data *seq = &asd_ha->seq;
        int i;
@@ -576,7 +574,7 @@ static inline void asd_free_edbs(struct asd_ha_struct *asd_ha)
        seq->edb_arr = NULL;
 }
 
-static inline void asd_free_escbs(struct asd_ha_struct *asd_ha)
+static void asd_free_escbs(struct asd_ha_struct *asd_ha)
 {
        struct asd_seq_data *seq = &asd_ha->seq;
        int i;
@@ -591,7 +589,7 @@ static inline void asd_free_escbs(struct asd_ha_struct *asd_ha)
        seq->escb_arr = NULL;
 }
 
-static inline void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha)
+static void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha)
 {
        int i;
 
index f210dac3203df688dd2a02e291f2107ca42c1643..56b17c22526e3ea8b465e42c11ef01325df5aadb 100644 (file)
@@ -32,8 +32,8 @@
  * Offset comes before value to remind that the operation of
  * this function is *offs = val.
  */
-static inline void asd_write_byte(struct asd_ha_struct *asd_ha,
-                                 unsigned long offs, u8 val)
+static void asd_write_byte(struct asd_ha_struct *asd_ha,
+                          unsigned long offs, u8 val)
 {
        if (unlikely(asd_ha->iospace))
                outb(val,
@@ -43,8 +43,8 @@ static inline void asd_write_byte(struct asd_ha_struct *asd_ha,
        wmb();
 }
 
-static inline void asd_write_word(struct asd_ha_struct *asd_ha,
-                                 unsigned long offs, u16 val)
+static void asd_write_word(struct asd_ha_struct *asd_ha,
+                          unsigned long offs, u16 val)
 {
        if (unlikely(asd_ha->iospace))
                outw(val,
@@ -54,8 +54,8 @@ static inline void asd_write_word(struct asd_ha_struct *asd_ha,
        wmb();
 }
 
-static inline void asd_write_dword(struct asd_ha_struct *asd_ha,
-                                  unsigned long offs, u32 val)
+static void asd_write_dword(struct asd_ha_struct *asd_ha,
+                           unsigned long offs, u32 val)
 {
        if (unlikely(asd_ha->iospace))
                outl(val,
@@ -67,8 +67,7 @@ static inline void asd_write_dword(struct asd_ha_struct *asd_ha,
 
 /* Reading from device address space.
  */
-static inline u8 asd_read_byte(struct asd_ha_struct *asd_ha,
-                              unsigned long offs)
+static u8 asd_read_byte(struct asd_ha_struct *asd_ha, unsigned long offs)
 {
        u8 val;
        if (unlikely(asd_ha->iospace))
@@ -80,8 +79,8 @@ static inline u8 asd_read_byte(struct asd_ha_struct *asd_ha,
        return val;
 }
 
-static inline u16 asd_read_word(struct asd_ha_struct *asd_ha,
-                               unsigned long offs)
+static u16 asd_read_word(struct asd_ha_struct *asd_ha,
+                        unsigned long offs)
 {
        u16 val;
        if (unlikely(asd_ha->iospace))
@@ -93,8 +92,8 @@ static inline u16 asd_read_word(struct asd_ha_struct *asd_ha,
        return val;
 }
 
-static inline u32 asd_read_dword(struct asd_ha_struct *asd_ha,
-                                unsigned long offs)
+static u32 asd_read_dword(struct asd_ha_struct *asd_ha,
+                         unsigned long offs)
 {
        u32 val;
        if (unlikely(asd_ha->iospace))
@@ -124,22 +123,22 @@ static inline u32 asd_mem_offs_swb(void)
 /* We know that the register wanted is in the range
  * of the sliding window.
  */
-#define ASD_READ_SW(ww, type, ord)                                     \
-static inline type asd_read_##ww##_##ord (struct asd_ha_struct *asd_ha,\
-                                         u32 reg)                     \
-{                                                                      \
-       struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];    \
-       u32 map_offs=(reg - io_handle-> ww##_base )+asd_mem_offs_##ww ();\
-       return asd_read_##ord (asd_ha, (unsigned long) map_offs);      \
+#define ASD_READ_SW(ww, type, ord)                                     \
+static type asd_read_##ww##_##ord(struct asd_ha_struct *asd_ha,                \
+                                  u32 reg)                             \
+{                                                                      \
+       struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];     \
+       u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
+       return asd_read_##ord(asd_ha, (unsigned long)map_offs); \
 }
 
-#define ASD_WRITE_SW(ww, type, ord)                                    \
-static inline void asd_write_##ww##_##ord (struct asd_ha_struct *asd_ha,\
-                                 u32 reg, type val)                   \
-{                                                                      \
-       struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];    \
-       u32 map_offs=(reg - io_handle-> ww##_base )+asd_mem_offs_##ww ();\
-       asd_write_##ord (asd_ha, (unsigned long) map_offs, val);       \
+#define ASD_WRITE_SW(ww, type, ord)                                    \
+static void asd_write_##ww##_##ord(struct asd_ha_struct *asd_ha,       \
+                                   u32 reg, type val)                  \
+{                                                                      \
+       struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];     \
+       u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
+       asd_write_##ord(asd_ha, (unsigned long)map_offs, val);          \
 }
 
 ASD_READ_SW(swa, u8,  byte);
@@ -186,7 +185,7 @@ ASD_WRITE_SW(swc, u32, dword);
  * @asd_ha: pointer to host adapter structure
  * @reg: register desired to be within range of the new window
  */
-static inline void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg)
+static void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg)
 {
        u32 base = reg & ~(MBAR0_SWB_SIZE-1);
        pci_write_config_dword(asd_ha->pcidev, PCI_CONF_MBAR0_SWB, base);
index ab350504ca5a21b366d288d9b04fc6f55b3fc85e..46643319c5201d1a1fbdc0b060982c4198085347 100644 (file)
@@ -50,7 +50,7 @@
                           | CURRENT_SPINUP_HOLD | CURRENT_GTO_TIMEOUT \
                           | CURRENT_OOB_ERROR)
 
-static inline void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
+static void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
 {
        struct sas_phy *sas_phy = phy->sas_phy.phy;
 
@@ -81,7 +81,7 @@ static inline void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
                phy->sas_phy.oob_mode = SATA_OOB_MODE;
 }
 
-static inline void asd_phy_event_tasklet(struct asd_ascb *ascb,
+static void asd_phy_event_tasklet(struct asd_ascb *ascb,
                                         struct done_list_struct *dl)
 {
        struct asd_ha_struct *asd_ha = ascb->ha;
@@ -125,8 +125,7 @@ static inline void asd_phy_event_tasklet(struct asd_ascb *ascb,
 }
 
 /* If phys are enabled sparsely, this will do the right thing. */
-static inline unsigned ord_phy(struct asd_ha_struct *asd_ha,
-                              struct asd_phy *phy)
+static unsigned ord_phy(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
 {
        u8 enabled_mask = asd_ha->hw_prof.enabled_phys;
        int i, k = 0;
@@ -151,7 +150,7 @@ static inline unsigned ord_phy(struct asd_ha_struct *asd_ha,
  * LOCKING: the frame_rcvd_lock needs to be held since this parses the frame
  * buffer.
  */
-static inline void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr)
+static void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr)
 {
        if (phy->sas_phy.frame_rcvd[0] == 0x34
            && phy->sas_phy.oob_mode == SATA_OOB_MODE) {
@@ -232,9 +231,9 @@ static void asd_deform_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
        spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
 }
 
-static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
-                                          struct done_list_struct *dl,
-                                          int edb_id, int phy_id)
+static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
+                                   struct done_list_struct *dl,
+                                   int edb_id, int phy_id)
 {
        unsigned long flags;
        int edb_el = edb_id + ascb->edb_index;
@@ -255,9 +254,9 @@ static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
        sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED);
 }
 
-static inline void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
-                                             struct done_list_struct *dl,
-                                             int phy_id)
+static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
+                                      struct done_list_struct *dl,
+                                      int phy_id)
 {
        struct asd_ha_struct *asd_ha = ascb->ha;
        struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
@@ -308,9 +307,9 @@ out:
        ;
 }
 
-static inline void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb,
-                                             struct done_list_struct *dl,
-                                             int phy_id)
+static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb,
+                                      struct done_list_struct *dl,
+                                      int phy_id)
 {
        unsigned long flags;
        struct sas_ha_struct *sas_ha = &ascb->ha->sas_ha;
@@ -715,7 +714,7 @@ out:
        asd_ascb_free(ascb);
 }
 
-static inline void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd)
+static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd)
 {
        /* disable all speeds, then enable defaults */
        *speed_mask = SAS_SPEED_60_DIS | SAS_SPEED_30_DIS | SAS_SPEED_15_DIS
@@ -820,6 +819,8 @@ void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc)
 
 /* ---------- INITIATE LINK ADM TASK ---------- */
 
+#if 0
+
 static void link_adm_tasklet_complete(struct asd_ascb *ascb,
                                      struct done_list_struct *dl)
 {
@@ -852,6 +853,8 @@ void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
        ascb->tasklet_complete = link_adm_tasklet_complete;
 }
 
+#endif  /*  0  */
+
 /* ---------- SCB timer ---------- */
 
 /**
index 2a4c933eb89c060a906da809908dd7fb929747e1..4446e3d584dc932abd3e9844c2eb5c2f36fdd596 100644 (file)
@@ -590,8 +590,8 @@ static int asd_reset_flash(struct asd_ha_struct *asd_ha)
        return err;
 }
 
-static inline int asd_read_flash_seg(struct asd_ha_struct *asd_ha,
-                                    void *buffer, u32 offs, int size)
+static int asd_read_flash_seg(struct asd_ha_struct *asd_ha,
+                             void *buffer, u32 offs, int size)
 {
        asd_read_reg_string(asd_ha, buffer, asd_ha->hw_prof.flash.bar+offs,
                            size);
index c750fbf7013bb74b525cb77641e5c5daae246420..f4272ac4c6859810de9a940977067bad6c998500 100644 (file)
@@ -60,7 +60,7 @@ static u16 last_scb_site_no;
  *
  * Return 0 on success, negative on failure.
  */
-int asd_pause_cseq(struct asd_ha_struct *asd_ha)
+static int asd_pause_cseq(struct asd_ha_struct *asd_ha)
 {
        int     count = PAUSE_TRIES;
        u32     arp2ctl;
@@ -87,7 +87,7 @@ int asd_pause_cseq(struct asd_ha_struct *asd_ha)
  *
  * Return 0 on success, negative on error.
  */
-int asd_unpause_cseq(struct asd_ha_struct *asd_ha)
+static int asd_unpause_cseq(struct asd_ha_struct *asd_ha)
 {
        u32     arp2ctl;
        int     count = PAUSE_TRIES;
@@ -115,7 +115,7 @@ int asd_unpause_cseq(struct asd_ha_struct *asd_ha)
  *
  * Return 0 on success, negative on error.
  */
-static inline int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+static int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq)
 {
        u32    arp2ctl;
        int    count = PAUSE_TRIES;
@@ -143,7 +143,7 @@ static inline int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq)
  *
  * Return 0 on success, negative on failure.
  */
-int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
+static int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
 {
        int lseq;
        int err = 0;
@@ -164,7 +164,7 @@ int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
  *
  * Return 0 on success, negative on error.
  */
-static inline int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+static int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq)
 {
        u32 arp2ctl;
        int count = PAUSE_TRIES;
@@ -186,27 +186,6 @@ static inline int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq)
 }
 
 
-/**
- * asd_unpause_lseq - unpause the link sequencer(s)
- * @asd_ha: pointer to host adapter structure
- * @lseq_mask: mask of link sequencers of interest
- *
- * Return 0 on success, negative on failure.
- */
-int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
-{
-       int lseq;
-       int err = 0;
-
-       for_each_sequencer(lseq_mask, lseq_mask, lseq) {
-               err = asd_seq_unpause_lseq(asd_ha, lseq);
-               if (err)
-                       return err;
-       }
-
-       return err;
-}
-
 /* ---------- Downloading CSEQ/LSEQ microcode ---------- */
 
 static int asd_verify_cseq(struct asd_ha_struct *asd_ha, const u8 *_prog,
index 2ea6a0d5220896aec7426b60155bc701cd937718..ad787c55525f9c76161857cf0688075271689c86 100644 (file)
@@ -58,10 +58,6 @@ struct sequencer_file_header {
 } __attribute__((packed));
 
 #ifdef __KERNEL__
-int asd_pause_cseq(struct asd_ha_struct *asd_ha);
-int asd_unpause_cseq(struct asd_ha_struct *asd_ha);
-int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
-int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
 int asd_init_seqs(struct asd_ha_struct *asd_ha);
 int asd_start_seqs(struct asd_ha_struct *asd_ha);
 int asd_release_firmware(void);
index 008df9ab92a5f89b57c8f8cf36fa8ede7abc36d8..326765c9caf869a00e7fd000dc075075eb03cfce 100644 (file)
@@ -33,7 +33,7 @@ static void asd_unbuild_ata_ascb(struct asd_ascb *a);
 static void asd_unbuild_smp_ascb(struct asd_ascb *a);
 static void asd_unbuild_ssp_ascb(struct asd_ascb *a);
 
-static inline void asd_can_dequeue(struct asd_ha_struct *asd_ha, int num)
+static void asd_can_dequeue(struct asd_ha_struct *asd_ha, int num)
 {
        unsigned long flags;
 
@@ -51,9 +51,9 @@ static const u8 data_dir_flags[] = {
        [PCI_DMA_NONE]          = DATA_DIR_NONE, /* NO TRANSFER */
 };
 
-static inline int asd_map_scatterlist(struct sas_task *task,
-                                     struct sg_el *sg_arr,
-                                     gfp_t gfp_flags)
+static int asd_map_scatterlist(struct sas_task *task,
+                              struct sg_el *sg_arr,
+                              gfp_t gfp_flags)
 {
        struct asd_ascb *ascb = task->lldd_task;
        struct asd_ha_struct *asd_ha = ascb->ha;
@@ -131,7 +131,7 @@ err_unmap:
        return res;
 }
 
-static inline void asd_unmap_scatterlist(struct asd_ascb *ascb)
+static void asd_unmap_scatterlist(struct asd_ascb *ascb)
 {
        struct asd_ha_struct *asd_ha = ascb->ha;
        struct sas_task *task = ascb->uldd_task;
@@ -527,7 +527,7 @@ static void asd_unbuild_ssp_ascb(struct asd_ascb *a)
 
 /* ---------- Execute Task ---------- */
 
-static inline int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
+static int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
 {
        int res = 0;
        unsigned long flags;
index b9ac8f703a1d7914d3f269a4e6bddee9a90cda4c..633ff40c736a69f0b9ebc8ad2abd97adb14b981f 100644 (file)
@@ -336,7 +336,7 @@ static void asd_tmf_tasklet_complete(struct asd_ascb *ascb,
        asd_ascb_free(ascb);
 }
 
-static inline int asd_clear_nexus(struct sas_task *task)
+static int asd_clear_nexus(struct sas_task *task)
 {
        int res = TMF_RESP_FUNC_FAILED;
        int leftover;
index 3bedf2466bd1fdcca6b9e07391535843d2f63701..8e53f02cc311a6b8c99e78ec99ddd5ab4d6dd8ca 100644 (file)
@@ -2983,7 +2983,6 @@ static struct scsi_host_template acornscsi_template = {
        .this_id                = 7,
        .sg_tablesize           = SG_ALL,
        .cmd_per_lun            = 2,
-       .unchecked_isa_dma      = 0,
        .use_clustering         = DISABLE_CLUSTERING,
        .proc_name              = "acornscsi",
 };
index 49d838e90a241260ea6e2a907b5c7d45c6839753..a3398fe70a9c5f8d0214869f7bf8f921d30b07cd 100644 (file)
@@ -222,7 +222,6 @@ static struct scsi_host_template cumanascsi_template = {
        .this_id                = 7,
        .sg_tablesize           = SG_ALL,
        .cmd_per_lun            = 2,
-       .unchecked_isa_dma      = 0,
        .use_clustering         = DISABLE_CLUSTERING,
        .proc_name              = "CumanaSCSI-1",
 };
index 7aad15436d24d25002cfacee35837401db5e5bee..92d1cb1b21cb1d419043f24dc557799014978b33 100644 (file)
@@ -113,7 +113,7 @@ static const struct {
        unsigned char  asc;
        unsigned char  ascq;
        int            errno;
-} err[] = {
+} ch_err[] = {
 /* Just filled in what looks right. Hav'nt checked any standard paper for
    these errno assignments, so they may be wrong... */
        {
@@ -155,11 +155,11 @@ static int ch_find_errno(struct scsi_sense_hdr *sshdr)
        /* Check to see if additional sense information is available */
        if (scsi_sense_valid(sshdr) &&
            sshdr->asc != 0) {
-               for (i = 0; err[i].errno != 0; i++) {
-                       if (err[i].sense == sshdr->sense_key &&
-                           err[i].asc   == sshdr->asc &&
-                           err[i].ascq  == sshdr->ascq) {
-                               errno = -err[i].errno;
+               for (i = 0; ch_err[i].errno != 0; i++) {
+                       if (ch_err[i].sense == sshdr->sense_key &&
+                           ch_err[i].asc   == sshdr->asc &&
+                           ch_err[i].ascq  == sshdr->ascq) {
+                               errno = -ch_err[i].errno;
                                break;
                        }
                }
@@ -721,8 +721,8 @@ static long ch_ioctl(struct file *file,
        case CHIOGELEM:
        {
                struct changer_get_element cge;
-               u_char  cmd[12];
-               u_char  *buffer;
+               u_char ch_cmd[12];
+               u_char *buffer;
                unsigned int elem;
                int     result,i;
 
@@ -739,17 +739,18 @@ static long ch_ioctl(struct file *file,
                mutex_lock(&ch->lock);
 
        voltag_retry:
-               memset(cmd,0,sizeof(cmd));
-               cmd[0] = READ_ELEMENT_STATUS;
-               cmd[1] = (ch->device->lun << 5) |
+               memset(ch_cmd, 0, sizeof(ch_cmd));
+               ch_cmd[0] = READ_ELEMENT_STATUS;
+               ch_cmd[1] = (ch->device->lun << 5) |
                        (ch->voltags ? 0x10 : 0) |
                        ch_elem_to_typecode(ch,elem);
-               cmd[2] = (elem >> 8) & 0xff;
-               cmd[3] = elem        & 0xff;
-               cmd[5] = 1;
-               cmd[9] = 255;
+               ch_cmd[2] = (elem >> 8) & 0xff;
+               ch_cmd[3] = elem        & 0xff;
+               ch_cmd[5] = 1;
+               ch_cmd[9] = 255;
 
-               if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
+               result = ch_do_scsi(ch, ch_cmd, buffer, 256, DMA_FROM_DEVICE);
+               if (!result) {
                        cge.cge_status = buffer[18];
                        cge.cge_flags = 0;
                        if (buffer[18] & CESTATUS_EXCEPT) {
index e351db6c00779873a6f94bb7002118501c8b847c..075e2397273c6849f5cd1727c9bb749865e05e3b 100644 (file)
@@ -4761,7 +4761,6 @@ static struct scsi_host_template dc395x_driver_template = {
        .cmd_per_lun            = DC395x_MAX_CMD_PER_LUN,
        .eh_abort_handler       = dc395x_eh_abort,
        .eh_bus_reset_handler   = dc395x_eh_bus_reset,
-       .unchecked_isa_dma      = 0,
        .use_clustering         = DISABLE_CLUSTERING,
 };
 
index b5a60926e556657f7c9e1ead702548ffc002a381..952505c006dffeba8f13a3a5feb2d41d1575210e 100644 (file)
@@ -815,8 +815,6 @@ static int register_pio_HBA(long base, struct get_conf *gc, struct pci_dev *pdev
        else
                hd->primary = 1;
 
-       sh->unchecked_isa_dma = 0;      /* We can only do PIO */
-
        hd->next = NULL;        /* build a linked list of all HBAs */
        hd->prev = last_HBA;
        if (hd->prev != NULL)
index 0b2080d335750b0d89157a87f5170226dd14d1ca..c6d6e7c6559a6664008cbcf9fe75ae106577b476 100644 (file)
 
 /* The meaning of the Scsi_Pointer members in this driver is as follows:
  * ptr:                     Chaining
- * this_residual:           gdth_bufflen
- * buffer:                  gdth_sglist
+ * this_residual:           unused
+ * buffer:                  unused
  * dma_handle:              unused
- * buffers_residual:        gdth_sg_count
+ * buffers_residual:        unused
  * Status:                  unused
  * Message:                 unused
  * have_data_in:            unused
@@ -372,47 +372,6 @@ static const struct file_operations gdth_fops = {
     .release = gdth_close,
 };
 
-/*
- * gdth scsi_command access wrappers.
- *   below 6 functions are used throughout the driver to access scsi_command's
- *   io parameters. The reason we do not use the regular accessors from
- *   scsi_cmnd.h is because of gdth_execute(). Since it is unrecommended for
- *   llds to directly set scsi_cmnd's IO members. This driver will use SCp
- *   members for IO parameters, and will copy scsi_cmnd's members to Scp
- *   members in queuecommand. For internal commands through gdth_execute()
- *   SCp's members will be set directly.
- */
-static inline unsigned gdth_bufflen(struct scsi_cmnd *cmd)
-{
-       return (unsigned)cmd->SCp.this_residual;
-}
-
-static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen)
-{
-       cmd->SCp.this_residual = bufflen;
-}
-
-static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd)
-{
-       return (unsigned)cmd->SCp.buffers_residual;
-}
-
-static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count)
-{
-       cmd->SCp.buffers_residual = sg_count;
-}
-
-static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd)
-{
-       return cmd->SCp.buffer;
-}
-
-static inline void gdth_set_sglist(struct scsi_cmnd *cmd,
-                                   struct scatterlist *sglist)
-{
-       cmd->SCp.buffer = sglist;
-}
-
 #include "gdth_proc.h"
 #include "gdth_proc.c"
 
@@ -591,125 +550,111 @@ static int __init gdth_search_isa(ulong32 bios_adr)
 #endif /* CONFIG_ISA */
 
 #ifdef CONFIG_PCI
-static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
-                            ushort vendor, ushort dev);
+static bool gdth_pci_registered;
 
-static int __init gdth_search_pci(gdth_pci_str *pcistr)
+static bool gdth_search_vortex(ushort device)
 {
-    ushort device, cnt;
-    
-    TRACE(("gdth_search_pci()\n"));
-
-    cnt = 0;
-    for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device)
-        gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
-    for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP; 
-         device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device)
-        gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
-                    PCI_DEVICE_ID_VORTEX_GDTNEWRX);
-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
-                    PCI_DEVICE_ID_VORTEX_GDTNEWRX2);
-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
-                    PCI_DEVICE_ID_INTEL_SRC);
-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
-                    PCI_DEVICE_ID_INTEL_SRC_XSCALE);
-    return cnt;
+       if (device <= PCI_DEVICE_ID_VORTEX_GDT6555)
+               return true;
+       if (device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP &&
+           device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP)
+               return true;
+       if (device == PCI_DEVICE_ID_VORTEX_GDTNEWRX ||
+           device == PCI_DEVICE_ID_VORTEX_GDTNEWRX2)
+               return true;
+       return false;
 }
 
+static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out);
+static int gdth_pci_init_one(struct pci_dev *pdev,
+                            const struct pci_device_id *ent);
+static void gdth_pci_remove_one(struct pci_dev *pdev);
+static void gdth_remove_one(gdth_ha_str *ha);
+
 /* Vortex only makes RAID controllers.
  * We do not really want to specify all 550 ids here, so wildcard match.
  */
-static struct pci_device_id gdthtable[] __maybe_unused = {
-    {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
-    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
-    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
-    {0}
+static const struct pci_device_id gdthtable[] = {
+       { PCI_VDEVICE(VORTEX, PCI_ANY_ID) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC_XSCALE) },
+       { }     /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, gdthtable);
+
+static struct pci_driver gdth_pci_driver = {
+       .name           = "gdth",
+       .id_table       = gdthtable,
+       .probe          = gdth_pci_init_one,
+       .remove         = gdth_pci_remove_one,
 };
-MODULE_DEVICE_TABLE(pci,gdthtable);
 
-static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
-                                   ushort vendor, ushort device)
+static void gdth_pci_remove_one(struct pci_dev *pdev)
 {
-    ulong base0, base1, base2;
-    struct pci_dev *pdev;
+       gdth_ha_str *ha = pci_get_drvdata(pdev);
+
+       pci_set_drvdata(pdev, NULL);
+
+       list_del(&ha->list);
+       gdth_remove_one(ha);
+
+       pci_disable_device(pdev);
+}
+
+static int gdth_pci_init_one(struct pci_dev *pdev,
+                                      const struct pci_device_id *ent)
+{
+       ushort vendor = pdev->vendor;
+       ushort device = pdev->device;
+       ulong base0, base1, base2;
+       int rc;
+       gdth_pci_str gdth_pcistr;
+       gdth_ha_str *ha = NULL;
     
-    TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
-          *cnt, vendor, device));
+       TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
+              gdth_ctr_count, vendor, device));
 
-    pdev = NULL;
-    while ((pdev = pci_get_device(vendor, device, pdev))
-           != NULL) {
-        if (pci_enable_device(pdev))
-            continue;
-        if (*cnt >= MAXHA) {
-            pci_dev_put(pdev);
-            return;
-        }
+       memset(&gdth_pcistr, 0, sizeof(gdth_pcistr));
+
+       if (vendor == PCI_VENDOR_ID_VORTEX && !gdth_search_vortex(device))
+               return -ENODEV;
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       if (gdth_ctr_count >= MAXHA)
+               return -EBUSY;
 
         /* GDT PCI controller found, resources are already in pdev */
-        pcistr[*cnt].pdev = pdev;
-        pcistr[*cnt].irq = pdev->irq;
+       gdth_pcistr.pdev = pdev;
         base0 = pci_resource_flags(pdev, 0);
         base1 = pci_resource_flags(pdev, 1);
         base2 = pci_resource_flags(pdev, 2);
         if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
             device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
             if (!(base0 & IORESOURCE_MEM)) 
-                continue;
-            pcistr[*cnt].dpmem = pci_resource_start(pdev, 0);
+               return -ENODEV;
+           gdth_pcistr.dpmem = pci_resource_start(pdev, 0);
         } else {                                  /* GDT6110, GDT6120, .. */
             if (!(base0 & IORESOURCE_MEM) ||
                 !(base2 & IORESOURCE_MEM) ||
                 !(base1 & IORESOURCE_IO)) 
-                continue;
-            pcistr[*cnt].dpmem = pci_resource_start(pdev, 2);
-            pcistr[*cnt].io_mm = pci_resource_start(pdev, 0);
-            pcistr[*cnt].io    = pci_resource_start(pdev, 1);
+               return -ENODEV;
+           gdth_pcistr.dpmem = pci_resource_start(pdev, 2);
+           gdth_pcistr.io    = pci_resource_start(pdev, 1);
         }
         TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
-                pcistr[*cnt].pdev->bus->number,
-               PCI_SLOT(pcistr[*cnt].pdev->devfn),
-                pcistr[*cnt].irq, pcistr[*cnt].dpmem));
-        (*cnt)++;
-    }       
-}   
+               gdth_pcistr.pdev->bus->number,
+               PCI_SLOT(gdth_pcistr.pdev->devfn),
+               gdth_pcistr.irq,
+               gdth_pcistr.dpmem));
 
-static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
-{    
-    gdth_pci_str temp;
-    int i, changed;
-    
-    TRACE(("gdth_sort_pci() cnt %d\n",cnt));
-    if (cnt == 0)
-        return;
+       rc = gdth_pci_probe_one(&gdth_pcistr, &ha);
+       if (rc)
+               return rc;
 
-    do {
-        changed = FALSE;
-        for (i = 0; i < cnt-1; ++i) {
-            if (!reverse_scan) {
-                if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) ||
-                    (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
-                     PCI_SLOT(pcistr[i].pdev->devfn) >
-                     PCI_SLOT(pcistr[i+1].pdev->devfn))) {
-                    temp = pcistr[i];
-                    pcistr[i] = pcistr[i+1];
-                    pcistr[i+1] = temp;
-                    changed = TRUE;
-                }
-            } else {
-                if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) ||
-                    (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
-                     PCI_SLOT(pcistr[i].pdev->devfn) <
-                     PCI_SLOT(pcistr[i+1].pdev->devfn))) {
-                    temp = pcistr[i];
-                    pcistr[i] = pcistr[i+1];
-                    pcistr[i+1] = temp;
-                    changed = TRUE;
-                }
-            }
-        }
-    } while (changed);
+       return 0;
 }
 #endif /* CONFIG_PCI */
 
@@ -909,7 +854,8 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
 #endif /* CONFIG_ISA */
 
 #ifdef CONFIG_PCI
-static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
+                                  gdth_ha_str *ha)
 {
     register gdt6_dpram_str __iomem *dp6_ptr;
     register gdt6c_dpram_str __iomem *dp6c_ptr;
@@ -921,14 +867,14 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
 
     TRACE(("gdth_init_pci()\n"));
 
-    if (pcistr->pdev->vendor == PCI_VENDOR_ID_INTEL)
+    if (pdev->vendor == PCI_VENDOR_ID_INTEL)
         ha->oem_id = OEM_ID_INTEL;
     else
         ha->oem_id = OEM_ID_ICP;
-    ha->brd_phys = (pcistr->pdev->bus->number << 8) | (pcistr->pdev->devfn & 0xf8);
-    ha->stype = (ulong32)pcistr->pdev->device;
-    ha->irq = pcistr->irq;
-    ha->pdev = pcistr->pdev;
+    ha->brd_phys = (pdev->bus->number << 8) | (pdev->devfn & 0xf8);
+    ha->stype = (ulong32)pdev->device;
+    ha->irq = pdev->irq;
+    ha->pdev = pdev;
     
     if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6000B) {  /* GDT6000/B */
         TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
@@ -956,8 +902,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     continue;
                 }
                 iounmap(ha->brd);
-                pci_write_config_dword(pcistr->pdev, 
-                                       PCI_BASE_ADDRESS_0, i);
+               pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
                 ha->brd = ioremap(i, sizeof(gdt6_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -1066,8 +1011,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     continue;
                 }
                 iounmap(ha->brd);
-                pci_write_config_dword(pcistr->pdev, 
-                                       PCI_BASE_ADDRESS_2, i);
+               pci_write_config_dword(pdev, PCI_BASE_ADDRESS_2, i);
                 ha->brd = ioremap(i, sizeof(gdt6c_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -1159,16 +1103,16 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
         }
 
         /* manipulate config. space to enable DPMEM, start RP controller */
-        pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
+       pci_read_config_word(pdev, PCI_COMMAND, &command);
         command |= 6;
-        pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
-        if (pci_resource_start(pcistr->pdev, 8) == 1UL)
-            pci_resource_start(pcistr->pdev, 8) = 0UL;
+       pci_write_config_word(pdev, PCI_COMMAND, command);
+       if (pci_resource_start(pdev, 8) == 1UL)
+           pci_resource_start(pdev, 8) = 0UL;
         i = 0xFEFF0001UL;
-        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
+       pci_write_config_dword(pdev, PCI_ROM_ADDRESS, i);
         gdth_delay(1);
-        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
-                               pci_resource_start(pcistr->pdev, 8));
+       pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
+                              pci_resource_start(pdev, 8));
         
         dp6m_ptr = ha->brd;
 
@@ -1195,8 +1139,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     continue;
                 }
                 iounmap(ha->brd);
-                pci_write_config_dword(pcistr->pdev, 
-                                       PCI_BASE_ADDRESS_0, i);
+               pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
                 ha->brd = ioremap(i, sizeof(gdt6m_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -2353,12 +2296,12 @@ static void gdth_next(gdth_ha_str *ha)
 static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
                                     char *buffer, ushort count)
 {
-    ushort cpcount,i, max_sg = gdth_sg_count(scp);
+    ushort cpcount,i, max_sg = scsi_sg_count(scp);
     ushort cpsum,cpnow;
     struct scatterlist *sl;
     char *address;
 
-    cpcount = min_t(ushort, count, gdth_bufflen(scp));
+    cpcount = min_t(ushort, count, scsi_bufflen(scp));
 
     if (cpcount) {
         cpsum=0;
@@ -2366,7 +2309,7 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
             unsigned long flags;
             cpnow = (ushort)sl->length;
             TRACE(("copy_internal() now %d sum %d count %d %d\n",
-                          cpnow, cpsum, cpcount, gdth_bufflen(scp)));
+                          cpnow, cpsum, cpcount, scsi_bufflen(scp)));
             if (cpsum+cpnow > cpcount) 
                 cpnow = cpcount - cpsum;
             cpsum += cpnow;
@@ -2589,10 +2532,10 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive)
             cmdp->u.cache.BlockCnt = blockcnt;
         }
 
-        if (gdth_bufflen(scp)) {
+        if (scsi_bufflen(scp)) {
             cmndinfo->dma_dir = (read_write == 1 ?
                 PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);   
-            sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
+            sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
                                cmndinfo->dma_dir);
             if (mode64) {
                 struct scatterlist *sl;
@@ -2739,7 +2682,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
             cmdp->u.raw64.lun        = l;
             cmdp->u.raw64.bus        = b;
             cmdp->u.raw64.priority   = 0;
-            cmdp->u.raw64.sdlen      = gdth_bufflen(scp);
+            cmdp->u.raw64.sdlen      = scsi_bufflen(scp);
             cmdp->u.raw64.sense_len  = 16;
             cmdp->u.raw64.sense_data = sense_paddr;
             cmdp->u.raw64.direction  = 
@@ -2756,7 +2699,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
             cmdp->u.raw.bus        = b;
             cmdp->u.raw.priority   = 0;
             cmdp->u.raw.link_p     = 0;
-            cmdp->u.raw.sdlen      = gdth_bufflen(scp);
+            cmdp->u.raw.sdlen      = scsi_bufflen(scp);
             cmdp->u.raw.sense_len  = 16;
             cmdp->u.raw.sense_data = sense_paddr;
             cmdp->u.raw.direction  = 
@@ -2765,9 +2708,9 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
             cmdp->u.raw.sg_ranz    = 0;
         }
 
-        if (gdth_bufflen(scp)) {
+        if (scsi_bufflen(scp)) {
             cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL;
-            sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
+            sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
                                cmndinfo->dma_dir);
             if (mode64) {
                 struct scatterlist *sl;
@@ -3388,8 +3331,8 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
             /* retry */
             return 2;
         }
-        if (gdth_bufflen(scp))
-            pci_unmap_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
+        if (scsi_bufflen(scp))
+            pci_unmap_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
                          cmndinfo->dma_dir);
 
         if (cmndinfo->sense_paddr)
@@ -4031,10 +3974,6 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
     gdth_update_timeout(scp, scp->timeout_per_command * 6);
     cmndinfo->priority = DEFAULT_PRI;
 
-    gdth_set_bufflen(scp, scsi_bufflen(scp));
-    gdth_set_sg_count(scp, scsi_sg_count(scp));
-    gdth_set_sglist(scp, scsi_sglist(scp));
-
     return __gdth_queuecommand(ha, scp, cmndinfo);
 }
 
@@ -4955,12 +4894,16 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)
 #endif /* CONFIG_EISA */
 
 #ifdef CONFIG_PCI
-static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+static int gdth_pci_probe_one(gdth_pci_str *pcistr,
+                            gdth_ha_str **ha_out)
 {
        struct Scsi_Host *shp;
        gdth_ha_str *ha;
        dma_addr_t scratch_dma_handle = 0;
        int error, i;
+       struct pci_dev *pdev = pcistr->pdev;
+
+       *ha_out = NULL;
 
        shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
        if (!shp)
@@ -4968,13 +4911,13 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
        ha = shost_priv(shp);
 
        error = -ENODEV;
-       if (!gdth_init_pci(&pcistr[ctr],ha))
+       if (!gdth_init_pci(pdev, pcistr, ha))
                goto out_host_put;
 
        /* controller found and initialized */
        printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
-               pcistr[ctr].pdev->bus->number,
-               PCI_SLOT(pcistr[ctr].pdev->devfn),
+               pdev->bus->number,
+               PCI_SLOT(pdev->devfn),
                ha->irq);
 
        error = request_irq(ha->irq, gdth_interrupt,
@@ -5019,7 +4962,7 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
 
        ha->scratch_busy = FALSE;
        ha->req_first = NULL;
-       ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
+       ha->tid_cnt = pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
        if (max_ids > 0 && max_ids < ha->tid_cnt)
                ha->tid_cnt = max_ids;
        for (i = 0; i < GDTH_MAXCMDS; ++i)
@@ -5039,16 +4982,16 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
        /* 64-bit DMA only supported from FW >= x.43 */
        if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) ||
            !ha->dma64_support) {
-               if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                        printk(KERN_WARNING "GDT-PCI %d: "
                                "Unable to set 32-bit DMA\n", ha->hanum);
                                goto out_free_coal_stat;
                }
        } else {
                shp->max_cmd_len = 16;
-               if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
+               if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
                        printk("GDT-PCI %d: 64-bit DMA enabled\n", ha->hanum);
-               } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+               } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                        printk(KERN_WARNING "GDT-PCI %d: "
                                "Unable to set 64/32-bit DMA\n", ha->hanum);
                        goto out_free_coal_stat;
@@ -5062,13 +5005,17 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
        spin_lock_init(&ha->smp_lock);
        gdth_enable_int(ha);
 
-       error = scsi_add_host(shp, &pcistr[ctr].pdev->dev);
+       error = scsi_add_host(shp, &pdev->dev);
        if (error)
                goto out_free_coal_stat;
        list_add_tail(&ha->list, &gdth_instances);
 
+       pci_set_drvdata(ha->pdev, ha);
+
        scsi_scan_host(shp);
 
+       *ha_out = ha;
+
        return 0;
 
  out_free_coal_stat:
@@ -5185,16 +5132,8 @@ static int __init gdth_init(void)
 
 #ifdef CONFIG_PCI
        /* scanning for PCI controllers */
-       {
-               gdth_pci_str pcistr[MAXHA];
-               int cnt,ctr;
-
-               cnt = gdth_search_pci(pcistr);
-               printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt);
-               gdth_sort_pci(pcistr,cnt);
-               for (ctr = 0; ctr < cnt; ++ctr)
-                       gdth_pci_probe_one(pcistr, ctr);
-       }
+       if (pci_register_driver(&gdth_pci_driver) == 0)
+               gdth_pci_registered = true;
 #endif /* CONFIG_PCI */
 
        TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count));
@@ -5227,6 +5166,11 @@ static void __exit gdth_exit(void)
        del_timer_sync(&gdth_timer);
 #endif
 
+#ifdef CONFIG_PCI
+       if (gdth_pci_registered)
+               pci_unregister_driver(&gdth_pci_driver);
+#endif
+
        list_for_each_entry(ha, &gdth_instances, list)
                gdth_remove_one(ha);
 }
index 26e4e92515e0cfcc0793f9b01b15e1e669acbfe2..ca92476727cfae82b258107405023f9a98baf661 100644 (file)
@@ -839,8 +839,6 @@ typedef struct {
     struct pci_dev      *pdev;
     ulong               dpmem;                  /* DPRAM address */
     ulong               io;                     /* IO address */
-    ulong               io_mm;                  /* IO address mem. mapped */
-    unchar              irq;                    /* IRQ */
 } gdth_pci_str;
 
 
index 91f85226d08fc352ec7bbfe7cecaf585dae63cf7..ca73637524012adbdeb4a7cad69558b7dd045430 100644 (file)
@@ -322,6 +322,9 @@ int __init gvp11_detect(struct scsi_host_template *tpnt)
         */
        regs.SASR = &(DMA(instance)->SASR);
        regs.SCMD = &(DMA(instance)->SCMD);
+       HDATA(instance)->no_sync = 0xff;
+       HDATA(instance)->fast = 0;
+       HDATA(instance)->dma_mode = CTRL_DMA;
        wd33c93_init(instance, regs, dma_setup, dma_stop,
                     (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
                                             : WD33C93_FS_12_15);
index ed7e0a1fc34de02d3de7ead9c4f3370928d9c530..1592640a87b5404e14119b411596f80196468c81 100644 (file)
@@ -347,7 +347,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        shost->unchecked_isa_dma = sht->unchecked_isa_dma;
        shost->use_clustering = sht->use_clustering;
        shost->ordered_tag = sht->ordered_tag;
-       shost->active_mode = sht->supported_mode;
 
        if (sht->supported_mode == MODE_UNKNOWN)
                /* means we didn't set it ... default to INITIATOR */
index ff149ad6bc4ed103e44f7497b174391a94ede468..beecda991682c9984d93b727d7c17867bdbebd9b 100644 (file)
@@ -338,7 +338,8 @@ static int iop_get_config_mv(struct hptiop_hba *hba,
        req->header.size =
                cpu_to_le32(sizeof(struct hpt_iop_request_get_config));
        req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
-       req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_GET_CONFIG<<5);
+       req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG<<5);
+       req->header.context_hi32 = 0;
 
        if (iop_send_sync_request_mv(hba, 0, 20000)) {
                dprintk("Get config send cmd failed\n");
@@ -392,7 +393,8 @@ static int iop_set_config_mv(struct hptiop_hba *hba,
        req->header.size =
                cpu_to_le32(sizeof(struct hpt_iop_request_set_config));
        req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
-       req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_SET_CONFIG<<5);
+       req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);
+       req->header.context_hi32 = 0;
 
        if (iop_send_sync_request_mv(hba, 0, 20000)) {
                dprintk("Set config send cmd failed\n");
@@ -903,7 +905,6 @@ static struct scsi_host_template driver_template = {
        .eh_device_reset_handler    = hptiop_reset,
        .eh_bus_reset_handler       = hptiop_reset,
        .info                       = hptiop_info,
-       .unchecked_isa_dma          = 0,
        .emulated                   = 0,
        .use_clustering             = ENABLE_CLUSTERING,
        .proc_name                  = driver_name,
index 0cc8868ea35d03de01ebfbf25df8ab25f634f5b8..dbae3fdb85065c92819443b0046c3fc81e5785a6 100644 (file)
@@ -2581,8 +2581,8 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
        /* Map the sense buffer into bus memory */
        dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,
                                  SENSE_SIZE, DMA_FROM_DEVICE);
-       cblk->senseptr = cpu_to_le32((u32)dma_addr);
-       cblk->senselen = cpu_to_le32(SENSE_SIZE);
+       cblk->senseptr = (u32)dma_addr;
+       cblk->senselen = SENSE_SIZE;
        cmnd->SCp.ptr = (char *)(unsigned long)dma_addr;
        cblk->cdblen = cmnd->cmd_len;
 
@@ -2606,7 +2606,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
                dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],
                                          sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
                                          DMA_BIDIRECTIONAL);
-               cblk->bufptr = cpu_to_le32((u32)dma_addr);
+               cblk->bufptr = (u32)dma_addr;
                cmnd->SCp.dma_handle = dma_addr;
 
                cblk->sglen = nseg;
@@ -2616,7 +2616,8 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
                sg = &cblk->sglist[0];
                scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {
                        sg->data = cpu_to_le32((u32)sg_dma_address(sglist));
-                       total_len += sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
+                       sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
+                       total_len += sg_dma_len(sglist);
                        ++sg;
                }
 
index 7ed568f180ae6aee24e11364dd7f35ed63b1b533..7c615c70ec5c236f7416f9466f2cd5a920c5e865 100644 (file)
@@ -2377,7 +2377,7 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
                        if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
                                return;
 
-                       outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
+                       outl(1, ha->io_addr + IPS_REG_FLAP);
                        if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
@@ -2385,21 +2385,21 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
                                return;
 
                        /* Get Major version */
-                       outl(cpu_to_le32(0x1FF), ha->io_addr + IPS_REG_FLAP);
+                       outl(0x1FF, ha->io_addr + IPS_REG_FLAP);
                        if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        major = inb(ha->io_addr + IPS_REG_FLDP);
 
                        /* Get Minor version */
-                       outl(cpu_to_le32(0x1FE), ha->io_addr + IPS_REG_FLAP);
+                       outl(0x1FE, ha->io_addr + IPS_REG_FLAP);
                        if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
                        minor = inb(ha->io_addr + IPS_REG_FLDP);
 
                        /* Get SubMinor version */
-                       outl(cpu_to_le32(0x1FD), ha->io_addr + IPS_REG_FLAP);
+                       outl(0x1FD, ha->io_addr + IPS_REG_FLAP);
                        if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                                udelay(25);     /* 25 us */
 
@@ -3502,27 +3502,11 @@ ips_send_wait(ips_ha_t * ha, ips_scb_t * scb, int timeout, int intr)
 static void
 ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
 {
-        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_page(&sg[i]), KM_IRQ0) + sg[i].offset;
-                memcpy(buffer, &cdata[xfer_cnt], min_cnt);
-                kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
-                local_irq_restore(flags);
+       unsigned long flags;
 
-                xfer_cnt += min_cnt;
-        }
+       local_irq_save(flags);
+       scsi_sg_copy_from_buffer(scmd, data, count);
+       local_irq_restore(flags);
 }
 
 /****************************************************************************/
@@ -3535,27 +3519,11 @@ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
 static void
 ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
 {
-        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_page(&sg[i]), KM_IRQ0) + sg[i].offset;
-                memcpy(&cdata[xfer_cnt], buffer, min_cnt);
-                kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
-                local_irq_restore(flags);
+       unsigned long flags;
 
-                xfer_cnt += min_cnt;
-        }
+       local_irq_save(flags);
+       scsi_sg_copy_to_buffer(scmd, data, count);
+       local_irq_restore(flags);
 }
 
 /****************************************************************************/
@@ -3696,9 +3664,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
                        scb->cmd.basic_io.sg_count = scb->sg_len;
 
                        if (scb->cmd.basic_io.lba)
-                               scb->cmd.basic_io.lba =
-                                   cpu_to_le32(le32_to_cpu
-                                               (scb->cmd.basic_io.lba) +
+                               le32_add_cpu(&scb->cmd.basic_io.lba,
                                                le16_to_cpu(scb->cmd.basic_io.
                                                            sector_count));
                        else
@@ -3744,9 +3710,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
                        scb->cmd.basic_io.sg_count = scb->sg_len;
 
                        if (scb->cmd.basic_io.lba)
-                               scb->cmd.basic_io.lba =
-                                   cpu_to_le32(le32_to_cpu
-                                               (scb->cmd.basic_io.lba) +
+                               le32_add_cpu(&scb->cmd.basic_io.lba,
                                                le16_to_cpu(scb->cmd.basic_io.
                                                            sector_count));
                        else
@@ -4888,7 +4852,7 @@ ips_init_copperhead(ips_ha_t * ha)
                return (0);
 
        /* setup CCCR */
-       outl(cpu_to_le32(0x1010), ha->io_addr + IPS_REG_CCCR);
+       outl(0x1010, ha->io_addr + IPS_REG_CCCR);
 
        /* Enable busmastering */
        outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
@@ -5270,12 +5234,12 @@ ips_statinit(ips_ha_t * ha)
        ha->adapt->p_status_tail = ha->adapt->status;
 
        phys_status_start = ha->adapt->hw_status_start;
-       outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQSR);
-       outl(cpu_to_le32(phys_status_start + IPS_STATUS_Q_SIZE),
+       outl(phys_status_start, ha->io_addr + IPS_REG_SQSR);
+       outl(phys_status_start + IPS_STATUS_Q_SIZE,
             ha->io_addr + IPS_REG_SQER);
-       outl(cpu_to_le32(phys_status_start + IPS_STATUS_SIZE),
+       outl(phys_status_start + IPS_STATUS_SIZE,
             ha->io_addr + IPS_REG_SQHR);
-       outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQTR);
+       outl(phys_status_start, ha->io_addr + IPS_REG_SQTR);
 
        ha->adapt->hw_status_tail = phys_status_start;
 }
@@ -5332,7 +5296,7 @@ ips_statupd_copperhead(ips_ha_t * ha)
                ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
        }
 
-       outl(cpu_to_le32(ha->adapt->hw_status_tail),
+       outl(ha->adapt->hw_status_tail,
             ha->io_addr + IPS_REG_SQTR);
 
        return (ha->adapt->p_status_tail->value);
@@ -5434,8 +5398,8 @@ ips_issue_copperhead(ips_ha_t * ha, ips_scb_t * scb)
                }               /* end if */
        }                       /* end while */
 
-       outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR);
-       outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR);
+       outl(scb->scb_busaddr, ha->io_addr + IPS_REG_CCSAR);
+       outw(IPS_BIT_START_CMD, ha->io_addr + IPS_REG_CCCR);
 
        return (IPS_SUCCESS);
 }
@@ -5520,7 +5484,7 @@ ips_issue_i2o(ips_ha_t * ha, ips_scb_t * scb)
                          ips_name, ha->host_num, scb->cmd.basic_io.command_id);
        }
 
-       outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ);
+       outl(scb->scb_busaddr, ha->io_addr + IPS_REG_I2O_INMSGQ);
 
        return (IPS_SUCCESS);
 }
@@ -6412,7 +6376,7 @@ ips_program_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
 
        for (i = 0; i < buffersize; i++) {
                /* write a byte */
-               outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
+               outl(i + offset, ha->io_addr + IPS_REG_FLAP);
                if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
@@ -6597,7 +6561,7 @@ ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
        if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
                return (1);
 
-       outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
+       outl(1, ha->io_addr + IPS_REG_FLAP);
        if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                udelay(25);     /* 25 us */
        if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
@@ -6606,7 +6570,7 @@ ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
        checksum = 0xff;
        for (i = 2; i < buffersize; i++) {
 
-               outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
+               outl(i + offset, ha->io_addr + IPS_REG_FLAP);
                if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
                        udelay(25);     /* 25 us */
 
@@ -6842,7 +6806,6 @@ ips_register_scsi(int index)
        sh->sg_tablesize = sh->hostt->sg_tablesize;
        sh->can_queue = sh->hostt->can_queue;
        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;
        sh->max_sectors = 128;
 
index 8a178674cb18cd02928d0cd08a1ecf2be2503508..72b9b2a0eba3248bbb4f5d65534c7a4df49fb580 100644 (file)
@@ -528,6 +528,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
        struct iscsi_session *session = conn->session;
        struct scsi_cmnd *sc = ctask->sc;
        int datasn = be32_to_cpu(rhdr->datasn);
+       unsigned total_in_length = scsi_in(sc)->length;
 
        iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
        if (tcp_conn->in.datalen == 0)
@@ -542,10 +543,10 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
        tcp_ctask->exp_datasn++;
 
        tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
-       if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
+       if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
                debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
                          __FUNCTION__, tcp_ctask->data_offset,
-                         tcp_conn->in.datalen, scsi_bufflen(sc));
+                         tcp_conn->in.datalen, total_in_length);
                return ISCSI_ERR_DATA_OFFSET;
        }
 
@@ -558,8 +559,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 
                        if (res_count > 0 &&
                            (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
-                            res_count <= scsi_bufflen(sc)))
-                               scsi_set_resid(sc, res_count);
+                            res_count <= total_in_length))
+                               scsi_in(sc)->resid = res_count;
                        else
                                sc->result = (DID_BAD_TARGET << 16) |
                                        rhdr->cmd_status;
@@ -670,11 +671,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
                            r2t->data_length, session->max_burst);
 
        r2t->data_offset = be32_to_cpu(rhdr->data_offset);
-       if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
+       if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
                iscsi_conn_printk(KERN_ERR, conn,
                                  "invalid R2T with data len %u at offset %u "
                                  "and total length %d\n", r2t->data_length,
-                                 r2t->data_offset, scsi_bufflen(ctask->sc));
+                                 r2t->data_offset, scsi_out(ctask->sc)->length);
                __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
                            sizeof(void*));
                return ISCSI_ERR_DATALEN;
@@ -771,6 +772,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
                if (tcp_conn->in.datalen) {
                        struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
                        struct hash_desc *rx_hash = NULL;
+                       struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
 
                        /*
                         * Setup copy of Data-In into the Scsi_Cmnd
@@ -788,8 +790,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
                                  tcp_ctask->data_offset,
                                  tcp_conn->in.datalen);
                        return iscsi_segment_seek_sg(&tcp_conn->in.segment,
-                                                    scsi_sglist(ctask->sc),
-                                                    scsi_sg_count(ctask->sc),
+                                                    sdb->table.sgl,
+                                                    sdb->table.nents,
                                                     tcp_ctask->data_offset,
                                                     tcp_conn->in.datalen,
                                                     iscsi_tcp_process_data_in,
@@ -1332,7 +1334,8 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
                return 0;
 
        /* If we have immediate data, attach a payload */
-       err = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc), scsi_sg_count(sc),
+       err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
+                                      scsi_out(sc)->table.nents,
                                       0, ctask->imm_count);
        if (err)
                return err;
@@ -1386,6 +1389,7 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
        struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
        struct scsi_cmnd *sc = ctask->sc;
+       struct scsi_data_buffer *sdb = scsi_out(sc);
        int rc = 0;
 
 flush:
@@ -1412,9 +1416,8 @@ flush:
                                ctask->itt, tcp_ctask->sent, ctask->data_count);
 
                iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
-               rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
-                                             scsi_sg_count(sc),
-                                             tcp_ctask->sent,
+               rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+                                             sdb->table.nents, tcp_ctask->sent,
                                              ctask->data_count);
                if (rc)
                        goto fail;
@@ -1460,8 +1463,8 @@ flush:
                iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
                                        sizeof(struct iscsi_hdr));
 
-               rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
-                                             scsi_sg_count(sc),
+               rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+                                             sdb->table.nents,
                                              r2t->data_offset + r2t->sent,
                                              r2t->data_count);
                if (rc)
index bdd7de7da39a5819cea137dcb5b083f6f69a8d3c..010c1b9b178cb5ae5ea0e9f54e3a631c210f0a7e 100644 (file)
@@ -137,6 +137,70 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
        return 0;
 }
 
+/*
+ * make an extended cdb AHS
+ */
+static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+{
+       struct scsi_cmnd *cmd = ctask->sc;
+       unsigned rlen, pad_len;
+       unsigned short ahslength;
+       struct iscsi_ecdb_ahdr *ecdb_ahdr;
+       int rc;
+
+       ecdb_ahdr = iscsi_next_hdr(ctask);
+       rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
+
+       BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
+       ahslength = rlen + sizeof(ecdb_ahdr->reserved);
+
+       pad_len = iscsi_padding(rlen);
+
+       rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
+                          sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
+       if (rc)
+               return rc;
+
+       if (pad_len)
+               memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
+
+       ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
+       ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
+       ecdb_ahdr->reserved = 0;
+       memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
+
+       debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+                  "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+                  cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
+
+       return 0;
+}
+
+static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
+{
+       struct scsi_cmnd *sc = ctask->sc;
+       struct iscsi_rlength_ahdr *rlen_ahdr;
+       int rc;
+
+       rlen_ahdr = iscsi_next_hdr(ctask);
+       rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
+       if (rc)
+               return rc;
+
+       rlen_ahdr->ahslength =
+               cpu_to_be16(sizeof(rlen_ahdr->read_length) +
+                                                 sizeof(rlen_ahdr->reserved));
+       rlen_ahdr->ahstype = ISCSI_AHSTYPE_RLENGTH;
+       rlen_ahdr->reserved = 0;
+       rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length);
+
+       debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
+                  "rlen_ahdr->ahslength(%d)\n",
+                  be32_to_cpu(rlen_ahdr->read_length),
+                  be16_to_cpu(rlen_ahdr->ahslength));
+       return 0;
+}
+
 /**
  * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
  * @ctask: iscsi cmd task
@@ -150,7 +214,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
        struct iscsi_session *session = conn->session;
        struct iscsi_cmd *hdr = ctask->hdr;
        struct scsi_cmnd *sc = ctask->sc;
-       unsigned hdrlength;
+       unsigned hdrlength, cmd_len;
        int rc;
 
        ctask->hdr_len = 0;
@@ -161,17 +225,30 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
        hdr->flags = ISCSI_ATTR_SIMPLE;
        int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
        hdr->itt = build_itt(ctask->itt, session->age);
-       hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
        hdr->cmdsn = cpu_to_be32(session->cmdsn);
        session->cmdsn++;
        hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
-       memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
-       if (sc->cmd_len < MAX_COMMAND_SIZE)
-               memset(&hdr->cdb[sc->cmd_len], 0,
-                       MAX_COMMAND_SIZE - sc->cmd_len);
+       cmd_len = sc->cmd_len;
+       if (cmd_len < ISCSI_CDB_SIZE)
+               memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
+       else if (cmd_len > ISCSI_CDB_SIZE) {
+               rc = iscsi_prep_ecdb_ahs(ctask);
+               if (rc)
+                       return rc;
+               cmd_len = ISCSI_CDB_SIZE;
+       }
+       memcpy(hdr->cdb, sc->cmnd, cmd_len);
 
        ctask->imm_count = 0;
+       if (scsi_bidi_cmnd(sc)) {
+               hdr->flags |= ISCSI_FLAG_CMD_READ;
+               rc = iscsi_prep_bidi_ahs(ctask);
+               if (rc)
+                       return rc;
+       }
        if (sc->sc_data_direction == DMA_TO_DEVICE) {
+               unsigned out_len = scsi_out(sc)->length;
+               hdr->data_length = cpu_to_be32(out_len);
                hdr->flags |= ISCSI_FLAG_CMD_WRITE;
                /*
                 * Write counters:
@@ -192,19 +269,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
                ctask->unsol_datasn = 0;
 
                if (session->imm_data_en) {
-                       if (scsi_bufflen(sc) >= session->first_burst)
+                       if (out_len >= session->first_burst)
                                ctask->imm_count = min(session->first_burst,
                                                        conn->max_xmit_dlength);
                        else
-                               ctask->imm_count = min(scsi_bufflen(sc),
+                               ctask->imm_count = min(out_len,
                                                        conn->max_xmit_dlength);
                        hton24(hdr->dlength, ctask->imm_count);
                } else
                        zero_data(hdr->dlength);
 
                if (!session->initial_r2t_en) {
-                       ctask->unsol_count = min((session->first_burst),
-                               (scsi_bufflen(sc))) - ctask->imm_count;
+                       ctask->unsol_count = min(session->first_burst, out_len)
+                                                            - ctask->imm_count;
                        ctask->unsol_offset = ctask->imm_count;
                }
 
@@ -214,6 +291,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
        } else {
                hdr->flags |= ISCSI_FLAG_CMD_FINAL;
                zero_data(hdr->dlength);
+               hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
 
                if (sc->sc_data_direction == DMA_FROM_DEVICE)
                        hdr->flags |= ISCSI_FLAG_CMD_READ;
@@ -232,10 +310,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
                return EIO;
 
        conn->scsicmd_pdus_cnt++;
-       debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
-               "cmdsn %d win %d]\n",
-               sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
-               conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
+       debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
+               "len %d bidi_len %d cmdsn %d win %d]\n",
+               scsi_bidi_cmnd(sc) ? "bidirectional" :
+                    sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+               conn->id, sc, sc->cmnd[0], ctask->itt,
+               scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
                session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
        return 0;
 }
@@ -298,7 +378,12 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
                conn->session->tt->cleanup_cmd_task(conn, ctask);
 
        sc->result = err;
-       scsi_set_resid(sc, scsi_bufflen(sc));
+       if (!scsi_bidi_cmnd(sc))
+               scsi_set_resid(sc, scsi_bufflen(sc));
+       else {
+               scsi_out(sc)->resid = scsi_out(sc)->length;
+               scsi_in(sc)->resid = scsi_in(sc)->length;
+       }
        if (conn->ctask == ctask)
                conn->ctask = NULL;
        /* release ref from queuecommand */
@@ -433,6 +518,18 @@ invalid_datalen:
                           min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
        }
 
+       if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+                          ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
+               int res_count = be32_to_cpu(rhdr->bi_residual_count);
+
+               if (scsi_bidi_cmnd(sc) && res_count > 0 &&
+                               (rhdr->flags & ISCSI_FLAG_CMD_BIDI_OVERFLOW ||
+                                res_count <= scsi_in(sc)->length))
+                       scsi_in(sc)->resid = res_count;
+               else
+                       sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+       }
+
        if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
                           ISCSI_FLAG_CMD_OVERFLOW)) {
                int res_count = be32_to_cpu(rhdr->residual_count);
@@ -440,13 +537,11 @@ invalid_datalen:
                if (res_count > 0 &&
                    (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
                     res_count <= scsi_bufflen(sc)))
+                       /* write side for bidi or uni-io set_resid */
                        scsi_set_resid(sc, res_count);
                else
                        sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-       } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
-                                 ISCSI_FLAG_CMD_BIDI_OVERFLOW))
-               sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-
+       }
 out:
        debug_scsi("done [sc %lx res %d itt 0x%x]\n",
                   (long)sc, sc->result, ctask->itt);
@@ -1102,7 +1197,12 @@ reject:
 fault:
        spin_unlock(&session->lock);
        debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
-       scsi_set_resid(sc, scsi_bufflen(sc));
+       if (!scsi_bidi_cmnd(sc))
+               scsi_set_resid(sc, scsi_bufflen(sc));
+       else {
+               scsi_out(sc)->resid = scsi_out(sc)->length;
+               scsi_in(sc)->resid = scsi_in(sc)->length;
+       }
        sc->scsi_done(sc);
        spin_lock(host->host_lock);
        return 0;
index a4811e4106dffcafdb4215ad5505af4f85d912ae..744f06d04a363225cc9859b08df208a2cb0156ae 100644 (file)
@@ -691,7 +691,7 @@ static int sas_discover_sata_dev(struct domain_device *dev)
                /* incomplete response */
                SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to "
                            "dev %llx\n", SAS_ADDR(dev->sas_addr));
-               if (!le16_to_cpu(identify_x[83] & (1<<6)))
+               if (!(identify_x[83] & cpu_to_le16(1<<6)))
                        goto cont1;
                res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES,
                                        ATA_FEATURE_PUP_STBY_SPIN_UP,
index 1f8241563c6ccea625640eb69c22554d931f3d87..601ec5b6a7f6ab1a240ff130b0dbc6f989b3ec4e 100644 (file)
@@ -24,6 +24,8 @@
  */
 
 #include <linux/kthread.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
 
 #include "sas_internal.h"
 
@@ -1064,6 +1066,45 @@ void sas_target_destroy(struct scsi_target *starget)
        return;
 }
 
+static void sas_parse_addr(u8 *sas_addr, const char *p)
+{
+       int i;
+       for (i = 0; i < SAS_ADDR_SIZE; i++) {
+               u8 h, l;
+               if (!*p)
+                       break;
+               h = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
+               p++;
+               l = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
+               p++;
+               sas_addr[i] = (h<<4) | l;
+       }
+}
+
+#define SAS_STRING_ADDR_SIZE   16
+
+int sas_request_addr(struct Scsi_Host *shost, u8 *addr)
+{
+       int res;
+       const struct firmware *fw;
+
+       res = request_firmware(&fw, "sas_addr", &shost->shost_gendev);
+       if (res)
+               return res;
+
+       if (fw->size < SAS_STRING_ADDR_SIZE) {
+               res = -ENODEV;
+               goto out;
+       }
+
+       sas_parse_addr(addr, fw->data);
+
+out:
+       release_firmware(fw);
+       return res;
+}
+EXPORT_SYMBOL_GPL(sas_request_addr);
+
 EXPORT_SYMBOL_GPL(sas_queuecommand);
 EXPORT_SYMBOL_GPL(sas_target_alloc);
 EXPORT_SYMBOL_GPL(sas_slave_configure);
index 2ab2d24dcc1566dee30adbf448a6f01712bd6641..ec0b0f6e5e1a950ea9f4436b4888f184471f9af0 100644 (file)
@@ -23,7 +23,7 @@
 
 struct lpfc_sli2_slim;
 
-#define LPFC_MAX_TARGET                256     /* max number of targets supported */
+#define LPFC_MAX_TARGET                4096    /* max number of targets supported */
 #define LPFC_MAX_DISC_THREADS  64      /* max outstanding discovery els
                                           requests */
 #define LPFC_MAX_NS_RETRY      3       /* Number of retry attempts to contact
@@ -268,7 +268,6 @@ struct lpfc_vport {
 #define FC_NLP_MORE             0x40    /* More node to process in node tbl */
 #define FC_OFFLINE_MODE         0x80    /* Interface is offline for diag */
 #define FC_FABRIC               0x100   /* We are fabric attached */
-#define FC_ESTABLISH_LINK       0x200   /* Reestablish Link */
 #define FC_RSCN_DISCOVERY       0x400   /* Auth all devices after RSCN */
 #define FC_SCSI_SCAN_TMO        0x4000  /* scsi scan timer running */
 #define FC_ABORT_DISCOVERY      0x8000  /* we want to abort discovery */
@@ -433,8 +432,6 @@ struct lpfc_hba {
 
        uint32_t fc_eventTag;   /* event tag for link attention */
 
-
-       struct timer_list fc_estabtmo;  /* link establishment timer */
        /* These fields used to be binfo */
        uint32_t fc_pref_DID;   /* preferred D_ID */
        uint8_t  fc_pref_ALPA;  /* preferred AL_PA */
index b12a841703ca8f41d92acd754dccb4d8ef8452d5..74c9fc204211056204e9cb207cb06271642c43fc 100644 (file)
@@ -1954,7 +1954,9 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
                        (phba->sysfs_mbox.mbox->mb.mbxCommand !=
                                MBX_DUMP_MEMORY &&
                         phba->sysfs_mbox.mbox->mb.mbxCommand !=
-                               MBX_RESTART)) {
+                               MBX_RESTART &&
+                        phba->sysfs_mbox.mbox->mb.mbxCommand !=
+                               MBX_WRITE_VPARMS)) {
                        sysfs_mbox_idle(phba);
                        spin_unlock_irq(&phba->hbalock);
                        return -EPERM;
@@ -1962,7 +1964,11 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
 
                phba->sysfs_mbox.mbox->vport = vport;
 
-               if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
+               /* Don't allow mailbox commands to be sent when blocked
+                * or when in the middle of discovery
+                */
+               if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO ||
+                   vport->fc_flag & FC_NDISC_ACTIVE) {
                        sysfs_mbox_idle(phba);
                        spin_unlock_irq(&phba->hbalock);
                        return  -EAGAIN;
index 3d0ccd9b341de1272607790f4ff85e0503d44d8d..153afae567b5876d36f1a6978fa2fb8c03609e57 100644 (file)
@@ -63,7 +63,7 @@ lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
 {
        if (!mp) {
                lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                               "0146 Ignoring unsolicted CT No HBQ "
+                               "0146 Ignoring unsolicited CT No HBQ "
                                "status = x%x\n",
                                piocbq->iocb.ulpStatus);
        }
@@ -438,7 +438,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
                                    (!(vport->ct_flags & FC_CT_RFF_ID)) ||
                                    (!vport->cfg_restrict_login)) {
                                        ndlp = lpfc_setup_disc_node(vport, Did);
-                                       if (ndlp) {
+                                       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
                                                lpfc_debugfs_disc_trc(vport,
                                                LPFC_DISC_TRC_CT,
                                                "Parse GID_FTrsp: "
@@ -543,7 +543,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        struct lpfc_dmabuf *outp;
        struct lpfc_sli_ct_request *CTrsp;
        struct lpfc_nodelist *ndlp;
-       int rc, retry;
+       int rc;
 
        /* First save ndlp, before we overwrite it */
        ndlp = cmdiocb->context_un.ndlp;
@@ -563,45 +563,29 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        if (vport->load_flag & FC_UNLOADING)
                goto out;
 
-       if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) {
+       if (lpfc_els_chk_latt(vport)) {
                lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
                                 "0216 Link event during NS query\n");
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
                goto out;
        }
-
+       if (lpfc_error_lost_link(irsp)) {
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+                                "0226 NS query failed due to link event\n");
+               goto out;
+       }
        if (irsp->ulpStatus) {
                /* Check for retry */
                if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
-                       retry = 1;
-                       if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
-                               switch (irsp->un.ulpWord[4]) {
-                               case IOERR_NO_RESOURCES:
-                                       /* We don't increment the retry
-                                        * count for this case.
-                                        */
-                                       break;
-                               case IOERR_LINK_DOWN:
-                               case IOERR_SLI_ABORTED:
-                               case IOERR_SLI_DOWN:
-                                       retry = 0;
-                                       break;
-                               default:
-                                       vport->fc_ns_retry++;
-                               }
-                       }
-                       else
+                       if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
+                           irsp->un.ulpWord[4] != IOERR_NO_RESOURCES)
                                vport->fc_ns_retry++;
 
-                       if (retry) {
-                               /* CT command is being retried */
-                               rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
+                       /* CT command is being retried */
+                       rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
                                         vport->fc_ns_retry, 0);
-                               if (rc == 0) {
-                                       /* success */
-                                       goto out;
-                               }
-                       }
+                       if (rc == 0)
+                               goto out;
                }
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
                lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -780,7 +764,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 
        /* This is a target port, unregistered port, or the GFF_ID failed */
        ndlp = lpfc_setup_disc_node(vport, did);
-       if (ndlp) {
+       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
                lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
                                 "0242 Process x%x GFF "
                                 "NameServer Rsp Data: x%x x%x x%x\n",
index 783d1eea13efdb4cfe01d9ca49429244b6d74912..90272e65957a74569ba1fe7a0df9665668357d1f 100644 (file)
@@ -503,6 +503,8 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
                                ndlp->nlp_sid);
                if (ndlp->nlp_type & NLP_FCP_INITIATOR)
                        len +=  snprintf(buf+len, size-len, "FCP_INITIATOR ");
+               len += snprintf(buf+len, size-len, "usgmap:%x ",
+                       ndlp->nlp_usg_map);
                len += snprintf(buf+len, size-len, "refcnt:%x",
                        atomic_read(&ndlp->kref.refcount));
                len +=  snprintf(buf+len, size-len, "\n");
index cbb68a9422554524f33ba7bc6bdfe29c61678f24..886c5f1b11d2d7ce9663bdc009424a20a3f07552 100644 (file)
@@ -719,9 +719,9 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
                if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
                    icmd->un.elsreq64.bdl.ulpIoTag32) {
                        ndlp = (struct lpfc_nodelist *)(iocb->context1);
-                       if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
+                       if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
+                           (ndlp->nlp_DID == Fabric_DID))
                                lpfc_sli_issue_abort_iotag(phba, pring, iocb);
-                       }
                }
        }
        spin_unlock_irq(&phba->hbalock);
@@ -829,7 +829,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
        struct fc_rport *rport;
        struct serv_parm *sp;
        uint8_t  name[sizeof(struct lpfc_name)];
-       uint32_t rc;
+       uint32_t rc, keepDID = 0;
 
        /* Fabric nodes can have the same WWPN so we don't bother searching
         * by WWPN.  Just return the ndlp that was given to us.
@@ -858,11 +858,17 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
                        return ndlp;
                lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID);
        } else if (!NLP_CHK_NODE_ACT(new_ndlp)) {
+               rc = memcmp(&ndlp->nlp_portname, name,
+                           sizeof(struct lpfc_name));
+               if (!rc)
+                       return ndlp;
                new_ndlp = lpfc_enable_node(vport, new_ndlp,
                                                NLP_STE_UNUSED_NODE);
                if (!new_ndlp)
                        return ndlp;
-       }
+               keepDID = new_ndlp->nlp_DID;
+       } else
+               keepDID = new_ndlp->nlp_DID;
 
        lpfc_unreg_rpi(vport, new_ndlp);
        new_ndlp->nlp_DID = ndlp->nlp_DID;
@@ -893,12 +899,24 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
                        }
                        new_ndlp->nlp_type = ndlp->nlp_type;
                }
+               /* We shall actually free the ndlp with both nlp_DID and
+                * nlp_portname fields equals 0 to avoid any ndlp on the
+                * nodelist never to be used.
+                */
+               if (ndlp->nlp_DID == 0) {
+                       spin_lock_irq(&phba->ndlp_lock);
+                       NLP_SET_FREE_REQ(ndlp);
+                       spin_unlock_irq(&phba->ndlp_lock);
+               }
 
+               /* Two ndlps cannot have the same did on the nodelist */
+               ndlp->nlp_DID = keepDID;
                lpfc_drop_node(vport, ndlp);
        }
        else {
                lpfc_unreg_rpi(vport, ndlp);
-               ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
+               /* Two ndlps cannot have the same did */
+               ndlp->nlp_DID = keepDID;
                lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
        }
        return new_ndlp;
@@ -2091,7 +2109,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                }
 
                phba->fc_stat.elsXmitRetry++;
-               if (ndlp && delay) {
+               if (ndlp && NLP_CHK_NODE_ACT(ndlp) && delay) {
                        phba->fc_stat.elsDelayRetry++;
                        ndlp->nlp_retry = cmdiocb->retry;
 
@@ -2121,7 +2139,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        lpfc_issue_els_fdisc(vport, ndlp, cmdiocb->retry);
                        return 1;
                case ELS_CMD_PLOGI:
-                       if (ndlp) {
+                       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
                                ndlp->nlp_prev_state = ndlp->nlp_state;
                                lpfc_nlp_set_state(vport, ndlp,
                                                   NLP_STE_PLOGI_ISSUE);
@@ -2302,7 +2320,7 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
        mempool_free(pmb, phba->mbox_mem_pool);
-       if (ndlp) {
+       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
                lpfc_nlp_put(ndlp);
                /* This is the end of the default RPI cleanup logic for this
                 * ndlp. If no other discovery threads are using this ndlp.
@@ -2335,7 +2353,8 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
         * function can have cmdiocb->contest1 (ndlp) field set to NULL.
         */
        pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt);
-       if (ndlp && (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) {
+       if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
+           (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) {
                /* A LS_RJT associated with Default RPI cleanup has its own
                 * seperate code path.
                 */
@@ -2344,7 +2363,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        }
 
        /* Check to see if link went down during discovery */
-       if (!ndlp || lpfc_els_chk_latt(vport)) {
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || lpfc_els_chk_latt(vport)) {
                if (mbox) {
                        mp = (struct lpfc_dmabuf *) mbox->context1;
                        if (mp) {
@@ -2353,7 +2372,8 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        }
                        mempool_free(mbox, phba->mbox_mem_pool);
                }
-               if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
+               if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
+                   (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
                        if (lpfc_nlp_not_used(ndlp)) {
                                ndlp = NULL;
                                /* Indicate the node has already released,
@@ -2443,7 +2463,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                mempool_free(mbox, phba->mbox_mem_pool);
        }
 out:
-       if (ndlp) {
+       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
                spin_lock_irq(shost->host_lock);
                ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
                spin_unlock_irq(shost->host_lock);
@@ -3139,6 +3159,8 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                /* Another thread is walking fc_rscn_id_list on this vport */
                spin_unlock_irq(shost->host_lock);
                vport->fc_flag |= FC_RSCN_DISCOVERY;
+               /* Send back ACC */
+               lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
                return 0;
        }
        /* Indicate we are walking fc_rscn_id_list on this vport */
@@ -3928,7 +3950,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
                else {
                        struct lpfc_nodelist *ndlp;
                        ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext);
-                       if (ndlp)
+                       if (ndlp && NLP_CHK_NODE_ACT(ndlp))
                                remote_ID = ndlp->nlp_DID;
                }
                lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -4097,21 +4119,22 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                newnode = 1;
                if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
                        ndlp->nlp_type |= NLP_FABRIC;
-       } else {
-               if (!NLP_CHK_NODE_ACT(ndlp)) {
-                       ndlp = lpfc_enable_node(vport, ndlp,
-                                               NLP_STE_UNUSED_NODE);
-                       if (!ndlp)
-                               goto dropit;
-               }
-               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
-                       /* This is simular to the new node path */
-                       ndlp = lpfc_nlp_get(ndlp);
-                       if (!ndlp)
-                               goto dropit;
-                       lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
-                       newnode = 1;
-               }
+       } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+               ndlp = lpfc_enable_node(vport, ndlp,
+                                       NLP_STE_UNUSED_NODE);
+               if (!ndlp)
+                       goto dropit;
+               lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+               newnode = 1;
+               if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
+                       ndlp->nlp_type |= NLP_FABRIC;
+       } else if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
+               /* This is similar to the new node path */
+               ndlp = lpfc_nlp_get(ndlp);
+               if (!ndlp)
+                       goto dropit;
+               lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+               newnode = 1;
        }
 
        phba->fc_stat.elsRcvFrame++;
@@ -4451,7 +4474,6 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
                        return;
                }
                lpfc_nlp_init(vport, ndlp, NameServer_DID);
-               ndlp->nlp_type |= NLP_FABRIC;
        } else if (!NLP_CHK_NODE_ACT(ndlp)) {
                ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
                if (!ndlp) {
@@ -4465,6 +4487,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
                        return;
                }
        }
+       ndlp->nlp_type |= NLP_FABRIC;
 
        lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
 
@@ -4481,8 +4504,8 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
                if (ndlp_fdmi) {
                        lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
                        ndlp_fdmi->nlp_type |= NLP_FABRIC;
-                       ndlp_fdmi->nlp_state =
-                               NLP_STE_PLOGI_ISSUE;
+                       lpfc_nlp_set_state(vport, ndlp_fdmi,
+                               NLP_STE_PLOGI_ISSUE);
                        lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
                                             0);
                }
@@ -5074,39 +5097,3 @@ void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
                (piocb->iocb_cmpl) (phba, piocb, piocb);
        }
 }
-
-
-#if 0
-void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
-{
-       LIST_HEAD(completions);
-       struct lpfc_iocbq *tmp_iocb, *piocb;
-       IOCB_t *cmd;
-       struct lpfc_nodelist *ndlp;
-
-       spin_lock_irq(&phba->hbalock);
-       list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
-                                list) {
-
-               cmd = &piocb->iocb;
-               ndlp = (struct lpfc_nodelist *) piocb->context1;
-               if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
-                   ndlp != NULL &&
-                   ndlp->nlp_DID == Fabric_DID)
-                       list_move_tail(&piocb->list, &completions);
-       }
-       spin_unlock_irq(&phba->hbalock);
-
-       while (!list_empty(&completions)) {
-               piocb = list_get_first(&completions, struct lpfc_iocbq, list);
-               list_del_init(&piocb->list);
-
-               cmd = &piocb->iocb;
-               cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
-               cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
-               (piocb->iocb_cmpl) (phba, piocb, piocb);
-       }
-}
-#endif  /*  0  */
-
-
index 976653440fba8a3714d8f753fac8b1a52933df26..7cb68feb04fd11eb18c9a3e0d487ffe5a3b270a6 100644 (file)
@@ -69,7 +69,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
        rdata = rport->dd_data;
        ndlp = rdata->pnode;
 
-       if (!ndlp) {
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
                if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
                        printk(KERN_ERR "Cannot find remote node"
                        " to terminate I/O Data x%x\n",
@@ -114,7 +114,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
 
        rdata = rport->dd_data;
        ndlp = rdata->pnode;
-       if (!ndlp)
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
                return;
 
        vport = ndlp->vport;
@@ -243,8 +243,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
        if (warn_on) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
                                 "0203 Devloss timeout on "
-                                "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
-                                "NPort x%x Data: x%x x%x x%x\n",
+                                "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
+                                "NPort x%06x Data: x%x x%x x%x\n",
                                 *name, *(name+1), *(name+2), *(name+3),
                                 *(name+4), *(name+5), *(name+6), *(name+7),
                                 ndlp->nlp_DID, ndlp->nlp_flag,
@@ -252,8 +252,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
        } else {
                lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
                                 "0204 Devloss timeout on "
-                                "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
-                                "NPort x%x Data: x%x x%x x%x\n",
+                                "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
+                                "NPort x%06x Data: x%x x%x x%x\n",
                                 *name, *(name+1), *(name+2), *(name+3),
                                 *(name+4), *(name+5), *(name+6), *(name+7),
                                 ndlp->nlp_DID, ndlp->nlp_flag,
@@ -399,7 +399,10 @@ lpfc_work_done(struct lpfc_hba *phba)
                                vport = vports[i];
                        if (vport == NULL)
                                break;
+                       spin_lock_irq(&vport->work_port_lock);
                        work_port_events = vport->work_port_events;
+                       vport->work_port_events &= ~work_port_events;
+                       spin_unlock_irq(&vport->work_port_lock);
                        if (work_port_events & WORKER_DISC_TMO)
                                lpfc_disc_timeout_handler(vport);
                        if (work_port_events & WORKER_ELS_TMO)
@@ -416,9 +419,6 @@ lpfc_work_done(struct lpfc_hba *phba)
                                lpfc_ramp_down_queue_handler(phba);
                        if (work_port_events & WORKER_RAMP_UP_QUEUE)
                                lpfc_ramp_up_queue_handler(phba);
-                       spin_lock_irq(&vport->work_port_lock);
-                       vport->work_port_events &= ~work_port_events;
-                       spin_unlock_irq(&vport->work_port_lock);
                }
        lpfc_destroy_vport_work_array(phba, vports);
 
@@ -430,10 +430,10 @@ lpfc_work_done(struct lpfc_hba *phba)
                if (pring->flag & LPFC_STOP_IOCB_EVENT) {
                        pring->flag |= LPFC_DEFERRED_RING_EVENT;
                } else {
+                       pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
                        lpfc_sli_handle_slow_ring_event(phba, pring,
                                                        (status &
                                                         HA_RXMASK));
-                       pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
                }
                /*
                 * Turn on Ring interrupts
@@ -519,7 +519,9 @@ lpfc_do_work(void *p)
                        schedule();
                }
        }
+       spin_lock_irq(&phba->hbalock);
        phba->work_wait = NULL;
+       spin_unlock_irq(&phba->hbalock);
        return 0;
 }
 
@@ -809,11 +811,9 @@ out:
        mempool_free(pmb, phba->mbox_mem_pool);
 
        spin_lock_irq(shost->host_lock);
-       vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_ESTABLISH_LINK);
+       vport->fc_flag &= ~FC_ABORT_DISCOVERY;
        spin_unlock_irq(shost->host_lock);
 
-       del_timer_sync(&phba->fc_estabtmo);
-
        lpfc_can_disctmo(vport);
 
        /* turn on Link Attention interrupts */
@@ -1340,10 +1340,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                            i++) {
                                if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
                                        continue;
+                               if (phba->fc_topology == TOPOLOGY_LOOP) {
+                                       lpfc_vport_set_state(vports[i],
+                                                       FC_VPORT_LINKDOWN);
+                                       continue;
+                               }
                                if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
                                        lpfc_initial_fdisc(vports[i]);
-                               else if (phba->sli3_options &
-                                               LPFC_SLI3_NPIV_ENABLED) {
+                               else {
                                        lpfc_vport_set_state(vports[i],
                                                FC_VPORT_NO_FABRIC_SUPP);
                                        lpfc_printf_vlog(vport, KERN_ERR,
@@ -2190,10 +2194,6 @@ lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        if (did == Bcast_DID)
                return 0;
 
-       if (ndlp->nlp_DID == 0) {
-               return 0;
-       }
-
        /* First check for Direct match */
        if (ndlp->nlp_DID == did)
                return 1;
@@ -2301,7 +2301,8 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
                return ndlp;
        }
 
-       if (vport->fc_flag & FC_RSCN_MODE) {
+       if ((vport->fc_flag & FC_RSCN_MODE) &&
+           !(vport->fc_flag & FC_NDISC_ACTIVE)) {
                if (lpfc_rscn_payload_check(vport, did)) {
                        /* If we've already recieved a PLOGI from this NPort
                         * we don't need to try to discover it again.
@@ -2947,24 +2948,6 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
        return NULL;
 }
 
-#if 0
-/*
- * Search node lists for a remote port matching filter criteria
- * Caller needs to hold host_lock before calling this routine.
- */
-struct lpfc_nodelist *
-lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
-{
-       struct Scsi_Host     *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_nodelist *ndlp;
-
-       spin_lock_irq(shost->host_lock);
-       ndlp = __lpfc_find_node(vport, filter, param);
-       spin_unlock_irq(shost->host_lock);
-       return ndlp;
-}
-#endif  /*  0  */
-
 /*
  * This routine looks up the ndlp lists for the given RPI. If rpi found it
  * returns the node list element pointer else return NULL.
@@ -2975,20 +2958,6 @@ __lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
        return __lpfc_find_node(vport, lpfc_filter_by_rpi, &rpi);
 }
 
-#if 0
-struct lpfc_nodelist *
-lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
-{
-       struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-       struct lpfc_nodelist *ndlp;
-
-       spin_lock_irq(shost->host_lock);
-       ndlp = __lpfc_findnode_rpi(vport, rpi);
-       spin_unlock_irq(shost->host_lock);
-       return ndlp;
-}
-#endif  /*  0  */
-
 /*
  * This routine looks up the ndlp lists for the given WWPN. If WWPN found it
  * returns the node element list pointer else return NULL.
index 22843751c2caf1897bd240d514d5e85e3abf0d0d..fa757b251f8287505a21f271897598ae0141d3ea 100644 (file)
@@ -559,8 +559,10 @@ lpfc_hb_timeout(unsigned long ptr)
                phba->pport->work_port_events |= WORKER_HB_TMO;
        spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
 
+       spin_lock_irqsave(&phba->hbalock, iflag);
        if (phba->work_wait)
                wake_up(phba->work_wait);
+       spin_unlock_irqrestore(&phba->hbalock, iflag);
        return;
 }
 
@@ -714,12 +716,10 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
        struct lpfc_vport *vport = phba->pport;
        struct lpfc_sli   *psli = &phba->sli;
        struct lpfc_sli_ring  *pring;
-       struct lpfc_vport **vports;
        uint32_t event_data;
        unsigned long temperature;
        struct temp_event temp_event_data;
        struct Scsi_Host  *shost;
-       int i;
 
        /* If the pci channel is offline, ignore possible errors,
         * since we cannot communicate with the pci card anyway. */
@@ -729,25 +729,14 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
        if (!phba->cfg_enable_hba_reset)
                return;
 
-       if (phba->work_hs & HS_FFER6 ||
-           phba->work_hs & HS_FFER5) {
+       if (phba->work_hs & HS_FFER6) {
                /* Re-establishing Link */
                lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
                                "1301 Re-establishing Link "
                                "Data: x%x x%x x%x\n",
                                phba->work_hs,
                                phba->work_status[0], phba->work_status[1]);
-               vports = lpfc_create_vport_work_array(phba);
-               if (vports != NULL)
-                       for(i = 0;
-                           i <= phba->max_vpi && vports[i] != NULL;
-                           i++){
-                               shost = lpfc_shost_from_vport(vports[i]);
-                               spin_lock_irq(shost->host_lock);
-                               vports[i]->fc_flag |= FC_ESTABLISH_LINK;
-                               spin_unlock_irq(shost->host_lock);
-                       }
-               lpfc_destroy_vport_work_array(phba, vports);
+
                spin_lock_irq(&phba->hbalock);
                psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
                spin_unlock_irq(&phba->hbalock);
@@ -761,7 +750,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
                pring = &psli->ring[psli->fcp_ring];
                lpfc_sli_abort_iocb_ring(phba, pring);
 
-
                /*
                 * There was a firmware error.  Take the hba offline and then
                 * attempt to restart it.
@@ -770,7 +758,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
                lpfc_offline(phba);
                lpfc_sli_brdrestart(phba);
                if (lpfc_online(phba) == 0) {   /* Initialize the HBA */
-                       mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
                        lpfc_unblock_mgmt_io(phba);
                        return;
                }
@@ -1454,6 +1441,13 @@ lpfc_cleanup(struct lpfc_vport *vport)
                        NLP_SET_FREE_REQ(ndlp);
                spin_unlock_irq(&phba->ndlp_lock);
 
+               if (vport->port_type != LPFC_PHYSICAL_PORT &&
+                   ndlp->nlp_DID == Fabric_DID) {
+                       /* Just free up ndlp with Fabric_DID for vports */
+                       lpfc_nlp_put(ndlp);
+                       continue;
+               }
+
                if (ndlp->nlp_type & NLP_FABRIC)
                        lpfc_disc_state_machine(vport, ndlp, NULL,
                                        NLP_EVT_DEVICE_RECOVERY);
@@ -1491,31 +1485,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
        return;
 }
 
-static void
-lpfc_establish_link_tmo(unsigned long ptr)
-{
-       struct lpfc_hba   *phba = (struct lpfc_hba *) ptr;
-       struct lpfc_vport **vports;
-       unsigned long iflag;
-       int i;
-
-       /* Re-establishing Link, timer expired */
-       lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
-                       "1300 Re-establishing Link, timer expired "
-                       "Data: x%x x%x\n",
-                       phba->pport->fc_flag, phba->pport->port_state);
-       vports = lpfc_create_vport_work_array(phba);
-       if (vports != NULL)
-               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
-                       struct Scsi_Host *shost;
-                       shost = lpfc_shost_from_vport(vports[i]);
-                       spin_lock_irqsave(shost->host_lock, iflag);
-                       vports[i]->fc_flag &= ~FC_ESTABLISH_LINK;
-                       spin_unlock_irqrestore(shost->host_lock, iflag);
-               }
-       lpfc_destroy_vport_work_array(phba, vports);
-}
-
 void
 lpfc_stop_vport_timers(struct lpfc_vport *vport)
 {
@@ -1529,7 +1498,6 @@ static void
 lpfc_stop_phba_timers(struct lpfc_hba *phba)
 {
        del_timer_sync(&phba->fcp_poll_timer);
-       del_timer_sync(&phba->fc_estabtmo);
        lpfc_stop_vport_timers(phba->pport);
        del_timer_sync(&phba->sli.mbox_tmo);
        del_timer_sync(&phba->fabric_block_timer);
@@ -2005,10 +1973,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        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->hb_tmofunc);
        phba->hb_tmofunc.function = lpfc_hb_timeout;
        phba->hb_tmofunc.data = (unsigned long)phba;
@@ -2406,6 +2370,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
        struct lpfc_sli *psli = &phba->sli;
+       int error, retval;
 
        dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
        if (pci_enable_device_mem(pdev)) {
@@ -2416,15 +2381,40 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
 
        pci_set_master(pdev);
 
-       /* Re-establishing Link */
-       spin_lock_irq(shost->host_lock);
-       phba->pport->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->hbalock);
 
+       /* Enable configured interrupt method */
+       phba->intr_type = NONE;
+       if (phba->cfg_use_msi == 2) {
+               error = lpfc_enable_msix(phba);
+               if (!error)
+                       phba->intr_type = MSIX;
+       }
+
+       /* Fallback to MSI if MSI-X initialization failed */
+       if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
+               retval = pci_enable_msi(phba->pcidev);
+               if (!retval)
+                       phba->intr_type = MSI;
+               else
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                       "0470 Enable MSI failed, continuing "
+                                       "with IRQ\n");
+       }
+
+       /* MSI-X is the only case the doesn't need to call request_irq */
+       if (phba->intr_type != MSIX) {
+               retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
+                                    IRQF_SHARED, LPFC_DRIVER_NAME, phba);
+               if (retval) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "0471 Enable interrupt handler "
+                                       "failed\n");
+               } else if (phba->intr_type != MSI)
+                       phba->intr_type = INTx;
+       }
 
        /* Take device offline; this will perform cleanup */
        lpfc_offline(phba);
@@ -2445,9 +2435,7 @@ static void lpfc_io_resume(struct pci_dev *pdev)
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
 
-       if (lpfc_online(phba) == 0) {
-               mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
-       }
+       lpfc_online(phba);
 }
 
 static struct pci_device_id lpfc_id_table[] = {
index d513813f66975dfe59e09f8da95558f2e9661338..d08c4c890744d30b05da9b60dc018e71c2af8bcc 100644 (file)
@@ -451,7 +451,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        spin_unlock_irq(shost->host_lock);
 
                        if ((ndlp->nlp_flag & NLP_ADISC_SND) &&
-                               (vport->num_disc_nodes)) {
+                           (vport->num_disc_nodes)) {
                                /* Check to see if there are more
                                 * ADISCs to be sent
                                 */
@@ -461,20 +461,6 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                                        (vport->fc_npr_cnt))
                                        lpfc_els_disc_plogi(vport);
 
-                               if (vport->num_disc_nodes == 0) {
-                                       spin_lock_irq(shost->host_lock);
-                                       vport->fc_flag &= ~FC_NDISC_ACTIVE;
-                                       spin_unlock_irq(shost->host_lock);
-                                       lpfc_can_disctmo(vport);
-                                       lpfc_end_rscn(vport);
-                               }
-                       }
-                       else if (vport->num_disc_nodes) {
-                               /* Check to see if there are more
-                                * PLOGIs to be sent
-                                */
-                               lpfc_more_plogi(vport);
-
                                if (vport->num_disc_nodes == 0) {
                                        spin_lock_irq(shost->host_lock);
                                        vport->fc_flag &= ~FC_NDISC_ACTIVE;
@@ -484,6 +470,23 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                                }
                        }
                }
+       } else if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) &&
+                  (ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
+                  (vport->num_disc_nodes)) {
+               spin_lock_irq(shost->host_lock);
+               ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+               spin_unlock_irq(shost->host_lock);
+               /* Check to see if there are more
+                * PLOGIs to be sent
+                */
+               lpfc_more_plogi(vport);
+               if (vport->num_disc_nodes == 0) {
+                       spin_lock_irq(shost->host_lock);
+                       vport->fc_flag &= ~FC_NDISC_ACTIVE;
+                       spin_unlock_irq(shost->host_lock);
+                       lpfc_can_disctmo(vport);
+                       lpfc_end_rscn(vport);
+               }
        }
 
        lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox);
@@ -869,8 +872,11 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
 
        lp = (uint32_t *) prsp->virt;
        sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
-       if (wwn_to_u64(sp->portName.u.wwn) == 0 ||
-           wwn_to_u64(sp->nodeName.u.wwn) == 0) {
+
+       /* Some switches have FDMI servers returning 0 for WWN */
+       if ((ndlp->nlp_DID != FDMI_DID) &&
+               (wwn_to_u64(sp->portName.u.wwn) == 0 ||
+               wwn_to_u64(sp->nodeName.u.wwn) == 0)) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
                                 "0142 PLOGI RSP: Invalid WWN.\n");
                goto out;
index 70255c11d3adde772d88f8288441c8fed324b98e..0910a9ab76a506014073c7af98ad61df8a2a6100 100644 (file)
@@ -169,6 +169,9 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
                for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        shost = lpfc_shost_from_vport(vports[i]);
                        shost_for_each_device(sdev, shost) {
+                               if (vports[i]->cfg_lun_queue_depth <=
+                                   sdev->queue_depth)
+                                       continue;
                                if (sdev->ordered_tags)
                                        scsi_adjust_queue_depth(sdev,
                                                        MSG_ORDERED_TAG,
@@ -578,14 +581,14 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                            lpfc_cmd->result == IOERR_NO_RESOURCES ||
                            lpfc_cmd->result == RJT_LOGIN_REQUIRED) {
                                cmd->result = ScsiResult(DID_REQUEUE, 0);
-                       break;
-               } /* else: fall through */
+                               break;
+                       } /* else: fall through */
                default:
                        cmd->result = ScsiResult(DID_ERROR, 0);
                        break;
                }
 
-               if ((pnode == NULL )
+               if (!pnode || !NLP_CHK_NODE_ACT(pnode)
                    || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
                        cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY);
        } else {
@@ -606,6 +609,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        result = cmd->result;
        sdev = cmd->device;
        lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
+       spin_lock_irqsave(sdev->host->host_lock, flags);
+       lpfc_cmd->pCmd = NULL;  /* This must be done before scsi_done */
+       spin_unlock_irqrestore(sdev->host->host_lock, flags);
        cmd->scsi_done(cmd);
 
        if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
@@ -614,7 +620,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                 * wake up the thread.
                 */
                spin_lock_irqsave(sdev->host->host_lock, flags);
-               lpfc_cmd->pCmd = NULL;
                if (lpfc_cmd->waitq)
                        wake_up(lpfc_cmd->waitq);
                spin_unlock_irqrestore(sdev->host->host_lock, flags);
@@ -626,7 +631,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        if (!result)
                lpfc_rampup_queue_depth(vport, sdev);
 
-       if (!result && pnode != NULL &&
+       if (!result && pnode && NLP_CHK_NODE_ACT(pnode) &&
           ((jiffies - pnode->last_ramp_up_time) >
                LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
           ((jiffies - pnode->last_q_full_time) >
@@ -654,7 +659,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
         * Check for queue full.  If the lun is reporting queue full, then
         * back off the lun queue depth to prevent target overloads.
         */
-       if (result == SAM_STAT_TASK_SET_FULL && pnode != NULL) {
+       if (result == SAM_STAT_TASK_SET_FULL && pnode &&
+           NLP_CHK_NODE_ACT(pnode)) {
                pnode->last_q_full_time = jiffies;
 
                shost_for_each_device(tmp_sdev, sdev->host) {
@@ -684,7 +690,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
         * wake up the thread.
         */
        spin_lock_irqsave(sdev->host->host_lock, flags);
-       lpfc_cmd->pCmd = NULL;
        if (lpfc_cmd->waitq)
                wake_up(lpfc_cmd->waitq);
        spin_unlock_irqrestore(sdev->host->host_lock, flags);
@@ -704,6 +709,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
        int datadir = scsi_cmnd->sc_data_direction;
        char tag[2];
 
+       if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+               return;
+
        lpfc_cmd->fcp_rsp->rspSnsLen = 0;
        /* clear task management bits */
        lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
@@ -785,9 +793,9 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
        struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
        struct lpfc_nodelist *ndlp = rdata->pnode;
 
-       if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
+           ndlp->nlp_state != NLP_STE_MAPPED_NODE)
                return 0;
-       }
 
        piocbq = &(lpfc_cmd->cur_iocbq);
        piocbq->vport = vport;
@@ -842,7 +850,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
        struct lpfc_iocbq *iocbqrsp;
        int ret;
 
-       if (!rdata->pnode)
+       if (!rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode))
                return FAILED;
 
        lpfc_cmd->rdata = rdata;
@@ -959,7 +967,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
         * Catch race where our node has transitioned, but the
         * transport is still transitioning.
         */
-       if (!ndlp) {
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
                cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
                goto out_fail_command;
        }
@@ -1146,7 +1154,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
         * target is rediscovered or devloss timeout expires.
         */
        while (1) {
-               if (!pnode)
+               if (!pnode || !NLP_CHK_NODE_ACT(pnode))
                        goto out;
 
                if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
@@ -1162,7 +1170,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
                                goto out;
                        }
                        pnode = rdata->pnode;
-                       if (!pnode)
+                       if (!pnode || !NLP_CHK_NODE_ACT(pnode))
                                goto out;
                }
                if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
index fc0d9501aba628f41a79c0b4a8ae31f384d60ab2..70a0a9eab21106a70cba3bef3589a1ee3261db29 100644 (file)
@@ -2648,7 +2648,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
        spin_unlock_irq(&phba->pport->work_port_lock);
        spin_lock_irq(&phba->hbalock);
        phba->link_state = LPFC_LINK_UNKNOWN;
-       phba->pport->fc_flag |= FC_ESTABLISH_LINK;
        psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
        spin_unlock_irq(&phba->hbalock);
 
@@ -2669,8 +2668,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
        lpfc_offline_prep(phba);
        lpfc_offline(phba);
        lpfc_sli_brdrestart(phba);
-       if (lpfc_online(phba) == 0)             /* Initialize the HBA */
-               mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+       lpfc_online(phba);
        lpfc_unblock_mgmt_io(phba);
        return;
 }
@@ -2687,28 +2685,41 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
        unsigned long drvr_flag = 0;
        volatile uint32_t word0, ldata;
        void __iomem *to_slim;
+       int processing_queue = 0;
+
+       spin_lock_irqsave(&phba->hbalock, drvr_flag);
+       if (!pmbox) {
+               /* processing mbox queue from intr_handler */
+               processing_queue = 1;
+               phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+               pmbox = lpfc_mbox_get(phba);
+               if (!pmbox) {
+                       spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+                       return MBX_SUCCESS;
+               }
+       }
 
        if (pmbox->mbox_cmpl && pmbox->mbox_cmpl != lpfc_sli_def_mbox_cmpl &&
                pmbox->mbox_cmpl != lpfc_sli_wake_mbox_wait) {
                if(!pmbox->vport) {
+                       spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
                        lpfc_printf_log(phba, KERN_ERR,
                                        LOG_MBOX | LOG_VPORT,
                                        "1806 Mbox x%x failed. No vport\n",
                                        pmbox->mb.mbxCommand);
                        dump_stack();
-                       return MBX_NOT_FINISHED;
+                       goto out_not_finished;
                }
        }
 
-
        /* If the PCI channel is in offline state, do not post mbox. */
-       if (unlikely(pci_channel_offline(phba->pcidev)))
-               return MBX_NOT_FINISHED;
+       if (unlikely(pci_channel_offline(phba->pcidev))) {
+               spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+               goto out_not_finished;
+       }
 
-       spin_lock_irqsave(&phba->hbalock, drvr_flag);
        psli = &phba->sli;
 
-
        mb = &pmbox->mb;
        status = MBX_SUCCESS;
 
@@ -2717,14 +2728,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
 
                /* Mbox command <mbxCommand> cannot issue */
                LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-               return MBX_NOT_FINISHED;
+               goto out_not_finished;
        }
 
        if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
            !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
                spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
                LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-               return MBX_NOT_FINISHED;
+               goto out_not_finished;
        }
 
        if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
@@ -2738,14 +2749,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
 
                        /* Mbox command <mbxCommand> cannot issue */
                        LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-                       return MBX_NOT_FINISHED;
+                       goto out_not_finished;
                }
 
                if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
                        spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
                        /* Mbox command <mbxCommand> cannot issue */
                        LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-                       return MBX_NOT_FINISHED;
+                       goto out_not_finished;
                }
 
                /* Another mailbox command is still being processed, queue this
@@ -2792,7 +2803,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
                        spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
                        /* Mbox command <mbxCommand> cannot issue */
                        LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
-                       return MBX_NOT_FINISHED;
+                       goto out_not_finished;
                }
                /* timeout active mbox command */
                mod_timer(&psli->mbox_tmo, (jiffies +
@@ -2900,7 +2911,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
                                psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
                                spin_unlock_irqrestore(&phba->hbalock,
                                                       drvr_flag);
-                               return MBX_NOT_FINISHED;
+                               goto out_not_finished;
                        }
 
                        /* Check if we took a mbox interrupt while we were
@@ -2967,6 +2978,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
 
        spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
        return status;
+
+out_not_finished:
+       if (processing_queue) {
+               pmbox->mb.mbxStatus = MBX_NOT_FINISHED;
+               lpfc_mbox_cmpl_put(phba, pmbox);
+       }
+       return MBX_NOT_FINISHED;
 }
 
 /*
@@ -3463,26 +3481,21 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
        phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
        spin_unlock(&phba->pport->work_port_lock);
 
+       /* Return any pending or completed mbox cmds */
+       list_splice_init(&phba->sli.mboxq, &completions);
        if (psli->mbox_active) {
                list_add_tail(&psli->mbox_active->list, &completions);
                psli->mbox_active = NULL;
                psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
        }
-
-       /* Return any pending or completed mbox cmds */
-       list_splice_init(&phba->sli.mboxq, &completions);
        list_splice_init(&phba->sli.mboxq_cmpl, &completions);
-       INIT_LIST_HEAD(&psli->mboxq);
-       INIT_LIST_HEAD(&psli->mboxq_cmpl);
-
        spin_unlock_irqrestore(&phba->hbalock, flags);
 
        while (!list_empty(&completions)) {
                list_remove_head(&completions, pmb, LPFC_MBOXQ_t, list);
                pmb->mb.mbxStatus = MBX_NOT_FINISHED;
-               if (pmb->mbox_cmpl) {
+               if (pmb->mbox_cmpl)
                        pmb->mbox_cmpl(phba,pmb);
-               }
        }
        return 1;
 }
@@ -3612,6 +3625,15 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                abort_iocb, abort_iotag, abort_context,
                                irsp->ulpStatus, irsp->un.ulpWord[4]);
 
+               /*
+                *  If the iocb is not found in Firmware queue the iocb
+                *  might have completed already. Do not free it again.
+                */
+               if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
+                       spin_unlock_irq(&phba->hbalock);
+                       lpfc_sli_release_iocbq(phba, cmdiocb);
+                       return;
+               }
                /*
                 * make sure we have the right iocbq before taking it
                 * off the txcmplq and try to call completion routine.
@@ -4174,6 +4196,7 @@ lpfc_intr_handler(int irq, void *dev_id)
                        phba->pport->stopped = 1;
                }
 
+               spin_lock(&phba->hbalock);
                if ((work_ha_copy & HA_MBATT) &&
                    (phba->sli.mbox_active)) {
                        pmb = phba->sli.mbox_active;
@@ -4184,6 +4207,7 @@ lpfc_intr_handler(int irq, void *dev_id)
                        /* First check out the status word */
                        lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
                        if (pmbox->mbxOwner != OWN_HOST) {
+                               spin_unlock(&phba->hbalock);
                                /*
                                 * Stray Mailbox Interrupt, mbxCommand <cmd>
                                 * mbxStatus <status>
@@ -4199,10 +4223,10 @@ lpfc_intr_handler(int irq, void *dev_id)
                                /* clear mailbox attention bit */
                                work_ha_copy &= ~HA_MBATT;
                        } else {
+                               phba->sli.mbox_active = NULL;
+                               spin_unlock(&phba->hbalock);
                                phba->last_completion_time = jiffies;
                                del_timer(&phba->sli.mbox_tmo);
-
-                               phba->sli.mbox_active = NULL;
                                if (pmb->mbox_cmpl) {
                                        lpfc_sli_pcimem_bcopy(mbox, pmbox,
                                                        MAILBOX_CMD_SIZE);
@@ -4237,10 +4261,15 @@ lpfc_intr_handler(int irq, void *dev_id)
                                                pmb->context1 = mp;
                                                pmb->context2 = ndlp;
                                                pmb->vport = vport;
-                                               spin_lock(&phba->hbalock);
-                                               phba->sli.sli_flag &=
-                                                       ~LPFC_SLI_MBOX_ACTIVE;
-                                               spin_unlock(&phba->hbalock);
+                                               rc = lpfc_sli_issue_mbox(phba,
+                                                               pmb,
+                                                               MBX_NOWAIT);
+                                               if (rc != MBX_BUSY)
+                                                       lpfc_printf_log(phba,
+                                                       KERN_ERR,
+                                                       LOG_MBOX | LOG_SLI,
+                                                       "0306 rc should have"
+                                                       "been MBX_BUSY");
                                                goto send_current_mbox;
                                        }
                                }
@@ -4250,25 +4279,20 @@ lpfc_intr_handler(int irq, void *dev_id)
                                spin_unlock(&phba->pport->work_port_lock);
                                lpfc_mbox_cmpl_put(phba, pmb);
                        }
-               }
+               } else
+                       spin_unlock(&phba->hbalock);
                if ((work_ha_copy & HA_MBATT) &&
                    (phba->sli.mbox_active == NULL)) {
-send_next_mbox:
-                       spin_lock(&phba->hbalock);
-                       phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
-                       pmb = lpfc_mbox_get(phba);
-                       spin_unlock(&phba->hbalock);
 send_current_mbox:
                        /* Process next mailbox command if there is one */
-                       if (pmb != NULL) {
-                               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-                               if (rc == MBX_NOT_FINISHED) {
-                                       pmb->mb.mbxStatus = MBX_NOT_FINISHED;
-                                       lpfc_mbox_cmpl_put(phba, pmb);
-                                       goto send_next_mbox;
-                               }
-                       }
-
+                       do {
+                               rc = lpfc_sli_issue_mbox(phba, NULL,
+                                                        MBX_NOWAIT);
+                       } while (rc == MBX_NOT_FINISHED);
+                       if (rc != MBX_SUCCESS)
+                               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
+                                               LOG_SLI, "0349 rc should be "
+                                               "MBX_SUCCESS");
                }
 
                spin_lock(&phba->hbalock);
index ca540d1d041e2ef1d9cd5b9889f1756a11633782..b22b893019f4046647f7cbf6d74d11e481fb1d53 100644 (file)
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.2.5"
+#define LPFC_DRIVER_VERSION "8.2.6"
 
 #define LPFC_DRIVER_NAME "lpfc"
 
index 86d05beb00b864e84d3b25e8d311111361e79ac6..6feaf59b0b1b28eb962d886a5caec20bbff74a0a 100644 (file)
@@ -538,7 +538,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
        /* Otherwise, we will perform fabric logo as needed */
        if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
            ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
-           phba->link_state >= LPFC_LINK_UP) {
+           phba->link_state >= LPFC_LINK_UP &&
+           phba->fc_topology != TOPOLOGY_LOOP) {
                if (vport->cfg_enable_da_id) {
                        timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
                        if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0))
index 3b09ab21d701ba9d8726c48647cee64a85364bda..0248919bc2df47b3ed8aac6dc14384f78b098a66 100644 (file)
@@ -592,7 +592,6 @@ static struct scsi_host_template driver_template = {
        .this_id                        = 7,
        .sg_tablesize                   = SG_ALL,
        .cmd_per_lun                    = CMD_PER_LUN,
-       .unchecked_isa_dma              = 0,
        .use_clustering                 = DISABLE_CLUSTERING
 };
 
index 77a62a1b12c3e52cf76df0c3f65f58e607d293b8..b937e9cddb2381608f2002320a18f82fc4729a55 100644 (file)
@@ -68,6 +68,8 @@ static struct pci_device_id megasas_pci_table[] = {
        /* xscale IOP */
        {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
        /* ppc IOP */
+       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
+       /* ppc IOP */
        {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
        /* xscale IOP, vega */
        {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
@@ -488,12 +490,13 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
 
  /**
  * megasas_get_frame_count - Computes the number of frames
+ * @frame_type         : type of frame- io or pthru frame
  * @sge_count          : number of sg elements
  *
  * Returns the number of frames required for numnber of sge's (sge_count)
  */
 
-static u32 megasas_get_frame_count(u8 sge_count)
+static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
 {
        int num_cnt;
        int sge_bytes;
@@ -504,13 +507,22 @@ static u32 megasas_get_frame_count(u8 sge_count)
            sizeof(struct megasas_sge32);
 
        /*
-       * Main frame can contain 2 SGEs for 64-bit SGLs and
-       * 3 SGEs for 32-bit SGLs
-       */
-       if (IS_DMA64)
-               num_cnt = sge_count - 2;
-       else
-               num_cnt = sge_count - 3;
+        * Main frame can contain 2 SGEs for 64-bit SGLs and
+        * 3 SGEs for 32-bit SGLs for ldio &
+        * 1 SGEs for 64-bit SGLs and
+        * 2 SGEs for 32-bit SGLs for pthru frame
+        */
+       if (unlikely(frame_type == PTHRU_FRAME)) {
+               if (IS_DMA64)
+                       num_cnt = sge_count - 1;
+               else
+                       num_cnt = sge_count - 2;
+       } else {
+               if (IS_DMA64)
+                       num_cnt = sge_count - 2;
+               else
+                       num_cnt = sge_count - 3;
+       }
 
        if(num_cnt>0){
                sge_bytes = sge_sz * num_cnt;
@@ -592,7 +604,8 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
         * Compute the total number of frames this command consumes. FW uses
         * this number to pull sufficient number of frames from host memory.
         */
-       cmd->frame_count = megasas_get_frame_count(pthru->sge_count);
+       cmd->frame_count = megasas_get_frame_count(pthru->sge_count,
+                                                       PTHRU_FRAME);
 
        return cmd->frame_count;
 }
@@ -709,7 +722,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
         * Compute the total number of frames this command consumes. FW uses
         * this number to pull sufficient number of frames from host memory.
         */
-       cmd->frame_count = megasas_get_frame_count(ldio->sge_count);
+       cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME);
 
        return cmd->frame_count;
 }
@@ -1460,7 +1473,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
                        instance->instancet->disable_intr(instance->reg_set);
                        writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
 
-                       max_wait = 10;
+                       max_wait = 60;
                        cur_state = MFI_STATE_OPERATIONAL;
                        break;
 
@@ -1980,7 +1993,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
 
        switch(instance->pdev->device)
        {
-               case PCI_DEVICE_ID_LSI_SAS1078R:        
+               case PCI_DEVICE_ID_LSI_SAS1078R:
+               case PCI_DEVICE_ID_LSI_SAS1078DE:
                        instance->instancet = &megasas_instance_template_ppc;
                        break;
                case PCI_DEVICE_ID_LSI_SAS1064R:
@@ -2909,7 +2923,6 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        void *sense = NULL;
        dma_addr_t sense_handle;
        u32 *sense_ptr;
-       unsigned long *sense_buff;
 
        memset(kbuff_arr, 0, sizeof(kbuff_arr));
 
@@ -3014,14 +3027,14 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
         */
        if (ioc->sense_len) {
                /*
-                * sense_buff points to the location that has the user
+                * sense_ptr points to the location that has the user
                 * sense buffer address
                 */
-               sense_buff = (unsigned long *) ((unsigned long)ioc->frame.raw +
-                                                               ioc->sense_off);
+               sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
+                                    ioc->sense_off);
 
-               if (copy_to_user((void __user *)(unsigned long)(*sense_buff),
-                               sense, ioc->sense_len)) {
+               if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
+                                sense, ioc->sense_len)) {
                        printk(KERN_ERR "megasas: Failed to copy out to user "
                                        "sense data\n");
                        error = -EFAULT;
index 6466bdf548c2d8addce967c3b08f2fca7647d009..3a997eb457bf84813212c046beb08e73a51774cc 100644 (file)
@@ -26,6 +26,7 @@
  * Device IDs
  */
 #define        PCI_DEVICE_ID_LSI_SAS1078R              0x0060
+#define        PCI_DEVICE_ID_LSI_SAS1078DE             0x007C
 #define        PCI_DEVICE_ID_LSI_VERDE_ZCR             0x0413
 
 /*
@@ -542,6 +543,10 @@ struct megasas_ctrl_info {
 
 #define MEGASAS_FW_BUSY                                1
 
+/* Frame Type */
+#define IO_FRAME                               0
+#define PTHRU_FRAME                            1
+
 /*
  * When SCSI mid-layer calls driver's reset routine, driver waits for
  * MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
index be41aadccae569918dd7259c5290133bd1cf3997..d722235111a8d317d052874b3a7ace4579bafd64 100644 (file)
@@ -82,6 +82,9 @@ int mvme147_detect(struct scsi_host_template *tpnt)
     mvme147_host->irq = MVME147_IRQ_SCSI_PORT;
     regs.SASR = (volatile unsigned char *)0xfffe4000;
     regs.SCMD = (volatile unsigned char *)0xfffe4001;
+    HDATA(mvme147_host)->no_sync = 0xff;
+    HDATA(mvme147_host)->fast = 0;
+    HDATA(mvme147_host)->dma_mode = CTRL_DMA;
     wd33c93_init(mvme147_host, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
 
     if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, "MVME147 SCSI PORT", mvme147_intr))
index fad6cb5cba283acc8410e9d8bed1e996062d03b8..ce48e2d0193c64e379a5cfd1cfe5ab14f2a9a29a 100644 (file)
@@ -26,6 +26,7 @@
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_eh.h>
 
 #include <asm/lv1call.h>
 #include <asm/ps3stor.h>
@@ -90,78 +91,6 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
        return 0;
 }
 
-/*
- * copy data from device into scatter/gather buffer
- */
-static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
-{
-       int k, req_len, act_len, len, active;
-       void *kaddr;
-       struct scatterlist *sgpnt;
-       unsigned int buflen;
-
-       buflen = scsi_bufflen(cmd);
-       if (!buflen)
-               return 0;
-
-       if (!scsi_sglist(cmd))
-               return -1;
-
-       active = 1;
-       req_len = act_len = 0;
-       scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
-               if (active) {
-                       kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
-                       len = sgpnt->length;
-                       if ((req_len + len) > buflen) {
-                               active = 0;
-                               len = buflen - req_len;
-                       }
-                       memcpy(kaddr + sgpnt->offset, buf + req_len, len);
-                       flush_kernel_dcache_page(sg_page(sgpnt));
-                       kunmap_atomic(kaddr, KM_IRQ0);
-                       act_len += len;
-               }
-               req_len += sgpnt->length;
-       }
-       scsi_set_resid(cmd, buflen - act_len);
-       return 0;
-}
-
-/*
- * copy data from scatter/gather into device's buffer
- */
-static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf)
-{
-       int k, req_len, len, fin;
-       void *kaddr;
-       struct scatterlist *sgpnt;
-       unsigned int buflen;
-
-       buflen = scsi_bufflen(cmd);
-       if (!buflen)
-               return 0;
-
-       if (!scsi_sglist(cmd))
-               return -1;
-
-       req_len = fin = 0;
-       scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
-               kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
-               len = sgpnt->length;
-               if ((req_len + len) > buflen) {
-                       len = buflen - req_len;
-                       fin = 1;
-               }
-               memcpy(buf + req_len, kaddr + sgpnt->offset, len);
-               kunmap_atomic(kaddr, KM_IRQ0);
-               if (fin)
-                       return req_len + len;
-               req_len += sgpnt->length;
-       }
-       return req_len;
-}
-
 static int ps3rom_atapi_request(struct ps3_storage_device *dev,
                                struct scsi_cmnd *cmd)
 {
@@ -195,9 +124,7 @@ static int ps3rom_atapi_request(struct ps3_storage_device *dev,
                else
                        atapi_cmnd.proto = PIO_DATA_OUT_PROTO;
                atapi_cmnd.in_out = DIR_WRITE;
-               res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
-               if (res < 0)
-                       return DID_ERROR << 16;
+               scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
                break;
 
        default:
@@ -269,9 +196,7 @@ static int ps3rom_write_request(struct ps3_storage_device *dev,
        dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n",
                __func__, __LINE__, sectors, start_sector);
 
-       res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
-       if (res < 0)
-               return DID_ERROR << 16;
+       scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
 
        res = lv1_storage_write(dev->sbd.dev_id,
                                dev->regions[dev->region_idx].id, start_sector,
@@ -381,11 +306,13 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data)
        if (!status) {
                /* OK, completed */
                if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
-                       res = fill_from_dev_buffer(cmd, dev->bounce_buf);
-                       if (res) {
-                               cmd->result = DID_ERROR << 16;
-                               goto done;
-                       }
+                       int len;
+
+                       len = scsi_sg_copy_from_buffer(cmd,
+                                                      dev->bounce_buf,
+                                                      dev->bounce_size);
+
+                       scsi_set_resid(cmd, scsi_bufflen(cmd) - len);
                }
                cmd->result = DID_OK << 16;
                goto done;
@@ -404,11 +331,7 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data)
                goto done;
        }
 
-       cmd->sense_buffer[0]  = 0x70;
-       cmd->sense_buffer[2]  = sense_key;
-       cmd->sense_buffer[7]  = 16 - 6;
-       cmd->sense_buffer[12] = asc;
-       cmd->sense_buffer[13] = ascq;
+       scsi_build_sense_buffer(0, cmd->sense_buffer, sense_key, asc, ascq);
        cmd->result = SAM_STAT_CHECK_CONDITION;
 
 done:
@@ -427,7 +350,7 @@ static struct scsi_host_template ps3rom_host_template = {
        .cmd_per_lun =          1,
        .emulated =             1,              /* only sg driver uses this */
        .max_sectors =          PS3ROM_MAX_SECTORS,
-       .use_clustering =       DISABLE_CLUSTERING,
+       .use_clustering =       ENABLE_CLUSTERING,
        .module =               THIS_MODULE,
 };
 
index 68c0d09ffe786fe6416f69e948fd0a82e85d5e28..09ab3eac1c1abe9ac2e571e277cb3e1cfdfd4c8d 100644 (file)
 
 #include <linux/module.h>
 
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <asm/sn/io.h>
 #endif
 
-#if LINUX_VERSION_CODE < 0x020600
-#error "Kernels older than 2.6.0 are no longer supported"
-#endif
-
 
 /*
  * Compile time Options:
index 8c865b9e02b579f2d5bfc64a706fec3ea4063433..6208d562890d1cb3cfb3c85845dddf02086c4fb2 100644 (file)
@@ -16,7 +16,8 @@ config SCSI_QLA_FC
        22xx              ql2200_fw.bin
        2300, 2312, 6312  ql2300_fw.bin
        2322, 6322        ql2322_fw.bin
-       24xx              ql2400_fw.bin
+       24xx, 54xx        ql2400_fw.bin
+       25xx              ql2500_fw.bin
 
        Upon request, the driver caches the firmware image until
        the driver is unloaded.
index 4894dc886b6286fb446da3dbaa173269c0dd7a22..413d8cd6a3247c6365e2e77a83198f167dbbe8c1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -849,20 +849,20 @@ static void
 qla2x00_get_host_speed(struct Scsi_Host *shost)
 {
        scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
-       uint32_t speed = 0;
+       u32 speed = FC_PORTSPEED_UNKNOWN;
 
        switch (ha->link_data_rate) {
        case PORT_SPEED_1GB:
-               speed = 1;
+               speed = FC_PORTSPEED_1GBIT;
                break;
        case PORT_SPEED_2GB:
-               speed = 2;
+               speed = FC_PORTSPEED_2GBIT;
                break;
        case PORT_SPEED_4GB:
-               speed = 4;
+               speed = FC_PORTSPEED_4GBIT;
                break;
        case PORT_SPEED_8GB:
-               speed = 8;
+               speed = FC_PORTSPEED_8GBIT;
                break;
        }
        fc_host_speed(shost) = speed;
@@ -900,7 +900,8 @@ qla2x00_get_starget_node_name(struct scsi_target *starget)
        u64 node_name = 0;
 
        list_for_each_entry(fcport, &ha->fcports, list) {
-               if (starget->id == fcport->os_target_id) {
+               if (fcport->rport &&
+                   starget->id == fcport->rport->scsi_target_id) {
                        node_name = wwn_to_u64(fcport->node_name);
                        break;
                }
@@ -918,7 +919,8 @@ qla2x00_get_starget_port_name(struct scsi_target *starget)
        u64 port_name = 0;
 
        list_for_each_entry(fcport, &ha->fcports, list) {
-               if (starget->id == fcport->os_target_id) {
+               if (fcport->rport &&
+                   starget->id == fcport->rport->scsi_target_id) {
                        port_name = wwn_to_u64(fcport->port_name);
                        break;
                }
@@ -936,7 +938,8 @@ qla2x00_get_starget_port_id(struct scsi_target *starget)
        uint32_t port_id = ~0U;
 
        list_for_each_entry(fcport, &ha->fcports, list) {
-               if (starget->id == fcport->os_target_id) {
+               if (fcport->rport &&
+                   starget->id == fcport->rport->scsi_target_id) {
                        port_id = fcport->d_id.b.domain << 16 |
                            fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
                        break;
@@ -1196,6 +1199,7 @@ struct fc_function_template qla2xxx_transport_functions = {
        .show_host_node_name = 1,
        .show_host_port_name = 1,
        .show_host_supported_classes = 1,
+       .show_host_supported_speeds = 1,
 
        .get_host_port_id = qla2x00_get_host_port_id,
        .show_host_port_id = 1,
@@ -1276,9 +1280,23 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
 void
 qla2x00_init_host_attr(scsi_qla_host_t *ha)
 {
+       u32 speed = FC_PORTSPEED_UNKNOWN;
+
        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) = ha->max_npiv_vports;;
        fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count;
+
+       if (IS_QLA25XX(ha))
+               speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
+                   FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
+       else if (IS_QLA24XX_TYPE(ha))
+               speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
+                   FC_PORTSPEED_1GBIT;
+       else if (IS_QLA23XX(ha))
+               speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
+       else
+               speed = FC_PORTSPEED_1GBIT;
+       fc_host_supported_speeds(ha->host) = speed;
 }
index d88e98c476b01c156e52c6d790be0d981056631a..9d12d9f2620930015ec2d56c29a11b58660fe4de 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -1410,125 +1410,3 @@ qla2x00_dump_buffer(uint8_t * b, uint32_t size)
        if (cnt % 16)
                printk("\n");
 }
-
-/**************************************************************************
- *   qla2x00_print_scsi_cmd
- *      Dumps out info about the scsi cmd and srb.
- *   Input
- *      cmd : struct scsi_cmnd
- **************************************************************************/
-void
-qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd)
-{
-       int i;
-       struct scsi_qla_host *ha;
-       srb_t *sp;
-
-       ha = shost_priv(cmd->device->host);
-
-       sp = (srb_t *) cmd->SCp.ptr;
-       printk("SCSI Command @=0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
-       printk("  chan=0x%02x, target=0x%02x, lun=0x%02x, cmd_len=0x%02x\n",
-           cmd->device->channel, cmd->device->id, cmd->device->lun,
-           cmd->cmd_len);
-       printk(" CDB: ");
-       for (i = 0; i < cmd->cmd_len; i++) {
-               printk("0x%02x ", cmd->cmnd[i]);
-       }
-       printk("\n  seg_cnt=%d, allowed=%d, retries=%d\n",
-              scsi_sg_count(cmd), cmd->allowed, cmd->retries);
-       printk("  request buffer=0x%p, request buffer len=0x%x\n",
-              scsi_sglist(cmd), scsi_bufflen(cmd));
-       printk("  tag=%d, transfersize=0x%x\n",
-           cmd->tag, cmd->transfersize);
-       printk("  serial_number=%lx, SP=%p\n", cmd->serial_number, sp);
-       printk("  data direction=%d\n", cmd->sc_data_direction);
-
-       if (!sp)
-               return;
-
-       printk("  sp flags=0x%x\n", sp->flags);
-}
-
-#if defined(QL_DEBUG_ROUTINES)
-/*
- * qla2x00_formatted_dump_buffer
- *       Prints string plus buffer.
- *
- * Input:
- *       string  = Null terminated string (no newline at end).
- *       buffer  = buffer address.
- *       wd_size = word size 8, 16, 32 or 64 bits
- *       count   = number of words.
- */
-void
-qla2x00_formatted_dump_buffer(char *string, uint8_t * buffer,
-                               uint8_t wd_size, uint32_t count)
-{
-       uint32_t cnt;
-       uint16_t *buf16;
-       uint32_t *buf32;
-
-       if (strcmp(string, "") != 0)
-               printk("%s\n",string);
-
-       switch (wd_size) {
-               case 8:
-                       printk(" 0    1    2    3    4    5    6    7    "
-                               "8    9    Ah   Bh   Ch   Dh   Eh   Fh\n");
-                       printk("-----------------------------------------"
-                               "-------------------------------------\n");
-
-                       for (cnt = 1; cnt <= count; cnt++, buffer++) {
-                               printk("%02x",*buffer);
-                               if (cnt % 16 == 0)
-                                       printk("\n");
-                               else
-                                       printk("  ");
-                       }
-                       if (cnt % 16 != 0)
-                               printk("\n");
-                       break;
-               case 16:
-                       printk("   0      2      4      6      8      Ah "
-                               "       Ch     Eh\n");
-                       printk("-----------------------------------------"
-                               "-------------\n");
-
-                       buf16 = (uint16_t *) buffer;
-                       for (cnt = 1; cnt <= count; cnt++, buf16++) {
-                               printk("%4x",*buf16);
-
-                               if (cnt % 8 == 0)
-                                       printk("\n");
-                               else if (*buf16 < 10)
-                                       printk("   ");
-                               else
-                                       printk("  ");
-                       }
-                       if (cnt % 8 != 0)
-                               printk("\n");
-                       break;
-               case 32:
-                       printk("       0          4          8          Ch\n");
-                       printk("------------------------------------------\n");
-
-                       buf32 = (uint32_t *) buffer;
-                       for (cnt = 1; cnt <= count; cnt++, buf32++) {
-                               printk("%8x", *buf32);
-
-                               if (cnt % 4 == 0)
-                                       printk("\n");
-                               else if (*buf32 < 10)
-                                       printk("   ");
-                               else
-                                       printk("  ");
-                       }
-                       if (cnt % 4 != 0)
-                               printk("\n");
-                       break;
-               default:
-                       break;
-       }
-}
-#endif
index 524598afc81c2d561e8ef2542929bc64f320c290..2e9c0c097f5e1bddfd901e0398eac8c77bee9fa9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
 /* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */
 /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */
 /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
-/*
- *  Local Macro Definitions.
- */
-#if defined(QL_DEBUG_LEVEL_1)  || defined(QL_DEBUG_LEVEL_2) || \
-    defined(QL_DEBUG_LEVEL_3)  || defined(QL_DEBUG_LEVEL_4) || \
-    defined(QL_DEBUG_LEVEL_5)  || defined(QL_DEBUG_LEVEL_6) || \
-    defined(QL_DEBUG_LEVEL_7)  || defined(QL_DEBUG_LEVEL_8) || \
-    defined(QL_DEBUG_LEVEL_9)  || defined(QL_DEBUG_LEVEL_10) || \
-    defined(QL_DEBUG_LEVEL_11) || defined(QL_DEBUG_LEVEL_12) || \
-    defined(QL_DEBUG_LEVEL_13) || defined(QL_DEBUG_LEVEL_14) || \
-    defined(QL_DEBUG_LEVEL_15)
-    #define QL_DEBUG_ROUTINES
-#endif
+/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
 
 /*
 * Macros use for debugging the driver.
@@ -54,6 +42,7 @@
 #define DEBUG2_9_10(x) do { if (ql2xextended_error_logging) { x; } } while (0)
 #define DEBUG2_11(x)   do { if (ql2xextended_error_logging) { x; } } while (0)
 #define DEBUG2_13(x)   do { if (ql2xextended_error_logging) { x; } } while (0)
+#define DEBUG2_16(x)   do { if (ql2xextended_error_logging) { x; } } while (0)
 
 #if defined(QL_DEBUG_LEVEL_3)
 #define DEBUG3(x)      do {x;} while (0)
 #define DEBUG15(x)     do {} while (0)
 #endif
 
+#if defined(QL_DEBUG_LEVEL_16)
+#define DEBUG16(x)     do {x;} while (0)
+#else
+#define DEBUG16(x)     do {} while (0)
+#endif
+
 /*
  * Firmware Dump structure definition
  */
index 3750319f4968749d99a821fd1294610723c078e3..094d95f0764c6027cb421e4d3e5da9bf17012dfd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -24,6 +24,7 @@
 #include <linux/workqueue.h>
 #include <linux/firmware.h>
 #include <linux/aer.h>
+#include <linux/mutex.h>
 #include <asm/semaphore.h>
 
 #include <scsi/scsi.h>
@@ -192,9 +193,6 @@ typedef struct srb {
 
        uint16_t flags;
 
-       /* Single transfer DMA context */
-       dma_addr_t dma_handle;
-
        uint32_t request_sense_length;
        uint8_t *request_sense_ptr;
 } srb_t;
@@ -1542,8 +1540,6 @@ typedef struct fc_port {
        atomic_t state;
        uint32_t flags;
 
-       unsigned int os_target_id;
-
        int port_login_retry_count;
        int login_retry;
        atomic_t port_down_timer;
@@ -1613,6 +1609,7 @@ typedef struct fc_port {
 #define CT_ACCEPT_RESPONSE     0x8002
 #define CT_REASON_INVALID_COMMAND_CODE 0x01
 #define CT_REASON_CANNOT_PERFORM       0x09
+#define CT_REASON_COMMAND_UNSUPPORTED  0x0b
 #define CT_EXPL_ALREADY_REGISTERED     0x10
 
 #define NS_N_PORT_TYPE 0x01
@@ -2063,7 +2060,8 @@ struct isp_operations {
        void (*disable_intrs) (struct scsi_qla_host *);
 
        int (*abort_command) (struct scsi_qla_host *, srb_t *);
-       int (*abort_target) (struct fc_port *);
+       int (*target_reset) (struct fc_port *, unsigned int);
+       int (*lun_reset) (struct fc_port *, unsigned int);
        int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t,
                uint8_t, uint8_t, uint16_t *, uint8_t);
        int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t,
@@ -2117,6 +2115,46 @@ struct qla_msix_entry {
 
 #define        WATCH_INTERVAL          1       /* number of seconds */
 
+/* Work events.  */
+enum qla_work_type {
+       QLA_EVT_AEN,
+       QLA_EVT_HWE_LOG,
+};
+
+
+struct qla_work_evt {
+       struct list_head        list;
+       enum qla_work_type      type;
+       u32                     flags;
+#define QLA_EVT_FLAG_FREE      0x1
+
+       union {
+               struct {
+                       enum fc_host_event_code code;
+                       u32 data;
+               } aen;
+               struct {
+                       uint16_t code;
+                       uint16_t d1, d2, d3;
+               } hwe;
+       } u;
+};
+
+struct qla_chip_state_84xx {
+       struct list_head list;
+       struct kref kref;
+
+       void *bus;
+       spinlock_t access_lock;
+       struct mutex fw_update_mutex;
+       uint32_t fw_update;
+       uint32_t op_fw_version;
+       uint32_t op_fw_size;
+       uint32_t op_fw_seq_size;
+       uint32_t diag_fw_version;
+       uint32_t gold_fw_version;
+};
+
 /*
  * Linux Host Adapter structure
  */
@@ -2155,6 +2193,7 @@ typedef struct scsi_qla_host {
                uint32_t        vsan_enabled            :1;
                uint32_t        npiv_supported          :1;
                uint32_t        fce_enabled             :1;
+               uint32_t        hw_event_marker_found   :1;
        } flags;
 
        atomic_t        loop_state;
@@ -2204,6 +2243,7 @@ typedef struct scsi_qla_host {
 #define        DFLG_NO_CABLE                   BIT_4
 
 #define PCI_DEVICE_ID_QLOGIC_ISP2532   0x2532
+#define PCI_DEVICE_ID_QLOGIC_ISP8432   0x8432
        uint32_t        device_type;
 #define DT_ISP2100                     BIT_0
 #define DT_ISP2200                     BIT_1
@@ -2217,7 +2257,8 @@ typedef struct scsi_qla_host {
 #define DT_ISP5422                     BIT_9
 #define DT_ISP5432                     BIT_10
 #define DT_ISP2532                     BIT_11
-#define DT_ISP_LAST                    (DT_ISP2532 << 1)
+#define DT_ISP8432                     BIT_12
+#define DT_ISP_LAST                    (DT_ISP8432 << 1)
 
 #define DT_IIDMA                       BIT_26
 #define DT_FWI2                                BIT_27
@@ -2239,12 +2280,16 @@ typedef struct scsi_qla_host {
 #define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422)
 #define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432)
 #define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532)
+#define IS_QLA8432(ha) (DT_MASK(ha) & DT_ISP8432)
 
 #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
                         IS_QLA6312(ha) || IS_QLA6322(ha))
 #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha))
 #define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha))
 #define IS_QLA25XX(ha) (IS_QLA2532(ha))
+#define IS_QLA84XX(ha) (IS_QLA8432(ha))
+#define IS_QLA24XX_TYPE(ha)    (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \
+                       IS_QLA84XX(ha))
 
 #define IS_IIDMA_CAPABLE(ha)   ((ha)->device_type & DT_IIDMA)
 #define IS_FWI2_CAPABLE(ha)    ((ha)->device_type & DT_FWI2)
@@ -2356,6 +2401,8 @@ typedef struct scsi_qla_host {
         uint32_t       login_retry_count;
        int             max_q_depth;
 
+       struct list_head        work_list;
+
        /* Fibre Channel Device List. */
        struct list_head        fcports;
 
@@ -2423,8 +2470,6 @@ typedef struct scsi_qla_host {
 #define  MBX_TIMEDOUT          BIT_5
 #define  MBX_ACCESS_TIMEDOUT   BIT_6
 
-       mbx_cmd_t       mc;
-
        /* Basic firmware related information. */
        uint16_t        fw_major_version;
        uint16_t        fw_minor_version;
@@ -2458,6 +2503,10 @@ typedef struct scsi_qla_host {
        uint64_t        fce_wr, fce_rd;
        struct mutex    fce_mutex;
 
+       uint32_t        hw_event_start;
+       uint32_t        hw_event_ptr;
+       uint32_t        hw_event_pause_errors;
+
        uint8_t         host_str[16];
        uint32_t        pci_attr;
        uint16_t        chip_revision;
@@ -2493,6 +2542,13 @@ typedef struct scsi_qla_host {
        uint8_t         fcode_revision[16];
        uint32_t        fw_revision[4];
 
+       uint16_t        fdt_odd_index;
+       uint32_t        fdt_wrt_disable;
+       uint32_t        fdt_erase_cmd;
+       uint32_t        fdt_block_size;
+       uint32_t        fdt_unprotect_sec_cmd;
+       uint32_t        fdt_protect_sec_cmd;
+
        /* Needed for BEACON */
        uint16_t        beacon_blink_led;
        uint8_t         beacon_color_state;
@@ -2538,6 +2594,8 @@ typedef struct scsi_qla_host {
 #define VP_ERR_ADAP_NORESOURCES        5
        uint16_t        max_npiv_vports;        /* 63 or 125 per topoloty */
        int             cur_vport_count;
+
+       struct qla_chip_state_84xx *cs84xx;
 } scsi_qla_host_t;
 
 
index 2cd899bfe84bb17086a6314991503c8befc42c24..561a4411719d2a7791bc62ff9a0ce99f1820145a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
index 9337e138ed639ada65f29762140c9ef8f4ea4def..078f2a15f40bcb3814b53b7cb4942db61d08922e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -719,7 +719,7 @@ struct tsk_mgmt_entry {
 
        uint16_t timeout;               /* Command timeout. */
 
-       uint8_t lun[8];                 /* FCP LUN (BE). */
+       struct scsi_lun lun;            /* FCP LUN (BE). */
 
        uint32_t control_flags;         /* Control Flags. */
 #define TCF_NOTMCMD_TO_TARGET  BIT_31
@@ -793,7 +793,19 @@ struct device_reg_24xx {
 #define FA_VPD_NVRAM_ADDR      0x48000
 #define FA_FEATURE_ADDR                0x4C000
 #define FA_FLASH_DESCR_ADDR    0x50000
-#define FA_HW_EVENT_ADDR       0x54000
+#define FA_HW_EVENT0_ADDR      0x54000
+#define FA_HW_EVENT1_ADDR      0x54200
+#define FA_HW_EVENT_SIZE       0x200
+#define FA_HW_EVENT_ENTRY_SIZE 4
+/*
+ * Flash Error Log Event Codes.
+ */
+#define HW_EVENT_RESET_ERR     0xF00B
+#define HW_EVENT_ISP_ERR       0xF020
+#define HW_EVENT_PARITY_ERR    0xF022
+#define HW_EVENT_NVRAM_CHKSUM_ERR      0xF023
+#define HW_EVENT_FLASH_FW_ERR  0xF024
+
 #define FA_BOOT_LOG_ADDR       0x58000
 #define FA_FW_DUMP0_ADDR       0x60000
 #define FA_FW_DUMP1_ADDR       0x70000
@@ -1174,4 +1186,159 @@ struct vf_evfp_entry_24xx {
 };
 
 /* END MID Support ***********************************************************/
+
+/* Flash Description Table ***************************************************/
+
+struct qla_fdt_layout {
+       uint8_t sig[4];
+       uint16_t version;
+       uint16_t len;
+       uint16_t checksum;
+       uint8_t unused1[2];
+       uint8_t model[16];
+       uint16_t man_id;
+       uint16_t id;
+       uint8_t flags;
+       uint8_t erase_cmd;
+       uint8_t alt_erase_cmd;
+       uint8_t wrt_enable_cmd;
+       uint8_t wrt_enable_bits;
+       uint8_t wrt_sts_reg_cmd;
+       uint8_t unprotect_sec_cmd;
+       uint8_t read_man_id_cmd;
+       uint32_t block_size;
+       uint32_t alt_block_size;
+       uint32_t flash_size;
+       uint32_t wrt_enable_data;
+       uint8_t read_id_addr_len;
+       uint8_t wrt_disable_bits;
+       uint8_t read_dev_id_len;
+       uint8_t chip_erase_cmd;
+       uint16_t read_timeout;
+       uint8_t protect_sec_cmd;
+       uint8_t unused2[65];
+};
+
+/* 84XX Support **************************************************************/
+
+#define MBA_ISP84XX_ALERT      0x800f  /* Alert Notification. */
+#define A84_PANIC_RECOVERY     0x1
+#define A84_OP_LOGIN_COMPLETE  0x2
+#define A84_DIAG_LOGIN_COMPLETE        0x3
+#define A84_GOLD_LOGIN_COMPLETE        0x4
+
+#define MBC_ISP84XX_RESET      0x3a    /* Reset. */
+
+#define FSTATE_REMOTE_FC_DOWN  BIT_0
+#define FSTATE_NSL_LINK_DOWN   BIT_1
+#define FSTATE_IS_DIAG_FW      BIT_2
+#define FSTATE_LOGGED_IN       BIT_3
+#define FSTATE_WAITING_FOR_VERIFY      BIT_4
+
+#define VERIFY_CHIP_IOCB_TYPE  0x1B
+struct verify_chip_entry_84xx {
+       uint8_t entry_type;
+       uint8_t entry_count;
+       uint8_t sys_defined;
+       uint8_t entry_status;
+
+       uint32_t handle;
+
+       uint16_t options;
+#define VCO_DONT_UPDATE_FW     BIT_0
+#define VCO_FORCE_UPDATE       BIT_1
+#define VCO_DONT_RESET_UPDATE  BIT_2
+#define VCO_DIAG_FW            BIT_3
+#define VCO_END_OF_DATA                BIT_14
+#define VCO_ENABLE_DSD         BIT_15
+
+       uint16_t reserved_1;
+
+       uint16_t data_seg_cnt;
+       uint16_t reserved_2[3];
+
+       uint32_t fw_ver;
+       uint32_t exchange_address;
+
+       uint32_t reserved_3[3];
+       uint32_t fw_size;
+       uint32_t fw_seq_size;
+       uint32_t relative_offset;
+
+       uint32_t dseg_address[2];
+       uint32_t dseg_length;
+};
+
+struct verify_chip_rsp_84xx {
+       uint8_t entry_type;
+       uint8_t entry_count;
+       uint8_t sys_defined;
+       uint8_t entry_status;
+
+       uint32_t handle;
+
+       uint16_t comp_status;
+#define CS_VCS_CHIP_FAILURE    0x3
+#define CS_VCS_BAD_EXCHANGE    0x8
+#define CS_VCS_SEQ_COMPLETEi   0x40
+
+       uint16_t failure_code;
+#define VFC_CHECKSUM_ERROR     0x1
+#define VFC_INVALID_LEN                0x2
+#define VFC_ALREADY_IN_PROGRESS        0x8
+
+       uint16_t reserved_1[4];
+
+       uint32_t fw_ver;
+       uint32_t exchange_address;
+
+       uint32_t reserved_2[6];
+};
+
+#define ACCESS_CHIP_IOCB_TYPE  0x2B
+struct access_chip_84xx {
+       uint8_t entry_type;
+       uint8_t entry_count;
+       uint8_t sys_defined;
+       uint8_t entry_status;
+
+       uint32_t handle;
+
+       uint16_t options;
+#define ACO_DUMP_MEMORY                0x0
+#define ACO_LOAD_MEMORY                0x1
+#define ACO_CHANGE_CONFIG_PARAM        0x2
+#define ACO_REQUEST_INFO       0x3
+
+       uint16_t reserved1;
+
+       uint16_t dseg_count;
+       uint16_t reserved2[3];
+
+       uint32_t parameter1;
+       uint32_t parameter2;
+       uint32_t parameter3;
+
+       uint32_t reserved3[3];
+       uint32_t total_byte_cnt;
+       uint32_t reserved4;
+
+       uint32_t dseg_address[2];
+       uint32_t dseg_length;
+};
+
+struct access_chip_rsp_84xx {
+       uint8_t entry_type;
+       uint8_t entry_count;
+       uint8_t sys_defined;
+       uint8_t entry_status;
+
+       uint32_t handle;
+
+       uint16_t comp_status;
+       uint16_t failure_code;
+       uint32_t residual_count;
+
+       uint32_t reserved[12];
+};
 #endif
index 193f688ec3d788770a1596ddd97ad610f812f00b..a9571c214a9e5cd9f0711dc37bf4b1273a570ed5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -38,9 +38,6 @@ extern int qla2x00_loop_resync(scsi_qla_host_t *);
 extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
 extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
 
-extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t);
-
-extern void qla2x00_rescan_fcports(scsi_qla_host_t *);
 extern void qla2x00_update_fcports(scsi_qla_host_t *);
 
 extern int qla2x00_abort_isp(scsi_qla_host_t *);
@@ -50,6 +47,8 @@ extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
 extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *);
 extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
 
+extern void qla84xx_put_chip(struct scsi_qla_host *);
+
 /*
  * Global Data in qla_os.c source file.
  */
@@ -67,6 +66,10 @@ extern int num_hosts;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
+extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
+    fc_host_event_code, u32);
+extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
+    uint16_t, uint16_t);
 
 /*
  * Global Functions in qla_mid.c source file.
@@ -148,13 +151,18 @@ qla2x00_verify_checksum(scsi_qla_host_t *, uint32_t);
 extern int
 qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
 
+extern int
+qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *, dma_addr_t, size_t,
+    uint32_t);
+
 extern int
 qla2x00_abort_command(scsi_qla_host_t *, srb_t *);
 
-#if USE_ABORT_TGT
 extern int
-qla2x00_abort_target(fc_port_t *);
-#endif
+qla2x00_abort_target(struct fc_port *, unsigned int);
+
+extern int
+qla2x00_lun_reset(struct fc_port *, unsigned int);
 
 extern int
 qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
@@ -220,7 +228,8 @@ qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
     dma_addr_t);
 
 extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *);
-extern int qla24xx_abort_target(fc_port_t *);
+extern int qla24xx_abort_target(struct fc_port *, unsigned int);
+extern int qla24xx_lun_reset(struct fc_port *, unsigned int);
 
 extern int
 qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
@@ -246,6 +255,8 @@ qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
 extern int
 qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
 
+extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
+
 /*
  * Global Function Prototypes in qla_isr.c source file.
  */
@@ -298,6 +309,11 @@ extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
 extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
 extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
 
+extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
+    uint16_t, uint16_t);
+
+extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
+
 /*
  * Global Function Prototypes in qla_dbg.c source file.
  */
@@ -307,7 +323,6 @@ extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
 extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
 extern void qla2x00_dump_regs(scsi_qla_host_t *);
 extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
-extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *);
 
 /*
  * Global Function Prototypes in qla_gs.c source file.
index c1808763d40ef21608e6dab7fab271712098f975..750d7ef83aaefb54f3f4c79fb468fdb579c8fc1b 100644 (file)
@@ -1,17 +1,11 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
 #include "qla_def.h"
 
-static inline struct ct_sns_req *
-qla2x00_prep_ct_req(struct ct_sns_req *, uint16_t, uint16_t);
-
-static inline struct sns_cmd_pkt *
-qla2x00_prep_sns_cmd(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
-
 static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
 static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
 static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
@@ -1538,7 +1532,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
                eiter->a.sup_speed = __constant_cpu_to_be32(
                    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
                    FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
-       else if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+       else if (IS_QLA24XX_TYPE(ha))
                eiter->a.sup_speed = __constant_cpu_to_be32(
                    FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
                    FDMI_PORT_SPEED_4GB);
@@ -1847,8 +1841,10 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
                    "GPSC")) != QLA_SUCCESS) {
                        /* FM command unsupported? */
                        if (rval == QLA_INVALID_COMMAND &&
-                           ct_rsp->header.reason_code ==
-                           CT_REASON_INVALID_COMMAND_CODE) {
+                           (ct_rsp->header.reason_code ==
+                               CT_REASON_INVALID_COMMAND_CODE ||
+                            ct_rsp->header.reason_code ==
+                               CT_REASON_COMMAND_UNSUPPORTED)) {
                                DEBUG2(printk("scsi(%ld): GPSC command "
                                    "unsupported, disabling query...\n",
                                    ha->host_no));
index 364be7d068759c4972cc7fd414cc26c63c396323..01e26087c1dd599036202bb862c608675960d3e6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
 #include <asm/prom.h>
 #endif
 
-/* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
-#ifndef EXT_IS_LUN_BIT_SET
-#define EXT_IS_LUN_BIT_SET(P,L) \
-    (((P)->mask[L/8] & (0x80 >> (L%8)))?1:0)
-#define EXT_SET_LUN_BIT(P,L) \
-    ((P)->mask[L/8] |= (0x80 >> (L%8)))
-#endif
-
 /*
 *  QLogic ISP2x00 Hardware Support Function Prototypes.
 */
@@ -45,6 +37,9 @@ static int qla2x00_restart_isp(scsi_qla_host_t *);
 
 static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev);
 
+static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
+static int qla84xx_init_chip(scsi_qla_host_t *);
+
 /****************************************************************************/
 /*                QLogic ISP2x00 Hardware Support Functions.                */
 /****************************************************************************/
@@ -114,6 +109,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
                rval = qla2x00_setup_chip(ha);
                if (rval)
                        return (rval);
+               qla2xxx_get_flash_info(ha);
+       }
+       if (IS_QLA84XX(ha)) {
+               ha->cs84xx = qla84xx_get_chip(ha);
+               if (!ha->cs84xx) {
+                       qla_printk(KERN_ERR, ha,
+                           "Unable to configure ISP84XX.\n");
+                       return QLA_FUNCTION_FAILED;
+               }
        }
        rval = qla2x00_init_rings(ha);
 
@@ -500,6 +504,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha)
 static inline void
 qla24xx_reset_risc(scsi_qla_host_t *ha)
 {
+       int hw_evt = 0;
        unsigned long flags = 0;
        struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
        uint32_t cnt, d2;
@@ -528,6 +533,8 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
                d2 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
                barrier();
        }
+       if (cnt == 0)
+               hw_evt = 1;
 
        /* Wait for soft-reset to complete. */
        d2 = RD_REG_DWORD(&reg->ctrl_status);
@@ -536,6 +543,10 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
                d2 = RD_REG_DWORD(&reg->ctrl_status);
                barrier();
        }
+       if (cnt == 0 || hw_evt)
+               qla2xxx_hw_event_log(ha, HW_EVENT_RESET_ERR,
+                   RD_REG_WORD(&reg->mailbox1), RD_REG_WORD(&reg->mailbox2),
+                   RD_REG_WORD(&reg->mailbox3));
 
        WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
        RD_REG_DWORD(&reg->hccr);
@@ -1243,10 +1254,10 @@ static int
 qla2x00_fw_ready(scsi_qla_host_t *ha)
 {
        int             rval;
-       unsigned long   wtime, mtime;
+       unsigned long   wtime, mtime, cs84xx_time;
        uint16_t        min_wait;       /* Minimum wait time if loop is down */
        uint16_t        wait_time;      /* Wait time if loop is coming ready */
-       uint16_t        fw_state;
+       uint16_t        state[3];
 
        rval = QLA_SUCCESS;
 
@@ -1275,12 +1286,34 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
            ha->host_no));
 
        do {
-               rval = qla2x00_get_firmware_state(ha, &fw_state);
+               rval = qla2x00_get_firmware_state(ha, state);
                if (rval == QLA_SUCCESS) {
-                       if (fw_state < FSTATE_LOSS_OF_SYNC) {
+                       if (state[0] < FSTATE_LOSS_OF_SYNC) {
                                ha->device_flags &= ~DFLG_NO_CABLE;
                        }
-                       if (fw_state == FSTATE_READY) {
+                       if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
+                               DEBUG16(printk("scsi(%ld): fw_state=%x "
+                                   "84xx=%x.\n", ha->host_no, state[0],
+                                   state[2]));
+                               if ((state[2] & FSTATE_LOGGED_IN) &&
+                                    (state[2] & FSTATE_WAITING_FOR_VERIFY)) {
+                                       DEBUG16(printk("scsi(%ld): Sending "
+                                           "verify iocb.\n", ha->host_no));
+
+                                       cs84xx_time = jiffies;
+                                       rval = qla84xx_init_chip(ha);
+                                       if (rval != QLA_SUCCESS)
+                                               break;
+
+                                       /* Add time taken to initialize. */
+                                       cs84xx_time = jiffies - cs84xx_time;
+                                       wtime += cs84xx_time;
+                                       mtime += cs84xx_time;
+                                       DEBUG16(printk("scsi(%ld): Increasing "
+                                           "wait time by %ld. New time %ld\n",
+                                           ha->host_no, cs84xx_time, wtime));
+                               }
+                       } else if (state[0] == FSTATE_READY) {
                                DEBUG(printk("scsi(%ld): F/W Ready - OK \n",
                                    ha->host_no));
 
@@ -1294,7 +1327,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
                        rval = QLA_FUNCTION_FAILED;
 
                        if (atomic_read(&ha->loop_down_timer) &&
-                           fw_state != FSTATE_READY) {
+                           state[0] != FSTATE_READY) {
                                /* Loop down. Timeout on min_wait for states
                                 * other than Wait for Login.
                                 */
@@ -1319,11 +1352,11 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
                msleep(500);
 
                DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
-                   ha->host_no, fw_state, jiffies));
+                   ha->host_no, state[0], jiffies));
        } while (1);
 
        DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
-           ha->host_no, fw_state, jiffies));
+           ha->host_no, state[0], jiffies));
 
        if (rval) {
                DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n",
@@ -1555,6 +1588,10 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
                qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
                    "invalid -- WWPN) defaults.\n");
 
+               if (chksum)
+                       qla2xxx_hw_event_log(ha, HW_EVENT_NVRAM_CHKSUM_ERR, 0,
+                           MSW(chksum), LSW(chksum));
+
                /*
                 * Set default initialization control block.
                 */
@@ -2164,20 +2201,6 @@ cleanup_allocation:
        return (rval);
 }
 
-static void
-qla2x00_probe_for_all_luns(scsi_qla_host_t *ha)
-{
-       fc_port_t       *fcport;
-
-       qla2x00_mark_all_devices_lost(ha, 0);
-       list_for_each_entry(fcport, &ha->fcports, list) {
-               if (fcport->port_type != FCT_TARGET)
-                       continue;
-
-               qla2x00_update_fcport(ha, fcport);
-       }
-}
-
 static void
 qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
 {
@@ -2251,10 +2274,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
        if (fcport->port_type == FCT_TARGET)
                rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
        fc_remote_port_rolechg(rport, rport_ids.roles);
-
-       if (rport->scsi_target_id != -1 &&
-           rport->scsi_target_id < ha->host->max_id)
-               fcport->os_target_id = rport->scsi_target_id;
 }
 
 /*
@@ -2434,7 +2453,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
 
                        if (fcport->loop_id == FC_NO_LOOP_ID) {
                                fcport->loop_id = next_loopid;
-                               rval = qla2x00_find_new_loop_id(ha, fcport);
+                               rval = qla2x00_find_new_loop_id(
+                                   to_qla_parent(ha), fcport);
                                if (rval != QLA_SUCCESS) {
                                        /* Ran out of IDs to use */
                                        break;
@@ -2459,7 +2479,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
 
                        /* Find a new loop ID to use. */
                        fcport->loop_id = next_loopid;
-                       rval = qla2x00_find_new_loop_id(ha, fcport);
+                       rval = qla2x00_find_new_loop_id(to_qla_parent(ha),
+                           fcport);
                        if (rval != QLA_SUCCESS) {
                                /* Ran out of IDs to use */
                                break;
@@ -3192,25 +3213,6 @@ qla2x00_loop_resync(scsi_qla_host_t *ha)
        return (rval);
 }
 
-void
-qla2x00_rescan_fcports(scsi_qla_host_t *ha)
-{
-       int rescan_done;
-       fc_port_t *fcport;
-
-       rescan_done = 0;
-       list_for_each_entry(fcport, &ha->fcports, list) {
-               if ((fcport->flags & FCF_RESCAN_NEEDED) == 0)
-                       continue;
-
-               qla2x00_update_fcport(ha, fcport);
-               fcport->flags &= ~FCF_RESCAN_NEEDED;
-
-               rescan_done = 1;
-       }
-       qla2x00_probe_for_all_luns(ha);
-}
-
 void
 qla2x00_update_fcports(scsi_qla_host_t *ha)
 {
@@ -4044,16 +4046,16 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
        if (!ha->parent)
                return -EINVAL;
 
-       rval = qla2x00_fw_ready(ha);
+       rval = qla2x00_fw_ready(ha->parent);
        if (rval == QLA_SUCCESS) {
                clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
-               qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
+               qla2x00_marker(ha->parent, 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,
+       qla24xx_login_fabric(ha->parent, NPH_SNS, 0xff, 0xff, 0xfc,
            mb, BIT_1);
        if (mb[0] != MBS_COMMAND_COMPLETE) {
                DEBUG15(qla_printk(KERN_INFO, ha,
@@ -4067,7 +4069,77 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
        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);
+       rval = qla2x00_loop_resync(ha->parent);
 
        return rval;
 }
+
+/* 84XX Support **************************************************************/
+
+static LIST_HEAD(qla_cs84xx_list);
+static DEFINE_MUTEX(qla_cs84xx_mutex);
+
+static struct qla_chip_state_84xx *
+qla84xx_get_chip(struct scsi_qla_host *ha)
+{
+       struct qla_chip_state_84xx *cs84xx;
+
+       mutex_lock(&qla_cs84xx_mutex);
+
+       /* Find any shared 84xx chip. */
+       list_for_each_entry(cs84xx, &qla_cs84xx_list, list) {
+               if (cs84xx->bus == ha->pdev->bus) {
+                       kref_get(&cs84xx->kref);
+                       goto done;
+               }
+       }
+
+       cs84xx = kzalloc(sizeof(*cs84xx), GFP_KERNEL);
+       if (!cs84xx)
+               goto done;
+
+       kref_init(&cs84xx->kref);
+       spin_lock_init(&cs84xx->access_lock);
+       mutex_init(&cs84xx->fw_update_mutex);
+       cs84xx->bus = ha->pdev->bus;
+
+       list_add_tail(&cs84xx->list, &qla_cs84xx_list);
+done:
+       mutex_unlock(&qla_cs84xx_mutex);
+       return cs84xx;
+}
+
+static void
+__qla84xx_chip_release(struct kref *kref)
+{
+       struct qla_chip_state_84xx *cs84xx =
+           container_of(kref, struct qla_chip_state_84xx, kref);
+
+       mutex_lock(&qla_cs84xx_mutex);
+       list_del(&cs84xx->list);
+       mutex_unlock(&qla_cs84xx_mutex);
+       kfree(cs84xx);
+}
+
+void
+qla84xx_put_chip(struct scsi_qla_host *ha)
+{
+       if (ha->cs84xx)
+               kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
+}
+
+static int
+qla84xx_init_chip(scsi_qla_host_t *ha)
+{
+       int rval;
+       uint16_t status[2];
+
+       mutex_lock(&ha->cs84xx->fw_update_mutex);
+
+       rval = qla84xx_verify_chip(ha, status);
+
+       mutex_unlock(&ha->cs84xx->fw_update_mutex);
+
+       return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
+           QLA_SUCCESS;
+}
index 5d1a3f7c408f3193a1d0cf4b78d3e6356354b892..e9bae27737d1d9a2d9e7fc7414ecdeb6d36f3eb2 100644 (file)
@@ -1,11 +1,10 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
 
-static __inline__ uint16_t qla2x00_debounce_register(volatile uint16_t __iomem *);
 /*
  * qla2x00_debounce_register
  *      Debounce register.
@@ -32,94 +31,12 @@ qla2x00_debounce_register(volatile uint16_t __iomem *addr)
        return (first);
 }
 
-static __inline__ int qla2x00_normalize_dma_addr(
-    dma_addr_t *e_addr,  uint32_t *e_len,
-    dma_addr_t *ne_addr, uint32_t *ne_len);
-
-/**
- * qla2x00_normalize_dma_addr() - Normalize an DMA address.
- * @e_addr: Raw DMA address
- * @e_len: Raw DMA length
- * @ne_addr: Normalized second DMA address
- * @ne_len: Normalized second DMA length
- *
- * If the address does not span a 4GB page boundary, the contents of @ne_addr
- * and @ne_len are undefined.  @e_len is updated to reflect a normalization.
- *
- * Example:
- *
- *     ffffabc0ffffeeee        (e_addr) start of DMA address
- *     0000000020000000        (e_len)  length of DMA transfer
- *     ffffabc11fffeeed        end of DMA transfer
- *
- * Is the 4GB boundary crossed?
- *
- *     ffffabc0ffffeeee        (e_addr)
- *     ffffabc11fffeeed        (e_addr + e_len - 1)
- *     00000001e0000003        ((e_addr ^ (e_addr + e_len - 1))
- *     0000000100000000        ((e_addr ^ (e_addr + e_len - 1)) & ~(0xffffffff)
- *
- * Compute start of second DMA segment:
- *
- *     ffffabc0ffffeeee        (e_addr)
- *     ffffabc1ffffeeee        (0x100000000 + e_addr)
- *     ffffabc100000000        (0x100000000 + e_addr) & ~(0xffffffff)
- *     ffffabc100000000        (ne_addr)
- *
- * Compute length of second DMA segment:
- *
- *     00000000ffffeeee        (e_addr & 0xffffffff)
- *     0000000000001112        (0x100000000 - (e_addr & 0xffffffff))
- *     000000001fffeeee        (e_len - (0x100000000 - (e_addr & 0xffffffff))
- *     000000001fffeeee        (ne_len)
- *
- * Adjust length of first DMA segment
- *
- *     0000000020000000        (e_len)
- *     0000000000001112        (e_len - ne_len)
- *     0000000000001112        (e_len)
- *
- * Returns non-zero if the specified address was normalized, else zero.
- */
-static __inline__ int
-qla2x00_normalize_dma_addr(
-    dma_addr_t *e_addr,  uint32_t *e_len,
-    dma_addr_t *ne_addr, uint32_t *ne_len)
-{
-       int normalized;
-
-       normalized = 0;
-       if ((*e_addr ^ (*e_addr + *e_len - 1)) & ~(0xFFFFFFFFULL)) {
-               /* Compute normalized crossed address and len */
-               *ne_addr = (0x100000000ULL + *e_addr) & ~(0xFFFFFFFFULL);
-               *ne_len = *e_len - (0x100000000ULL - (*e_addr & 0xFFFFFFFFULL));
-               *e_len -= *ne_len;
-
-               normalized++;
-       }
-       return (normalized);
-}
-
-static __inline__ void qla2x00_poll(scsi_qla_host_t *);
 static inline void
 qla2x00_poll(scsi_qla_host_t *ha)
 {
        ha->isp_ops->intr_handler(0, ha);
 }
 
-static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *);
-/*
- * This routine will wait for fabric devices for
- * the reset delay.
- */
-static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *ha)
-{
-       uint16_t        fw_state;
-
-       qla2x00_get_firmware_state(ha, &fw_state);
-}
-
-static __inline__ scsi_qla_host_t * to_qla_parent(scsi_qla_host_t *);
 static __inline__ scsi_qla_host_t *
 to_qla_parent(scsi_qla_host_t *ha)
 {
@@ -152,7 +69,6 @@ qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked)
        return (QLA_SUCCESS);
 }
 
-static inline uint8_t *host_to_fcp_swap(uint8_t *, uint32_t);
 static inline uint8_t *
 host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
 {
@@ -166,7 +82,6 @@ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
        return fcp;
 }
 
-static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t);
 static inline int
 qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id)
 {
index 024c662ec34d47ed75ae0e2e94192e6ca3f820e3..5489d5024673a326b5345f5545151a7dab37a533 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -11,9 +11,6 @@
 
 #include <scsi/scsi_tcq.h>
 
-static inline uint16_t qla2x00_get_cmd_direction(struct scsi_cmnd *cmd);
-static inline cont_entry_t *qla2x00_prep_cont_type0_iocb(scsi_qla_host_t *);
-static inline cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *);
 static request_t *qla2x00_req_pkt(scsi_qla_host_t *ha);
 static void qla2x00_isp_cmd(scsi_qla_host_t *ha);
 
index f0337036c7bb144242567963591c368999deecbd..285479b62d8f02084ad0daebc12ab249f16348c0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -14,9 +14,6 @@ static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
 static void qla2x00_status_entry(scsi_qla_host_t *, void *);
 static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
 static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *);
-static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);
-
-static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *);
 
 /**
  * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
@@ -33,7 +30,6 @@ qla2100_intr_handler(int irq, void *dev_id)
        scsi_qla_host_t *ha;
        struct device_reg_2xxx __iomem *reg;
        int             status;
-       unsigned long   flags;
        unsigned long   iter;
        uint16_t        hccr;
        uint16_t        mb[4];
@@ -48,7 +44,7 @@ qla2100_intr_handler(int irq, void *dev_id)
        reg = &ha->iobase->isp;
        status = 0;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock(&ha->hardware_lock);
        for (iter = 50; iter--; ) {
                hccr = RD_REG_WORD(&reg->hccr);
                if (hccr & HCCR_RISC_PAUSE) {
@@ -99,7 +95,7 @@ qla2100_intr_handler(int irq, void *dev_id)
                        RD_REG_WORD(&reg->hccr);
                }
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock(&ha->hardware_lock);
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
@@ -125,7 +121,6 @@ qla2300_intr_handler(int irq, void *dev_id)
        scsi_qla_host_t *ha;
        struct device_reg_2xxx __iomem *reg;
        int             status;
-       unsigned long   flags;
        unsigned long   iter;
        uint32_t        stat;
        uint16_t        hccr;
@@ -141,7 +136,7 @@ qla2300_intr_handler(int irq, void *dev_id)
        reg = &ha->iobase->isp;
        status = 0;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock(&ha->hardware_lock);
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
                if (stat & HSR_RISC_PAUSED) {
@@ -211,7 +206,7 @@ qla2300_intr_handler(int irq, void *dev_id)
                WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
                RD_REG_WORD_RELAXED(&reg->hccr);
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock(&ha->hardware_lock);
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
@@ -276,6 +271,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
        uint32_t        rscn_entry, host_pid;
        uint8_t         rscn_queue_index;
+       unsigned long   flags;
+       scsi_qla_host_t *vha;
+       int             i;
 
        /* Setup to process RIO completion. */
        handle_cnt = 0;
@@ -351,6 +349,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
                    mb[1], mb[2], mb[3]);
 
+               qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
                ha->isp_ops->fw_dump(ha, 1);
 
                if (IS_FWI2_CAPABLE(ha)) {
@@ -375,6 +374,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    ha->host_no));
                qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n");
 
+               qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
                set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                break;
 
@@ -383,6 +383,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    ha->host_no));
                qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");
 
+               qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
                set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                break;
 
@@ -410,6 +411,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
 
                ha->flags.management_server_logged_in = 0;
+               qla2x00_post_aen_work(ha, FCH_EVT_LIP, mb[1]);
                break;
 
        case MBA_LOOP_UP:               /* Loop Up Event */
@@ -429,12 +431,14 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    link_speed);
 
                ha->flags.management_server_logged_in = 0;
+               qla2x00_post_aen_work(ha, FCH_EVT_LINKUP, ha->link_data_rate);
                break;
 
        case MBA_LOOP_DOWN:             /* Loop Down Event */
-               DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n",
-                   ha->host_no, mb[1]));
-               qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]);
+               DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
+                   "(%x %x %x).\n", ha->host_no, mb[1], mb[2], mb[3]));
+               qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x %x %x).\n",
+                   mb[1], mb[2], mb[3]);
 
                if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
                        atomic_set(&ha->loop_state, LOOP_DOWN);
@@ -452,6 +456,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                ha->link_data_rate = PORT_SPEED_UNKNOWN;
                if (ql2xfdmienable)
                        set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
+               qla2x00_post_aen_work(ha, FCH_EVT_LINKDOWN, 0);
                break;
 
        case MBA_LIP_RESET:             /* LIP reset occurred */
@@ -475,6 +480,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                ha->operating_mode = LOOP;
                ha->flags.management_server_logged_in = 0;
+               qla2x00_post_aen_work(ha, FCH_EVT_LIPRESET, mb[1]);
                break;
 
        case MBA_POINT_TO_POINT:        /* Point-to-Point */
@@ -538,6 +544,18 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                break;
 
        case MBA_PORT_UPDATE:           /* Port database update */
+               if ((ha->flags.npiv_supported) && (ha->num_vhosts)) {
+                       for_each_mapped_vp_idx(ha, i) {
+                               list_for_each_entry(vha, &ha->vp_list,
+                                   vp_list) {
+                                       if ((mb[3] & 0xff)
+                                           == vha->vp_idx) {
+                                               ha = vha;
+                                               break;
+                                       }
+                               }
+                       }
+               }
                /*
                 * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
                 * event etc. earlier indicating loop is down) then process
@@ -572,12 +590,18 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                break;
 
        case MBA_RSCN_UPDATE:           /* State Change Registration */
-               /* Check if the Vport has issued a SCR */
-               if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags))
-                       break;
-               /* Only handle SCNs for our Vport index. */
-               if (ha->flags.npiv_supported && ha->vp_idx != mb[3])
-                       break;
+               if ((ha->flags.npiv_supported) && (ha->num_vhosts)) {
+                       for_each_mapped_vp_idx(ha, i) {
+                               list_for_each_entry(vha, &ha->vp_list,
+                                   vp_list) {
+                                       if ((mb[3] & 0xff)
+                                           == vha->vp_idx) {
+                                               ha = vha;
+                                               break;
+                                       }
+                               }
+                       }
+               }
 
                DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
                    ha->host_no));
@@ -612,6 +636,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
                set_bit(RSCN_UPDATE, &ha->dpc_flags);
+               qla2x00_post_aen_work(ha, FCH_EVT_RSCN, rscn_entry);
                break;
 
        /* case MBA_RIO_RESPONSE: */
@@ -637,6 +662,42 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
                ha->host_no, mb[1], mb[2]));
                break;
+
+       case MBA_ISP84XX_ALERT:
+               DEBUG2(printk("scsi(%ld): ISP84XX Alert Notification -- "
+                   "%04x %04x %04x\n", ha->host_no, mb[1], mb[2], mb[3]));
+
+               spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
+               switch (mb[1]) {
+               case A84_PANIC_RECOVERY:
+                       qla_printk(KERN_INFO, ha, "Alert 84XX: panic recovery "
+                           "%04x %04x\n", mb[2], mb[3]);
+                       break;
+               case A84_OP_LOGIN_COMPLETE:
+                       ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
+                       DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
+                           "firmware version %x\n", ha->cs84xx->op_fw_version));
+                       break;
+               case A84_DIAG_LOGIN_COMPLETE:
+                       ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
+                       DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
+                           "diagnostic firmware version %x\n",
+                           ha->cs84xx->diag_fw_version));
+                       break;
+               case A84_GOLD_LOGIN_COMPLETE:
+                       ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
+                       ha->cs84xx->fw_update = 1;
+                       DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX: gold "
+                           "firmware version %x\n",
+                           ha->cs84xx->gold_fw_version));
+                       break;
+               default:
+                       qla_printk(KERN_ERR, ha,
+                           "Alert 84xx: Invalid Alert %04x %04x %04x\n",
+                           mb[1], mb[2], mb[3]);
+               }
+               spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
+               break;
        }
 
        if (!ha->parent && ha->num_vhosts)
@@ -803,9 +864,6 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
                case STATUS_CONT_TYPE:
                        qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
                        break;
-               case MS_IOCB_TYPE:
-                       qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt);
-                       break;
                default:
                        /* Type Not Supported. */
                        DEBUG4(printk(KERN_WARNING
@@ -1339,44 +1397,6 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
        }
 }
 
-/**
- * qla2x00_ms_entry() - Process a Management Server entry.
- * @ha: SCSI driver HA context
- * @index: Response queue out pointer
- */
-static void
-qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt)
-{
-       srb_t          *sp;
-
-       DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
-           __func__, ha->host_no, pkt, pkt->handle1));
-
-       /* Validate handle. */
-       if (pkt->handle1 < MAX_OUTSTANDING_COMMANDS)
-               sp = ha->outstanding_cmds[pkt->handle1];
-       else
-               sp = NULL;
-
-       if (sp == NULL) {
-               DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
-                   ha->host_no));
-               qla_printk(KERN_WARNING, ha, "MS entry - invalid handle\n");
-
-               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-               return;
-       }
-
-       CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->status);
-       CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
-
-       /* Free outstanding command slot. */
-       ha->outstanding_cmds[pkt->handle1] = NULL;
-
-       qla2x00_sp_compl(ha, sp);
-}
-
-
 /**
  * qla24xx_mbx_completion() - Process mailbox command completions.
  * @ha: SCSI driver HA context
@@ -1449,9 +1469,6 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
                case STATUS_CONT_TYPE:
                        qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
                        break;
-               case MS_IOCB_TYPE:
-                       qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt);
-                       break;
                case VP_RPT_ID_IOCB_TYPE:
                        qla24xx_report_id_acquisition(ha,
                            (struct vp_rpt_id_entry_24xx *)pkt);
@@ -1533,7 +1550,6 @@ qla24xx_intr_handler(int irq, void *dev_id)
        scsi_qla_host_t *ha;
        struct device_reg_24xx __iomem *reg;
        int             status;
-       unsigned long   flags;
        unsigned long   iter;
        uint32_t        stat;
        uint32_t        hccr;
@@ -1549,13 +1565,19 @@ qla24xx_intr_handler(int irq, void *dev_id)
        reg = &ha->iobase->isp24;
        status = 0;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock(&ha->hardware_lock);
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
                        if (pci_channel_offline(ha->pdev))
                                break;
 
+                       if (ha->hw_event_pause_errors == 0)
+                               qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
+                                   0, MSW(stat), LSW(stat));
+                       else if (ha->hw_event_pause_errors < 0xffffffff)
+                               ha->hw_event_pause_errors++;
+
                        hccr = RD_REG_DWORD(&reg->hccr);
 
                        qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
@@ -1597,7 +1619,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
                RD_REG_DWORD_RELAXED(&reg->hccr);
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock(&ha->hardware_lock);
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
@@ -1608,66 +1630,21 @@ qla24xx_intr_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-/**
- * qla24xx_ms_entry() - Process a Management Server entry.
- * @ha: SCSI driver HA context
- * @index: Response queue out pointer
- */
-static void
-qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
-{
-       srb_t          *sp;
-
-       DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
-           __func__, ha->host_no, pkt, pkt->handle));
-
-       DEBUG9(printk("%s: ct pkt dump:\n", __func__));
-       DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx)));
-
-       /* Validate handle. */
-       if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
-               sp = ha->outstanding_cmds[pkt->handle];
-       else
-               sp = NULL;
-
-       if (sp == NULL) {
-               DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
-                   ha->host_no));
-               DEBUG10(printk("scsi(%ld): MS entry - invalid handle\n",
-                   ha->host_no));
-               qla_printk(KERN_WARNING, ha, "MS entry - invalid handle %d\n",
-                   pkt->handle);
-
-               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-               return;
-       }
-
-       CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->comp_status);
-       CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
-
-       /* Free outstanding command slot. */
-       ha->outstanding_cmds[pkt->handle] = NULL;
-
-       qla2x00_sp_compl(ha, sp);
-}
-
 static irqreturn_t
 qla24xx_msix_rsp_q(int irq, void *dev_id)
 {
        scsi_qla_host_t *ha;
        struct device_reg_24xx __iomem *reg;
-       unsigned long flags;
 
        ha = dev_id;
        reg = &ha->iobase->isp24;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock(&ha->hardware_lock);
 
        qla24xx_process_response_queue(ha);
-
        WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
 
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock(&ha->hardware_lock);
 
        return IRQ_HANDLED;
 }
@@ -1678,7 +1655,6 @@ qla24xx_msix_default(int irq, void *dev_id)
        scsi_qla_host_t *ha;
        struct device_reg_24xx __iomem *reg;
        int             status;
-       unsigned long   flags;
        uint32_t        stat;
        uint32_t        hccr;
        uint16_t        mb[4];
@@ -1687,13 +1663,19 @@ qla24xx_msix_default(int irq, void *dev_id)
        reg = &ha->iobase->isp24;
        status = 0;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock(&ha->hardware_lock);
        do {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
                        if (pci_channel_offline(ha->pdev))
                                break;
 
+                       if (ha->hw_event_pause_errors == 0)
+                               qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
+                                   0, MSW(stat), LSW(stat));
+                       else if (ha->hw_event_pause_errors < 0xffffffff)
+                               ha->hw_event_pause_errors++;
+
                        hccr = RD_REG_DWORD(&reg->hccr);
 
                        qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
@@ -1734,7 +1716,7 @@ qla24xx_msix_default(int irq, void *dev_id)
                }
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
        } while (0);
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock(&ha->hardware_lock);
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
@@ -1821,10 +1803,9 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
 {
        int ret;
        device_reg_t __iomem *reg = ha->iobase;
-       unsigned long flags;
 
        /* If possible, enable MSI-X. */
-       if (!IS_QLA2432(ha) && !IS_QLA2532(ha))
+       if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
                goto skip_msix;
 
         if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
@@ -1859,7 +1840,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
            "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
 skip_msix:
 
-       if (!IS_QLA24XX(ha) && !IS_QLA2532(ha))
+       if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
                goto skip_msi;
 
        ret = pci_enable_msi(ha->pdev);
@@ -1882,7 +1863,7 @@ skip_msi:
 clear_risc_ints:
 
        ha->isp_ops->disable_intrs(ha);
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock_irq(&ha->hardware_lock);
        if (IS_FWI2_CAPABLE(ha)) {
                WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
                WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
@@ -1891,7 +1872,7 @@ clear_risc_ints:
                WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);
                WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irq(&ha->hardware_lock);
        ha->isp_ops->enable_intrs(ha);
 
 fail:
index bb103580e1ba8b874e59bb8987c2b5addad940cb..7d0a8a4c77196ea302262dcfc2d61f0d6d8931b2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -310,7 +310,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
        }
 
        mcp->in_mb = MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -367,7 +367,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
                }
        }
 
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -417,7 +417,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *ha, uint16_t *major, uint16_t *minor,
        mcp->out_mb = MBX_0;
        mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->flags = 0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        rval = qla2x00_mailbox_command(ha, mcp);
 
        /* Return mailbox data. */
@@ -466,7 +466,7 @@ qla2x00_get_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
        mcp->mb[0] = MBC_GET_FIRMWARE_OPTION;
        mcp->out_mb = MBX_0;
        mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -524,7 +524,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
                mcp->mb[12] = 0;        /* Undocumented, but used */
                mcp->out_mb |= MBX_12|MBX_11|MBX_10;
        }
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -576,7 +576,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
        mcp->mb[7] = 0x2525;
        mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -587,6 +587,14 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
                if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
                    mcp->mb[7] != 0x2525)
                        rval = QLA_FUNCTION_FAILED;
+               if (rval == QLA_FUNCTION_FAILED) {
+                       struct device_reg_24xx __iomem *reg =
+                           &ha->iobase->isp24;
+
+                       qla2xxx_hw_event_log(ha, HW_EVENT_ISP_ERR, 0,
+                           LSW(RD_REG_DWORD(&reg->hccr)),
+                           LSW(RD_REG_DWORD(&reg->istatus)));
+               }
        }
 
        if (rval != QLA_SUCCESS) {
@@ -640,7 +648,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
                mcp->in_mb |= MBX_1;
        }
 
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -674,8 +682,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
  *     Kernel context.
  */
 int
-qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
-    size_t size)
+qla2x00_issue_iocb_timeout(scsi_qla_host_t *ha, void *buffer,
+    dma_addr_t phys_addr, size_t size, uint32_t tov)
 {
        int             rval;
        mbx_cmd_t       mc;
@@ -689,7 +697,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
        mcp->mb[7] = LSW(MSD(phys_addr));
        mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_2|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = tov;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -710,6 +718,14 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void*  buffer, dma_addr_t phys_addr,
        return rval;
 }
 
+int
+qla2x00_issue_iocb(scsi_qla_host_t *ha, void *buffer, dma_addr_t phys_addr,
+    size_t size)
+{
+       return qla2x00_issue_iocb_timeout(ha, buffer, phys_addr, size,
+           MBX_TOV_SECONDS);
+}
+
 /*
  * qla2x00_abort_command
  *     Abort command aborts a specified IOCB.
@@ -760,7 +776,7 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
        mcp->mb[6] = (uint16_t)sp->cmd->device->lun;
        mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -776,36 +792,20 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
        return rval;
 }
 
-#if USE_ABORT_TGT
-/*
- * qla2x00_abort_target
- *     Issue abort target mailbox command.
- *
- * Input:
- *     ha = adapter block pointer.
- *
- * Returns:
- *     qla2x00 local function return status code.
- *
- * Context:
- *     Kernel context.
- */
 int
-qla2x00_abort_target(fc_port_t *fcport)
+qla2x00_abort_target(struct fc_port *fcport, unsigned int l)
 {
-       int        rval;
+       int rval, rval2;
        mbx_cmd_t  mc;
        mbx_cmd_t  *mcp = &mc;
        scsi_qla_host_t *ha;
 
-       if (fcport == NULL)
-               return 0;
-
        DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
 
+       l = l;
        ha = fcport->ha;
        mcp->mb[0] = MBC_ABORT_TARGET;
-       mcp->out_mb = MBX_2|MBX_1|MBX_0;
+       mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
        if (HAS_EXTENDED_IDS(ha)) {
                mcp->mb[1] = fcport->loop_id;
                mcp->mb[10] = 0;
@@ -814,27 +814,70 @@ qla2x00_abort_target(fc_port_t *fcport)
                mcp->mb[1] = fcport->loop_id << 8;
        }
        mcp->mb[2] = ha->loop_reset_delay;
+       mcp->mb[9] = ha->vp_idx;
 
        mcp->in_mb = MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+                   ha->host_no, rval));
+       }
 
-       /* Issue marker command. */
-       ha->marker_needed = 1;
+       /* Issue marker IOCB. */
+       rval2 = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID);
+       if (rval2 != QLA_SUCCESS) {
+               DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
+                   "(%x).\n", __func__, ha->host_no, rval2));
+       } else {
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+       }
+
+       return rval;
+}
+
+int
+qla2x00_lun_reset(struct fc_port *fcport, unsigned int l)
+{
+       int rval, rval2;
+       mbx_cmd_t  mc;
+       mbx_cmd_t  *mcp = &mc;
+       scsi_qla_host_t *ha;
+
+       DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
+
+       ha = fcport->ha;
+       mcp->mb[0] = MBC_LUN_RESET;
+       mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
+       if (HAS_EXTENDED_IDS(ha))
+               mcp->mb[1] = fcport->loop_id;
+       else
+               mcp->mb[1] = fcport->loop_id << 8;
+       mcp->mb[2] = l;
+       mcp->mb[3] = 0;
+       mcp->mb[9] = ha->vp_idx;
 
+       mcp->in_mb = MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(ha, mcp);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n",
+               DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
                    ha->host_no, rval));
+       }
+
+       /* Issue marker IOCB. */
+       rval2 = qla2x00_marker(ha, fcport->loop_id, l, MK_SYNC_ID_LUN);
+       if (rval2 != QLA_SUCCESS) {
+               DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
+                   "(%x).\n", __func__, ha->host_no, rval2));
        } else {
-               /*EMPTY*/
-               DEBUG11(printk("qla2x00_abort_target(%ld): done.\n",
-                   ha->host_no));
+               DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
        }
 
        return rval;
 }
-#endif
 
 /*
  * qla2x00_get_adapter_id
@@ -871,7 +914,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
        mcp->mb[9] = ha->vp_idx;
        mcp->out_mb = MBX_9|MBX_0;
        mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
        if (mcp->mb[0] == MBS_COMMAND_ERROR)
@@ -928,7 +971,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *ha, uint8_t *retry_cnt, uint8_t *tov,
        mcp->mb[0] = MBC_GET_RETRY_COUNT;
        mcp->out_mb = MBX_0;
        mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -995,7 +1038,7 @@ qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size)
        mcp->in_mb = MBX_5|MBX_4|MBX_0;
        mcp->buf_size = size;
        mcp->flags = MBX_DMA_OUT;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        rval = qla2x00_mailbox_command(ha, mcp);
 
        if (rval != QLA_SUCCESS) {
@@ -1173,7 +1216,7 @@ gpd_error_out:
  *     Kernel context.
  */
 int
-qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
+qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *states)
 {
        int rval;
        mbx_cmd_t mc;
@@ -1184,13 +1227,15 @@ qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
 
        mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
        mcp->out_mb = MBX_0;
-       mcp->in_mb = MBX_2|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
-       /* Return firmware state. */
-       *dptr = mcp->mb[1];
+       /* Return firmware states. */
+       states[0] = mcp->mb[1];
+       states[1] = mcp->mb[2];
+       states[2] = mcp->mb[3];
 
        if (rval != QLA_SUCCESS) {
                /*EMPTY*/
@@ -1246,7 +1291,7 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
        }
 
        mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -1318,7 +1363,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha)
                mcp->mb[3] = 0;
        }
        mcp->in_mb = MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -1743,7 +1788,7 @@ qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
        }
 
        mcp->in_mb = MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -1791,7 +1836,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha)
        mcp->mb[3] = 0;
        mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -1852,7 +1897,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
                mcp->out_mb |= MBX_6|MBX_3|MBX_2|MBX_1;
        }
        mcp->in_mb = MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -1896,7 +1941,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
        mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
        mcp->out_mb = MBX_0;
        mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -2036,7 +2081,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
                mcp->mb[1] = loop_id << 8;
                mcp->out_mb |= MBX_1;
        }
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = IOCTL_CMD;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -2082,7 +2127,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, struct link_statistics *stats,
        mcp->mb[10] = 0;
        mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
        mcp->in_mb = MBX_2|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = IOCTL_CMD;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -2180,17 +2225,15 @@ struct tsk_mgmt_cmd {
        } p;
 };
 
-int
-qla24xx_abort_target(fc_port_t *fcport)
+static int
+__qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
+    unsigned int l)
 {
-       int             rval;
+       int             rval, rval2;
        struct tsk_mgmt_cmd *tsk;
        dma_addr_t      tsk_dma;
        scsi_qla_host_t *ha, *pha;
 
-       if (fcport == NULL)
-               return 0;
-
        DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
 
        ha = fcport->ha;
@@ -2207,47 +2250,61 @@ qla24xx_abort_target(fc_port_t *fcport)
        tsk->p.tsk.entry_count = 1;
        tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
        tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
-       tsk->p.tsk.control_flags = __constant_cpu_to_le32(TCF_TARGET_RESET);
+       tsk->p.tsk.control_flags = cpu_to_le32(type);
        tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa;
        tsk->p.tsk.port_id[1] = fcport->d_id.b.area;
        tsk->p.tsk.port_id[2] = fcport->d_id.b.domain;
        tsk->p.tsk.vp_index = fcport->vp_idx;
+       if (type == TCF_LUN_RESET) {
+               int_to_scsilun(l, &tsk->p.tsk.lun);
+               host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun,
+                   sizeof(tsk->p.tsk.lun));
+       }
 
        rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0);
        if (rval != QLA_SUCCESS) {
-               DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB "
-                   "(%x).\n", __func__, ha->host_no, rval));
-               goto atarget_done;
+               DEBUG2_3_11(printk("%s(%ld): failed to issue %s Reset IOCB "
+                   "(%x).\n", __func__, ha->host_no, name, rval));
        } else if (tsk->p.sts.entry_status != 0) {
                DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
                    "-- error status (%x).\n", __func__, ha->host_no,
                    tsk->p.sts.entry_status));
                rval = QLA_FUNCTION_FAILED;
-               goto atarget_done;
        } else if (tsk->p.sts.comp_status !=
            __constant_cpu_to_le16(CS_COMPLETE)) {
                DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
                    "-- completion status (%x).\n", __func__,
                    ha->host_no, le16_to_cpu(tsk->p.sts.comp_status)));
                rval = QLA_FUNCTION_FAILED;
-               goto atarget_done;
        }
 
        /* Issue marker IOCB. */
-       rval = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID);
-       if (rval != QLA_SUCCESS) {
+       rval2 = qla2x00_marker(ha, fcport->loop_id, l,
+           type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID);
+       if (rval2 != QLA_SUCCESS) {
                DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
-                   "(%x).\n", __func__, ha->host_no, rval));
+                   "(%x).\n", __func__, ha->host_no, rval2));
        } else {
                DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
        }
 
-atarget_done:
        dma_pool_free(pha->s_dma_pool, tsk, tsk_dma);
 
        return rval;
 }
 
+int
+qla24xx_abort_target(struct fc_port *fcport, unsigned int l)
+{
+       return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l);
+}
+
+int
+qla24xx_lun_reset(struct fc_port *fcport, unsigned int l)
+{
+       return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l);
+}
+
 #if 0
 
 int
@@ -2304,7 +2361,7 @@ qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g,
        mcp->mb[4] = sw_em_4g | BIT_15;
        mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -2372,7 +2429,7 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *ha, dma_addr_t eft_dma,
        mcp->mb[7] = TC_AEN_DISABLE;
        mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
        if (rval != QLA_SUCCESS) {
@@ -2401,7 +2458,7 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *ha)
        mcp->mb[1] = TC_EFT_DISABLE;
        mcp->out_mb = MBX_1|MBX_0;
        mcp->in_mb = MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
        if (rval != QLA_SUCCESS) {
@@ -2441,7 +2498,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *ha, dma_addr_t fce_dma,
        mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
            MBX_1|MBX_0;
        mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
        if (rval != QLA_SUCCESS) {
@@ -2477,7 +2534,7 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *ha, uint64_t *wr, uint64_t *rd)
        mcp->out_mb = MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
            MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
        if (rval != QLA_SUCCESS) {
@@ -2525,7 +2582,7 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr,
        mcp->mb[10] = 0;
        mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -2559,7 +2616,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id,
        mcp->mb[4] = mcp->mb[5] = 0;
        mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
        mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -2877,7 +2934,7 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
        }
 
        mcp->in_mb = MBX_0;
-       mcp->tov = 30;
+       mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
        rval = qla2x00_mailbox_command(ha, mcp);
 
@@ -2890,3 +2947,104 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
 
        return rval;
 }
+
+/* 84XX Support **************************************************************/
+
+struct cs84xx_mgmt_cmd {
+       union {
+               struct verify_chip_entry_84xx req;
+               struct verify_chip_rsp_84xx rsp;
+       } p;
+};
+
+int
+qla84xx_verify_chip(struct scsi_qla_host *ha, uint16_t *status)
+{
+       int rval, retry;
+       struct cs84xx_mgmt_cmd *mn;
+       dma_addr_t mn_dma;
+       uint16_t options;
+       unsigned long flags;
+
+       DEBUG16(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+       mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
+       if (mn == NULL) {
+               DEBUG2_3(printk("%s(%ld): failed to allocate Verify ISP84XX "
+                   "IOCB.\n", __func__, ha->host_no));
+               return QLA_MEMORY_ALLOC_FAILED;
+       }
+
+       /* Force Update? */
+       options = ha->cs84xx->fw_update ? VCO_FORCE_UPDATE : 0;
+       /* Diagnostic firmware? */
+       /* options |= MENLO_DIAG_FW; */
+       /* We update the firmware with only one data sequence. */
+       options |= VCO_END_OF_DATA;
+
+       retry = 0;
+       do {
+               memset(mn, 0, sizeof(*mn));
+               mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE;
+               mn->p.req.entry_count = 1;
+               mn->p.req.options = cpu_to_le16(options);
+
+               DEBUG16(printk("%s(%ld): Dump of Verify Request.\n", __func__,
+                   ha->host_no));
+               DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
+                   sizeof(*mn)));
+
+               rval = qla2x00_issue_iocb_timeout(ha, mn, mn_dma, 0, 120);
+               if (rval != QLA_SUCCESS) {
+                       DEBUG2_16(printk("%s(%ld): failed to issue Verify "
+                           "IOCB (%x).\n", __func__, ha->host_no, rval));
+                       goto verify_done;
+               }
+
+               DEBUG16(printk("%s(%ld): Dump of Verify Response.\n", __func__,
+                   ha->host_no));
+               DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
+                   sizeof(*mn)));
+
+               status[0] = le16_to_cpu(mn->p.rsp.comp_status);
+               status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
+                   le16_to_cpu(mn->p.rsp.failure_code) : 0;
+               DEBUG2_16(printk("%s(%ld): cs=%x fc=%x\n", __func__,
+                   ha->host_no, status[0], status[1]));
+
+               if (status[0] != CS_COMPLETE) {
+                       rval = QLA_FUNCTION_FAILED;
+                       if (!(options & VCO_DONT_UPDATE_FW)) {
+                               DEBUG2_16(printk("%s(%ld): Firmware update "
+                                   "failed. Retrying without update "
+                                   "firmware.\n", __func__, ha->host_no));
+                               options |= VCO_DONT_UPDATE_FW;
+                               options &= ~VCO_FORCE_UPDATE;
+                               retry = 1;
+                       }
+               } else {
+                       DEBUG2_16(printk("%s(%ld): firmware updated to %x.\n",
+                           __func__, ha->host_no,
+                           le32_to_cpu(mn->p.rsp.fw_ver)));
+
+                       /* NOTE: we only update OP firmware. */
+                       spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
+                       ha->cs84xx->op_fw_version =
+                           le32_to_cpu(mn->p.rsp.fw_ver);
+                       spin_unlock_irqrestore(&ha->cs84xx->access_lock,
+                           flags);
+               }
+       } while (retry);
+
+verify_done:
+       dma_pool_free(ha->s_dma_pool, mn, mn_dma);
+
+       if (rval != QLA_SUCCESS) {
+               DEBUG2_16(printk("%s(%ld): failed=%x.\n", __func__,
+                   ha->host_no, rval));
+       } else {
+               DEBUG16(printk("%s(%ld): done.\n", __func__, ha->host_no));
+       }
+
+       return rval;
+}
index cf784cdafb010c2b4ad3a3af374df991ea1c9283..f2b04979e5f072ca38f3d57edb8c8a6c3b7e4a53 100644 (file)
@@ -1,20 +1,8 @@
 /*
- *                  QLOGIC LINUX SOFTWARE
- *
- * QLogic ISP2x00 device driver for Linux 2.6.x
- * Copyright (C) 2003-2005 QLogic Corporation
- * (www.qlogic.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
+ * See LICENSE.qla2xxx for copyright and licensing details.
  */
 #include "qla_def.h"
 
@@ -28,8 +16,6 @@
 #include <scsi/scsicam.h>
 #include <linux/delay.h>
 
-void qla2x00_vp_stop_timer(scsi_qla_host_t *);
-
 void
 qla2x00_vp_stop_timer(scsi_qla_host_t *vha)
 {
@@ -268,9 +254,17 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
 static int
 qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
 {
+       scsi_qla_host_t *ha = vha->parent;
+
        if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) {
                /* VP acquired. complete port configuration */
-               qla24xx_configure_vp(vha);
+               if (atomic_read(&ha->loop_state) == LOOP_READY) {
+                       qla24xx_configure_vp(vha);
+               } else {
+                       set_bit(VP_IDX_ACQUIRED, &vha->vp_flags);
+                       set_bit(VP_DPC_NEEDED, &ha->dpc_flags);
+               }
+
                return 0;
        }
 
index 3c1b43356adb7624c513f6186b2d6f915a7d80d9..8b33b163b1d427717ccea65b5e20f1822438e632 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -26,9 +26,6 @@ char qla2x00_version_str[40];
  */
 static struct kmem_cache *srb_cachep;
 
-/*
- * Ioctl related information.
- */
 int num_hosts;
 int ql2xlogintimeout = 20;
 module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
@@ -103,9 +100,9 @@ static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
                void (*fn)(struct scsi_cmnd *));
 static int qla2xxx_eh_abort(struct scsi_cmnd *);
 static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
+static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
 static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
 static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
-static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *);
 
 static int qla2x00_change_queue_depth(struct scsi_device *, int);
 static int qla2x00_change_queue_type(struct scsi_device *, int);
@@ -117,6 +114,7 @@ static struct scsi_host_template qla2x00_driver_template = {
 
        .eh_abort_handler       = qla2xxx_eh_abort,
        .eh_device_reset_handler = qla2xxx_eh_device_reset,
+       .eh_target_reset_handler = qla2xxx_eh_target_reset,
        .eh_bus_reset_handler   = qla2xxx_eh_bus_reset,
        .eh_host_reset_handler  = qla2xxx_eh_host_reset,
 
@@ -148,6 +146,7 @@ struct scsi_host_template qla24xx_driver_template = {
 
        .eh_abort_handler       = qla2xxx_eh_abort,
        .eh_device_reset_handler = qla2xxx_eh_device_reset,
+       .eh_target_reset_handler = qla2xxx_eh_target_reset,
        .eh_bus_reset_handler   = qla2xxx_eh_bus_reset,
        .eh_host_reset_handler  = qla2xxx_eh_host_reset,
 
@@ -253,9 +252,9 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str)
 
                strcpy(str, "PCIe (");
                if (lspeed == 1)
-                       strcat(str, "2.5Gb/s ");
+                       strcat(str, "2.5GT/s ");
                else if (lspeed == 2)
-                       strcat(str, "5.0Gb/s ");
+                       strcat(str, "5.0GT/s ");
                else
                        strcat(str, "<unknown> ");
                snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth);
@@ -340,6 +339,8 @@ qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str)
                strcat(str, "[T10 CRC] ");
        if (ha->fw_attributes & BIT_5)
                strcat(str, "[VI] ");
+       if (ha->fw_attributes & BIT_10)
+               strcat(str, "[84XX] ");
        if (ha->fw_attributes & BIT_13)
                strcat(str, "[Experimental]");
        return str;
@@ -570,8 +571,6 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
        else
                return_status = QLA_FUNCTION_FAILED;
 
-       DEBUG2(printk("%s return_status=%d\n",__func__,return_status));
-
        return (return_status);
 }
 
@@ -685,7 +684,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 
                DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n",
                    __func__, ha->host_no, sp, serial));
-               DEBUG3(qla2x00_print_scsi_cmd(cmd));
 
                spin_unlock_irqrestore(&pha->hardware_lock, flags);
                if (ha->isp_ops->abort_command(ha, sp)) {
@@ -719,190 +717,122 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
        return ret;
 }
 
-/**************************************************************************
-* qla2x00_eh_wait_for_pending_target_commands
-*
-* Description:
-*    Waits for all the commands to come back from the specified target.
-*
-* Input:
-*    ha - pointer to scsi_qla_host structure.
-*    t  - target
-* Returns:
-*    Either SUCCESS or FAILED.
-*
-* Note:
-**************************************************************************/
+enum nexus_wait_type {
+       WAIT_HOST = 0,
+       WAIT_TARGET,
+       WAIT_LUN,
+};
+
 static int
-qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
+qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha, unsigned int t,
+    unsigned int l, enum nexus_wait_type type)
 {
-       int     cnt;
-       int     status;
-       srb_t           *sp;
-       struct scsi_cmnd *cmd;
+       int cnt, match, status;
+       srb_t *sp;
        unsigned long flags;
        scsi_qla_host_t *pha = to_qla_parent(ha);
 
-       status = 0;
-
-       /*
-        * Waiting for all commands for the designated target in the active
-        * array
-        */
-       for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-               spin_lock_irqsave(&pha->hardware_lock, flags);
+       status = QLA_SUCCESS;
+       spin_lock_irqsave(&pha->hardware_lock, flags);
+       for (cnt = 1; status == QLA_SUCCESS && cnt < MAX_OUTSTANDING_COMMANDS;
+           cnt++) {
                sp = pha->outstanding_cmds[cnt];
-               if (sp) {
-                       cmd = sp->cmd;
-                       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(&pha->hardware_lock, flags);
+               if (!sp)
+                       continue;
+               if (ha->vp_idx != sp->ha->vp_idx)
+                       continue;
+               match = 0;
+               switch (type) {
+               case WAIT_HOST:
+                       match = 1;
+                       break;
+               case WAIT_TARGET:
+                       match = sp->cmd->device->id == t;
+                       break;
+               case WAIT_LUN:
+                       match = (sp->cmd->device->id == t &&
+                           sp->cmd->device->lun == l);
+                       break;
                }
+               if (!match)
+                       continue;
+
+               spin_unlock_irqrestore(&pha->hardware_lock, flags);
+               status = qla2x00_eh_wait_on_command(ha, sp->cmd);
+               spin_lock_irqsave(&pha->hardware_lock, flags);
        }
-       return (status);
+       spin_unlock_irqrestore(&pha->hardware_lock, flags);
+
+       return status;
 }
 
+static char *reset_errors[] = {
+       "HBA not online",
+       "HBA not ready",
+       "Task management failed",
+       "Waiting for command completions",
+};
 
-/**************************************************************************
-* qla2xxx_eh_device_reset
-*
-* Description:
-*    The device reset function will reset the target and abort any
-*    executing commands.
-*
-*    NOTE: The use of SP is undefined within this context.  Do *NOT*
-*          attempt to use this value, even if you determine it is
-*          non-null.
-*
-* Input:
-*    cmd = Linux SCSI command packet of the command that cause the
-*          bus device reset.
-*
-* Returns:
-*    SUCCESS/FAILURE (defined as macro in scsi.h).
-*
-**************************************************************************/
 static int
-qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
+__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
+    struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int))
 {
        scsi_qla_host_t *ha = shost_priv(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-       int ret = FAILED;
-       unsigned int id, lun;
-       unsigned long serial;
+       int err;
 
        qla2x00_block_error_handler(cmd);
 
-       id = cmd->device->id;
-       lun = cmd->device->lun;
-       serial = cmd->serial_number;
-
        if (!fcport)
-               return ret;
+               return FAILED;
 
-       qla_printk(KERN_INFO, ha,
-           "scsi(%ld:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, id, lun);
+       qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
+           ha->host_no, cmd->device->id, cmd->device->lun, name);
 
+       err = 0;
        if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
-               goto eh_dev_reset_done;
-
-       if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {
-               if (qla2x00_device_reset(ha, fcport) == 0)
-                       ret = SUCCESS;
-
-#if defined(LOGOUT_AFTER_DEVICE_RESET)
-               if (ret == SUCCESS) {
-                       if (fcport->flags & FC_FABRIC_DEVICE) {
-                               ha->isp_ops->fabric_logout(ha, fcport->loop_id);
-                               qla2x00_mark_device_lost(ha, fcport, 0, 0);
-                       }
-               }
-#endif
-       } else {
-               DEBUG2(printk(KERN_INFO
-                   "%s failed: loop not ready\n",__func__));
-       }
-
-       if (ret == FAILED) {
-               DEBUG3(printk("%s(%ld): device reset failed\n",
-                   __func__, ha->host_no));
-               qla_printk(KERN_INFO, ha, "%s: device reset failed\n",
-                   __func__);
+               goto eh_reset_failed;
+       err = 1;
+       if (qla2x00_wait_for_loop_ready(ha) != QLA_SUCCESS)
+               goto eh_reset_failed;
+       err = 2;
+       if (do_reset(fcport, cmd->device->lun) != QLA_SUCCESS)
+               goto eh_reset_failed;
+       err = 3;
+       if (qla2x00_eh_wait_for_pending_commands(ha, cmd->device->id,
+           cmd->device->lun, type) != QLA_SUCCESS)
+               goto eh_reset_failed;
+
+       qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
+           ha->host_no, cmd->device->id, cmd->device->lun, name);
+
+       return SUCCESS;
+
+ eh_reset_failed:
+       qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET FAILED: %s.\n",
+           ha->host_no, cmd->device->id, cmd->device->lun, name,
+           reset_errors[err]);
+       return FAILED;
+}
 
-               goto eh_dev_reset_done;
-       }
+static int
+qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
+{
+       scsi_qla_host_t *ha = shost_priv(cmd->device->host);
 
-       /* Flush outstanding commands. */
-       if (qla2x00_eh_wait_for_pending_target_commands(ha, id))
-               ret = FAILED;
-       if (ret == FAILED) {
-               DEBUG3(printk("%s(%ld): failed while waiting for commands\n",
-                   __func__, ha->host_no));
-               qla_printk(KERN_INFO, ha,
-                   "%s: failed while waiting for commands\n", __func__);
-       } else
-               qla_printk(KERN_INFO, ha,
-                   "scsi(%ld:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no,
-                   id, lun);
- eh_dev_reset_done:
-       return ret;
+       return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
+           ha->isp_ops->lun_reset);
 }
 
-/**************************************************************************
-* qla2x00_eh_wait_for_pending_commands
-*
-* Description:
-*    Waits for all the commands to come back from the specified host.
-*
-* Input:
-*    ha - pointer to scsi_qla_host structure.
-*
-* Returns:
-*    1 : SUCCESS
-*    0 : FAILED
-*
-* Note:
-**************************************************************************/
 static int
-qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
+qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
 {
-       int     cnt;
-       int     status;
-       srb_t           *sp;
-       struct scsi_cmnd *cmd;
-       unsigned long flags;
-
-       status = 1;
+       scsi_qla_host_t *ha = shost_priv(cmd->device->host);
 
-       /*
-        * Waiting for all commands for the designated target in the active
-        * array
-        */
-       for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-               spin_lock_irqsave(&ha->hardware_lock, flags);
-               sp = ha->outstanding_cmds[cnt];
-               if (sp) {
-                       cmd = sp->cmd;
-                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-                       status = qla2x00_eh_wait_on_command(ha, cmd);
-                       if (status == 0)
-                               break;
-               }
-               else {
-                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-               }
-       }
-       return (status);
+       return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
+           ha->isp_ops->target_reset);
 }
 
-
 /**************************************************************************
 * qla2xxx_eh_bus_reset
 *
@@ -953,7 +883,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
                goto eh_bus_reset_done;
 
        /* Flush outstanding commands. */
-       if (!qla2x00_eh_wait_for_pending_commands(pha))
+       if (qla2x00_eh_wait_for_pending_commands(pha, 0, 0, WAIT_HOST) !=
+           QLA_SUCCESS)
                ret = FAILED;
 
 eh_bus_reset_done:
@@ -1024,7 +955,8 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
        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(pha))
+       if (qla2x00_eh_wait_for_pending_commands(pha, 0, 0, WAIT_HOST) ==
+           QLA_SUCCESS)
                ret = SUCCESS;
 
        if (ha->parent)
@@ -1080,7 +1012,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
                        if (fcport->port_type != FCT_TARGET)
                                continue;
 
-                       ret = qla2x00_device_reset(ha, fcport);
+                       ret = ha->isp_ops->target_reset(fcport, 0);
                        if (ret != QLA_SUCCESS) {
                                DEBUG2_3(printk("%s(%ld): bus_reset failed: "
                                    "target_reset=%d d_id=%x.\n", __func__,
@@ -1095,26 +1027,6 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
        return QLA_SUCCESS;
 }
 
-/*
- * qla2x00_device_reset
- *     Issue bus device reset message to the target.
- *
- * Input:
- *     ha = adapter block pointer.
- *     t = SCSI ID.
- *     TARGET_QUEUE_LOCK must be released.
- *     ADAPTER_STATE_LOCK must be released.
- *
- * Context:
- *     Kernel context.
- */
-static int
-qla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport)
-{
-       /* Abort Target command will clear Reservation */
-       return ha->isp_ops->abort_target(reset_fcport);
-}
-
 void
 qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res)
 {
@@ -1292,7 +1204,8 @@ static struct isp_operations qla2100_isp_ops = {
        .enable_intrs           = qla2x00_enable_intrs,
        .disable_intrs          = qla2x00_disable_intrs,
        .abort_command          = qla2x00_abort_command,
-       .abort_target           = qla2x00_abort_target,
+       .target_reset           = qla2x00_abort_target,
+       .lun_reset              = qla2x00_lun_reset,
        .fabric_login           = qla2x00_login_fabric,
        .fabric_logout          = qla2x00_fabric_logout,
        .calc_req_entries       = qla2x00_calc_iocbs_32,
@@ -1325,7 +1238,8 @@ static struct isp_operations qla2300_isp_ops = {
        .enable_intrs           = qla2x00_enable_intrs,
        .disable_intrs          = qla2x00_disable_intrs,
        .abort_command          = qla2x00_abort_command,
-       .abort_target           = qla2x00_abort_target,
+       .target_reset           = qla2x00_abort_target,
+       .lun_reset              = qla2x00_lun_reset,
        .fabric_login           = qla2x00_login_fabric,
        .fabric_logout          = qla2x00_fabric_logout,
        .calc_req_entries       = qla2x00_calc_iocbs_32,
@@ -1358,7 +1272,8 @@ static struct isp_operations qla24xx_isp_ops = {
        .enable_intrs           = qla24xx_enable_intrs,
        .disable_intrs          = qla24xx_disable_intrs,
        .abort_command          = qla24xx_abort_command,
-       .abort_target           = qla24xx_abort_target,
+       .target_reset           = qla24xx_abort_target,
+       .lun_reset              = qla24xx_lun_reset,
        .fabric_login           = qla24xx_login_fabric,
        .fabric_logout          = qla24xx_fabric_logout,
        .calc_req_entries       = NULL,
@@ -1391,7 +1306,8 @@ static struct isp_operations qla25xx_isp_ops = {
        .enable_intrs           = qla24xx_enable_intrs,
        .disable_intrs          = qla24xx_disable_intrs,
        .abort_command          = qla24xx_abort_command,
-       .abort_target           = qla24xx_abort_target,
+       .target_reset           = qla24xx_abort_target,
+       .lun_reset              = qla24xx_lun_reset,
        .fabric_login           = qla24xx_login_fabric,
        .fabric_logout          = qla24xx_fabric_logout,
        .calc_req_entries       = NULL,
@@ -1464,6 +1380,13 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha)
                ha->device_type |= DT_IIDMA;
                ha->fw_srisc_address = RISC_START_ADDRESS_2400;
                break;
+       case PCI_DEVICE_ID_QLOGIC_ISP8432:
+               ha->device_type |= DT_ISP8432;
+               ha->device_type |= DT_ZIO_SUPPORTED;
+               ha->device_type |= DT_FWI2;
+               ha->device_type |= DT_IIDMA;
+               ha->fw_srisc_address = RISC_START_ADDRESS_2400;
+               break;
        case PCI_DEVICE_ID_QLOGIC_ISP5422:
                ha->device_type |= DT_ISP5422;
                ha->device_type |= DT_FWI2;
@@ -1587,6 +1510,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        sht = &qla2x00_driver_template;
        if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
@@ -1677,7 +1601,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                if (IS_QLA2322(ha) || IS_QLA6322(ha))
                        ha->optrom_size = OPTROM_SIZE_2322;
                ha->isp_ops = &qla2300_isp_ops;
-       } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+       } else if (IS_QLA24XX_TYPE(ha)) {
                host->max_id = MAX_TARGETS_2200;
                ha->mbx_count = MAILBOX_REGISTER_COUNT;
                ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
@@ -1699,6 +1623,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                ha->gid_list_info_size = 8;
                ha->optrom_size = OPTROM_SIZE_25XX;
                ha->isp_ops = &qla25xx_isp_ops;
+               ha->hw_event_start = PCI_FUNC(pdev->devfn) ?
+                   FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR;
        }
        host->can_queue = ha->request_q_length + 128;
 
@@ -1713,6 +1639,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        INIT_LIST_HEAD(&ha->list);
        INIT_LIST_HEAD(&ha->fcports);
        INIT_LIST_HEAD(&ha->vp_list);
+       INIT_LIST_HEAD(&ha->work_list);
 
        set_bit(0, (unsigned long *) ha->vp_idx_map);
 
@@ -1819,6 +1746,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
 
        qla2x00_dfs_remove(ha);
 
+       qla84xx_put_chip(ha);
+
        qla2x00_free_sysfs_attr(ha);
 
        fc_remove_host(ha->host);
@@ -2206,6 +2135,97 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
        kfree(ha->nvram);
 }
 
+struct qla_work_evt *
+qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
+    int locked)
+{
+       struct qla_work_evt *e;
+
+       e = kzalloc(sizeof(struct qla_work_evt), locked ? GFP_ATOMIC:
+           GFP_KERNEL);
+       if (!e)
+               return NULL;
+
+       INIT_LIST_HEAD(&e->list);
+       e->type = type;
+       e->flags = QLA_EVT_FLAG_FREE;
+       return e;
+}
+
+int
+qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
+{
+       unsigned long flags;
+
+       if (!locked)
+               spin_lock_irqsave(&ha->hardware_lock, flags);
+       list_add_tail(&e->list, &ha->work_list);
+       qla2xxx_wake_dpc(ha);
+       if (!locked)
+               spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       return QLA_SUCCESS;
+}
+
+int
+qla2x00_post_aen_work(struct scsi_qla_host *ha, enum fc_host_event_code code,
+    u32 data)
+{
+       struct qla_work_evt *e;
+
+       e = qla2x00_alloc_work(ha, QLA_EVT_AEN, 1);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+
+       e->u.aen.code = code;
+       e->u.aen.data = data;
+       return qla2x00_post_work(ha, e, 1);
+}
+
+int
+qla2x00_post_hwe_work(struct scsi_qla_host *ha, uint16_t code, uint16_t d1,
+    uint16_t d2, uint16_t d3)
+{
+       struct qla_work_evt *e;
+
+       e = qla2x00_alloc_work(ha, QLA_EVT_HWE_LOG, 1);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+
+       e->u.hwe.code = code;
+       e->u.hwe.d1 = d1;
+       e->u.hwe.d2 = d2;
+       e->u.hwe.d3 = d3;
+       return qla2x00_post_work(ha, e, 1);
+}
+
+static void
+qla2x00_do_work(struct scsi_qla_host *ha)
+{
+       struct qla_work_evt *e;
+
+       spin_lock_irq(&ha->hardware_lock);
+       while (!list_empty(&ha->work_list)) {
+               e = list_entry(ha->work_list.next, struct qla_work_evt, list);
+               list_del_init(&e->list);
+               spin_unlock_irq(&ha->hardware_lock);
+
+               switch (e->type) {
+               case QLA_EVT_AEN:
+                       fc_host_post_event(ha->host, fc_get_event_number(),
+                           e->u.aen.code, e->u.aen.data);
+                       break;
+               case QLA_EVT_HWE_LOG:
+                       qla2xxx_hw_event_log(ha, e->u.hwe.code, e->u.hwe.d1,
+                           e->u.hwe.d2, e->u.hwe.d3);
+                       break;
+               }
+               if (e->flags & QLA_EVT_FLAG_FREE)
+                       kfree(e);
+               spin_lock_irq(&ha->hardware_lock);
+       }
+       spin_unlock_irq(&ha->hardware_lock);
+}
+
 /**************************************************************************
 * qla2x00_do_dpc
 *   This kernel thread is a task that is schedule by the interrupt handler
@@ -2257,6 +2277,8 @@ qla2x00_do_dpc(void *data)
                        continue;
                }
 
+               qla2x00_do_work(ha);
+
                if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) {
 
                        DEBUG(printk("scsi(%ld): dpc: sched "
@@ -2291,12 +2313,6 @@ qla2x00_do_dpc(void *data)
                if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))
                        qla2x00_update_fcports(ha);
 
-               if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) {
-                       DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n",
-                           ha->host_no));
-                       qla2x00_loop_reset(ha);
-               }
-
                if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) &&
                    (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) {
 
@@ -2367,19 +2383,6 @@ qla2x00_do_dpc(void *data)
                            ha->host_no));
                }
 
-               if ((test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags)) &&
-                   atomic_read(&ha->loop_state) != LOOP_DOWN) {
-
-                       clear_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags);
-                       DEBUG(printk("scsi(%ld): qla2x00_login_retry()\n",
-                           ha->host_no));
-
-                       set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
-
-                       DEBUG(printk("scsi(%ld): qla2x00_login_retry - end\n",
-                           ha->host_no));
-               }
-
                if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
 
                        DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n",
@@ -2397,18 +2400,6 @@ qla2x00_do_dpc(void *data)
                            ha->host_no));
                }
 
-               if (test_and_clear_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags)) {
-
-                       DEBUG(printk("scsi(%ld): Rescan flagged fcports...\n",
-                           ha->host_no));
-
-                       qla2x00_rescan_fcports(ha);
-
-                       DEBUG(printk("scsi(%ld): Rescan flagged fcports..."
-                           "end.\n",
-                           ha->host_no));
-               }
-
                if (!ha->interrupts_on)
                        ha->isp_ops->enable_intrs(ha);
 
@@ -2586,7 +2577,8 @@ qla2x00_timer(scsi_qla_host_t *ha)
                        set_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags);
                        start_dpc++;
 
-                       if (!(ha->device_flags & DFLG_NO_CABLE)) {
+                       if (!(ha->device_flags & DFLG_NO_CABLE) &&
+                           !ha->parent) {
                                DEBUG(printk("scsi(%ld): Loop down - "
                                    "aborting ISP.\n",
                                    ha->host_no));
@@ -2610,10 +2602,8 @@ qla2x00_timer(scsi_qla_host_t *ha)
        /* Schedule the DPC routine if needed */
        if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
            test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
-           test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) ||
            test_bit(FCPORT_UPDATE_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) ||
@@ -2665,7 +2655,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha)
                blob = &qla_fw_blobs[FW_ISP2300];
        } else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
                blob = &qla_fw_blobs[FW_ISP2322];
-       } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+       } else if (IS_QLA24XX_TYPE(ha)) {
                blob = &qla_fw_blobs[FW_ISP24XX];
        } else if (IS_QLA25XX(ha)) {
                blob = &qla_fw_blobs[FW_ISP25XX];
@@ -2815,6 +2805,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) },
+       { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8432) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
index 249e4d90fdc550cb7e95bdbc1608f5a400a540cb..2801c2664b40a6186b9e0ba058a02bd3a9eef353 100644 (file)
@@ -1,26 +1,12 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
-/*
- * Compile time Options:
- *     0 - Disable and 1 - Enable
- */
-#define DEBUG_QLA2100          0       /* For Debug of qla2x00 */
-
-#define USE_ABORT_TGT          1       /* Use Abort Target mbx cmd */
-
 #define MAX_RETRIES_OF_ISP_ABORT       5
 
 /* Max time to wait for the loop to be in LOOP_READY state */
 #define MAX_LOOP_TIMEOUT       (60 * 5)
 
-/*
- * Some vendor subsystems do not recover properly after a device reset.  Define
- * the following to force a logout after a successful device reset.
- */
-#undef LOGOUT_AFTER_DEVICE_RESET
-
 #include "qla_version.h"
index 26822c8807eecb6e1adc0d5eed29f4de93735aaa..1728ab3ccb201f19677885d488d8b12726cf094d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -543,79 +543,174 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
        }
 }
 
-static int
-qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
-    uint32_t dwords)
+void
+qla2xxx_get_flash_info(scsi_qla_host_t *ha)
 {
-       int ret;
-       uint32_t liter, miter;
-       uint32_t sec_mask, rest_addr, conf_addr;
-       uint32_t fdata, findex, cnt;
+#define FLASH_BLK_SIZE_32K     0x8000
+#define FLASH_BLK_SIZE_64K     0x10000
+       uint16_t cnt, chksum;
+       uint16_t *wptr;
+       struct qla_fdt_layout *fdt;
        uint8_t man_id, flash_id;
-       struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
-       dma_addr_t optrom_dma;
-       void *optrom = NULL;
-       uint32_t *s, *d;
 
-       ret = QLA_SUCCESS;
+       if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
+               return;
 
-       /* Prepare burst-capable write on supported ISPs. */
-       if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
-           dwords > OPTROM_BURST_DWORDS) {
-               optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
-                   &optrom_dma, GFP_KERNEL);
-               if (!optrom) {
-                       qla_printk(KERN_DEBUG, ha,
-                           "Unable to allocate memory for optrom burst write "
-                           "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
-               }
+       wptr = (uint16_t *)ha->request_ring;
+       fdt = (struct qla_fdt_layout *)ha->request_ring;
+       ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring,
+           FA_FLASH_DESCR_ADDR << 2, OPTROM_BURST_SIZE);
+       if (*wptr == __constant_cpu_to_le16(0xffff))
+               goto no_flash_data;
+       if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' ||
+           fdt->sig[3] != 'D')
+               goto no_flash_data;
+
+       for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1;
+           cnt++)
+               chksum += le16_to_cpu(*wptr++);
+       if (chksum) {
+               DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FDT detected: "
+                   "checksum=0x%x id=%c version=0x%x.\n", chksum, fdt->sig[0],
+                   le16_to_cpu(fdt->version)));
+               DEBUG9(qla2x00_dump_buffer((uint8_t *)fdt, sizeof(*fdt)));
+               goto no_flash_data;
        }
 
-       qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
-       DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
-           ha->host_no, man_id, flash_id));
+       ha->fdt_odd_index = le16_to_cpu(fdt->man_id) == 0x1f;
+       ha->fdt_wrt_disable = fdt->wrt_disable_bits;
+       ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd);
+       ha->fdt_block_size = le32_to_cpu(fdt->block_size);
+       if (fdt->unprotect_sec_cmd) {
+               ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0300 |
+                   fdt->unprotect_sec_cmd);
+               ha->fdt_protect_sec_cmd = fdt->protect_sec_cmd ?
+                   flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd):
+                   flash_conf_to_access_addr(0x0336);
+       }
 
-       conf_addr = flash_conf_to_access_addr(0x03d8);
+       DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[FDT]: (0x%x/0x%x) erase=0x%x "
+           "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n",
+           le16_to_cpu(fdt->man_id), le16_to_cpu(fdt->id), ha->fdt_erase_cmd,
+           ha->fdt_protect_sec_cmd, ha->fdt_unprotect_sec_cmd,
+           ha->fdt_odd_index, ha->fdt_wrt_disable, ha->fdt_block_size));
+       return;
+
+no_flash_data:
+       qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
+       ha->fdt_wrt_disable = 0x9c;
+       ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8);
        switch (man_id) {
        case 0xbf: /* STT flash. */
-               if (flash_id == 0x8e) {
-                       rest_addr = 0x3fff;
-                       sec_mask = 0x7c000;
-               } else {
-                       rest_addr = 0x1fff;
-                       sec_mask = 0x7e000;
-               }
+               if (flash_id == 0x8e)
+                       ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+               else
+                       ha->fdt_block_size = FLASH_BLK_SIZE_32K;
+
                if (flash_id == 0x80)
-                       conf_addr = flash_conf_to_access_addr(0x0352);
+                       ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0352);
                break;
        case 0x13: /* ST M25P80. */
-               rest_addr = 0x3fff;
-               sec_mask = 0x7c000;
+               ha->fdt_block_size = FLASH_BLK_SIZE_64K;
                break;
-       case 0x1f: // Atmel 26DF081A
-               rest_addr = 0x3fff;
-               sec_mask = 0x7c000;
-               conf_addr = flash_conf_to_access_addr(0x0320);
+       case 0x1f: /* Atmel 26DF081A. */
+               ha->fdt_odd_index = 1;
+               ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+               ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0320);
+               ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0339);
+               ha->fdt_protect_sec_cmd = flash_conf_to_access_addr(0x0336);
                break;
        default:
                /* Default to 64 kb sector size. */
-               rest_addr = 0x3fff;
-               sec_mask = 0x7c000;
+               ha->fdt_block_size = FLASH_BLK_SIZE_64K;
                break;
        }
 
+       DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[MID]: (0x%x/0x%x) erase=0x%x "
+           "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", man_id, flash_id,
+           ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd,
+           ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable,
+           ha->fdt_block_size));
+}
+
+static void
+qla24xx_unprotect_flash(scsi_qla_host_t *ha)
+{
+       struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
        /* Enable flash write. */
        WRT_REG_DWORD(&reg->ctrl_status,
            RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
        RD_REG_DWORD(&reg->ctrl_status);        /* PCI Posting. */
 
+       if (!ha->fdt_wrt_disable)
+               return;
+
        /* Disable flash write-protection. */
        qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
        /* Some flash parts need an additional zero-write to clear bits.*/
        qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
+}
+
+static void
+qla24xx_protect_flash(scsi_qla_host_t *ha)
+{
+       uint32_t cnt;
+       struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+       if (!ha->fdt_wrt_disable)
+               goto skip_wrt_protect;
+
+       /* Enable flash write-protection and wait for completion. */
+       qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101),
+           ha->fdt_wrt_disable);
+       for (cnt = 300; cnt &&
+           qla24xx_read_flash_dword(ha,
+                   flash_conf_to_access_addr(0x005)) & BIT_0;
+           cnt--) {
+               udelay(10);
+       }
+
+skip_wrt_protect:
+       /* Disable flash write. */
+       WRT_REG_DWORD(&reg->ctrl_status,
+           RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
+       RD_REG_DWORD(&reg->ctrl_status);        /* PCI Posting. */
+}
+
+static int
+qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
+    uint32_t dwords)
+{
+       int ret;
+       uint32_t liter, miter;
+       uint32_t sec_mask, rest_addr;
+       uint32_t fdata, findex;
+       dma_addr_t optrom_dma;
+       void *optrom = NULL;
+       uint32_t *s, *d;
+
+       ret = QLA_SUCCESS;
+
+       /* Prepare burst-capable write on supported ISPs. */
+       if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
+           dwords > OPTROM_BURST_DWORDS) {
+               optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
+                   &optrom_dma, GFP_KERNEL);
+               if (!optrom) {
+                       qla_printk(KERN_DEBUG, ha,
+                           "Unable to allocate memory for optrom burst write "
+                           "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
+               }
+       }
+
+       rest_addr = (ha->fdt_block_size >> 2) - 1;
+       sec_mask = 0x80000 - (ha->fdt_block_size >> 2);
+
+       qla24xx_unprotect_flash(ha);
 
        for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
-               if (man_id == 0x1f) {
+               if (ha->fdt_odd_index) {
                        findex = faddr << 2;
                        fdata = findex & sec_mask;
                } else {
@@ -625,13 +720,13 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
 
                /* Are we at the beginning of a sector? */
                if ((findex & rest_addr) == 0) {
-                       /* Do sector unprotect at 4K boundry for Atmel part. */
-                       if (man_id == 0x1f)
+                       /* Do sector unprotect. */
+                       if (ha->fdt_unprotect_sec_cmd)
                                qla24xx_write_flash_dword(ha,
-                                   flash_conf_to_access_addr(0x0339),
+                                   ha->fdt_unprotect_sec_cmd,
                                    (fdata & 0xff00) | ((fdata << 16) &
                                    0xff0000) | ((fdata >> 16) & 0xff));
-                       ret = qla24xx_write_flash_dword(ha, conf_addr,
+                       ret = qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
                            (fdata & 0xff00) |((fdata << 16) &
                            0xff0000) | ((fdata >> 16) & 0xff));
                        if (ret != QLA_SUCCESS) {
@@ -681,28 +776,16 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
                        break;
                }
 
-               /* Do sector protect at 4K boundry for Atmel part. */
-               if (man_id == 0x1f &&
+               /* Do sector protect. */
+               if (ha->fdt_unprotect_sec_cmd &&
                    ((faddr & rest_addr) == rest_addr))
                        qla24xx_write_flash_dword(ha,
-                           flash_conf_to_access_addr(0x0336),
+                           ha->fdt_protect_sec_cmd,
                            (fdata & 0xff00) | ((fdata << 16) &
                            0xff0000) | ((fdata >> 16) & 0xff));
        }
 
-       /* Enable flash write-protection and wait for completion. */
-       qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
-       for (cnt = 300; cnt &&
-           qla24xx_read_flash_dword(ha,
-                   flash_conf_to_access_addr(0x005)) & BIT_0;
-           cnt--) {
-               udelay(10);
-       }
-
-       /* Disable flash write. */
-       WRT_REG_DWORD(&reg->ctrl_status,
-           RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
-       RD_REG_DWORD(&reg->ctrl_status);        /* PCI Posting. */
+       qla24xx_protect_flash(ha);
 
        if (optrom)
                dma_free_coherent(&ha->pdev->dev,
@@ -2221,3 +2304,107 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
 
        return ret;
 }
+
+static int
+qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
+{
+       uint32_t d[2], faddr;
+
+       /* Locate first empty entry. */
+       for (;;) {
+               if (ha->hw_event_ptr >=
+                   ha->hw_event_start + FA_HW_EVENT_SIZE) {
+                       DEBUG2(qla_printk(KERN_WARNING, ha,
+                           "HW event -- Log Full!\n"));
+                       return QLA_MEMORY_ALLOC_FAILED;
+               }
+
+               qla24xx_read_flash_data(ha, d, ha->hw_event_ptr, 2);
+               faddr = flash_data_to_access_addr(ha->hw_event_ptr);
+               ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
+               if (d[0] == __constant_cpu_to_le32(0xffffffff) &&
+                   d[1] == __constant_cpu_to_le32(0xffffffff)) {
+                       qla24xx_unprotect_flash(ha);
+
+                       qla24xx_write_flash_dword(ha, faddr++,
+                           cpu_to_le32(jiffies));
+                       qla24xx_write_flash_dword(ha, faddr++, 0);
+                       qla24xx_write_flash_dword(ha, faddr++, *fdata++);
+                       qla24xx_write_flash_dword(ha, faddr++, *fdata);
+
+                       qla24xx_protect_flash(ha);
+                       break;
+               }
+       }
+       return QLA_SUCCESS;
+}
+
+int
+qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1,
+    uint16_t d2, uint16_t d3)
+{
+#define QMARK(a, b, c, d) \
+    cpu_to_le32(LSB(a) << 24 | LSB(b) << 16 | LSB(c) << 8 | LSB(d))
+
+       int rval;
+       uint32_t marker[2], fdata[4];
+
+       if (ha->hw_event_start == 0)
+               return QLA_FUNCTION_FAILED;
+
+       DEBUG2(qla_printk(KERN_WARNING, ha,
+           "HW event -- code=%x, d1=%x, d2=%x, d3=%x.\n", code, d1, d2, d3));
+
+       /* If marker not already found, locate or write.  */
+       if (!ha->flags.hw_event_marker_found) {
+               /* Create marker. */
+               marker[0] = QMARK('L', ha->fw_major_version,
+                   ha->fw_minor_version, ha->fw_subminor_version);
+               marker[1] = QMARK(QLA_DRIVER_MAJOR_VER, QLA_DRIVER_MINOR_VER,
+                   QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER);
+
+               /* Locate marker. */
+               ha->hw_event_ptr = ha->hw_event_start;
+               for (;;) {
+                       qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr,
+                           4);
+                       if (fdata[0] == __constant_cpu_to_le32(0xffffffff) &&
+                           fdata[1] == __constant_cpu_to_le32(0xffffffff))
+                               break;
+                       ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
+                       if (ha->hw_event_ptr >=
+                           ha->hw_event_start + FA_HW_EVENT_SIZE) {
+                               DEBUG2(qla_printk(KERN_WARNING, ha,
+                                   "HW event -- Log Full!\n"));
+                               return QLA_MEMORY_ALLOC_FAILED;
+                       }
+                       if (fdata[2] == marker[0] && fdata[3] == marker[1]) {
+                               ha->flags.hw_event_marker_found = 1;
+                               break;
+                       }
+               }
+               /* No marker, write it. */
+               if (!ha->flags.hw_event_marker_found) {
+                       rval = qla2xxx_hw_event_store(ha, marker);
+                       if (rval != QLA_SUCCESS) {
+                               DEBUG2(qla_printk(KERN_WARNING, ha,
+                                   "HW event -- Failed marker write=%x.!\n",
+                                   rval));
+                               return rval;
+                       }
+                       ha->flags.hw_event_marker_found = 1;
+               }
+       }
+
+       /* Store error.  */
+       fdata[0] = cpu_to_le32(code << 16 | d1);
+       fdata[1] = cpu_to_le32(d2 << 16 | d3);
+       rval = qla2xxx_hw_event_store(ha, fdata);
+       if (rval != QLA_SUCCESS) {
+               DEBUG2(qla_printk(KERN_WARNING, ha,
+                   "HW event -- Failed error write=%x.!\n",
+                   rval));
+       }
+
+       return rval;
+}
index ea08a129fee91827b4c3b285f78c8ae171782cdf..f42f17acf2cf21b7b5d9b62e5c0b18e7f4bc8040 100644 (file)
@@ -1,15 +1,15 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
+ * Copyright (c)  2003-2008 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.02.00-k9"
+#define QLA2XXX_VERSION      "8.02.01-k1"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   2
-#define QLA_DRIVER_PATCH_VER   0
+#define QLA_DRIVER_PATCH_VER   1
 #define QLA_DRIVER_BETA_VER    0
index fe415ec8565592924853f0d5c57da5f05453d502..1b667a70cffaac586c33f0781ad77569fc22e527 100644 (file)
@@ -216,6 +216,7 @@ union external_hw_config_reg {
 #define MBOX_CMD_ABOUT_FW                      0x0009
 #define MBOX_CMD_PING                          0x000B
 #define MBOX_CMD_LUN_RESET                     0x0016
+#define MBOX_CMD_TARGET_WARM_RESET             0x0017
 #define MBOX_CMD_GET_MANAGEMENT_DATA           0x001E
 #define MBOX_CMD_GET_FW_STATUS                 0x001F
 #define MBOX_CMD_SET_ISNS_SERVICE              0x0021
@@ -677,7 +678,8 @@ struct qla4_marker_entry {
        uint32_t system_defined; /* 04-07 */
        uint16_t target;        /* 08-09 */
        uint16_t modifier;      /* 0A-0B */
-#define MM_LUN_RESET        0
+#define MM_LUN_RESET           0
+#define MM_TGT_WARM_RESET      1
 
        uint16_t flags;         /* 0C-0D */
        uint16_t reserved1;     /* 0E-0F */
index a3608e028bf69328bc886b72dff2adc3291a2696..96ebfb021f6cae3f8a6a3695bd2db20f97c580e2 100644 (file)
@@ -27,6 +27,8 @@ int qla4xxx_relogin_device(struct scsi_qla_host * ha,
                           struct ddb_entry * ddb_entry);
 int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
                      int lun);
+int qla4xxx_reset_target(struct scsi_qla_host * ha,
+                        struct ddb_entry * ddb_entry);
 int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
                      uint32_t offset, uint32_t len);
 int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
@@ -68,6 +70,8 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
 int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
                                uint32_t fw_ddb_index, uint32_t state);
 void qla4xxx_dump_buffer(void *b, uint32_t size);
+int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
+       struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
 
 extern int ql4xextended_error_logging;
 extern int ql4xdiscoverywait;
index e4461b5d767a2305c0a1c6067e08f53db22235eb..912a67494adff6928cc52f760d34b2da89149e6e 100644 (file)
@@ -66,8 +66,8 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
  *
  * This routine issues a marker IOCB.
  **/
-static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
-                                   struct ddb_entry *ddb_entry, int lun)
+int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
+       struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod)
 {
        struct qla4_marker_entry *marker_entry;
        unsigned long flags = 0;
@@ -87,7 +87,7 @@ static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
        marker_entry->hdr.entryType = ET_MARKER;
        marker_entry->hdr.entryCount = 1;
        marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
-       marker_entry->modifier = cpu_to_le16(MM_LUN_RESET);
+       marker_entry->modifier = cpu_to_le16(mrkr_mod);
        int_to_scsilun(lun, &marker_entry->lun);
        wmb();
 
@@ -210,14 +210,6 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
        /* Get real lun and adapter */
        ddb_entry = srb->ddb;
 
-       /* Send marker(s) if needed. */
-       if (ha->marker_needed == 1) {
-               if (qla4xxx_send_marker_iocb(ha, ddb_entry,
-                                            cmd->device->lun) != QLA_SUCCESS)
-                       return QLA_ERROR;
-
-               ha->marker_needed = 0;
-       }
        tot_dsds = 0;
 
        /* Acquire hardware specific lock */
index fc84db4069f42d267d870b4deb56a763319312c0..a91a57c57bffbd979d7fbc2c4b0c9b7880ef5ac4 100644 (file)
 #include "ql4_dbg.h"
 #include "ql4_inline.h"
 
-/**
- * qla2x00_process_completed_request() - Process a Fast Post response.
- * @ha: SCSI driver HA context
- * @index: SRB index
- **/
-static void qla4xxx_process_completed_request(struct scsi_qla_host *ha,
-                                             uint32_t index)
-{
-       struct srb *srb;
-
-       srb = qla4xxx_del_from_active_array(ha, index);
-       if (srb) {
-               /* Save ISP completion status */
-               srb->cmd->result = DID_OK << 16;
-               qla4xxx_srb_compl(ha, srb);
-       } else {
-               DEBUG2(printk("scsi%ld: Invalid ISP SCSI completion handle = "
-                             "%d\n", ha->host_no, index));
-               set_bit(DPC_RESET_HA, &ha->dpc_flags);
-       }
-}
-
 /**
  * qla4xxx_status_entry - processes status IOCBs
  * @ha: Pointer to host adapter structure.
@@ -47,14 +25,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
        uint32_t residual;
        uint16_t sensebytecnt;
 
-       if (sts_entry->completionStatus == SCS_COMPLETE &&
-           sts_entry->scsiStatus == 0) {
-               qla4xxx_process_completed_request(ha,
-                                                 le32_to_cpu(sts_entry->
-                                                             handle));
-               return;
-       }
-
        srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
        if (!srb) {
                /* FIXMEdg: Don't we need to reset ISP in this case??? */
@@ -62,6 +32,9 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
                              "handle 0x%x, sp=%p. This cmd may have already "
                              "been completed.\n", ha->host_no, __func__,
                              le32_to_cpu(sts_entry->handle), srb));
+               dev_warn(&ha->pdev->dev, "%s invalid status entry:"
+                       " handle=0x%0x\n", __func__, sts_entry->handle);
+               set_bit(DPC_RESET_HA, &ha->dpc_flags);
                return;
        }
 
@@ -88,10 +61,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
        scsi_status = sts_entry->scsiStatus;
        switch (sts_entry->completionStatus) {
        case SCS_COMPLETE:
-               if (scsi_status == 0) {
-                       cmd->result = DID_OK << 16;
-                       break;
-               }
 
                if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
                        cmd->result = DID_ERROR << 16;
@@ -100,7 +69,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
 
                if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) {
                        scsi_set_resid(cmd, residual);
-                       if ((scsi_bufflen(cmd) - residual) < cmd->underflow) {
+                       if (!scsi_status && ((scsi_bufflen(cmd) - residual) <
+                               cmd->underflow)) {
 
                                cmd->result = DID_ERROR << 16;
 
index 35cd73c72a6886e8b5582d4b2840d7b3b189f013..c577d79bd7e8676faa222b6a1e1b9eaf7fc122a2 100644 (file)
@@ -713,6 +713,45 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
        return status;
 }
 
+/**
+ * qla4xxx_reset_target - issues target Reset
+ * @ha: Pointer to host adapter structure.
+ * @db_entry: Pointer to device database entry
+ * @un_entry: Pointer to lun entry structure
+ *
+ * This routine performs a TARGET RESET on the specified target.
+ * The caller must ensure that the ddb_entry pointers
+ * are valid before calling this routine.
+ **/
+int qla4xxx_reset_target(struct scsi_qla_host *ha,
+                        struct ddb_entry *ddb_entry)
+{
+       uint32_t mbox_cmd[MBOX_REG_COUNT];
+       uint32_t mbox_sts[MBOX_REG_COUNT];
+       int status = QLA_SUCCESS;
+
+       DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
+                     ddb_entry->os_target_id));
+
+       /*
+        * Send target reset command to ISP, so that the ISP will return all
+        * outstanding requests with RESET status
+        */
+       memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+       memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+       mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
+       mbox_cmd[1] = ddb_entry->fw_ddb_index;
+       mbox_cmd[5] = 0x01;     /* Immediate Command Enable */
+
+       qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+                               &mbox_sts[0]);
+       if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
+           mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
+               status = QLA_ERROR;
+
+       return status;
+}
 
 int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
                      uint32_t offset, uint32_t len)
index 8b92f348f02c73ad8e139be5ede91843d31afc47..0c786944d2c2ad3b6f1efcd53134e4ece3f849af 100644 (file)
@@ -71,6 +71,7 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
 static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
                                void (*done) (struct scsi_cmnd *));
 static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
+static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_slave_alloc(struct scsi_device *device);
 static int qla4xxx_slave_configure(struct scsi_device *device);
@@ -84,6 +85,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
        .queuecommand           = qla4xxx_queuecommand,
 
        .eh_device_reset_handler = qla4xxx_eh_device_reset,
+       .eh_target_reset_handler = qla4xxx_eh_target_reset,
        .eh_host_reset_handler  = qla4xxx_eh_host_reset,
 
        .slave_configure        = qla4xxx_slave_configure,
@@ -1482,7 +1484,7 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
 }
 
 /**
- * qla4xxx_eh_wait_for_active_target_commands - wait for active cmds to finish.
+ * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
  * @ha: pointer to to HBA
  * @t: target id
  * @l: lun id
@@ -1490,20 +1492,22 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
  * This function waits for all outstanding commands to a lun to complete. It
  * returns 0 if all pending commands are returned and 1 otherwise.
  **/
-static int qla4xxx_eh_wait_for_active_target_commands(struct scsi_qla_host *ha,
-                                                int t, int l)
+static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
+                                       struct scsi_target *stgt,
+                                       struct scsi_device *sdev)
 {
        int cnt;
        int status = 0;
        struct scsi_cmnd *cmd;
 
        /*
-        * Waiting for all commands for the designated target in the active
-        * array
+        * Waiting for all commands for the designated target or dev
+        * in the active array
         */
        for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
                cmd = scsi_host_find_tag(ha->host, cnt);
-               if (cmd && cmd->device->id == t && cmd->device->lun == l) {
+               if (cmd && stgt == scsi_target(cmd->device) &&
+                   (!sdev || sdev == cmd->device)) {
                        if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
                                status++;
                                break;
@@ -1548,24 +1552,19 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
                goto eh_dev_reset_done;
        }
 
-       /* Send marker. */
-       ha->marker_needed = 1;
-
-       /*
-        * If we are coming down the EH path, wait for all commands to complete
-        * for the device.
-        */
-       if (cmd->device->host->shost_state == SHOST_RECOVERY) {
-               if (qla4xxx_eh_wait_for_active_target_commands(ha,
-                                                         cmd->device->id,
-                                                         cmd->device->lun)){
-                       dev_info(&ha->pdev->dev,
-                                  "DEVICE RESET FAILED - waiting for "
-                                  "commands.\n");
-                       goto eh_dev_reset_done;
-               }
+       if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
+                                        cmd->device)) {
+               dev_info(&ha->pdev->dev,
+                          "DEVICE RESET FAILED - waiting for "
+                          "commands.\n");
+               goto eh_dev_reset_done;
        }
 
+       /* Send marker. */
+       if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
+               MM_LUN_RESET) != QLA_SUCCESS)
+               goto eh_dev_reset_done;
+
        dev_info(&ha->pdev->dev,
                   "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
                   ha->host_no, cmd->device->channel, cmd->device->id,
@@ -1578,6 +1577,59 @@ eh_dev_reset_done:
        return ret;
 }
 
+/**
+ * qla4xxx_eh_target_reset - callback for target reset.
+ * @cmd: Pointer to Linux's SCSI command structure
+ *
+ * This routine is called by the Linux OS to reset the target.
+ **/
+static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
+{
+       struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
+       struct ddb_entry *ddb_entry = cmd->device->hostdata;
+       int stat;
+
+       if (!ddb_entry)
+               return FAILED;
+
+       starget_printk(KERN_INFO, scsi_target(cmd->device),
+                      "WARM TARGET RESET ISSUED.\n");
+
+       DEBUG2(printk(KERN_INFO
+                     "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
+                     "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
+                     ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ,
+                     ha->dpc_flags, cmd->result, cmd->allowed));
+
+       stat = qla4xxx_reset_target(ha, ddb_entry);
+       if (stat != QLA_SUCCESS) {
+               starget_printk(KERN_INFO, scsi_target(cmd->device),
+                              "WARM TARGET RESET FAILED.\n");
+               return FAILED;
+       }
+
+       if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
+                                        NULL)) {
+               starget_printk(KERN_INFO, scsi_target(cmd->device),
+                              "WARM TARGET DEVICE RESET FAILED - "
+                              "waiting for commands.\n");
+               return FAILED;
+       }
+
+       /* Send marker. */
+       if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
+               MM_TGT_WARM_RESET) != QLA_SUCCESS) {
+               starget_printk(KERN_INFO, scsi_target(cmd->device),
+                              "WARM TARGET DEVICE RESET FAILED - "
+                              "marker iocb failed.\n");
+               return FAILED;
+       }
+
+       starget_printk(KERN_INFO, scsi_target(cmd->device),
+                      "WARM TARGET RESET SUCCEEDED.\n");
+       return SUCCESS;
+}
+
 /**
  * qla4xxx_eh_host_reset - kernel callback
  * @cmd: Pointer to Linux's SCSI command structure
index 86e13183c9bab421418f3fb706662d0f24d6f666..52182a744ba652fbee765293f576b37fd4c95b7d 100644 (file)
@@ -289,7 +289,7 @@ raid_class_release(struct raid_template *r)
 {
        struct raid_internal *i = to_raid_internal(r);
 
-       attribute_container_unregister(&i->r.raid_attrs.ac);
+       BUG_ON(attribute_container_unregister(&i->r.raid_attrs.ac));
 
        kfree(i);
 }
index c78b836f59dd33bac178a41a1dfc11f3d2209ad4..f6980bd9d8f9a9a8b75a57de89cd9c8e26cc214c 100644 (file)
@@ -165,6 +165,51 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
 
 static DEFINE_MUTEX(host_cmd_pool_mutex);
 
+/**
+ * scsi_pool_alloc_command - internal function to get a fully allocated command
+ * @pool:      slab pool to allocate the command from
+ * @gfp_mask:  mask for the allocation
+ *
+ * Returns a fully allocated command (with the allied sense buffer) or
+ * NULL on failure
+ */
+static struct scsi_cmnd *
+scsi_pool_alloc_command(struct scsi_host_cmd_pool *pool, gfp_t gfp_mask)
+{
+       struct scsi_cmnd *cmd;
+
+       cmd = kmem_cache_alloc(pool->cmd_slab, gfp_mask | pool->gfp_mask);
+       if (!cmd)
+               return NULL;
+
+       memset(cmd, 0, sizeof(*cmd));
+
+       cmd->sense_buffer = kmem_cache_alloc(pool->sense_slab,
+                                            gfp_mask | pool->gfp_mask);
+       if (!cmd->sense_buffer) {
+               kmem_cache_free(pool->cmd_slab, cmd);
+               return NULL;
+       }
+
+       return cmd;
+}
+
+/**
+ * scsi_pool_free_command - internal function to release a command
+ * @pool:      slab pool to allocate the command from
+ * @cmd:       command to release
+ *
+ * the command must previously have been allocated by
+ * scsi_pool_alloc_command.
+ */
+static void
+scsi_pool_free_command(struct scsi_host_cmd_pool *pool,
+                        struct scsi_cmnd *cmd)
+{
+       kmem_cache_free(pool->sense_slab, cmd->sense_buffer);
+       kmem_cache_free(pool->cmd_slab, cmd);
+}
+
 /**
  * __scsi_get_command - Allocate a struct scsi_cmnd
  * @shost: host to transmit command
@@ -178,20 +223,7 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
        struct scsi_cmnd *cmd;
        unsigned char *buf;
 
-       cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
-                              gfp_mask | shost->cmd_pool->gfp_mask);
-
-       if (likely(cmd)) {
-               buf = kmem_cache_alloc(shost->cmd_pool->sense_slab,
-                                      gfp_mask | shost->cmd_pool->gfp_mask);
-               if (likely(buf)) {
-                       memset(cmd, 0, sizeof(*cmd));
-                       cmd->sense_buffer = buf;
-               } else {
-                       kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
-                       cmd = NULL;
-               }
-       }
+       cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
 
        if (unlikely(!cmd)) {
                unsigned long flags;
@@ -268,11 +300,8 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd,
        }
        spin_unlock_irqrestore(&shost->free_list_lock, flags);
 
-       if (likely(cmd != NULL)) {
-               kmem_cache_free(shost->cmd_pool->sense_slab,
-                               cmd->sense_buffer);
-               kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
-       }
+       if (likely(cmd != NULL))
+               scsi_pool_free_command(shost->cmd_pool, cmd);
 
        put_device(dev);
 }
@@ -301,30 +330,16 @@ void scsi_put_command(struct scsi_cmnd *cmd)
 }
 EXPORT_SYMBOL(scsi_put_command);
 
-/**
- * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
- * @shost: host to allocate the freelist for.
- *
- * Description: The command freelist protects against system-wide out of memory
- * deadlock by preallocating one SCSI command structure for each host, so the
- * system can always write to a swap file on a device associated with that host.
- *
- * Returns:    Nothing.
- */
-int scsi_setup_command_freelist(struct Scsi_Host *shost)
+static struct scsi_host_cmd_pool *scsi_get_host_cmd_pool(gfp_t gfp_mask)
 {
-       struct scsi_host_cmd_pool *pool;
-       struct scsi_cmnd *cmd;
-
-       spin_lock_init(&shost->free_list_lock);
-       INIT_LIST_HEAD(&shost->free_list);
-
+       struct scsi_host_cmd_pool *retval = NULL, *pool;
        /*
         * Select a command slab for this host and create it if not
         * yet existent.
         */
        mutex_lock(&host_cmd_pool_mutex);
-       pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
+       pool = (gfp_mask & __GFP_DMA) ? &scsi_cmd_dma_pool :
+               &scsi_cmd_pool;
        if (!pool->users) {
                pool->cmd_slab = kmem_cache_create(pool->cmd_name,
                                                   sizeof(struct scsi_cmnd), 0,
@@ -342,37 +357,122 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
        }
 
        pool->users++;
-       shost->cmd_pool = pool;
+       retval = pool;
+ fail:
        mutex_unlock(&host_cmd_pool_mutex);
+       return retval;
+}
+
+static void scsi_put_host_cmd_pool(gfp_t gfp_mask)
+{
+       struct scsi_host_cmd_pool *pool;
 
+       mutex_lock(&host_cmd_pool_mutex);
+       pool = (gfp_mask & __GFP_DMA) ? &scsi_cmd_dma_pool :
+               &scsi_cmd_pool;
        /*
-        * Get one backup command for this host.
+        * This may happen if a driver has a mismatched get and put
+        * of the command pool; the driver should be implicated in
+        * the stack trace
         */
-       cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
-                              GFP_KERNEL | shost->cmd_pool->gfp_mask);
-       if (!cmd)
-               goto fail2;
+       BUG_ON(pool->users == 0);
 
-       cmd->sense_buffer = kmem_cache_alloc(shost->cmd_pool->sense_slab,
-                                            GFP_KERNEL |
-                                            shost->cmd_pool->gfp_mask);
-       if (!cmd->sense_buffer)
-               goto fail2;
-
-       list_add(&cmd->list, &shost->free_list);
-       return 0;
-
- fail2:
-       if (cmd)
-               kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
-       mutex_lock(&host_cmd_pool_mutex);
        if (!--pool->users) {
                kmem_cache_destroy(pool->cmd_slab);
                kmem_cache_destroy(pool->sense_slab);
        }
- fail:
        mutex_unlock(&host_cmd_pool_mutex);
-       return -ENOMEM;
+}
+
+/**
+ * scsi_allocate_command - get a fully allocated SCSI command
+ * @gfp_mask:  allocation mask
+ *
+ * This function is for use outside of the normal host based pools.
+ * It allocates the relevant command and takes an additional reference
+ * on the pool it used.  This function *must* be paired with
+ * scsi_free_command which also has the identical mask, otherwise the
+ * free pool counts will eventually go wrong and you'll trigger a bug.
+ *
+ * This function should *only* be used by drivers that need a static
+ * command allocation at start of day for internal functions.
+ */
+struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask)
+{
+       struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
+
+       if (!pool)
+               return NULL;
+
+       return scsi_pool_alloc_command(pool, gfp_mask);
+}
+EXPORT_SYMBOL(scsi_allocate_command);
+
+/**
+ * scsi_free_command - free a command allocated by scsi_allocate_command
+ * @gfp_mask:  mask used in the original allocation
+ * @cmd:       command to free
+ *
+ * Note: using the original allocation mask is vital because that's
+ * what determines which command pool we use to free the command.  Any
+ * mismatch will cause the system to BUG eventually.
+ */
+void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd)
+{
+       struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
+
+       /*
+        * this could trigger if the mask to scsi_allocate_command
+        * doesn't match this mask.  Otherwise we're guaranteed that this
+        * succeeds because scsi_allocate_command must have taken a reference
+        * on the pool
+        */
+       BUG_ON(!pool);
+
+       scsi_pool_free_command(pool, cmd);
+       /*
+        * scsi_put_host_cmd_pool is called twice; once to release the
+        * reference we took above, and once to release the reference
+        * originally taken by scsi_allocate_command
+        */
+       scsi_put_host_cmd_pool(gfp_mask);
+       scsi_put_host_cmd_pool(gfp_mask);
+}
+EXPORT_SYMBOL(scsi_free_command);
+
+/**
+ * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
+ * @shost: host to allocate the freelist for.
+ *
+ * Description: The command freelist protects against system-wide out of memory
+ * deadlock by preallocating one SCSI command structure for each host, so the
+ * system can always write to a swap file on a device associated with that host.
+ *
+ * Returns:    Nothing.
+ */
+int scsi_setup_command_freelist(struct Scsi_Host *shost)
+{
+       struct scsi_cmnd *cmd;
+       const gfp_t gfp_mask = shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL;
+
+       spin_lock_init(&shost->free_list_lock);
+       INIT_LIST_HEAD(&shost->free_list);
+
+       shost->cmd_pool = scsi_get_host_cmd_pool(gfp_mask);
+
+       if (!shost->cmd_pool)
+               return -ENOMEM;
+
+       /*
+        * Get one backup command for this host.
+        */
+       cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
+       if (!cmd) {
+               scsi_put_host_cmd_pool(gfp_mask);
+               return -ENOMEM;
+       }
+       list_add(&cmd->list, &shost->free_list);
+       return 0;
 }
 
 /**
@@ -386,17 +486,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
 
                cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list);
                list_del_init(&cmd->list);
-               kmem_cache_free(shost->cmd_pool->sense_slab,
-                               cmd->sense_buffer);
-               kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+               scsi_pool_free_command(shost->cmd_pool, cmd);
        }
-
-       mutex_lock(&host_cmd_pool_mutex);
-       if (!--shost->cmd_pool->users) {
-               kmem_cache_destroy(shost->cmd_pool->cmd_slab);
-               kmem_cache_destroy(shost->cmd_pool->sense_slab);
-       }
-       mutex_unlock(&host_cmd_pool_mutex);
+       shost->cmd_pool = NULL;
+       scsi_put_host_cmd_pool(shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL);
 }
 
 #ifdef CONFIG_SCSI_LOGGING
index d1777a9a9625de074ab98ba51179595085f7af51..07103c399fe0c2e7ce840fcdcb7d995bd277ca73 100644 (file)
 #include <linux/vmalloc.h>
 #include <linux/moduleparam.h>
 #include <linux/scatterlist.h>
-
 #include <linux/blkdev.h>
-#include "scsi.h"
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
+#include <scsi/scsi_eh.h>
 
 #include <linux/stat.h>
 
 #include "scsi_logging.h"
-#include "scsi_debug.h"
 
 #define SCSI_DEBUG_VERSION "1.81"
 static const char * scsi_debug_version_date = "20070104";
@@ -146,7 +148,6 @@ static int scsi_debug_cmnd_count = 0;
 #define DEV_READONLY(TGT)      (0)
 #define DEV_REMOVEABLE(TGT)    (0)
 
-static unsigned int sdebug_store_size; /* in bytes */
 static unsigned int sdebug_store_sectors;
 static sector_t sdebug_capacity;       /* in sectors */
 
@@ -165,6 +166,9 @@ static int sdebug_sectors_per;              /* sectors per cylinder */
 
 #define SDEBUG_SENSE_LEN 32
 
+#define SCSI_DEBUG_CANQUEUE  255
+#define SCSI_DEBUG_MAX_CMD_LEN 16
+
 struct sdebug_dev_info {
        struct list_head dev_list;
        unsigned char sense_buff[SDEBUG_SENSE_LEN];     /* weak nexus */
@@ -202,30 +206,6 @@ struct sdebug_queued_cmd {
 };
 static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
 
-static struct scsi_host_template sdebug_driver_template = {
-       .proc_info =            scsi_debug_proc_info,
-       .name =                 "SCSI DEBUG",
-       .info =                 scsi_debug_info,
-       .slave_alloc =          scsi_debug_slave_alloc,
-       .slave_configure =      scsi_debug_slave_configure,
-       .slave_destroy =        scsi_debug_slave_destroy,
-       .ioctl =                scsi_debug_ioctl,
-       .queuecommand =         scsi_debug_queuecommand,
-       .eh_abort_handler =     scsi_debug_abort,
-       .eh_bus_reset_handler = scsi_debug_bus_reset,
-       .eh_device_reset_handler = scsi_debug_device_reset,
-       .eh_host_reset_handler = scsi_debug_host_reset,
-       .bios_param =           scsi_debug_biosparam,
-       .can_queue =            SCSI_DEBUG_CANQUEUE,
-       .this_id =              7,
-       .sg_tablesize =         256,
-       .cmd_per_lun =          16,
-       .max_sectors =          0xffff,
-       .unchecked_isa_dma =    0,
-       .use_clustering =       DISABLE_CLUSTERING,
-       .module =               THIS_MODULE,
-};
-
 static unsigned char * fake_storep;    /* ramdisk storage */
 
 static int num_aborts = 0;
@@ -238,8 +218,6 @@ static DEFINE_RWLOCK(atomic_rw);
 
 static char sdebug_proc_name[] = "scsi_debug";
 
-static int sdebug_driver_probe(struct device *);
-static int sdebug_driver_remove(struct device *);
 static struct bus_type pseudo_lld_bus;
 
 static struct device_driver sdebug_driverfs_driver = {
@@ -255,94 +233,77 @@ static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
 static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
                                   0, 0, 0x0, 0x0};
 
-/* function declarations */
-static int resp_inquiry(struct scsi_cmnd * SCpnt, int target,
-                       struct sdebug_dev_info * devip);
-static int resp_requests(struct scsi_cmnd * SCpnt,
-                        struct sdebug_dev_info * devip);
-static int resp_start_stop(struct scsi_cmnd * scp,
-                          struct sdebug_dev_info * devip);
-static int resp_report_tgtpgs(struct scsi_cmnd * scp,
-                             struct sdebug_dev_info * devip);
-static int resp_readcap(struct scsi_cmnd * SCpnt,
-                       struct sdebug_dev_info * devip);
-static int resp_readcap16(struct scsi_cmnd * SCpnt,
-                         struct sdebug_dev_info * devip);
-static int resp_mode_sense(struct scsi_cmnd * scp, int target,
-                          struct sdebug_dev_info * devip);
-static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
-                           struct sdebug_dev_info * devip);
-static int resp_log_sense(struct scsi_cmnd * scp,
-                         struct sdebug_dev_info * devip);
-static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
-                    unsigned int num, struct sdebug_dev_info * devip);
-static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
-                     unsigned int num, struct sdebug_dev_info * devip);
-static int resp_report_luns(struct scsi_cmnd * SCpnt,
-                           struct sdebug_dev_info * devip);
-static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
-                           unsigned int num, struct sdebug_dev_info *devip);
-static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
-                                int arr_len);
-static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
-                               int max_arr_len);
-static void timer_intr_handler(unsigned long);
-static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev);
-static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
-                           int asc, int asq);
-static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
-                          struct sdebug_dev_info * devip);
-static int schedule_resp(struct scsi_cmnd * cmnd,
-                        struct sdebug_dev_info * devip,
-                        done_funct_t done, int scsi_result, int delta_jiff);
-static void __init sdebug_build_parts(unsigned char * ramp);
-static void __init init_all_queued(void);
-static void stop_all_queued(void);
-static int stop_queued_cmnd(struct scsi_cmnd * cmnd);
-static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
-                          int target_dev_id, int dev_id_num,
-                          const char * dev_id_str, int dev_id_str_len);
-static int inquiry_evpd_88(unsigned char * arr, int target_dev_id);
-static int do_create_driverfs_files(void);
-static void do_remove_driverfs_files(void);
-
 static int sdebug_add_adapter(void);
 static void sdebug_remove_adapter(void);
-static void sdebug_max_tgts_luns(void);
 
-static struct device pseudo_primary;
-static struct bus_type pseudo_lld_bus;
+static void sdebug_max_tgts_luns(void)
+{
+       struct sdebug_host_info *sdbg_host;
+       struct Scsi_Host *hpnt;
+
+       spin_lock(&sdebug_host_list_lock);
+       list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
+               hpnt = sdbg_host->shost;
+               if ((hpnt->this_id >= 0) &&
+                   (scsi_debug_num_tgts > hpnt->this_id))
+                       hpnt->max_id = scsi_debug_num_tgts + 1;
+               else
+                       hpnt->max_id = scsi_debug_num_tgts;
+               /* scsi_debug_max_luns; */
+               hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
+       }
+       spin_unlock(&sdebug_host_list_lock);
+}
+
+static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
+                           int asc, int asq)
+{
+       unsigned char *sbuff;
+
+       sbuff = devip->sense_buff;
+       memset(sbuff, 0, SDEBUG_SENSE_LEN);
+
+       scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
+
+       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+               printk(KERN_INFO "scsi_debug:    [sense_key,asc,ascq]: "
+                     "[0x%x,0x%x,0x%x]\n", key, asc, asq);
+}
 
 static void get_data_transfer_info(unsigned char *cmd,
                                   unsigned long long *lba, unsigned int *num)
 {
-       int i;
-
        switch (*cmd) {
        case WRITE_16:
        case READ_16:
-               for (*lba = 0, i = 0; i < 8; ++i) {
-                       if (i > 0)
-                               *lba <<= 8;
-                       *lba += cmd[2 + i];
-               }
-               *num = cmd[13] + (cmd[12] << 8) +
-                       (cmd[11] << 16) + (cmd[10] << 24);
+               *lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
+                       (u64)cmd[7] << 16 | (u64)cmd[6] << 24 |
+                       (u64)cmd[5] << 32 | (u64)cmd[4] << 40 |
+                       (u64)cmd[3] << 48 | (u64)cmd[2] << 56;
+
+               *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 |
+                       (u32)cmd[10] << 24;
                break;
        case WRITE_12:
        case READ_12:
-               *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
-               *num = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
+               *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
+                       (u32)cmd[2] << 24;
+
+               *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 |
+                       (u32)cmd[6] << 24;
                break;
        case WRITE_10:
        case READ_10:
        case XDWRITEREAD_10:
-               *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
-               *num = cmd[8] + (cmd[7] << 8);
+               *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
+                       (u32)cmd[2] << 24;
+
+               *num = (u32)cmd[8] | (u32)cmd[7] << 8;
                break;
        case WRITE_6:
        case READ_6:
-               *lba = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
+               *lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
+                       (u32)(cmd[1] & 0x1f) << 16;
                *num = (0 == cmd[4]) ? 256 : cmd[4];
                break;
        default:
@@ -350,344 +311,69 @@ static void get_data_transfer_info(unsigned char *cmd,
        }
 }
 
-static
-int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
+static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
 {
-       unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
-       int len, k;
-       unsigned int num;
-       unsigned long long lba;
-       int errsts = 0;
-       int target = SCpnt->device->id;
-       struct sdebug_dev_info * devip = NULL;
-       int inj_recovered = 0;
-       int inj_transport = 0;
-       int delay_override = 0;
-
-       if (done == NULL)
-               return 0;       /* assume mid level reprocessing command */
+       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
+               printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd);
+       }
+       return -EINVAL;
+       /* return -ENOTTY; // correct return but upsets fdisk */
+}
 
-       scsi_set_resid(SCpnt, 0);
-       if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
-               printk(KERN_INFO "scsi_debug: cmd ");
-               for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
-                       printk("%02x ", (int)cmd[k]);
-               printk("\n");
+static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
+                          struct sdebug_dev_info * devip)
+{
+       if (devip->reset) {
+               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+                       printk(KERN_INFO "scsi_debug: Reporting Unit "
+                              "attention: power on reset\n");
+               devip->reset = 0;
+               mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0);
+               return check_condition_result;
        }
-        if(target == sdebug_driver_template.this_id) {
-               printk(KERN_INFO "scsi_debug: initiator's id used as "
-                      "target!\n");
-               return schedule_resp(SCpnt, NULL, done,
-                                    DID_NO_CONNECT << 16, 0);
-        }
+       if ((0 == reset_only) && devip->stopped) {
+               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+                       printk(KERN_INFO "scsi_debug: Reporting Not "
+                              "ready: initializing command required\n");
+               mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY,
+                               0x2);
+               return check_condition_result;
+       }
+       return 0;
+}
 
-       if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
-           (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
-               return schedule_resp(SCpnt, NULL, done,
-                                    DID_NO_CONNECT << 16, 0);
-       devip = devInfoReg(SCpnt->device);
-       if (NULL == devip)
-               return schedule_resp(SCpnt, NULL, done,
-                                    DID_NO_CONNECT << 16, 0);
+/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
+static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
+                               int arr_len)
+{
+       int act_len;
+       struct scsi_data_buffer *sdb = scsi_in(scp);
 
-        if ((scsi_debug_every_nth != 0) &&
-            (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
-                scsi_debug_cmnd_count = 0;
-               if (scsi_debug_every_nth < -1)
-                       scsi_debug_every_nth = -1;
-               if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
-                       return 0; /* ignore command causing timeout */
-               else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
-                       inj_recovered = 1; /* to reads and writes below */
-               else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
-                       inj_transport = 1; /* to reads and writes below */
-        }
+       if (!sdb->length)
+               return 0;
+       if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
+               return (DID_ERROR << 16);
 
-       if (devip->wlun) {
-               switch (*cmd) {
-               case INQUIRY:
-               case REQUEST_SENSE:
-               case TEST_UNIT_READY:
-               case REPORT_LUNS:
-                       break;  /* only allowable wlun commands */
-               default:
-                       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                               printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
-                                      "not supported for wlun\n", *cmd);
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
-                                       INVALID_OPCODE, 0);
-                       errsts = check_condition_result;
-                       return schedule_resp(SCpnt, devip, done, errsts,
-                                            0);
-               }
-       }
+       act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
+                                     arr, arr_len);
+       if (sdb->resid)
+               sdb->resid -= act_len;
+       else
+               sdb->resid = scsi_bufflen(scp) - act_len;
 
-       switch (*cmd) {
-       case INQUIRY:     /* mandatory, ignore unit attention */
-               delay_override = 1;
-               errsts = resp_inquiry(SCpnt, target, devip);
-               break;
-       case REQUEST_SENSE:     /* mandatory, ignore unit attention */
-               delay_override = 1;
-               errsts = resp_requests(SCpnt, devip);
-               break;
-       case REZERO_UNIT:       /* actually this is REWIND for SSC */
-       case START_STOP:
-               errsts = resp_start_stop(SCpnt, devip);
-               break;
-       case ALLOW_MEDIUM_REMOVAL:
-               if ((errsts = check_readiness(SCpnt, 1, devip)))
-                       break;
-               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       printk(KERN_INFO "scsi_debug: Medium removal %s\n",
-                               cmd[4] ? "inhibited" : "enabled");
-               break;
-       case SEND_DIAGNOSTIC:     /* mandatory */
-               errsts = check_readiness(SCpnt, 1, devip);
-               break;
-       case TEST_UNIT_READY:     /* mandatory */
-               delay_override = 1;
-               errsts = check_readiness(SCpnt, 0, devip);
-               break;
-        case RESERVE:
-               errsts = check_readiness(SCpnt, 1, devip);
-                break;
-        case RESERVE_10:
-               errsts = check_readiness(SCpnt, 1, devip);
-                break;
-        case RELEASE:
-               errsts = check_readiness(SCpnt, 1, devip);
-                break;
-        case RELEASE_10:
-               errsts = check_readiness(SCpnt, 1, devip);
-                break;
-       case READ_CAPACITY:
-               errsts = resp_readcap(SCpnt, devip);
-               break;
-       case SERVICE_ACTION_IN:
-               if (SAI_READ_CAPACITY_16 != cmd[1]) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
-                                       INVALID_OPCODE, 0);
-                       errsts = check_condition_result;
-                       break;
-               }
-               errsts = resp_readcap16(SCpnt, devip);
-               break;
-       case MAINTENANCE_IN:
-               if (MI_REPORT_TARGET_PGS != cmd[1]) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
-                                       INVALID_OPCODE, 0);
-                       errsts = check_condition_result;
-                       break;
-               }
-               errsts = resp_report_tgtpgs(SCpnt, devip);
-               break;
-       case READ_16:
-       case READ_12:
-       case READ_10:
-       case READ_6:
-               if ((errsts = check_readiness(SCpnt, 0, devip)))
-                       break;
-               if (scsi_debug_fake_rw)
-                       break;
-               get_data_transfer_info(cmd, &lba, &num);
-               errsts = resp_read(SCpnt, lba, num, devip);
-               if (inj_recovered && (0 == errsts)) {
-                       mk_sense_buffer(devip, RECOVERED_ERROR,
-                                       THRESHOLD_EXCEEDED, 0);
-                       errsts = check_condition_result;
-               } else if (inj_transport && (0 == errsts)) {
-                        mk_sense_buffer(devip, ABORTED_COMMAND,
-                                        TRANSPORT_PROBLEM, ACK_NAK_TO);
-                        errsts = check_condition_result;
-                }
-               break;
-       case REPORT_LUNS:       /* mandatory, ignore unit attention */
-               delay_override = 1;
-               errsts = resp_report_luns(SCpnt, devip);
-               break;
-       case VERIFY:            /* 10 byte SBC-2 command */
-               errsts = check_readiness(SCpnt, 0, devip);
-               break;
-       case WRITE_16:
-       case WRITE_12:
-       case WRITE_10:
-       case WRITE_6:
-               if ((errsts = check_readiness(SCpnt, 0, devip)))
-                       break;
-               if (scsi_debug_fake_rw)
-                       break;
-               get_data_transfer_info(cmd, &lba, &num);
-               errsts = resp_write(SCpnt, lba, num, devip);
-               if (inj_recovered && (0 == errsts)) {
-                       mk_sense_buffer(devip, RECOVERED_ERROR,
-                                       THRESHOLD_EXCEEDED, 0);
-                       errsts = check_condition_result;
-               }
-               break;
-       case MODE_SENSE:
-       case MODE_SENSE_10:
-               errsts = resp_mode_sense(SCpnt, target, devip);
-               break;
-       case MODE_SELECT:
-               errsts = resp_mode_select(SCpnt, 1, devip);
-               break;
-       case MODE_SELECT_10:
-               errsts = resp_mode_select(SCpnt, 0, devip);
-               break;
-       case LOG_SENSE:
-               errsts = resp_log_sense(SCpnt, devip);
-               break;
-       case SYNCHRONIZE_CACHE:
-               delay_override = 1;
-               errsts = check_readiness(SCpnt, 0, devip);
-               break;
-       case WRITE_BUFFER:
-               errsts = check_readiness(SCpnt, 1, devip);
-               break;
-       case XDWRITEREAD_10:
-               if (!scsi_bidi_cmnd(SCpnt)) {
-                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
-                                       INVALID_FIELD_IN_CDB, 0);
-                       errsts = check_condition_result;
-                       break;
-               }
-
-               errsts = check_readiness(SCpnt, 0, devip);
-               if (errsts)
-                       break;
-               if (scsi_debug_fake_rw)
-                       break;
-               get_data_transfer_info(cmd, &lba, &num);
-               errsts = resp_read(SCpnt, lba, num, devip);
-               if (errsts)
-                       break;
-               errsts = resp_write(SCpnt, lba, num, devip);
-               if (errsts)
-                       break;
-               errsts = resp_xdwriteread(SCpnt, lba, num, devip);
-               break;
-       default:
-               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
-                              "supported\n", *cmd);
-               if ((errsts = check_readiness(SCpnt, 1, devip)))
-                       break;  /* Unit attention takes precedence */
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
-               errsts = check_condition_result;
-               break;
-       }
-       return schedule_resp(SCpnt, devip, done, errsts,
-                            (delay_override ? 0 : scsi_debug_delay));
-}
-
-static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
-{
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
-               printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd);
-       }
-       return -EINVAL;
-       /* return -ENOTTY; // correct return but upsets fdisk */
-}
-
-static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
-                          struct sdebug_dev_info * devip)
-{
-       if (devip->reset) {
-               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       printk(KERN_INFO "scsi_debug: Reporting Unit "
-                              "attention: power on reset\n");
-               devip->reset = 0;
-               mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0);
-               return check_condition_result;
-       }
-       if ((0 == reset_only) && devip->stopped) {
-               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       printk(KERN_INFO "scsi_debug: Reporting Not "
-                              "ready: initializing command required\n");
-               mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY,
-                               0x2);
-               return check_condition_result;
-       }
-       return 0;
-}
-
-/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
-static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
-                               int arr_len)
-{
-       int k, req_len, act_len, len, active;
-       void * kaddr;
-       void * kaddr_off;
-       struct scatterlist *sg;
-       struct scsi_data_buffer *sdb = scsi_in(scp);
-
-       if (!sdb->length)
-               return 0;
-       if (!sdb->table.sgl)
-               return (DID_ERROR << 16);
-       if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
-               return (DID_ERROR << 16);
-       active = 1;
-       req_len = act_len = 0;
-       for_each_sg(sdb->table.sgl, sg, sdb->table.nents, k) {
-               if (active) {
-                       kaddr = (unsigned char *)
-                               kmap_atomic(sg_page(sg), KM_USER0);
-                       if (NULL == kaddr)
-                               return (DID_ERROR << 16);
-                       kaddr_off = (unsigned char *)kaddr + sg->offset;
-                       len = sg->length;
-                       if ((req_len + len) > arr_len) {
-                               active = 0;
-                               len = arr_len - req_len;
-                       }
-                       memcpy(kaddr_off, arr + req_len, len);
-                       kunmap_atomic(kaddr, KM_USER0);
-                       act_len += len;
-               }
-               req_len += sg->length;
-       }
-       if (sdb->resid)
-               sdb->resid -= act_len;
-       else
-               sdb->resid = req_len - act_len;
        return 0;
 }
 
 /* Returns number of bytes fetched into 'arr' or -1 if error. */
-static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
-                              int max_arr_len)
+static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
+                              int arr_len)
 {
-       int k, req_len, len, fin;
-       void * kaddr;
-       void * kaddr_off;
-       struct scatterlist * sg;
-
-       if (0 == scsi_bufflen(scp))
+       if (!scsi_bufflen(scp))
                return 0;
-       if (NULL == scsi_sglist(scp))
-               return -1;
        if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
                return -1;
-       req_len = fin = 0;
-       scsi_for_each_sg(scp, sg, scsi_sg_count(scp), k) {
-               kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
-               if (NULL == kaddr)
-                       return -1;
-               kaddr_off = (unsigned char *)kaddr + sg->offset;
-               len = sg->length;
-               if ((req_len + len) > max_arr_len) {
-                       len = max_arr_len - req_len;
-                       fin = 1;
-               }
-               memcpy(arr + req_len, kaddr_off, len);
-               kunmap_atomic(kaddr, KM_USER0);
-               if (fin)
-                       return req_len + len;
-               req_len += sg->length;
-       }
-       return req_len;
+
+       return scsi_sg_copy_to_buffer(scp, arr, arr_len);
 }
 
 
@@ -1159,6 +845,14 @@ static int resp_start_stop(struct scsi_cmnd * scp,
        return 0;
 }
 
+static sector_t get_sdebug_capacity(void)
+{
+       if (scsi_debug_virtual_gb > 0)
+               return 2048 * 1024 * scsi_debug_virtual_gb;
+       else
+               return sdebug_store_sectors;
+}
+
 #define SDEBUG_READCAP_ARR_SZ 8
 static int resp_readcap(struct scsi_cmnd * scp,
                        struct sdebug_dev_info * devip)
@@ -1170,11 +864,7 @@ static int resp_readcap(struct scsi_cmnd * scp,
        if ((errsts = check_readiness(scp, 1, devip)))
                return errsts;
        /* following just in case virtual_gb changed */
-       if (scsi_debug_virtual_gb > 0) {
-               sdebug_capacity = 2048 * 1024;
-               sdebug_capacity *= scsi_debug_virtual_gb;
-       } else
-               sdebug_capacity = sdebug_store_sectors;
+       sdebug_capacity = get_sdebug_capacity();
        memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
        if (sdebug_capacity < 0xffffffff) {
                capac = (unsigned int)sdebug_capacity - 1;
@@ -1207,11 +897,7 @@ static int resp_readcap16(struct scsi_cmnd * scp,
        alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
                     + cmd[13]);
        /* following just in case virtual_gb changed */
-       if (scsi_debug_virtual_gb > 0) {
-               sdebug_capacity = 2048 * 1024;
-               sdebug_capacity *= scsi_debug_virtual_gb;
-       } else
-               sdebug_capacity = sdebug_store_sectors;
+       sdebug_capacity = get_sdebug_capacity();
        memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
        capac = sdebug_capacity - 1;
        for (k = 0; k < 8; ++k, capac >>= 8)
@@ -1505,13 +1191,9 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
                offset = 8;
        }
        ap = arr + offset;
-       if ((bd_len > 0) && (0 == sdebug_capacity)) {
-               if (scsi_debug_virtual_gb > 0) {
-                       sdebug_capacity = 2048 * 1024;
-                       sdebug_capacity *= scsi_debug_virtual_gb;
-               } else
-                       sdebug_capacity = sdebug_store_sectors;
-       }
+       if ((bd_len > 0) && (!sdebug_capacity))
+               sdebug_capacity = get_sdebug_capacity();
+
        if (8 == bd_len) {
                if (sdebug_capacity > 0xfffffffe) {
                        ap[0] = 0xff;
@@ -1808,25 +1490,53 @@ static int resp_log_sense(struct scsi_cmnd * scp,
                    min(len, SDEBUG_MAX_INQ_ARR_SZ));
 }
 
-static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
-                    unsigned int num, struct sdebug_dev_info * devip)
+static int check_device_access_params(struct sdebug_dev_info *devi,
+                                     unsigned long long lba, unsigned int num)
 {
-       unsigned long iflags;
-       unsigned int block, from_bottom;
-       unsigned long long u;
-       int ret;
-
        if (lba + num > sdebug_capacity) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
-                               0);
+               mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
                return check_condition_result;
        }
        /* transfer length excessive (tie in to block limits VPD page) */
        if (num > sdebug_store_sectors) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-                               0);
+               mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
                return check_condition_result;
        }
+       return 0;
+}
+
+static int do_device_access(struct scsi_cmnd *scmd,
+                           struct sdebug_dev_info *devi,
+                           unsigned long long lba, unsigned int num, int write)
+{
+       int ret;
+       unsigned int block, rest = 0;
+       int (*func)(struct scsi_cmnd *, unsigned char *, int);
+
+       func = write ? fetch_to_dev_buffer : fill_from_dev_buffer;
+
+       block = do_div(lba, sdebug_store_sectors);
+       if (block + num > sdebug_store_sectors)
+               rest = block + num - sdebug_store_sectors;
+
+       ret = func(scmd, fake_storep + (block * SECT_SIZE),
+                  (num - rest) * SECT_SIZE);
+       if (!ret && rest)
+               ret = func(scmd, fake_storep, rest * SECT_SIZE);
+
+       return ret;
+}
+
+static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
+                    unsigned int num, struct sdebug_dev_info *devip)
+{
+       unsigned long iflags;
+       int ret;
+
+       ret = check_device_access_params(devip, lba, num);
+       if (ret)
+               return ret;
+
        if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
            (lba <= OPT_MEDIUM_ERR_ADDR) &&
            ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
@@ -1845,74 +1555,30 @@ static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
                return check_condition_result;
        }
        read_lock_irqsave(&atomic_rw, iflags);
-       if ((lba + num) <= sdebug_store_sectors)
-               ret = fill_from_dev_buffer(SCpnt,
-                                          fake_storep + (lba * SECT_SIZE),
-                                          num * SECT_SIZE);
-       else {
-               /* modulo when one arg is 64 bits needs do_div() */
-               u = lba;
-               block = do_div(u, sdebug_store_sectors);
-               from_bottom = 0;
-               if ((block + num) > sdebug_store_sectors)
-                       from_bottom = (block + num) - sdebug_store_sectors;
-               ret = fill_from_dev_buffer(SCpnt,
-                                          fake_storep + (block * SECT_SIZE),
-                                          (num - from_bottom) * SECT_SIZE);
-               if ((0 == ret) && (from_bottom > 0))
-                       ret = fill_from_dev_buffer(SCpnt, fake_storep,
-                                                  from_bottom * SECT_SIZE);
-       }
+       ret = do_device_access(SCpnt, devip, lba, num, 0);
        read_unlock_irqrestore(&atomic_rw, iflags);
        return ret;
 }
 
-static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
-                     unsigned int num, struct sdebug_dev_info * devip)
+static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
+                     unsigned int num, struct sdebug_dev_info *devip)
 {
        unsigned long iflags;
-       unsigned int block, to_bottom;
-       unsigned long long u;
-       int res;
+       int ret;
 
-       if (lba + num > sdebug_capacity) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
-                               0);
-               return check_condition_result;
-       }
-       /* transfer length excessive (tie in to block limits VPD page) */
-       if (num > sdebug_store_sectors) {
-               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-                               0);
-               return check_condition_result;
-       }
+       ret = check_device_access_params(devip, lba, num);
+       if (ret)
+               return ret;
 
        write_lock_irqsave(&atomic_rw, iflags);
-       if ((lba + num) <= sdebug_store_sectors)
-               res = fetch_to_dev_buffer(SCpnt,
-                                         fake_storep + (lba * SECT_SIZE),
-                                         num * SECT_SIZE);
-       else {
-               /* modulo when one arg is 64 bits needs do_div() */
-               u = lba;
-               block = do_div(u, sdebug_store_sectors);
-               to_bottom = 0;
-               if ((block + num) > sdebug_store_sectors)
-                       to_bottom = (block + num) - sdebug_store_sectors;
-               res = fetch_to_dev_buffer(SCpnt,
-                                         fake_storep + (block * SECT_SIZE),
-                                         (num - to_bottom) * SECT_SIZE);
-               if ((0 == res) && (to_bottom > 0))
-                       res = fetch_to_dev_buffer(SCpnt, fake_storep,
-                                                 to_bottom * SECT_SIZE);
-       }
+       ret = do_device_access(SCpnt, devip, lba, num, 1);
        write_unlock_irqrestore(&atomic_rw, iflags);
-       if (-1 == res)
+       if (-1 == ret)
                return (DID_ERROR << 16);
-       else if ((res < (num * SECT_SIZE)) &&
+       else if ((ret < (num * SECT_SIZE)) &&
                 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
                printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
-                      " IO sent=%d bytes\n", num * SECT_SIZE, res);
+                      " IO sent=%d bytes\n", num * SECT_SIZE, ret);
        return 0;
 }
 
@@ -1987,16 +1653,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
        if (!buf)
                return ret;
 
-       offset = 0;
-       scsi_for_each_sg(scp, sg, scsi_sg_count(scp), i) {
-               kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
-               if (!kaddr)
-                       goto out;
-
-               memcpy(buf + offset, kaddr + sg->offset, sg->length);
-               offset += sg->length;
-               kunmap_atomic(kaddr, KM_USER0);
-       }
+       scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
 
        offset = 0;
        for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
@@ -2045,48 +1702,18 @@ static void timer_intr_handler(unsigned long indx)
        spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
-static int scsi_debug_slave_alloc(struct scsi_device * sdp)
-{
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
-                      sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
-       set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags);
-       return 0;
-}
-
-static int scsi_debug_slave_configure(struct scsi_device * sdp)
-{
-       struct sdebug_dev_info * devip;
-
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n",
-                      sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
-       if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
-               sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
-       devip = devInfoReg(sdp);
-       if (NULL == devip)
-               return 1;       /* no resources, will be marked offline */
-       sdp->hostdata = devip;
-       if (sdp->host->cmd_per_lun)
-               scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING,
-                                       sdp->host->cmd_per_lun);
-       blk_queue_max_segment_size(sdp->request_queue, 256 * 1024);
-       return 0;
-}
 
-static void scsi_debug_slave_destroy(struct scsi_device * sdp)
+static struct sdebug_dev_info *
+sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
 {
-       struct sdebug_dev_info * devip =
-                               (struct sdebug_dev_info *)sdp->hostdata;
+       struct sdebug_dev_info *devip;
 
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n",
-                      sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
+       devip = kzalloc(sizeof(*devip), flags);
        if (devip) {
-               /* make this slot avaliable for re-use */
-               devip->used = 0;
-               sdp->hostdata = NULL;
+               devip->sdbg_host = sdbg_host;
+               list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
        }
+       return devip;
 }
 
 static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
@@ -2098,8 +1725,8 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
 
        if (devip)
                return devip;
-       sdbg_host = *(struct sdebug_host_info **) sdev->host->hostdata;
-        if(! sdbg_host) {
+       sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
+       if (!sdbg_host) {
                 printk(KERN_ERR "Host info NULL\n");
                return NULL;
         }
@@ -2113,155 +1740,84 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
                                open_devip = devip;
                }
        }
-       if (NULL == open_devip) { /* try and make a new one */
-               open_devip = kzalloc(sizeof(*open_devip),GFP_ATOMIC);
-               if (NULL == open_devip) {
+       if (!open_devip) { /* try and make a new one */
+               open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
+               if (!open_devip) {
                        printk(KERN_ERR "%s: out of memory at line %d\n",
                                __FUNCTION__, __LINE__);
                        return NULL;
                }
-               open_devip->sdbg_host = sdbg_host;
-               list_add_tail(&open_devip->dev_list,
-               &sdbg_host->dev_info_list);
-       }
-        if (open_devip) {
-               open_devip->channel = sdev->channel;
-               open_devip->target = sdev->id;
-               open_devip->lun = sdev->lun;
-               open_devip->sdbg_host = sdbg_host;
-               open_devip->reset = 1;
-               open_devip->used = 1;
-               memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
-               if (scsi_debug_dsense)
-                       open_devip->sense_buff[0] = 0x72;
-               else {
-                       open_devip->sense_buff[0] = 0x70;
-                       open_devip->sense_buff[7] = 0xa;
-               }
-               if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
-                       open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
-               return open_devip;
-        }
-        return NULL;
-}
-
-static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
-                           int asc, int asq)
-{
-       unsigned char * sbuff;
+       }
 
-       sbuff = devip->sense_buff;
-       memset(sbuff, 0, SDEBUG_SENSE_LEN);
-       if (scsi_debug_dsense) {
-               sbuff[0] = 0x72;  /* descriptor, current */
-               sbuff[1] = key;
-               sbuff[2] = asc;
-               sbuff[3] = asq;
-       } else {
-               sbuff[0] = 0x70;  /* fixed, current */
-               sbuff[2] = key;
-               sbuff[7] = 0xa;   /* implies 18 byte sense buffer */
-               sbuff[12] = asc;
-               sbuff[13] = asq;
+       open_devip->channel = sdev->channel;
+       open_devip->target = sdev->id;
+       open_devip->lun = sdev->lun;
+       open_devip->sdbg_host = sdbg_host;
+       open_devip->reset = 1;
+       open_devip->used = 1;
+       memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
+       if (scsi_debug_dsense)
+               open_devip->sense_buff[0] = 0x72;
+       else {
+               open_devip->sense_buff[0] = 0x70;
+               open_devip->sense_buff[7] = 0xa;
        }
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug:    [sense_key,asc,ascq]: "
-                     "[0x%x,0x%x,0x%x]\n", key, asc, asq);
-}
+       if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
+               open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
 
-static int scsi_debug_abort(struct scsi_cmnd * SCpnt)
-{
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: abort\n");
-       ++num_aborts;
-       stop_queued_cmnd(SCpnt);
-       return SUCCESS;
+       return open_devip;
 }
 
-static int scsi_debug_biosparam(struct scsi_device *sdev,
-               struct block_device * bdev, sector_t capacity, int *info)
+static int scsi_debug_slave_alloc(struct scsi_device *sdp)
 {
-       int res;
-       unsigned char *buf;
-
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: biosparam\n");
-       buf = scsi_bios_ptable(bdev);
-       if (buf) {
-               res = scsi_partsize(buf, capacity,
-                                   &info[2], &info[0], &info[1]);
-               kfree(buf);
-               if (! res)
-                       return res;
-       }
-       info[0] = sdebug_heads;
-       info[1] = sdebug_sectors_per;
-       info[2] = sdebug_cylinders_per;
+               printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
+                      sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
+       set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags);
        return 0;
 }
 
-static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
+static int scsi_debug_slave_configure(struct scsi_device *sdp)
 {
-       struct sdebug_dev_info * devip;
+       struct sdebug_dev_info *devip;
 
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: device_reset\n");
-       ++num_dev_resets;
-       if (SCpnt) {
-               devip = devInfoReg(SCpnt->device);
-               if (devip)
-                       devip->reset = 1;
-       }
-       return SUCCESS;
+               printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n",
+                      sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
+       if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
+               sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
+       devip = devInfoReg(sdp);
+       if (NULL == devip)
+               return 1;       /* no resources, will be marked offline */
+       sdp->hostdata = devip;
+       if (sdp->host->cmd_per_lun)
+               scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING,
+                                       sdp->host->cmd_per_lun);
+       blk_queue_max_segment_size(sdp->request_queue, 256 * 1024);
+       return 0;
 }
 
-static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
+static void scsi_debug_slave_destroy(struct scsi_device *sdp)
 {
-       struct sdebug_host_info *sdbg_host;
-        struct sdebug_dev_info * dev_info;
-        struct scsi_device * sdp;
-        struct Scsi_Host * hp;
+       struct sdebug_dev_info *devip =
+               (struct sdebug_dev_info *)sdp->hostdata;
 
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: bus_reset\n");
-       ++num_bus_resets;
-       if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
-               sdbg_host = *(struct sdebug_host_info **) hp->hostdata;
-               if (sdbg_host) {
-                       list_for_each_entry(dev_info,
-                                            &sdbg_host->dev_info_list,
-                                            dev_list)
-                               dev_info->reset = 1;
-               }
+               printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n",
+                      sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
+       if (devip) {
+               /* make this slot avaliable for re-use */
+               devip->used = 0;
+               sdp->hostdata = NULL;
        }
-       return SUCCESS;
-}
-
-static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
-{
-       struct sdebug_host_info * sdbg_host;
-        struct sdebug_dev_info * dev_info;
-
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: host_reset\n");
-       ++num_host_resets;
-        spin_lock(&sdebug_host_list_lock);
-        list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
-                list_for_each_entry(dev_info, &sdbg_host->dev_info_list,
-                                    dev_list)
-                        dev_info->reset = 1;
-        }
-        spin_unlock(&sdebug_host_list_lock);
-       stop_all_queued();
-       return SUCCESS;
 }
 
 /* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */
-static int stop_queued_cmnd(struct scsi_cmnd * cmnd)
+static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
 {
        unsigned long iflags;
        int k;
-       struct sdebug_queued_cmd * sqcp;
+       struct sdebug_queued_cmd *sqcp;
 
        spin_lock_irqsave(&queued_arr_lock, iflags);
        for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
@@ -2282,7 +1838,7 @@ static void stop_all_queued(void)
 {
        unsigned long iflags;
        int k;
-       struct sdebug_queued_cmd * sqcp;
+       struct sdebug_queued_cmd *sqcp;
 
        spin_lock_irqsave(&queued_arr_lock, iflags);
        for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
@@ -2296,6 +1852,93 @@ static void stop_all_queued(void)
        spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
+static int scsi_debug_abort(struct scsi_cmnd * SCpnt)
+{
+       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+               printk(KERN_INFO "scsi_debug: abort\n");
+       ++num_aborts;
+       stop_queued_cmnd(SCpnt);
+       return SUCCESS;
+}
+
+static int scsi_debug_biosparam(struct scsi_device *sdev,
+               struct block_device * bdev, sector_t capacity, int *info)
+{
+       int res;
+       unsigned char *buf;
+
+       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+               printk(KERN_INFO "scsi_debug: biosparam\n");
+       buf = scsi_bios_ptable(bdev);
+       if (buf) {
+               res = scsi_partsize(buf, capacity,
+                                   &info[2], &info[0], &info[1]);
+               kfree(buf);
+               if (! res)
+                       return res;
+       }
+       info[0] = sdebug_heads;
+       info[1] = sdebug_sectors_per;
+       info[2] = sdebug_cylinders_per;
+       return 0;
+}
+
+static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
+{
+       struct sdebug_dev_info * devip;
+
+       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+               printk(KERN_INFO "scsi_debug: device_reset\n");
+       ++num_dev_resets;
+       if (SCpnt) {
+               devip = devInfoReg(SCpnt->device);
+               if (devip)
+                       devip->reset = 1;
+       }
+       return SUCCESS;
+}
+
+static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
+{
+       struct sdebug_host_info *sdbg_host;
+        struct sdebug_dev_info * dev_info;
+        struct scsi_device * sdp;
+        struct Scsi_Host * hp;
+
+       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+               printk(KERN_INFO "scsi_debug: bus_reset\n");
+       ++num_bus_resets;
+       if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
+               sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
+               if (sdbg_host) {
+                       list_for_each_entry(dev_info,
+                                            &sdbg_host->dev_info_list,
+                                            dev_list)
+                               dev_info->reset = 1;
+               }
+       }
+       return SUCCESS;
+}
+
+static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
+{
+       struct sdebug_host_info * sdbg_host;
+        struct sdebug_dev_info * dev_info;
+
+       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+               printk(KERN_INFO "scsi_debug: host_reset\n");
+       ++num_host_resets;
+        spin_lock(&sdebug_host_list_lock);
+        list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
+                list_for_each_entry(dev_info, &sdbg_host->dev_info_list,
+                                    dev_list)
+                        dev_info->reset = 1;
+        }
+        spin_unlock(&sdebug_host_list_lock);
+       stop_all_queued();
+       return SUCCESS;
+}
+
 /* Initializes timers in queued array */
 static void __init init_all_queued(void)
 {
@@ -2313,7 +1956,8 @@ static void __init init_all_queued(void)
        spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
-static void __init sdebug_build_parts(unsigned char * ramp)
+static void __init sdebug_build_parts(unsigned char *ramp,
+                                     unsigned long store_size)
 {
        struct partition * pp;
        int starts[SDEBUG_MAX_PARTS + 2];
@@ -2321,7 +1965,7 @@ static void __init sdebug_build_parts(unsigned char * ramp)
        int heads_by_sects, start_sec, end_sec;
 
        /* assume partition table already zeroed */
-       if ((scsi_debug_num_parts < 1) || (sdebug_store_size < 1048576))
+       if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
                return;
        if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
                scsi_debug_num_parts = SDEBUG_MAX_PARTS;
@@ -2419,7 +2063,6 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
                return 0;
        }
 }
-
 /* Note: The following macros create attribute files in the
    /sys/module/scsi_debug/parameters directory. Unfortunately this
    driver is unaware of a change and cannot trigger auxiliary actions
@@ -2736,11 +2379,9 @@ static ssize_t sdebug_virtual_gb_store(struct device_driver * ddp,
 
        if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
                scsi_debug_virtual_gb = n;
-               if (scsi_debug_virtual_gb > 0) {
-                       sdebug_capacity = 2048 * 1024;
-                       sdebug_capacity *= scsi_debug_virtual_gb;
-               } else
-                       sdebug_capacity = sdebug_store_sectors;
+
+               sdebug_capacity = get_sdebug_capacity();
+
                return count;
        }
        return -EINVAL;
@@ -2756,21 +2397,10 @@ static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf)
 static ssize_t sdebug_add_host_store(struct device_driver * ddp,
                                     const char * buf, size_t count)
 {
-        int delta_hosts;
-       char work[20];
+       int delta_hosts;
 
-        if (1 != sscanf(buf, "%10s", work))
+       if (sscanf(buf, "%d", &delta_hosts) != 1)
                return -EINVAL;
-       {       /* temporary hack around sscanf() problem with -ve nums */
-               int neg = 0;
-
-               if ('-' == *work)
-                       neg = 1;
-               if (1 != sscanf(work + neg, "%d", &delta_hosts))
-                       return -EINVAL;
-               if (neg)
-                       delta_hosts = -delta_hosts;
-       }
        if (delta_hosts > 0) {
                do {
                        sdebug_add_adapter();
@@ -2782,7 +2412,7 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp,
        }
        return count;
 }
-DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show, 
+DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
            sdebug_add_host_store);
 
 static ssize_t sdebug_vpd_use_hostno_show(struct device_driver * ddp,
@@ -2851,22 +2481,29 @@ static void do_remove_driverfs_files(void)
        driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host);
 }
 
+static void pseudo_0_release(struct device *dev)
+{
+       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+               printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
+}
+
+static struct device pseudo_primary = {
+       .bus_id         = "pseudo_0",
+       .release        = pseudo_0_release,
+};
+
 static int __init scsi_debug_init(void)
 {
-       unsigned int sz;
+       unsigned long sz;
        int host_to_add;
        int k;
        int ret;
 
        if (scsi_debug_dev_size_mb < 1)
                scsi_debug_dev_size_mb = 1;  /* force minimum 1 MB ramdisk */
-       sdebug_store_size = (unsigned int)scsi_debug_dev_size_mb * 1048576;
-       sdebug_store_sectors = sdebug_store_size / SECT_SIZE;
-       if (scsi_debug_virtual_gb > 0) {
-               sdebug_capacity = 2048 * 1024;
-               sdebug_capacity *= scsi_debug_virtual_gb;
-       } else
-               sdebug_capacity = sdebug_store_sectors;
+       sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
+       sdebug_store_sectors = sz / SECT_SIZE;
+       sdebug_capacity = get_sdebug_capacity();
 
        /* play around with geometry, don't waste too much on track 0 */
        sdebug_heads = 8;
@@ -2885,7 +2522,6 @@ static int __init scsi_debug_init(void)
                               (sdebug_sectors_per * sdebug_heads);
        }
 
-       sz = sdebug_store_size;
        fake_storep = vmalloc(sz);
        if (NULL == fake_storep) {
                printk(KERN_ERR "scsi_debug_init: out of memory, 1\n");
@@ -2893,7 +2529,7 @@ static int __init scsi_debug_init(void)
        }
        memset(fake_storep, 0, sz);
        if (scsi_debug_num_parts > 0)
-               sdebug_build_parts(fake_storep);
+               sdebug_build_parts(fake_storep, sz);
 
        ret = device_register(&pseudo_primary);
        if (ret < 0) {
@@ -2922,8 +2558,6 @@ static int __init scsi_debug_init(void)
 
        init_all_queued();
 
-       sdebug_driver_template.proc_name = sdebug_proc_name;
-
        host_to_add = scsi_debug_add_host;
         scsi_debug_add_host = 0;
 
@@ -2972,30 +2606,6 @@ static void __exit scsi_debug_exit(void)
 device_initcall(scsi_debug_init);
 module_exit(scsi_debug_exit);
 
-static void pseudo_0_release(struct device * dev)
-{
-       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-               printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
-}
-
-static struct device pseudo_primary = {
-       .bus_id         = "pseudo_0",
-       .release        = pseudo_0_release,
-};
-
-static int pseudo_lld_bus_match(struct device *dev,
-                          struct device_driver *dev_driver)
-{
-        return 1;
-}
-
-static struct bus_type pseudo_lld_bus = {
-        .name = "pseudo",
-        .match = pseudo_lld_bus_match,
-       .probe = sdebug_driver_probe,
-       .remove = sdebug_driver_remove,
-};
-
 static void sdebug_release_adapter(struct device * dev)
 {
         struct sdebug_host_info *sdbg_host;
@@ -3009,8 +2619,7 @@ static int sdebug_add_adapter(void)
        int k, devs_per_host;
         int error = 0;
         struct sdebug_host_info *sdbg_host;
-        struct sdebug_dev_info *sdbg_devinfo;
-        struct list_head *lh, *lh_sf;
+       struct sdebug_dev_info *sdbg_devinfo, *tmp;
 
         sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
         if (NULL == sdbg_host) {
@@ -3023,16 +2632,13 @@ static int sdebug_add_adapter(void)
 
        devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
         for (k = 0; k < devs_per_host; k++) {
-                sdbg_devinfo = kzalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
-                if (NULL == sdbg_devinfo) {
+               sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
+               if (!sdbg_devinfo) {
                         printk(KERN_ERR "%s: out of memory at line %d\n",
                                __FUNCTION__, __LINE__);
                         error = -ENOMEM;
                        goto clean;
                 }
-                sdbg_devinfo->sdbg_host = sdbg_host;
-                list_add_tail(&sdbg_devinfo->dev_list,
-                              &sdbg_host->dev_info_list);
         }
 
         spin_lock(&sdebug_host_list_lock);
@@ -3053,9 +2659,8 @@ static int sdebug_add_adapter(void)
         return error;
 
 clean:
-       list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
-               sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
-                                         dev_list);
+       list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
+                                dev_list) {
                list_del(&sdbg_devinfo->dev_list);
                kfree(sdbg_devinfo);
        }
@@ -3083,6 +2688,263 @@ static void sdebug_remove_adapter(void)
         --scsi_debug_add_host;
 }
 
+static
+int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
+{
+       unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
+       int len, k;
+       unsigned int num;
+       unsigned long long lba;
+       int errsts = 0;
+       int target = SCpnt->device->id;
+       struct sdebug_dev_info *devip = NULL;
+       int inj_recovered = 0;
+       int inj_transport = 0;
+       int delay_override = 0;
+
+       scsi_set_resid(SCpnt, 0);
+       if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
+               printk(KERN_INFO "scsi_debug: cmd ");
+               for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
+                       printk("%02x ", (int)cmd[k]);
+               printk("\n");
+       }
+
+       if (target == SCpnt->device->host->hostt->this_id) {
+               printk(KERN_INFO "scsi_debug: initiator's id used as "
+                      "target!\n");
+               return schedule_resp(SCpnt, NULL, done,
+                                    DID_NO_CONNECT << 16, 0);
+       }
+
+       if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
+           (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
+               return schedule_resp(SCpnt, NULL, done,
+                                    DID_NO_CONNECT << 16, 0);
+       devip = devInfoReg(SCpnt->device);
+       if (NULL == devip)
+               return schedule_resp(SCpnt, NULL, done,
+                                    DID_NO_CONNECT << 16, 0);
+
+       if ((scsi_debug_every_nth != 0) &&
+           (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
+               scsi_debug_cmnd_count = 0;
+               if (scsi_debug_every_nth < -1)
+                       scsi_debug_every_nth = -1;
+               if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
+                       return 0; /* ignore command causing timeout */
+               else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
+                       inj_recovered = 1; /* to reads and writes below */
+               else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
+                       inj_transport = 1; /* to reads and writes below */
+       }
+
+       if (devip->wlun) {
+               switch (*cmd) {
+               case INQUIRY:
+               case REQUEST_SENSE:
+               case TEST_UNIT_READY:
+               case REPORT_LUNS:
+                       break;  /* only allowable wlun commands */
+               default:
+                       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+                               printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
+                                      "not supported for wlun\n", *cmd);
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_OPCODE, 0);
+                       errsts = check_condition_result;
+                       return schedule_resp(SCpnt, devip, done, errsts,
+                                            0);
+               }
+       }
+
+       switch (*cmd) {
+       case INQUIRY:     /* mandatory, ignore unit attention */
+               delay_override = 1;
+               errsts = resp_inquiry(SCpnt, target, devip);
+               break;
+       case REQUEST_SENSE:     /* mandatory, ignore unit attention */
+               delay_override = 1;
+               errsts = resp_requests(SCpnt, devip);
+               break;
+       case REZERO_UNIT:       /* actually this is REWIND for SSC */
+       case START_STOP:
+               errsts = resp_start_stop(SCpnt, devip);
+               break;
+       case ALLOW_MEDIUM_REMOVAL:
+               errsts = check_readiness(SCpnt, 1, devip);
+               if (errsts)
+                       break;
+               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+                       printk(KERN_INFO "scsi_debug: Medium removal %s\n",
+                              cmd[4] ? "inhibited" : "enabled");
+               break;
+       case SEND_DIAGNOSTIC:     /* mandatory */
+               errsts = check_readiness(SCpnt, 1, devip);
+               break;
+       case TEST_UNIT_READY:     /* mandatory */
+               delay_override = 1;
+               errsts = check_readiness(SCpnt, 0, devip);
+               break;
+       case RESERVE:
+               errsts = check_readiness(SCpnt, 1, devip);
+               break;
+       case RESERVE_10:
+               errsts = check_readiness(SCpnt, 1, devip);
+               break;
+       case RELEASE:
+               errsts = check_readiness(SCpnt, 1, devip);
+               break;
+       case RELEASE_10:
+               errsts = check_readiness(SCpnt, 1, devip);
+               break;
+       case READ_CAPACITY:
+               errsts = resp_readcap(SCpnt, devip);
+               break;
+       case SERVICE_ACTION_IN:
+               if (SAI_READ_CAPACITY_16 != cmd[1]) {
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_OPCODE, 0);
+                       errsts = check_condition_result;
+                       break;
+               }
+               errsts = resp_readcap16(SCpnt, devip);
+               break;
+       case MAINTENANCE_IN:
+               if (MI_REPORT_TARGET_PGS != cmd[1]) {
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_OPCODE, 0);
+                       errsts = check_condition_result;
+                       break;
+               }
+               errsts = resp_report_tgtpgs(SCpnt, devip);
+               break;
+       case READ_16:
+       case READ_12:
+       case READ_10:
+       case READ_6:
+               errsts = check_readiness(SCpnt, 0, devip);
+               if (errsts)
+                       break;
+               if (scsi_debug_fake_rw)
+                       break;
+               get_data_transfer_info(cmd, &lba, &num);
+               errsts = resp_read(SCpnt, lba, num, devip);
+               if (inj_recovered && (0 == errsts)) {
+                       mk_sense_buffer(devip, RECOVERED_ERROR,
+                                       THRESHOLD_EXCEEDED, 0);
+                       errsts = check_condition_result;
+               } else if (inj_transport && (0 == errsts)) {
+                       mk_sense_buffer(devip, ABORTED_COMMAND,
+                                       TRANSPORT_PROBLEM, ACK_NAK_TO);
+                       errsts = check_condition_result;
+               }
+               break;
+       case REPORT_LUNS:       /* mandatory, ignore unit attention */
+               delay_override = 1;
+               errsts = resp_report_luns(SCpnt, devip);
+               break;
+       case VERIFY:            /* 10 byte SBC-2 command */
+               errsts = check_readiness(SCpnt, 0, devip);
+               break;
+       case WRITE_16:
+       case WRITE_12:
+       case WRITE_10:
+       case WRITE_6:
+               errsts = check_readiness(SCpnt, 0, devip);
+               if (errsts)
+                       break;
+               if (scsi_debug_fake_rw)
+                       break;
+               get_data_transfer_info(cmd, &lba, &num);
+               errsts = resp_write(SCpnt, lba, num, devip);
+               if (inj_recovered && (0 == errsts)) {
+                       mk_sense_buffer(devip, RECOVERED_ERROR,
+                                       THRESHOLD_EXCEEDED, 0);
+                       errsts = check_condition_result;
+               }
+               break;
+       case MODE_SENSE:
+       case MODE_SENSE_10:
+               errsts = resp_mode_sense(SCpnt, target, devip);
+               break;
+       case MODE_SELECT:
+               errsts = resp_mode_select(SCpnt, 1, devip);
+               break;
+       case MODE_SELECT_10:
+               errsts = resp_mode_select(SCpnt, 0, devip);
+               break;
+       case LOG_SENSE:
+               errsts = resp_log_sense(SCpnt, devip);
+               break;
+       case SYNCHRONIZE_CACHE:
+               delay_override = 1;
+               errsts = check_readiness(SCpnt, 0, devip);
+               break;
+       case WRITE_BUFFER:
+               errsts = check_readiness(SCpnt, 1, devip);
+               break;
+       case XDWRITEREAD_10:
+               if (!scsi_bidi_cmnd(SCpnt)) {
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_FIELD_IN_CDB, 0);
+                       errsts = check_condition_result;
+                       break;
+               }
+
+               errsts = check_readiness(SCpnt, 0, devip);
+               if (errsts)
+                       break;
+               if (scsi_debug_fake_rw)
+                       break;
+               get_data_transfer_info(cmd, &lba, &num);
+               errsts = resp_read(SCpnt, lba, num, devip);
+               if (errsts)
+                       break;
+               errsts = resp_write(SCpnt, lba, num, devip);
+               if (errsts)
+                       break;
+               errsts = resp_xdwriteread(SCpnt, lba, num, devip);
+               break;
+       default:
+               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+                       printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
+                              "supported\n", *cmd);
+               errsts = check_readiness(SCpnt, 1, devip);
+               if (errsts)
+                       break;  /* Unit attention takes precedence */
+               mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
+               errsts = check_condition_result;
+               break;
+       }
+       return schedule_resp(SCpnt, devip, done, errsts,
+                            (delay_override ? 0 : scsi_debug_delay));
+}
+
+static struct scsi_host_template sdebug_driver_template = {
+       .proc_info =            scsi_debug_proc_info,
+       .proc_name =            sdebug_proc_name,
+       .name =                 "SCSI DEBUG",
+       .info =                 scsi_debug_info,
+       .slave_alloc =          scsi_debug_slave_alloc,
+       .slave_configure =      scsi_debug_slave_configure,
+       .slave_destroy =        scsi_debug_slave_destroy,
+       .ioctl =                scsi_debug_ioctl,
+       .queuecommand =         scsi_debug_queuecommand,
+       .eh_abort_handler =     scsi_debug_abort,
+       .eh_bus_reset_handler = scsi_debug_bus_reset,
+       .eh_device_reset_handler = scsi_debug_device_reset,
+       .eh_host_reset_handler = scsi_debug_host_reset,
+       .bios_param =           scsi_debug_biosparam,
+       .can_queue =            SCSI_DEBUG_CANQUEUE,
+       .this_id =              7,
+       .sg_tablesize =         256,
+       .cmd_per_lun =          16,
+       .max_sectors =          0xffff,
+       .use_clustering =       DISABLE_CLUSTERING,
+       .module =               THIS_MODULE,
+};
+
 static int sdebug_driver_probe(struct device * dev)
 {
         int error = 0;
@@ -3120,9 +2982,8 @@ static int sdebug_driver_probe(struct device * dev)
 
 static int sdebug_driver_remove(struct device * dev)
 {
-        struct list_head *lh, *lh_sf;
         struct sdebug_host_info *sdbg_host;
-        struct sdebug_dev_info *sdbg_devinfo;
+       struct sdebug_dev_info *sdbg_devinfo, *tmp;
 
        sdbg_host = to_sdebug_host(dev);
 
@@ -3134,9 +2995,8 @@ static int sdebug_driver_remove(struct device * dev)
 
         scsi_remove_host(sdbg_host->shost);
 
-        list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
-                sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
-                                          dev_list);
+       list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
+                                dev_list) {
                 list_del(&sdbg_devinfo->dev_list);
                 kfree(sdbg_devinfo);
         }
@@ -3145,20 +3005,15 @@ static int sdebug_driver_remove(struct device * dev)
         return 0;
 }
 
-static void sdebug_max_tgts_luns(void)
+static int pseudo_lld_bus_match(struct device *dev,
+                               struct device_driver *dev_driver)
 {
-       struct sdebug_host_info * sdbg_host;
-       struct Scsi_Host *hpnt;
-
-       spin_lock(&sdebug_host_list_lock);
-       list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
-               hpnt = sdbg_host->shost;
-               if ((hpnt->this_id >= 0) &&
-                   (scsi_debug_num_tgts > hpnt->this_id))
-                       hpnt->max_id = scsi_debug_num_tgts + 1;
-               else
-                       hpnt->max_id = scsi_debug_num_tgts;
-               hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* scsi_debug_max_luns; */
-       }
-       spin_unlock(&sdebug_host_list_lock);
+       return 1;
 }
+
+static struct bus_type pseudo_lld_bus = {
+       .name = "pseudo",
+       .match = pseudo_lld_bus_match,
+       .probe = sdebug_driver_probe,
+       .remove = sdebug_driver_remove,
+};
diff --git a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h
deleted file mode 100644 (file)
index 965dd5e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _SCSI_DEBUG_H
-
-#include <linux/types.h>
-
-static int scsi_debug_slave_alloc(struct scsi_device *);
-static int scsi_debug_slave_configure(struct scsi_device *);
-static void scsi_debug_slave_destroy(struct scsi_device *);
-static int scsi_debug_queuecommand(struct scsi_cmnd *,
-                                  void (*done) (struct scsi_cmnd *));
-static int scsi_debug_ioctl(struct scsi_device *, int, void __user *);
-static int scsi_debug_biosparam(struct scsi_device *, struct block_device *,
-               sector_t, int[]);
-static int scsi_debug_abort(struct scsi_cmnd *);
-static int scsi_debug_bus_reset(struct scsi_cmnd *);
-static int scsi_debug_device_reset(struct scsi_cmnd *);
-static int scsi_debug_host_reset(struct scsi_cmnd *);
-static int scsi_debug_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-static const char * scsi_debug_info(struct Scsi_Host *);
-
-#define SCSI_DEBUG_CANQUEUE  255       /* needs to be >= 1 */
-
-#define SCSI_DEBUG_MAX_CMD_LEN 16
-
-#endif
index 045a0868fc7b4540ac53676206ab1f5136355f13..221f31e36d26e5c4f7bfe88b7abde0b2996c982e 100644 (file)
@@ -524,6 +524,41 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
        return rtn;
 }
 
+static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
+{
+       sdev->was_reset = 1;
+       sdev->expecting_cc_ua = 1;
+}
+
+/**
+ * scsi_try_target_reset - Ask host to perform a target reset
+ * @scmd:      SCSI cmd used to send a target reset
+ *
+ * Notes:
+ *    There is no timeout for this operation.  if this operation is
+ *    unreliable for a given host, then the host itself needs to put a
+ *    timer on it, and set the host back to a consistent state prior to
+ *    returning.
+ */
+static int scsi_try_target_reset(struct scsi_cmnd *scmd)
+{
+       unsigned long flags;
+       int rtn;
+
+       if (!scmd->device->host->hostt->eh_target_reset_handler)
+               return FAILED;
+
+       rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd);
+       if (rtn == SUCCESS) {
+               spin_lock_irqsave(scmd->device->host->host_lock, flags);
+               __starget_for_each_device(scsi_target(scmd->device), NULL,
+                                         __scsi_report_device_reset);
+               spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+       }
+
+       return rtn;
+}
+
 /**
  * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
  * @scmd:      SCSI cmd used to send BDR
@@ -542,11 +577,8 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
                return FAILED;
 
        rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
-       if (rtn == SUCCESS) {
-               scmd->device->was_reset = 1;
-               scmd->device->expecting_cc_ua = 1;
-       }
-
+       if (rtn == SUCCESS)
+               __scsi_report_device_reset(scmd->device, NULL);
        return rtn;
 }
 
@@ -584,8 +616,9 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 {
        if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
                if (scsi_try_bus_device_reset(scmd) != SUCCESS)
-                       if (scsi_try_bus_reset(scmd) != SUCCESS)
-                               scsi_try_host_reset(scmd);
+                       if (scsi_try_target_reset(scmd) != SUCCESS)
+                               if (scsi_try_bus_reset(scmd) != SUCCESS)
+                                       scsi_try_host_reset(scmd);
 }
 
 /**
@@ -1059,6 +1092,56 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
        return list_empty(work_q);
 }
 
+/**
+ * scsi_eh_target_reset - send target reset if needed
+ * @shost:     scsi host being recovered.
+ * @work_q:     &list_head for pending commands.
+ * @done_q:    &list_head for processed commands.
+ *
+ * Notes:
+ *    Try a target reset.
+ */
+static int scsi_eh_target_reset(struct Scsi_Host *shost,
+                               struct list_head *work_q,
+                               struct list_head *done_q)
+{
+       struct scsi_cmnd *scmd, *tgtr_scmd, *next;
+       unsigned int id;
+       int rtn;
+
+       for (id = 0; id <= shost->max_id; id++) {
+               tgtr_scmd = NULL;
+               list_for_each_entry(scmd, work_q, eh_entry) {
+                       if (id == scmd_id(scmd)) {
+                               tgtr_scmd = scmd;
+                               break;
+                       }
+               }
+               if (!tgtr_scmd)
+                       continue;
+
+               SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
+                                                 "to target %d\n",
+                                                 current->comm, id));
+               rtn = scsi_try_target_reset(tgtr_scmd);
+               if (rtn == SUCCESS) {
+                       list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
+                               if (id == scmd_id(scmd))
+                                       if (!scsi_device_online(scmd->device) ||
+                                           !scsi_eh_tur(tgtr_scmd))
+                                               scsi_eh_finish_cmd(scmd,
+                                                                  done_q);
+                       }
+               } else
+                       SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset"
+                                                         " failed target: "
+                                                         "%d\n",
+                                                         current->comm, id));
+       }
+
+       return list_empty(work_q);
+}
+
 /**
  * scsi_eh_bus_reset - send a bus reset 
  * @shost:     &scsi host being recovered.
@@ -1447,9 +1530,11 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost,
 {
        if (!scsi_eh_stu(shost, work_q, done_q))
                if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
-                       if (!scsi_eh_bus_reset(shost, work_q, done_q))
-                               if (!scsi_eh_host_reset(work_q, done_q))
-                                       scsi_eh_offline_sdevs(work_q, done_q);
+                       if (!scsi_eh_target_reset(shost, work_q, done_q))
+                               if (!scsi_eh_bus_reset(shost, work_q, done_q))
+                                       if (!scsi_eh_host_reset(work_q, done_q))
+                                               scsi_eh_offline_sdevs(work_q,
+                                                                     done_q);
 }
 EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
 
@@ -1619,10 +1704,8 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
        struct scsi_device *sdev;
 
        __shost_for_each_device(sdev, shost) {
-               if (channel == sdev_channel(sdev)) {
-                       sdev->was_reset = 1;
-                       sdev->expecting_cc_ua = 1;
-               }
+               if (channel == sdev_channel(sdev))
+                       __scsi_report_device_reset(sdev, NULL);
        }
 }
 EXPORT_SYMBOL(scsi_report_bus_reset);
@@ -1655,10 +1738,8 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
 
        __shost_for_each_device(sdev, shost) {
                if (channel == sdev_channel(sdev) &&
-                   target == sdev_id(sdev)) {
-                       sdev->was_reset = 1;
-                       sdev->expecting_cc_ua = 1;
-               }
+                   target == sdev_id(sdev))
+                       __scsi_report_device_reset(sdev, NULL);
        }
 }
 EXPORT_SYMBOL(scsi_report_device_reset);
@@ -1714,6 +1795,11 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
                if (rtn == SUCCESS)
                        break;
                /* FALLTHROUGH */
+       case SCSI_TRY_RESET_TARGET:
+               rtn = scsi_try_target_reset(scmd);
+               if (rtn == SUCCESS)
+                       break;
+               /* FALLTHROUGH */
        case SCSI_TRY_RESET_BUS:
                rtn = scsi_try_bus_reset(scmd);
                if (rtn == SUCCESS)
@@ -1907,3 +1993,31 @@ int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
        }
 }
 EXPORT_SYMBOL(scsi_get_sense_info_fld);
+
+/**
+ * scsi_build_sense_buffer - build sense data in a buffer
+ * @desc:      Sense format (non zero == descriptor format,
+ *             0 == fixed format)
+ * @buf:       Where to build sense data
+ * @key:       Sense key
+ * @asc:       Additional sense code
+ * @ascq:      Additional sense code qualifier
+ *
+ **/
+void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)
+{
+       if (desc) {
+               buf[0] = 0x72;  /* descriptor, current */
+               buf[1] = key;
+               buf[2] = asc;
+               buf[3] = ascq;
+               buf[7] = 0;
+       } else {
+               buf[0] = 0x70;  /* fixed, current */
+               buf[2] = key;
+               buf[7] = 0xa;
+               buf[12] = asc;
+               buf[13] = ascq;
+       }
+}
+EXPORT_SYMBOL(scsi_build_sense_buffer);
index f40898dc2d1427990926617792a2bcc89f47e465..67f412bb4974b91783009fb3404c4a589bb6f6c8 100644 (file)
@@ -784,7 +784,7 @@ EXPORT_SYMBOL(scsi_release_buffers);
  * in req->data_len and req->next_rq->data_len. The upper-layer driver can
  * decide what to do with this information.
  */
-void scsi_end_bidi_request(struct scsi_cmnd *cmd)
+static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
 {
        struct request *req = cmd->request;
        unsigned int dlen = req->data_len;
@@ -839,7 +839,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        int this_count = scsi_bufflen(cmd);
        struct request_queue *q = cmd->device->request_queue;
        struct request *req = cmd->request;
-       int clear_errors = 1;
+       int error = 0;
        struct scsi_sense_hdr sshdr;
        int sense_valid = 0;
        int sense_deferred = 0;
@@ -853,7 +853,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        if (blk_pc_request(req)) { /* SG_IO ioctl from block level */
                req->errors = result;
                if (result) {
-                       clear_errors = 0;
                        if (sense_valid && req->sense) {
                                /*
                                 * SG_IO wants current and deferred errors
@@ -865,6 +864,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                memcpy(req->sense, cmd->sense_buffer,  len);
                                req->sense_len = len;
                        }
+                       if (!sense_deferred)
+                               error = -EIO;
                }
                if (scsi_bidi_cmnd(cmd)) {
                        /* will also release_buffers */
@@ -885,14 +886,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                      "%d bytes done.\n",
                                      req->nr_sectors, good_bytes));
 
-       if (clear_errors)
-               req->errors = 0;
-
        /* A number of bytes were successfully read.  If there
         * are leftovers and there is some kind of error
         * (result != 0), retry the rest.
         */
-       if (scsi_end_request(cmd, 0, good_bytes, result == 0) == NULL)
+       if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
                return;
 
        /* good_bytes = 0, or (inclusive) there were leftovers and
index a0f308bd145b062e2403af9b57a2c32d92108ca0..ee8496aa0336682eedc40879dfca871d6551ff3c 100644 (file)
@@ -621,9 +621,7 @@ static int __init scsi_tgt_init(void)
 {
        int err;
 
-       scsi_tgt_cmd_cache = kmem_cache_create("scsi_tgt_cmd",
-                                              sizeof(struct scsi_tgt_cmd),
-                                              0, 0, NULL);
+       scsi_tgt_cmd_cache =  KMEM_CACHE(scsi_tgt_cmd, 0);
        if (!scsi_tgt_cmd_cache)
                return -ENOMEM;
 
index 26cfc56c7091e6d5cf388eba98c456cc1a6ab8c8..03e359670506cf1403463616a1c410d72a709fab 100644 (file)
@@ -263,10 +263,11 @@ static int __init sgiwd93_probe(struct platform_device *pdev)
        regs.SASR = wdregs + 3;
        regs.SCMD = wdregs + 7;
 
-       wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
+       hdata->wh.no_sync = 0;
+       hdata->wh.fast = 1;
+       hdata->wh.dma_mode = CTRL_BURST;
 
-       if (hdata->wh.no_sync == 0xff)
-               hdata->wh.no_sync = 0;
+       wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
 
        err = request_irq(irq, sgiwd93_intr, 0, "SGI WD93", host);
        if (err) {
index 0a52d9d2da2cc43678c9d099aa0e00eb2b0ecfef..df83bea2c62029fff5d13122c3d7e9059ca76ad8 100644 (file)
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static const char *verstr = "20080221";
+static const char *verstr = "20080224";
 
 #include <linux/module.h>
 
@@ -183,6 +183,7 @@ static int modes_defined;
 
 static struct st_buffer *new_tape_buffer(int, int, int);
 static int enlarge_buffer(struct st_buffer *, int, int);
+static void clear_buffer(struct st_buffer *);
 static void normalize_buffer(struct st_buffer *);
 static int append_to_buffer(const char __user *, struct st_buffer *, int);
 static int from_buffer(struct st_buffer *, char __user *, int);
@@ -442,6 +443,7 @@ static void st_sleep_done(void *data, char *sense, int result, int resid)
 
        memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
        (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
+       (STp->buffer)->cmdstat.residual = resid;
        DEB( STp->write_pending = 0; )
 
        if (SRpnt->waiting)
@@ -626,7 +628,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
 
 
 /* Flush the write buffer (never need to write if variable blocksize). */
-static int flush_write_buffer(struct scsi_tape * STp)
+static int st_flush_write_buffer(struct scsi_tape * STp)
 {
        int offset, transfer, blks;
        int result;
@@ -717,7 +719,7 @@ static int flush_buffer(struct scsi_tape *STp, int seek_next)
                return 0;
        STps = &(STp->ps[STp->partition]);
        if (STps->rw == ST_WRITING)     /* Writing */
-               return flush_write_buffer(STp);
+               return st_flush_write_buffer(STp);
 
        if (STp->block_size == 0)
                return 0;
@@ -1159,6 +1161,7 @@ static int st_open(struct inode *inode, struct file *filp)
                goto err_out;
        }
 
+       (STp->buffer)->cleared = 0;
        (STp->buffer)->writing = 0;
        (STp->buffer)->syscall_result = 0;
 
@@ -1211,7 +1214,7 @@ static int st_flush(struct file *filp, fl_owner_t id)
                return 0;
 
        if (STps->rw == ST_WRITING && !STp->pos_unknown) {
-               result = flush_write_buffer(STp);
+               result = st_flush_write_buffer(STp);
                if (result != 0 && result != (-ENOSPC))
                        goto out;
        }
@@ -1432,8 +1435,14 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
                if (STp->block_size)
                        bufsize = STp->block_size > st_fixed_buffer_size ?
                                STp->block_size : st_fixed_buffer_size;
-               else
+               else {
                        bufsize = count;
+                       /* Make sure that data from previous user is not leaked even if
+                          HBA does not return correct residual */
+                       if (is_read && STp->sili && !STbp->cleared)
+                               clear_buffer(STbp);
+               }
+
                if (bufsize > STbp->buffer_size &&
                    !enlarge_buffer(STbp, bufsize, STp->restr_dma)) {
                        printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n",
@@ -1783,6 +1792,8 @@ static long read_tape(struct scsi_tape *STp, long count,
        memset(cmd, 0, MAX_COMMAND_SIZE);
        cmd[0] = READ_6;
        cmd[1] = (STp->block_size != 0);
+       if (!cmd[1] && STp->sili)
+               cmd[1] |= 2;
        cmd[2] = blks >> 16;
        cmd[3] = blks >> 8;
        cmd[4] = blks;
@@ -1911,8 +1922,11 @@ static long read_tape(struct scsi_tape *STp, long count,
 
        }
        /* End of error handling */ 
-       else                    /* Read successful */
+       else {                  /* Read successful */
                STbp->buffer_bytes = bytes;
+               if (STp->sili) /* In fixed block mode residual is always zero here */
+                       STbp->buffer_bytes -= STp->buffer->cmdstat.residual;
+       }
 
        if (STps->drv_block >= 0) {
                if (STp->block_size == 0)
@@ -2090,7 +2104,8 @@ static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char
                       name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
                       STp->scsi2_logical);
                printk(KERN_INFO
-                      "%s:    sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate);
+                      "%s:    sysv: %d nowait: %d sili: %d\n", name, STm->sysv, STp->immediate,
+                       STp->sili);
                printk(KERN_INFO "%s:    debugging: %d\n",
                       name, debugging);
        }
@@ -2133,6 +2148,7 @@ static int st_set_options(struct scsi_tape *STp, long options)
                STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
                STp->immediate = (options & MT_ST_NOWAIT) != 0;
                STm->sysv = (options & MT_ST_SYSV) != 0;
+               STp->sili = (options & MT_ST_SILI) != 0;
                DEB( debugging = (options & MT_ST_DEBUGGING) != 0;
                     st_log_options(STp, STm, name); )
        } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
@@ -2164,6 +2180,8 @@ static int st_set_options(struct scsi_tape *STp, long options)
                        STp->immediate = value;
                if ((options & MT_ST_SYSV) != 0)
                        STm->sysv = value;
+               if ((options & MT_ST_SILI) != 0)
+                       STp->sili = value;
                 DEB(
                if ((options & MT_ST_DEBUGGING) != 0)
                        debugging = value;
@@ -3655,6 +3673,8 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
                STbuffer->frp_segs += 1;
                got += b_size;
                STbuffer->buffer_size = got;
+               if (STbuffer->cleared)
+                       memset(page_address(STbuffer->frp[segs].page), 0, b_size);
                segs++;
        }
        STbuffer->b_data = page_address(STbuffer->frp[0].page);
@@ -3663,6 +3683,17 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
 }
 
 
+/* Make sure that no data from previous user is in the internal buffer */
+static void clear_buffer(struct st_buffer * st_bp)
+{
+       int i;
+
+       for (i=0; i < st_bp->frp_segs; i++)
+               memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length);
+       st_bp->cleared = 1;
+}
+
+
 /* Release the extra buffer */
 static void normalize_buffer(struct st_buffer * STbuffer)
 {
@@ -3987,6 +4018,7 @@ static int st_probe(struct device *dev)
        tpnt->two_fm = ST_TWO_FM;
        tpnt->fast_mteom = ST_FAST_MTEOM;
        tpnt->scsi2_logical = ST_SCSI2LOGICAL;
+       tpnt->sili = ST_SILI;
        tpnt->immediate = ST_NOWAIT;
        tpnt->default_drvbuffer = 0xff;         /* No forced buffering */
        tpnt->partition = 0;
@@ -4333,6 +4365,46 @@ static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf)
 
 CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
 
+static ssize_t st_options_show(struct class_device *class_dev, char *buf)
+{
+       struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
+       struct scsi_tape *STp;
+       int i, j, options;
+       ssize_t l = 0;
+
+       for (i=0; i < st_dev_max; i++) {
+               for (j=0; j < ST_NBR_MODES; j++)
+                       if (&scsi_tapes[i]->modes[j] == STm)
+                               break;
+               if (j < ST_NBR_MODES)
+                       break;
+       }
+       if (i == st_dev_max)
+               return 0;  /* should never happen */
+
+       STp = scsi_tapes[i];
+
+       options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0;
+       options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0;
+       options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0;
+       DEB( options |= debugging ? MT_ST_DEBUGGING : 0 );
+       options |= STp->two_fm ? MT_ST_TWO_FM : 0;
+       options |= STp->fast_mteom ? MT_ST_FAST_MTEOM : 0;
+       options |= STm->defaults_for_writes ? MT_ST_DEF_WRITES : 0;
+       options |= STp->can_bsr ? MT_ST_CAN_BSR : 0;
+       options |= STp->omit_blklims ? MT_ST_NO_BLKLIMS : 0;
+       options |= STp->can_partitions ? MT_ST_CAN_PARTITIONS : 0;
+       options |= STp->scsi2_logical ? MT_ST_SCSI2LOGICAL : 0;
+       options |= STm->sysv ? MT_ST_SYSV : 0;
+       options |= STp->immediate ? MT_ST_NOWAIT : 0;
+       options |= STp->sili ? MT_ST_SILI : 0;
+
+       l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options);
+       return l;
+}
+
+CLASS_DEVICE_ATTR(options, S_IRUGO, st_options_show, NULL);
+
 static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
 {
        int i, rew, error;
@@ -4370,6 +4442,9 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
                error = class_device_create_file(st_class_member,
                                        &class_device_attr_default_compression);
                if (error) goto out;
+               error = class_device_create_file(st_class_member,
+                                       &class_device_attr_options);
+               if (error) goto out;
 
                if (mode == 0 && rew == 0) {
                        error = sysfs_create_link(&STp->device->sdev_gendev.kobj,
index 5931726fcf93c8f6cd3df2235a4748af1a8b49ca..b92712f959315ddf23c4cc134da9703f13029763 100644 (file)
@@ -12,6 +12,7 @@ struct st_cmdstatus {
        int midlevel_result;
        struct scsi_sense_hdr sense_hdr;
        int have_sense;
+       int residual;
        u64 uremainder64;
        u8 flags;
        u8 remainder_valid;
@@ -34,6 +35,7 @@ struct st_request {
 struct st_buffer {
        unsigned char dma;      /* DMA-able buffer */
        unsigned char do_dio;   /* direct i/o set up? */
+       unsigned char cleared;  /* internal buffer cleared after open? */
        int buffer_size;
        int buffer_blocks;
        int buffer_bytes;
@@ -122,6 +124,7 @@ struct scsi_tape {
        unsigned char try_dio_now;              /* try direct i/o before next close? */
        unsigned char c_algo;                   /* compression algorithm */
        unsigned char pos_unknown;                      /* after reset position unknown */
+       unsigned char sili;                     /* use SILI when reading in variable b mode */
        int tape_type;
        int long_timeout;       /* timeout for commands known to take long time */
 
index b6b5c9c376772c414829bb45b5c96fea7490e7eb..d2f947935554ef4ccfda1816c68e9cca4ecc08bd 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright 1995-2003 Kai Makisara.
 
-   Last modified: Mon Apr  7 22:49:18 2003 by makisara
+   Last modified: Thu Feb 21 21:47:07 2008 by kai.makisara
 */
 
 #ifndef _ST_OPTIONS_H
    The default is BSD semantics. */
 #define ST_SYSV 0
 
+/* If ST_SILI is non-zero, the SILI bit is set when reading in variable block
+   mode and the block size is determined using the residual returned by the HBA. */
+#define ST_SILI 0
+
 /* Time to wait for the drive to become ready if blocking open */
 #define ST_BLOCK_SECONDS     120
 
index 654430edf74db0525b35605e06b176126cb5aab1..f308a030882916aed13c1805ef9213758e1313eb 100644 (file)
@@ -33,6 +33,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_dbg.h>
+#include <scsi/scsi_eh.h>
 
 #define DRV_NAME "stex"
 #define ST_DRIVER_VERSION "3.6.0000.1"
@@ -362,22 +363,14 @@ static struct status_msg *stex_get_status(struct st_hba *hba)
        return status;
 }
 
-static void stex_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
-{
-       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
-
-       cmd->sense_buffer[0] = 0x70;    /* fixed format, current */
-       cmd->sense_buffer[2] = sk;
-       cmd->sense_buffer[7] = 18 - 8;  /* additional sense length */
-       cmd->sense_buffer[12] = asc;
-       cmd->sense_buffer[13] = ascq;
-}
-
 static void stex_invalid_field(struct scsi_cmnd *cmd,
                               void (*done)(struct scsi_cmnd *))
 {
+       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
        /* "Invalid field in cbd" */
-       stex_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+       scsi_build_sense_buffer(0, cmd->sense_buffer, ILLEGAL_REQUEST, 0x24,
+                               0x0);
        done(cmd);
 }
 
@@ -426,49 +419,13 @@ static int stex_map_sg(struct st_hba *hba,
        return 0;
 }
 
-static void stex_internal_copy(struct scsi_cmnd *cmd,
-       const void *src, size_t *count, int sg_count, int direction)
-{
-       size_t lcount;
-       size_t len;
-       void *s, *d, *base = NULL;
-       size_t offset;
-
-       if (*count > scsi_bufflen(cmd))
-               *count = scsi_bufflen(cmd);
-       lcount = *count;
-       while (lcount) {
-               len = lcount;
-               s = (void *)src;
-
-               offset = *count - lcount;
-               s += offset;
-               base = scsi_kmap_atomic_sg(scsi_sglist(cmd),
-                                          sg_count, &offset, &len);
-               if (!base) {
-                       *count -= lcount;
-                       return;
-               }
-               d = base + offset;
-
-               if (direction == ST_TO_CMD)
-                       memcpy(d, s, len);
-               else
-                       memcpy(s, d, len);
-
-               lcount -= len;
-               scsi_kunmap_atomic_sg(base);
-       }
-}
-
 static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
 {
        struct st_frame *p;
        size_t count = sizeof(struct st_frame);
 
        p = hba->copy_buffer;
-       stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
-                          ST_FROM_CMD);
+       count = scsi_sg_copy_to_buffer(ccb->cmd, p, count);
        memset(p->base, 0, sizeof(u32)*6);
        *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
        p->rom_addr = 0;
@@ -486,8 +443,7 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
        p->subid =
                hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
 
-       stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
-                          ST_TO_CMD);
+       count = scsi_sg_copy_from_buffer(ccb->cmd, p, count);
 }
 
 static void
@@ -554,10 +510,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
                unsigned char page;
                page = cmd->cmnd[2] & 0x3f;
                if (page == 0x8 || page == 0x3f) {
-                       size_t cp_len = sizeof(ms10_caching_page);
-                       stex_internal_copy(cmd, ms10_caching_page,
-                                          &cp_len, scsi_sg_count(cmd),
-                                          ST_TO_CMD);
+                       scsi_sg_copy_from_buffer(cmd, ms10_caching_page,
+                                                sizeof(ms10_caching_page));
                        cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
                        done(cmd);
                } else
@@ -586,10 +540,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
                if (id != host->max_id - 1)
                        break;
                if (lun == 0 && (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
-                       size_t cp_len = sizeof(console_inq_page);
-                       stex_internal_copy(cmd, console_inq_page,
-                                          &cp_len, scsi_sg_count(cmd),
-                                          ST_TO_CMD);
+                       scsi_sg_copy_from_buffer(cmd, (void *)console_inq_page,
+                                                sizeof(console_inq_page));
                        cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
                        done(cmd);
                } else
@@ -606,8 +558,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
                        ver.signature[0] = PASSTHRU_SIGNATURE;
                        ver.console_id = host->max_id - 1;
                        ver.host_no = hba->host->host_no;
-                       stex_internal_copy(cmd, &ver, &cp_len,
-                                          scsi_sg_count(cmd), ST_TO_CMD);
+                       cp_len = scsi_sg_copy_from_buffer(cmd, &ver, cp_len);
                        cmd->result = sizeof(ver) == cp_len ?
                                DID_OK << 16 | COMMAND_COMPLETE << 8 :
                                DID_ERROR << 16 | COMMAND_COMPLETE << 8;
@@ -700,15 +651,12 @@ static void stex_copy_data(struct st_ccb *ccb,
 
        if (ccb->cmd == NULL)
                return;
-       stex_internal_copy(ccb->cmd,
-               resp->variable, &count, scsi_sg_count(ccb->cmd), ST_TO_CMD);
+       count = scsi_sg_copy_from_buffer(ccb->cmd, resp->variable, count);
 }
 
 static void stex_ys_commands(struct st_hba *hba,
        struct st_ccb *ccb, struct status_msg *resp)
 {
-       size_t count;
-
        if (ccb->cmd->cmnd[0] == MGT_CMD &&
                resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
                scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) -
@@ -724,9 +672,8 @@ static void stex_ys_commands(struct st_hba *hba,
                resp->scsi_status == SAM_STAT_GOOD) {
                ST_INQ *inq_data;
 
-               count = STEX_EXTRA_SIZE;
-               stex_internal_copy(ccb->cmd, hba->copy_buffer,
-                       &count, scsi_sg_count(ccb->cmd), ST_FROM_CMD);
+               scsi_sg_copy_to_buffer(ccb->cmd, hba->copy_buffer,
+                                      STEX_EXTRA_SIZE);
                inq_data = (ST_INQ *)hba->copy_buffer;
                if (inq_data->DeviceTypeQualifier != 0)
                        ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
index 02d9727f017a9af8f602b06126c79dffa4304034..aaa4fd0dd1b90b0e6019ecda1587ecc7b32b67f6 100644 (file)
@@ -582,3 +582,4 @@ static struct scsi_host_template driver_template = {
 
 #include "scsi_module.c"
 
+MODULE_LICENSE("GPL");
index f286c37da7e0dfb51fc44435c4c54d0a6120ba28..5fda881c2470aa6c08cb670b470583d7e756f571 100644 (file)
@@ -1973,10 +1973,7 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
        hostdata->incoming_ptr = 0;
        hostdata->outgoing_len = 0;
        hostdata->default_sx_per = DEFAULT_SX_PER;
-       hostdata->no_sync = 0xff;       /* sync defaults to off */
        hostdata->no_dma = 0;   /* default is DMA enabled */
-       hostdata->fast = 0;     /* default is Fast SCSI transfers disabled */
-       hostdata->dma_mode = CTRL_DMA;  /* default is Single Byte DMA */
 
 #ifdef PROC_INTERFACE
        hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
index f5582332af046d4cb00ea31b3beeebccd7da2384..574b201b99d8b0f31c268434546c4930ceb94eb7 100644 (file)
@@ -37,7 +37,7 @@ attribute_container_set_no_classdevs(struct attribute_container *atc)
 }
 
 int attribute_container_register(struct attribute_container *cont);
-int attribute_container_unregister(struct attribute_container *cont);
+int __must_check attribute_container_unregister(struct attribute_container *cont);
 void attribute_container_create_device(struct device *dev,
                                       int (*fn)(struct attribute_container *,
                                                 struct device *,
index 6f8d2d45a8fb502b086757d410482070b8ec1654..ef01d6aa5934e8f72cfcf0e63b3f81d3936e2062 100644 (file)
@@ -192,6 +192,7 @@ struct      mtpos {
 #define MT_ST_SCSI2LOGICAL      0x800
 #define MT_ST_SYSV              0x1000
 #define MT_ST_NOWAIT            0x2000
+#define MT_ST_SILI             0x4000
 
 /* The mode parameters to be controlled. Parameter chosen with bits 20-28 */
 #define MT_ST_CLEAR_DEFAULT    0xfffff
index a3d567a974e8319de915ebf48423a434fca3880f..71fc8136004892903bebc866f5aee249e0de06d7 100644 (file)
@@ -213,6 +213,11 @@ int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t,
                     sg_alloc_fn *);
 int sg_alloc_table(struct sg_table *, unsigned int, gfp_t);
 
+size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
+                          void *buf, size_t buflen);
+size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
+                        void *buf, size_t buflen);
+
 /*
  * Maximum number of entries that will be allocated in one piece, if
  * a list larger than this is required then chaining will be utilized.
index 1d6cc22e5f42a49ab4e42a3db982c8b4a9107f04..6696cf79c4f72744a6e3494f1c9b82d5def8271e 100644 (file)
@@ -86,9 +86,10 @@ static inline int transport_container_register(struct transport_container *tc)
        return attribute_container_register(&tc->ac);
 }
 
-static inline int transport_container_unregister(struct transport_container *tc)
+static inline void transport_container_unregister(struct transport_container *tc)
 {
-       return attribute_container_unregister(&tc->ac);
+       if (unlikely(attribute_container_unregister(&tc->ac)))
+               BUG();
 }
 
 int transport_class_register(struct transport_class *);
index 5ffec8ad6964c7ac9cebe0edfdb0517bff106064..e0593bfae62254b1901e484172c16f7f9a3b8209 100644 (file)
@@ -112,6 +112,7 @@ struct iscsi_ahs_hdr {
 
 #define ISCSI_AHSTYPE_CDB              1
 #define ISCSI_AHSTYPE_RLENGTH          2
+#define ISCSI_CDB_SIZE                 16
 
 /* iSCSI PDU Header */
 struct iscsi_cmd {
@@ -125,7 +126,7 @@ struct iscsi_cmd {
        __be32 data_length;
        __be32 cmdsn;
        __be32 exp_statsn;
-       uint8_t cdb[16];        /* SCSI Command Block */
+       uint8_t cdb[ISCSI_CDB_SIZE];    /* SCSI Command Block */
        /* Additional Data (Command Dependent) */
 };
 
@@ -154,7 +155,8 @@ struct iscsi_ecdb_ahdr {
        __be16 ahslength;       /* CDB length - 15, including reserved byte */
        uint8_t ahstype;
        uint8_t reserved;
-       uint8_t ecdb[260 - 16]; /* 4-byte aligned extended CDB spillover */
+       /* 4-byte aligned extended CDB spillover */
+       uint8_t ecdb[260 - ISCSI_CDB_SIZE];
 };
 
 /* SCSI Response Header */
index 39e1cac24bb751503fdef353a764292326b32037..98724ba65a79751d483e4aeb3ec4cd449b17bb2d 100644 (file)
@@ -677,4 +677,6 @@ extern void sas_ssp_task_response(struct device *dev, struct sas_task *task,
                                  struct ssp_response_iu *iu);
 struct sas_phy *sas_find_local_phy(struct domain_device *dev);
 
+int sas_request_addr(struct Scsi_Host *shost, u8 *addr);
+
 #endif /* _SASLIB_H_ */
index dd5edc915417bf9c9538059091bfc5a7e654c5f3..c583193ae929333a440ff7ae69efb74082a974dc 100644 (file)
@@ -47,12 +47,12 @@ static inline int dev_is_sata(struct domain_device *dev)
 {
        return 0;
 }
-int sas_ata_init_host_and_port(struct domain_device *found_dev,
+static inline int sas_ata_init_host_and_port(struct domain_device *found_dev,
                               struct scsi_target *starget)
 {
        return 0;
 }
-void sas_ata_task_abort(struct sas_task *task)
+static inline void sas_ata_task_abort(struct sas_task *task)
 {
 }
 #endif
index de28aab820b0cca9cdd7261c4000ee965f821e1d..8d20e60a94b7e18b25f8d1c44d393635cd892211 100644 (file)
@@ -130,6 +130,9 @@ extern void scsi_release_buffers(struct scsi_cmnd *cmd);
 extern int scsi_dma_map(struct scsi_cmnd *cmd);
 extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
 
+struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask);
+void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd);
+
 static inline unsigned scsi_sg_count(struct scsi_cmnd *cmd)
 {
        return cmd->sdb.table.nents;
@@ -175,4 +178,18 @@ static inline struct scsi_data_buffer *scsi_out(struct scsi_cmnd *cmd)
        return &cmd->sdb;
 }
 
+static inline int scsi_sg_copy_from_buffer(struct scsi_cmnd *cmd,
+                                          void *buf, int buflen)
+{
+       return sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
+                                  buf, buflen);
+}
+
+static inline int scsi_sg_copy_to_buffer(struct scsi_cmnd *cmd,
+                                        void *buf, int buflen)
+{
+       return sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
+                                buf, buflen);
+}
+
 #endif /* _SCSI_SCSI_CMND_H */
index 25071d5d9bf813e95b49efa567fbed23c16f2236..d3a133b4a072bf2104a0204d29084be7b79bd186 100644 (file)
@@ -57,13 +57,16 @@ extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
 
 extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
                                   u64 * info_out);
+
+extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
+
 /*
  * Reset request from external source
  */
 #define SCSI_TRY_RESET_DEVICE  1
 #define SCSI_TRY_RESET_BUS     2
 #define SCSI_TRY_RESET_HOST    3
+#define SCSI_TRY_RESET_TARGET  4
 
 extern int scsi_reset_provider(struct scsi_device *, int);
 
index 530ff4c553f86a1b307b8f3259ed1bf0a09b283e..49132862bfaaf7098bcdb72b0cb5e833976b89cc 100644 (file)
@@ -172,6 +172,7 @@ struct scsi_host_template {
         */
        int (* eh_abort_handler)(struct scsi_cmnd *);
        int (* eh_device_reset_handler)(struct scsi_cmnd *);
+       int (* eh_target_reset_handler)(struct scsi_cmnd *);
        int (* eh_bus_reset_handler)(struct scsi_cmnd *);
        int (* eh_host_reset_handler)(struct scsi_cmnd *);
 
index acca4901046c45b055d98ff0b5858a3bc4056ff4..b80c21100d783ceeee87fa828600d90b322120ab 100644 (file)
@@ -8,6 +8,7 @@
  */
 #include <linux/module.h>
 #include <linux/scatterlist.h>
+#include <linux/highmem.h>
 
 /**
  * sg_next - return the next scatterlist entry in a list
@@ -292,3 +293,104 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
        return ret;
 }
 EXPORT_SYMBOL(sg_alloc_table);
+
+/**
+ * sg_copy_buffer - Copy data between a linear buffer and an SG list
+ * @sgl:                The SG list
+ * @nents:              Number of SG entries
+ * @buf:                Where to copy from
+ * @buflen:             The number of bytes to copy
+ * @to_buffer:                  transfer direction (non zero == from an sg list to a
+ *                      buffer, 0 == from a buffer to an sg list
+ *
+ * Returns the number of copied bytes.
+ *
+ **/
+static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
+                            void *buf, size_t buflen, int to_buffer)
+{
+       struct scatterlist *sg;
+       size_t buf_off = 0;
+       int i;
+
+       WARN_ON(!irqs_disabled());
+
+       for_each_sg(sgl, sg, nents, i) {
+               struct page *page;
+               int n = 0;
+               unsigned int sg_off = sg->offset;
+               unsigned int sg_copy = sg->length;
+
+               if (sg_copy > buflen)
+                       sg_copy = buflen;
+               buflen -= sg_copy;
+
+               while (sg_copy > 0) {
+                       unsigned int page_copy;
+                       void *p;
+
+                       page_copy = PAGE_SIZE - sg_off;
+                       if (page_copy > sg_copy)
+                               page_copy = sg_copy;
+
+                       page = nth_page(sg_page(sg), n);
+                       p = kmap_atomic(page, KM_BIO_SRC_IRQ);
+
+                       if (to_buffer)
+                               memcpy(buf + buf_off, p + sg_off, page_copy);
+                       else {
+                               memcpy(p + sg_off, buf + buf_off, page_copy);
+                               flush_kernel_dcache_page(page);
+                       }
+
+                       kunmap_atomic(p, KM_BIO_SRC_IRQ);
+
+                       buf_off += page_copy;
+                       sg_off += page_copy;
+                       if (sg_off == PAGE_SIZE) {
+                               sg_off = 0;
+                               n++;
+                       }
+                       sg_copy -= page_copy;
+               }
+
+               if (!buflen)
+                       break;
+       }
+
+       return buf_off;
+}
+
+/**
+ * sg_copy_from_buffer - Copy from a linear buffer to an SG list
+ * @sgl:                The SG list
+ * @nents:              Number of SG entries
+ * @buf:                Where to copy from
+ * @buflen:             The number of bytes to copy
+ *
+ * Returns the number of copied bytes.
+ *
+ **/
+size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
+                          void *buf, size_t buflen)
+{
+       return sg_copy_buffer(sgl, nents, buf, buflen, 0);
+}
+EXPORT_SYMBOL(sg_copy_from_buffer);
+
+/**
+ * sg_copy_to_buffer - Copy from an SG list to a linear buffer
+ * @sgl:                The SG list
+ * @nents:              Number of SG entries
+ * @buf:                Where to copy to
+ * @buflen:             The number of bytes to copy
+ *
+ * Returns the number of copied bytes.
+ *
+ **/
+size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
+                        void *buf, size_t buflen)
+{
+       return sg_copy_buffer(sgl, nents, buf, buflen, 1);
+}
+EXPORT_SYMBOL(sg_copy_to_buffer);