Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
Linus Torvalds [Tue, 15 Sep 2009 00:53:36 +0000 (17:53 -0700)]
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (209 commits)
  [SCSI] fix oops during scsi scanning
  [SCSI] libsrp: fix memory leak in srp_ring_free()
  [SCSI] libiscsi, bnx2i: make bound ep check common
  [SCSI] libiscsi: add completion function for drivers that do not need pdu processing
  [SCSI] scsi_dh_rdac: changes for rdac debug logging
  [SCSI] scsi_dh_rdac: changes to collect the rdac debug information during the initialization
  [SCSI] scsi_dh_rdac: move the init code from rdac_activate to rdac_bus_attach
  [SCSI] sg: fix oops in the error path in sg_build_indirect()
  [SCSI] mptsas : Bump version to 3.04.12
  [SCSI] mptsas : FW event thread and scsi mid layer deadlock in SYNCHRONIZE CACHE command
  [SCSI] mptsas : Send DID_NO_CONNECT for pending IOs of removed device
  [SCSI] mptsas : PAE Kernel more than 4 GB kernel panic
  [SCSI] mptsas : NULL pointer on big endian systems causing Expander not to tear off
  [SCSI] mptsas : Sanity check for phyinfo is added
  [SCSI] scsi_dh_rdac: Add support for Sun StorageTek ST2500, ST2510 and ST2530
  [SCSI] pmcraid: PMC-Sierra MaxRAID driver to support 6Gb/s SAS RAID controller
  [SCSI] qla2xxx: Update version number to 8.03.01-k6.
  [SCSI] qla2xxx: Properly delete rports attached to a vport.
  [SCSI] qla2xxx: Correct various NPIV issues.
  [SCSI] qla2xxx: Correct qla2x00_eh_wait_on_command() to wait correctly.
  ...

112 files changed:
MAINTAINERS
arch/s390/include/asm/timex.h
arch/s390/kernel/debug.c
arch/s390/kernel/time.c
drivers/md/dm-mpath.c
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.h
drivers/message/fusion/mptspi.c
drivers/misc/enclosure.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
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fc.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/bnx2i/bnx2i_init.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/ch.c
drivers/scsi/constants.c
drivers/scsi/device_handler/scsi_dh.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/device_handler/scsi_dh_emc.c
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/fcoe.h
drivers/scsi/fcoe/libfcoe.c
drivers/scsi/fnic/fnic_fcs.c
drivers/scsi/fnic/fnic_main.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ipr.h
drivers/scsi/iscsi_tcp.c
drivers/scsi/libfc/fc_disc.c
drivers/scsi/libfc/fc_elsct.c
drivers/scsi/libfc/fc_exch.c
drivers/scsi/libfc/fc_fcp.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/libiscsi.c
drivers/scsi/libsrp.c
drivers/scsi/lpfc/Makefile
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_bsg.c [new file with mode: 0644]
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_mem.c
drivers/scsi/lpfc/lpfc_nl.h
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/lpfc/lpfc_vport.c
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.h
drivers/scsi/mpt2sas/mpt2sas_config.c
drivers/scsi/mpt2sas/mpt2sas_ctl.c
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mpt2sas/mpt2sas_transport.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pmcraid.c [new file with mode: 0644]
drivers/scsi/pmcraid.h [new file with mode: 0644]
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_def.h
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_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_version.h
drivers/scsi/qla4xxx/ql4_isr.c
drivers/scsi/scsi.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/sd.c
drivers/scsi/ses.c
drivers/scsi/sg.c
drivers/scsi/stex.c
include/linux/enclosure.h
include/scsi/fc/fc_gs.h
include/scsi/fc_encode.h
include/scsi/fc_frame.h
include/scsi/iscsi_if.h
include/scsi/libfc.h
include/scsi/libiscsi.h
include/scsi/scsi_device.h
include/scsi/scsi_dh.h

index 256d72a..837b598 100644 (file)
@@ -4009,6 +4009,14 @@ S:       Maintained
 F:     drivers/block/pktcdvd.c
 F:     include/linux/pktcdvd.h
 
+PMC SIERRA MaxRAID DRIVER
+P:     Anil Ravindranath
+M:     anil_ravindranath@pmc-sierra.com
+L:     linux-scsi@vger.kernel.org
+W:     http://www.pmc-sierra.com/
+S:     Supported
+F:     drivers/scsi/pmcraid.*
+
 POSIX CLOCKS and TIMERS
 M:     Thomas Gleixner <tglx@linutronix.de>
 S:     Supported
@@ -4447,7 +4455,7 @@ F:        drivers/scsi/sg.c
 F:     include/scsi/sg.h
 
 SCSI SUBSYSTEM
-M:     "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
+M:     "James E.J. Bottomley" <James.Bottomley@suse.de>
 L:     linux-scsi@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git
index 24aa1cd..68d9fea 100644 (file)
@@ -88,6 +88,14 @@ int get_sync_clock(unsigned long long *clock);
 void init_cpu_timer(void);
 unsigned long long monotonic_clock(void);
 
+void tod_to_timeval(__u64, struct timespec *);
+
+static inline
+void stck_to_timespec(unsigned long long stck, struct timespec *ts)
+{
+       tod_to_timeval(stck - TOD_UNIX_EPOCH, ts);
+}
+
 extern u64 sched_clock_base_cc;
 
 /**
index be8bcea..4c51256 100644 (file)
@@ -63,8 +63,6 @@ typedef struct
 } debug_sprintf_entry_t;
 
 
-extern void tod_to_timeval(uint64_t todval, struct timespec *xtime);
-
 /* internal function prototyes */
 
 static int debug_init(void);
@@ -1450,17 +1448,13 @@ debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
                         int area, debug_entry_t * entry, char *out_buf)
 {
        struct timespec time_spec;
-       unsigned long long time;
        char *except_str;
        unsigned long caller;
        int rc = 0;
        unsigned int level;
 
        level = entry->id.fields.level;
-       time = entry->id.stck;
-       /* adjust todclock to 1970 */
-       time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
-       tod_to_timeval(time, &time_spec);
+       stck_to_timespec(entry->id.stck, &time_spec);
 
        if (entry->id.fields.exception)
                except_str = "*";
index 54e327e..e3dc28b 100644 (file)
@@ -91,6 +91,7 @@ void tod_to_timeval(__u64 todval, struct timespec *xtime)
        todval -= (sec * 1000000) << 12;
        xtime->tv_nsec = ((todval * 1000) >> 12);
 }
+EXPORT_SYMBOL(tod_to_timeval);
 
 void clock_comparator_work(void)
 {
index 6f0d90d..32d0b87 100644 (file)
@@ -64,6 +64,7 @@ struct multipath {
        spinlock_t lock;
 
        const char *hw_handler_name;
+       char *hw_handler_params;
        unsigned nr_priority_groups;
        struct list_head priority_groups;
        unsigned pg_init_required;      /* pg_init needs calling? */
@@ -219,6 +220,7 @@ static void free_multipath(struct multipath *m)
        }
 
        kfree(m->hw_handler_name);
+       kfree(m->hw_handler_params);
        mempool_destroy(m->mpio_pool);
        kfree(m);
 }
@@ -615,6 +617,17 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
                        dm_put_device(ti, p->path.dev);
                        goto bad;
                }
+
+               if (m->hw_handler_params) {
+                       r = scsi_dh_set_params(q, m->hw_handler_params);
+                       if (r < 0) {
+                               ti->error = "unable to set hardware "
+                                                       "handler parameters";
+                               scsi_dh_detach(q);
+                               dm_put_device(ti, p->path.dev);
+                               goto bad;
+                       }
+               }
        }
 
        r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error);
@@ -705,6 +718,7 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
 static int parse_hw_handler(struct arg_set *as, struct multipath *m)
 {
        unsigned hw_argc;
+       int ret;
        struct dm_target *ti = m->ti;
 
        static struct param _params[] = {
@@ -726,17 +740,33 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m)
        request_module("scsi_dh_%s", m->hw_handler_name);
        if (scsi_dh_handler_exist(m->hw_handler_name) == 0) {
                ti->error = "unknown hardware handler type";
-               kfree(m->hw_handler_name);
-               m->hw_handler_name = NULL;
-               return -EINVAL;
+               ret = -EINVAL;
+               goto fail;
        }
 
-       if (hw_argc > 1)
-               DMWARN("Ignoring user-specified arguments for "
-                      "hardware handler \"%s\"", m->hw_handler_name);
+       if (hw_argc > 1) {
+               char *p;
+               int i, j, len = 4;
+
+               for (i = 0; i <= hw_argc - 2; i++)
+                       len += strlen(as->argv[i]) + 1;
+               p = m->hw_handler_params = kzalloc(len, GFP_KERNEL);
+               if (!p) {
+                       ti->error = "memory allocation failed";
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+               j = sprintf(p, "%d", hw_argc - 1);
+               for (i = 0, p+=j+1; i <= hw_argc - 2; i++, p+=j+1)
+                       j = sprintf(p, "%s", as->argv[i]);
+       }
        consume(as, hw_argc - 1);
 
        return 0;
+fail:
+       kfree(m->hw_handler_name);
+       m->hw_handler_name = NULL;
+       return ret;
 }
 
 static int parse_features(struct arg_set *as, struct multipath *m)
index 5d0ba4f..76fa2ee 100644 (file)
@@ -1015,9 +1015,9 @@ mpt_add_sge_64bit(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
 {
        SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
        pSge->Address.Low = cpu_to_le32
-                       (lower_32_bits((unsigned long)(dma_addr)));
+                       (lower_32_bits(dma_addr));
        pSge->Address.High = cpu_to_le32
-                       (upper_32_bits((unsigned long)dma_addr));
+                       (upper_32_bits(dma_addr));
        pSge->FlagsLength = cpu_to_le32
                        ((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
 }
@@ -1038,8 +1038,8 @@ mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr)
        u32 tmp;
 
        pSge->Address.Low = cpu_to_le32
-                       (lower_32_bits((unsigned long)(dma_addr)));
-       tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
+                       (lower_32_bits(dma_addr));
+       tmp = (u32)(upper_32_bits(dma_addr));
 
        /*
         * 1078 errata workaround for the 36GB limitation
@@ -1101,7 +1101,7 @@ mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
                pChain->NextChainOffset = next;
 
                pChain->Address.Low = cpu_to_le32(tmp);
-               tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
+               tmp = (u32)(upper_32_bits(dma_addr));
                pChain->Address.High = cpu_to_le32(tmp);
 }
 
@@ -1297,12 +1297,8 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
        psge = (char *)&ioc_init->HostPageBufferSGE;
        flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
            MPI_SGE_FLAGS_SYSTEM_ADDRESS |
-           MPI_SGE_FLAGS_32_BIT_ADDRESSING |
            MPI_SGE_FLAGS_HOST_TO_IOC |
            MPI_SGE_FLAGS_END_OF_BUFFER;
-       if (sizeof(dma_addr_t) == sizeof(u64)) {
-           flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
-       }
        flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
        flags_length |= ioc->HostPageBuffer_sz;
        ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
@@ -2224,8 +2220,6 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
        int      hard;
        int      rc=0;
        int      ii;
-       u8       cb_idx;
-       int      handlers;
        int      ret = 0;
        int      reset_alt_ioc_active = 0;
        int      irq_allocated = 0;
@@ -2548,34 +2542,6 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                mpt_get_manufacturing_pg_0(ioc);
        }
 
-       /*
-        * Call each currently registered protocol IOC reset handler
-        * with post-reset indication.
-        * NOTE: If we're doing _IOC_BRINGUP, there can be no
-        * MptResetHandlers[] registered yet.
-        */
-       if (hard_reset_done) {
-               rc = handlers = 0;
-               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
-                       if ((ret == 0) && MptResetHandlers[cb_idx]) {
-                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                                   "Calling IOC post_reset handler #%d\n",
-                                   ioc->name, cb_idx));
-                               rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
-                               handlers++;
-                       }
-
-                       if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
-                               drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                                   "Calling IOC post_reset handler #%d\n",
-                                   ioc->alt_ioc->name, cb_idx));
-                               rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
-                               handlers++;
-                       }
-               }
-               /* FIXME?  Examine results here? */
-       }
-
  out:
        if ((ret != 0) && irq_allocated) {
                free_irq(ioc->pci_irq, ioc);
@@ -3938,6 +3904,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
        int count = 0;
        u32 diag1val = 0;
        MpiFwHeader_t *cached_fw;       /* Pointer to FW */
+       u8       cb_idx;
 
        /* Clear any existing interrupts */
        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
@@ -3956,6 +3923,18 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
                else
                        mdelay(1);
 
+               /*
+                * Call each currently registered protocol IOC reset handler
+                * with pre-reset indication.
+                * NOTE: If we're doing _IOC_BRINGUP, there can be no
+                * MptResetHandlers[] registered yet.
+                */
+               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+                       if (MptResetHandlers[cb_idx])
+                               (*(MptResetHandlers[cb_idx]))(ioc,
+                                               MPT_IOC_PRE_RESET);
+               }
+
                for (count = 0; count < 60; count ++) {
                        doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
                        doorbell &= MPI_IOC_STATE_MASK;
@@ -4052,25 +4031,15 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
                 * NOTE: If we're doing _IOC_BRINGUP, there can be no
                 * MptResetHandlers[] registered yet.
                 */
-               {
-                       u8       cb_idx;
-                       int      r = 0;
-
-                       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
-                               if (MptResetHandlers[cb_idx]) {
-                                       dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                                               "Calling IOC pre_reset handler #%d\n",
-                                               ioc->name, cb_idx));
-                                       r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
-                                       if (ioc->alt_ioc) {
-                                               dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-                                                       "Calling alt-%s pre_reset handler #%d\n",
-                                                       ioc->name, ioc->alt_ioc->name, cb_idx));
-                                               r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
-                                       }
+               for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+                       if (MptResetHandlers[cb_idx]) {
+                               mpt_signal_reset(cb_idx,
+                                       ioc, MPT_IOC_PRE_RESET);
+                               if (ioc->alt_ioc) {
+                                       mpt_signal_reset(cb_idx,
+                                       ioc->alt_ioc, MPT_IOC_PRE_RESET);
                                }
                        }
-                       /* FIXME?  Examine results here? */
                }
 
                if (ioc->cached_fw)
@@ -6956,7 +6925,7 @@ EXPORT_SYMBOL(mpt_halt_firmware);
 int
 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
 {
-       int              rc;
+       int      rc;
        u8       cb_idx;
        unsigned long    flags;
        unsigned long    time_count;
@@ -6982,8 +6951,6 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
                ioc->alt_ioc->ioc_reset_in_progress = 1;
        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 
-       /* FIXME: If do_ioc_recovery fails, repeat....
-        */
 
        /* The SCSI driver needs to adjust timeouts on all current
         * commands prior to the diagnostic reset being issued.
@@ -7020,6 +6987,15 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
        }
        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
 
+       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+               if (MptResetHandlers[cb_idx]) {
+                       mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
+                       if (ioc->alt_ioc)
+                               mpt_signal_reset(cb_idx,
+                                       ioc->alt_ioc, MPT_IOC_POST_RESET);
+               }
+       }
+
        dtmprintk(ioc,
            printk(MYIOC_s_DEBUG_FMT
                "HardResetHandler: completed (%d seconds): %s\n", ioc->name,
index 1c8514d..8dd4d21 100644 (file)
@@ -76,8 +76,8 @@
 #define COPYRIGHT      "Copyright (c) 1999-2008 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON       "3.04.10"
-#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.04.09"
+#define MPT_LINUX_VERSION_COMMON       "3.04.12"
+#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.04.12"
 #define WHAT_MAGIC_STRING              "@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
 /*
  *     Try to keep these at 2^N-1
  */
-#define MPT_FC_CAN_QUEUE       127
+#define MPT_FC_CAN_QUEUE       1024
 #define MPT_SCSI_CAN_QUEUE     127
+#define MPT_SAS_CAN_QUEUE      127
 
 /*
  * Set the MAX_SGE value based on user input.
@@ -879,23 +880,9 @@ typedef enum {
 
 typedef struct _MPT_SCSI_HOST {
        MPT_ADAPTER              *ioc;
-       int                       port;
-       u32                       pad0;
-       MPT_LOCAL_REPLY          *pLocal;               /* used for internal commands */
-       struct timer_list         timer;
-               /* Pool of memory for holding SCpnts before doing
-                * OS callbacks. freeQ is the free pool.
-                */
-       u8                        negoNvram;            /* DV disabled, nego NVRAM */
-       u8                        pad1;
-       u8                        rsvd[2];
-       MPT_FRAME_HDR            *cmdPtr;               /* Ptr to nonOS request */
-       struct scsi_cmnd         *abortSCpnt;
-       MPT_LOCAL_REPLY           localReply;           /* internal cmd reply struct */
        ushort                    sel_timeout[MPT_MAX_FC_DEVICES];
        char                      *info_kbuf;
        long                      last_queue_full;
-       u16                       tm_iocstatus;
        u16                       spi_pending;
        struct list_head          target_reset_list;
 } MPT_SCSI_HOST;
index e61df13..ebf6ae0 100644 (file)
@@ -1288,25 +1288,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
                 ioc->name, ioc->ScsiLookup));
 
-       /* Clear the TM flags
-        */
-       hd->abortSCpnt = NULL;
-
-       /* Clear the pointer used to store
-        * single-threaded commands, i.e., those
-        * issued during a bus scan, dv and
-        * configuration pages.
-        */
-       hd->cmdPtr = NULL;
-
-       /* Initialize this SCSI Hosts' timers
-        * To use, set the timer expires field
-        * and add_timer
-        */
-       init_timer(&hd->timer);
-       hd->timer.data = (unsigned long) hd;
-       hd->timer.function = mptscsih_timer_expired;
-
        hd->last_queue_full = 0;
 
        sh->transportt = mptfc_transport_template;
index 55ff252..83873e3 100644 (file)
@@ -72,6 +72,7 @@
  */
 #define MPTSAS_RAID_CHANNEL    1
 
+#define SAS_CONFIG_PAGE_TIMEOUT                30
 MODULE_AUTHOR(MODULEAUTHOR);
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
@@ -324,7 +325,6 @@ mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
 {
        struct fw_event_work *fw_event, *next;
        struct mptsas_target_reset_event *target_reset_list, *n;
-       u8      flush_q;
        MPT_SCSI_HOST   *hd = shost_priv(ioc->sh);
 
        /* flush the target_reset_list */
@@ -344,15 +344,10 @@ mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
             !ioc->fw_event_q || in_interrupt())
                return;
 
-       flush_q = 0;
        list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
                if (cancel_delayed_work(&fw_event->work))
                        mptsas_free_fw_event(ioc, fw_event);
-               else
-                       flush_q = 1;
        }
-       if (flush_q)
-               flush_workqueue(ioc->fw_event_q);
 }
 
 
@@ -661,7 +656,7 @@ mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
        cfg.pageAddr = starget->id;
        cfg.cfghdr.hdr = &hdr;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
-       cfg.timeout = 10;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 
        if (mpt_config(ioc, &cfg) != 0)
                goto out;
@@ -851,7 +846,13 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
                port_details->num_phys--;
                port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
                memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
-               sas_port_delete_phy(port_details->port, phy_info->phy);
+               if (phy_info->phy) {
+                       devtprintk(ioc, dev_printk(KERN_DEBUG,
+                               &phy_info->phy->dev, MYIOC_s_FMT
+                               "delete phy %d, phy-obj (0x%p)\n", ioc->name,
+                               phy_info->phy_id, phy_info->phy));
+                       sas_port_delete_phy(port_details->port, phy_info->phy);
+               }
                phy_info->port_details = NULL;
        }
 
@@ -1272,7 +1273,6 @@ mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                }
                mptsas_cleanup_fw_event_q(ioc);
                mptsas_queue_rescan(ioc);
-               mptsas_fw_event_on(ioc);
                break;
        default:
                break;
@@ -1318,7 +1318,7 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
        cfg.pageAddr = form + form_specific;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;    /* read */
-       cfg.timeout = 10;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 
        error = mpt_config(ioc, &cfg);
        if (error)
@@ -1592,6 +1592,7 @@ mptsas_firmware_event_work(struct work_struct *work)
                mptsas_scan_sas_topology(ioc);
                ioc->in_rescan = 0;
                mptsas_free_fw_event(ioc, fw_event);
+               mptsas_fw_event_on(ioc);
                return;
        }
 
@@ -1891,7 +1892,7 @@ static struct scsi_host_template mptsas_driver_template = {
        .eh_bus_reset_handler           = mptscsih_bus_reset,
        .eh_host_reset_handler          = mptscsih_host_reset,
        .bios_param                     = mptscsih_bios_param,
-       .can_queue                      = MPT_FC_CAN_QUEUE,
+       .can_queue                      = MPT_SAS_CAN_QUEUE,
        .this_id                        = -1,
        .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
        .max_sectors                    = 8192,
@@ -1926,7 +1927,7 @@ static int mptsas_get_linkerrors(struct sas_phy *phy)
        cfg.pageAddr = phy->identify.phy_identifier;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;    /* read */
-       cfg.timeout = 10;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 
        error = mpt_config(ioc, &cfg);
        if (error)
@@ -2278,7 +2279,7 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
        cfg.pageAddr = 0;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;    /* read */
-       cfg.timeout = 10;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 
        error = mpt_config(ioc, &cfg);
        if (error)
@@ -2349,7 +2350,7 @@ mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
 
        cfg.cfghdr.ehdr = &hdr;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
-       cfg.timeout = 10;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
        cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
        cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
        cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
@@ -2411,7 +2412,7 @@ mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
 
        cfg.cfghdr.ehdr = &hdr;
        cfg.dir = 0;    /* read */
-       cfg.timeout = 10;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 
        /* Get Phy Pg 0 for each Phy. */
        cfg.physAddr = -1;
@@ -2479,7 +2480,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
        cfg.physAddr = -1;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;    /* read */
-       cfg.timeout = 10;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 
        memset(device_info, 0, sizeof(struct mptsas_devinfo));
        error = mpt_config(ioc, &cfg);
@@ -2554,7 +2555,7 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
        cfg.pageAddr = form + form_specific;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;    /* read */
-       cfg.timeout = 10;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 
        memset(port_info, 0, sizeof(struct mptsas_portinfo));
        error = mpt_config(ioc, &cfg);
@@ -2635,7 +2636,7 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
        cfg.pageAddr = form + form_specific;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
        cfg.dir = 0;    /* read */
-       cfg.timeout = 10;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 
        error = mpt_config(ioc, &cfg);
        if (error)
@@ -3307,6 +3308,7 @@ mptsas_send_expander_event(struct fw_event_work *fw_event)
        expander_data = (MpiEventDataSasExpanderStatusChange_t *)
            fw_event->event_data;
        memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
+       sas_address = le64_to_cpu(sas_address);
        port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
 
        if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
@@ -4760,10 +4762,9 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* set 16 byte cdb's */
        sh->max_cmd_len = 16;
-
-       sh->max_id = ioc->pfacts[0].PortSCSIID;
+       sh->can_queue = min_t(int, ioc->req_depth - 10, sh->can_queue);
+       sh->max_id = -1;
        sh->max_lun = max_lun;
-
        sh->transportt = mptsas_transport_template;
 
        /* Required entry.
@@ -4821,25 +4822,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
                 ioc->name, ioc->ScsiLookup));
 
-       /* Clear the TM flags
-        */
-       hd->abortSCpnt = NULL;
-
-       /* Clear the pointer used to store
-        * single-threaded commands, i.e., those
-        * issued during a bus scan, dv and
-        * configuration pages.
-        */
-       hd->cmdPtr = NULL;
-
-       /* Initialize this SCSI Hosts' timers
-        * To use, set the timer expires field
-        * and add_timer
-        */
-       init_timer(&hd->timer);
-       hd->timer.data = (unsigned long) hd;
-       hd->timer.function = mptscsih_timer_expired;
-
        ioc->sas_data.ptClear = mpt_pt_clear;
 
        hd->last_queue_full = 0;
index 8440f78..c295786 100644 (file)
@@ -628,6 +628,16 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                return 1;
        }
 
+       if (ioc->bus_type == SAS) {
+               VirtDevice *vdevice = sc->device->hostdata;
+
+               if (!vdevice || !vdevice->vtarget ||
+                   vdevice->vtarget->deleted) {
+                       sc->result = DID_NO_CONNECT << 16;
+                       goto out;
+               }
+       }
+
        sc->host_scribble = NULL;
        sc->result = DID_OK << 16;              /* Set default reply as OK */
        pScsiReq = (SCSIIORequest_t *) mf;
@@ -689,6 +699,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
                switch(status) {
                case MPI_IOCSTATUS_BUSY:                        /* 0x0002 */
+               case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:      /* 0x0006 */
                        /* CHECKME!
                         * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
                         * But not: DID_BUS_BUSY lest one risk
@@ -872,7 +883,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                case MPI_IOCSTATUS_INVALID_SGL:                 /* 0x0003 */
                case MPI_IOCSTATUS_INTERNAL_ERROR:              /* 0x0004 */
                case MPI_IOCSTATUS_RESERVED:                    /* 0x0005 */
-               case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:      /* 0x0006 */
                case MPI_IOCSTATUS_INVALID_FIELD:               /* 0x0007 */
                case MPI_IOCSTATUS_INVALID_STATE:               /* 0x0008 */
                case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
@@ -892,7 +902,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 #endif
 
        } /* end of address reply case */
-
+out:
        /* Unmap the DMA buffers, if any. */
        scsi_dma_unmap(sc);
 
@@ -1729,9 +1739,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
         */
        mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
        ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
-
-       hd->abortSCpnt = SCpnt;
-
        retval = mptscsih_IssueTaskMgmt(hd,
                         MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
                         vdevice->vtarget->channel,
@@ -2293,7 +2300,10 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
                else
                        max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
        } else
-               max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+                max_depth = ioc->sh->can_queue;
+
+       if (!sdev->tagged_supported)
+               max_depth = 1;
 
        if (qdepth > max_depth)
                qdepth = max_depth;
@@ -2627,50 +2637,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
        return 1;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*     mptscsih_timer_expired - Call back for timer process.
- *     Used only for dv functionality.
- *     @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
- *
- */
-void
-mptscsih_timer_expired(unsigned long data)
-{
-       MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
-       MPT_ADAPTER     *ioc = hd->ioc;
-
-       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", ioc->name, hd->cmdPtr));
-
-       if (hd->cmdPtr) {
-               MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
-
-               if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
-                       /* Desire to issue a task management request here.
-                        * TM requests MUST be single threaded.
-                        * If old eh code and no TM current, issue request.
-                        * If new eh code, do nothing. Wait for OS cmd timeout
-                        *      for bus reset.
-                        */
-               } else {
-                       /* Perform a FW reload */
-                       if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
-                               printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
-                       }
-               }
-       } else {
-               /* This should NEVER happen */
-               printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", ioc->name);
-       }
-
-       /* No more processing.
-        * TM call will generate an interrupt for SCSI TM Management.
-        * The FW will reply to all outstanding commands, callback will finish cleanup.
-        * Hard reset clean-up will free all resources.
-        */
-       ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", ioc->name));
-
-       return;
-}
 
 /**
  *     mptscsih_get_completion_code -
@@ -3265,6 +3231,5 @@ EXPORT_SYMBOL(mptscsih_scandv_complete);
 EXPORT_SYMBOL(mptscsih_event_process);
 EXPORT_SYMBOL(mptscsih_ioc_reset);
 EXPORT_SYMBOL(mptscsih_change_queue_depth);
-EXPORT_SYMBOL(mptscsih_timer_expired);
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
index eb3f677..e0b33e0 100644 (file)
@@ -129,7 +129,6 @@ extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRA
 extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
-extern void mptscsih_timer_expired(unsigned long data);
 extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
 extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
 extern struct device_attribute *mptscsih_host_attrs[];
index c5b808f..69f4257 100644 (file)
@@ -1472,28 +1472,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
                 ioc->name, ioc->ScsiLookup));
 
-       /* Clear the TM flags
-        */
-       hd->abortSCpnt = NULL;
-
-       /* Clear the pointer used to store
-        * single-threaded commands, i.e., those
-        * issued during a bus scan, dv and
-        * configuration pages.
-        */
-       hd->cmdPtr = NULL;
-
-       /* Initialize this SCSI Hosts' timers
-        * To use, set the timer expires field
-        * and add_timer
-        */
-       init_timer(&hd->timer);
-       hd->timer.data = (unsigned long) hd;
-       hd->timer.function = mptscsih_timer_expired;
-
        ioc->spi_data.Saf_Te = mpt_saf_te;
-
-       hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
        ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                "saf_te %x\n",
                ioc->name,
index 348443b..7b03930 100644 (file)
@@ -33,24 +33,44 @@ static DEFINE_MUTEX(container_list_lock);
 static struct class enclosure_class;
 
 /**
- * enclosure_find - find an enclosure given a device
- * @dev:       the device to find for
+ * enclosure_find - find an enclosure given a parent device
+ * @dev:       the parent to match against
+ * @start:     Optional enclosure device to start from (NULL if none)
  *
- * Looks through the list of registered enclosures to see
- * if it can find a match for a device.  Returns NULL if no
- * enclosure is found. Obtains a reference to the enclosure class
- * device which must be released with device_put().
+ * Looks through the list of registered enclosures to find all those
+ * with @dev as a parent.  Returns NULL if no enclosure is
+ * found. @start can be used as a starting point to obtain multiple
+ * enclosures per parent (should begin with NULL and then be set to
+ * each returned enclosure device). Obtains a reference to the
+ * enclosure class device which must be released with device_put().
+ * If @start is not NULL, a reference must be taken on it which is
+ * released before returning (this allows a loop through all
+ * enclosures to exit with only the reference on the enclosure of
+ * interest held).  Note that the @dev may correspond to the actual
+ * device housing the enclosure, in which case no iteration via @start
+ * is required.
  */
-struct enclosure_device *enclosure_find(struct device *dev)
+struct enclosure_device *enclosure_find(struct device *dev,
+                                       struct enclosure_device *start)
 {
        struct enclosure_device *edev;
 
        mutex_lock(&container_list_lock);
-       list_for_each_entry(edev, &container_list, node) {
-               if (edev->edev.parent == dev) {
-                       get_device(&edev->edev);
-                       mutex_unlock(&container_list_lock);
-                       return edev;
+       edev = list_prepare_entry(start, &container_list, node);
+       if (start)
+               put_device(&start->edev);
+
+       list_for_each_entry_continue(edev, &container_list, node) {
+               struct device *parent = edev->edev.parent;
+               /* parent might not be immediate, so iterate up to
+                * the root of the tree if necessary */
+               while (parent) {
+                       if (parent == dev) {
+                               get_device(&edev->edev);
+                               mutex_unlock(&container_list_lock);
+                               return edev;
+                       }
+                       parent = parent->parent;
                }
        }
        mutex_unlock(&container_list_lock);
@@ -295,6 +315,9 @@ int enclosure_add_device(struct enclosure_device *edev, int component,
 
        cdev = &edev->component[component];
 
+       if (cdev->dev == dev)
+               return -EEXIST;
+
        if (cdev->dev)
                enclosure_remove_links(cdev);
 
@@ -312,19 +335,25 @@ EXPORT_SYMBOL_GPL(enclosure_add_device);
  * Returns zero on success or an error.
  *
  */
-int enclosure_remove_device(struct enclosure_device *edev, int component)
+int enclosure_remove_device(struct enclosure_device *edev, struct device *dev)
 {
        struct enclosure_component *cdev;
+       int i;
 
-       if (!edev || component >= edev->components)
+       if (!edev || !dev)
                return -EINVAL;
 
-       cdev = &edev->component[component];
-
-       device_del(&cdev->cdev);
-       put_device(cdev->dev);
-       cdev->dev = NULL;
-       return device_add(&cdev->cdev);
+       for (i = 0; i < edev->components; i++) {
+               cdev = &edev->component[i];
+               if (cdev->dev == dev) {
+                       enclosure_remove_links(cdev);
+                       device_del(&cdev->cdev);
+                       put_device(dev);
+                       cdev->dev = NULL;
+                       return device_add(&cdev->cdev);
+               }
+       }
+       return -ENODEV;
 }
 EXPORT_SYMBOL_GPL(enclosure_remove_device);
 
index 2ccbd18..1be6bf7 100644 (file)
@@ -42,6 +42,12 @@ static char *init_device;
 module_param_named(device, init_device, charp, 0400);
 MODULE_PARM_DESC(device, "specify initial device");
 
+static struct kmem_cache *zfcp_cache_hw_align(const char *name,
+                                             unsigned long size)
+{
+       return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL);
+}
+
 static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter)
 {
        int idx;
@@ -78,7 +84,7 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
        struct zfcp_port *port;
        struct zfcp_unit *unit;
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        read_lock_irq(&zfcp_data.config_lock);
        adapter = zfcp_get_adapter_by_busid(busid);
        if (adapter)
@@ -93,31 +99,23 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
        unit = zfcp_unit_enqueue(port, lun);
        if (IS_ERR(unit))
                goto out_unit;
-       up(&zfcp_data.config_sema);
+       mutex_unlock(&zfcp_data.config_mutex);
        ccw_device_set_online(adapter->ccw_device);
 
        zfcp_erp_wait(adapter);
        flush_work(&unit->scsi_work);
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        zfcp_unit_put(unit);
 out_unit:
        zfcp_port_put(port);
 out_port:
        zfcp_adapter_put(adapter);
 out_adapter:
-       up(&zfcp_data.config_sema);
+       mutex_unlock(&zfcp_data.config_mutex);
        return;
 }
 
-static struct kmem_cache *zfcp_cache_create(int size, char *name)
-{
-       int align = 1;
-       while ((size - align) > 0)
-               align <<= 1;
-       return kmem_cache_create(name , size, align, 0, NULL);
-}
-
 static void __init zfcp_init_device_setup(char *devstr)
 {
        char *token;
@@ -158,24 +156,27 @@ static int __init zfcp_module_init(void)
 {
        int retval = -ENOMEM;
 
-       zfcp_data.fsf_req_qtcb_cache = zfcp_cache_create(
-                       sizeof(struct zfcp_fsf_req_qtcb), "zfcp_fsf");
-       if (!zfcp_data.fsf_req_qtcb_cache)
+       zfcp_data.gpn_ft_cache = zfcp_cache_hw_align("zfcp_gpn",
+                                       sizeof(struct ct_iu_gpn_ft_req));
+       if (!zfcp_data.gpn_ft_cache)
                goto out;
 
-       zfcp_data.sr_buffer_cache = zfcp_cache_create(
-                       sizeof(struct fsf_status_read_buffer), "zfcp_sr");
+       zfcp_data.qtcb_cache = zfcp_cache_hw_align("zfcp_qtcb",
+                                       sizeof(struct fsf_qtcb));
+       if (!zfcp_data.qtcb_cache)
+               goto out_qtcb_cache;
+
+       zfcp_data.sr_buffer_cache = zfcp_cache_hw_align("zfcp_sr",
+                                       sizeof(struct fsf_status_read_buffer));
        if (!zfcp_data.sr_buffer_cache)
                goto out_sr_cache;
 
-       zfcp_data.gid_pn_cache = zfcp_cache_create(
-                       sizeof(struct zfcp_gid_pn_data), "zfcp_gid");
+       zfcp_data.gid_pn_cache = zfcp_cache_hw_align("zfcp_gid",
+                                       sizeof(struct zfcp_gid_pn_data));
        if (!zfcp_data.gid_pn_cache)
                goto out_gid_cache;
 
-       zfcp_data.work_queue = create_singlethread_workqueue("zfcp_wq");
-
-       sema_init(&zfcp_data.config_sema, 1);
+       mutex_init(&zfcp_data.config_mutex);
        rwlock_init(&zfcp_data.config_lock);
 
        zfcp_data.scsi_transport_template =
@@ -209,7 +210,9 @@ out_transport:
 out_gid_cache:
        kmem_cache_destroy(zfcp_data.sr_buffer_cache);
 out_sr_cache:
-       kmem_cache_destroy(zfcp_data.fsf_req_qtcb_cache);
+       kmem_cache_destroy(zfcp_data.qtcb_cache);
+out_qtcb_cache:
+       kmem_cache_destroy(zfcp_data.gpn_ft_cache);
 out:
        return retval;
 }
@@ -263,7 +266,7 @@ static void zfcp_sysfs_unit_release(struct device *dev)
  * @port: pointer to port where unit is added
  * @fcp_lun: FCP LUN of unit to be enqueued
  * Returns: pointer to enqueued unit on success, ERR_PTR on error
- * Locks: config_sema must be held to serialize changes to the unit list
+ * Locks: config_mutex must be held to serialize changes to the unit list
  *
  * Sets up some unit internal structures and creates sysfs entry.
  */
@@ -271,6 +274,13 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
 {
        struct zfcp_unit *unit;
 
+       read_lock_irq(&zfcp_data.config_lock);
+       if (zfcp_get_unit_by_lun(port, fcp_lun)) {
+               read_unlock_irq(&zfcp_data.config_lock);
+               return ERR_PTR(-EINVAL);
+       }
+       read_unlock_irq(&zfcp_data.config_lock);
+
        unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
        if (!unit)
                return ERR_PTR(-ENOMEM);
@@ -282,8 +292,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
        unit->port = port;
        unit->fcp_lun = fcp_lun;
 
-       dev_set_name(&unit->sysfs_device, "0x%016llx",
-                    (unsigned long long) fcp_lun);
+       if (dev_set_name(&unit->sysfs_device, "0x%016llx",
+                        (unsigned long long) fcp_lun)) {
+               kfree(unit);
+               return ERR_PTR(-ENOMEM);
+       }
        unit->sysfs_device.parent = &port->sysfs_device;
        unit->sysfs_device.release = zfcp_sysfs_unit_release;
        dev_set_drvdata(&unit->sysfs_device, unit);
@@ -299,20 +312,15 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
        unit->latencies.cmd.channel.min = 0xFFFFFFFF;
        unit->latencies.cmd.fabric.min = 0xFFFFFFFF;
 
-       read_lock_irq(&zfcp_data.config_lock);
-       if (zfcp_get_unit_by_lun(port, fcp_lun)) {
-               read_unlock_irq(&zfcp_data.config_lock);
-               goto err_out_free;
+       if (device_register(&unit->sysfs_device)) {
+               put_device(&unit->sysfs_device);
+               return ERR_PTR(-EINVAL);
        }
-       read_unlock_irq(&zfcp_data.config_lock);
-
-       if (device_register(&unit->sysfs_device))
-               goto err_out_free;
 
        if (sysfs_create_group(&unit->sysfs_device.kobj,
                               &zfcp_sysfs_unit_attrs)) {
                device_unregister(&unit->sysfs_device);
-               return ERR_PTR(-EIO);
+               return ERR_PTR(-EINVAL);
        }
 
        zfcp_unit_get(unit);
@@ -327,10 +335,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
        zfcp_port_get(port);
 
        return unit;
-
-err_out_free:
-       kfree(unit);
-       return ERR_PTR(-EINVAL);
 }
 
 /**
@@ -353,37 +357,47 @@ void zfcp_unit_dequeue(struct zfcp_unit *unit)
 
 static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
 {
-       /* must only be called with zfcp_data.config_sema taken */
-       adapter->pool.fsf_req_erp =
-               mempool_create_slab_pool(1, zfcp_data.fsf_req_qtcb_cache);
-       if (!adapter->pool.fsf_req_erp)
+       /* must only be called with zfcp_data.config_mutex taken */
+       adapter->pool.erp_req =
+               mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
+       if (!adapter->pool.erp_req)
+               return -ENOMEM;
+
+       adapter->pool.gid_pn_req =
+               mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
+       if (!adapter->pool.gid_pn_req)
                return -ENOMEM;
 
-       adapter->pool.fsf_req_scsi =
-               mempool_create_slab_pool(1, zfcp_data.fsf_req_qtcb_cache);
-       if (!adapter->pool.fsf_req_scsi)
+       adapter->pool.scsi_req =
+               mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
+       if (!adapter->pool.scsi_req)
                return -ENOMEM;
 
-       adapter->pool.fsf_req_abort =
-               mempool_create_slab_pool(1, zfcp_data.fsf_req_qtcb_cache);
-       if (!adapter->pool.fsf_req_abort)
+       adapter->pool.scsi_abort =
+               mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
+       if (!adapter->pool.scsi_abort)
                return -ENOMEM;
 
-       adapter->pool.fsf_req_status_read =
+       adapter->pool.status_read_req =
                mempool_create_kmalloc_pool(FSF_STATUS_READS_RECOM,
                                            sizeof(struct zfcp_fsf_req));
-       if (!adapter->pool.fsf_req_status_read)
+       if (!adapter->pool.status_read_req)
                return -ENOMEM;
 
-       adapter->pool.data_status_read =
+       adapter->pool.qtcb_pool =
+               mempool_create_slab_pool(4, zfcp_data.qtcb_cache);
+       if (!adapter->pool.qtcb_pool)
+               return -ENOMEM;
+
+       adapter->pool.status_read_data =
                mempool_create_slab_pool(FSF_STATUS_READS_RECOM,
                                         zfcp_data.sr_buffer_cache);
-       if (!adapter->pool.data_status_read)
+       if (!adapter->pool.status_read_data)
                return -ENOMEM;
 
-       adapter->pool.data_gid_pn =
+       adapter->pool.gid_pn_data =
                mempool_create_slab_pool(1, zfcp_data.gid_pn_cache);
-       if (!adapter->pool.data_gid_pn)
+       if (!adapter->pool.gid_pn_data)
                return -ENOMEM;
 
        return 0;
@@ -391,19 +405,21 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
 
 static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
 {
-       /* zfcp_data.config_sema must be held */
-       if (adapter->pool.fsf_req_erp)
-               mempool_destroy(adapter->pool.fsf_req_erp);
-       if (adapter->pool.fsf_req_scsi)
-               mempool_destroy(adapter->pool.fsf_req_scsi);
-       if (adapter->pool.fsf_req_abort)
-               mempool_destroy(adapter->pool.fsf_req_abort);
-       if (adapter->pool.fsf_req_status_read)
-               mempool_destroy(adapter->pool.fsf_req_status_read);
-       if (adapter->pool.data_status_read)
-               mempool_destroy(adapter->pool.data_status_read);
-       if (adapter->pool.data_gid_pn)
-               mempool_destroy(adapter->pool.data_gid_pn);
+       /* zfcp_data.config_mutex must be held */
+       if (adapter->pool.erp_req)
+               mempool_destroy(adapter->pool.erp_req);
+       if (adapter->pool.scsi_req)
+               mempool_destroy(adapter->pool.scsi_req);
+       if (adapter->pool.scsi_abort)
+               mempool_destroy(adapter->pool.scsi_abort);
+       if (adapter->pool.qtcb_pool)
+               mempool_destroy(adapter->pool.qtcb_pool);
+       if (adapter->pool.status_read_req)
+               mempool_destroy(adapter->pool.status_read_req);
+       if (adapter->pool.status_read_data)
+               mempool_destroy(adapter->pool.status_read_data);
+       if (adapter->pool.gid_pn_data)
+               mempool_destroy(adapter->pool.gid_pn_data);
 }
 
 /**
@@ -418,7 +434,7 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
 int zfcp_status_read_refill(struct zfcp_adapter *adapter)
 {
        while (atomic_read(&adapter->stat_miss) > 0)
-               if (zfcp_fsf_status_read(adapter)) {
+               if (zfcp_fsf_status_read(adapter->qdio)) {
                        if (atomic_read(&adapter->stat_miss) >= 16) {
                                zfcp_erp_adapter_reopen(adapter, 0, "axsref1",
                                                        NULL);
@@ -446,6 +462,27 @@ static void zfcp_print_sl(struct seq_file *m, struct service_level *sl)
                   adapter->fsf_lic_version);
 }
 
+static int zfcp_setup_adapter_work_queue(struct zfcp_adapter *adapter)
+{
+       char name[TASK_COMM_LEN];
+
+       snprintf(name, sizeof(name), "zfcp_q_%s",
+                dev_name(&adapter->ccw_device->dev));
+       adapter->work_queue = create_singlethread_workqueue(name);
+
+       if (adapter->work_queue)
+               return 0;
+       return -ENOMEM;
+}
+
+static void zfcp_destroy_adapter_work_queue(struct zfcp_adapter *adapter)
+{
+       if (adapter->work_queue)
+               destroy_workqueue(adapter->work_queue);
+       adapter->work_queue = NULL;
+
+}
+
 /**
  * zfcp_adapter_enqueue - enqueue a new adapter to the list
  * @ccw_device: pointer to the struct cc_device
@@ -455,7 +492,7 @@ static void zfcp_print_sl(struct seq_file *m, struct service_level *sl)
  * Enqueues an adapter at the end of the adapter list in the driver data.
  * All adapter internal structures are set up.
  * Proc-fs entries are also created.
- * locks:      config_sema must be held to serialise changes to the adapter list
+ * locks: config_mutex must be held to serialize changes to the adapter list
  */
 int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 {
@@ -463,37 +500,37 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 
        /*
         * Note: It is safe to release the list_lock, as any list changes
-        * are protected by the config_sema, which must be held to get here
+        * are protected by the config_mutex, which must be held to get here
         */
 
        adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL);
        if (!adapter)
                return -ENOMEM;
 
-       adapter->gs = kzalloc(sizeof(struct zfcp_wka_ports), GFP_KERNEL);
-       if (!adapter->gs) {
-               kfree(adapter);
-               return -ENOMEM;
-       }
-
        ccw_device->handler = NULL;
        adapter->ccw_device = ccw_device;
        atomic_set(&adapter->refcount, 0);
 
-       if (zfcp_qdio_allocate(adapter))
-               goto qdio_allocate_failed;
+       if (zfcp_qdio_setup(adapter))
+               goto qdio_failed;
 
        if (zfcp_allocate_low_mem_buffers(adapter))
-               goto failed_low_mem_buffers;
+               goto low_mem_buffers_failed;
 
        if (zfcp_reqlist_alloc(adapter))
-               goto failed_low_mem_buffers;
+               goto low_mem_buffers_failed;
 
-       if (zfcp_adapter_debug_register(adapter))
+       if (zfcp_dbf_adapter_register(adapter))
                goto debug_register_failed;
 
+       if (zfcp_setup_adapter_work_queue(adapter))
+               goto work_queue_failed;
+
+       if (zfcp_fc_gs_setup(adapter))
+               goto generic_services_failed;
+
        init_waitqueue_head(&adapter->remove_wq);
-       init_waitqueue_head(&adapter->erp_thread_wqh);
+       init_waitqueue_head(&adapter->erp_ready_wq);
        init_waitqueue_head(&adapter->erp_done_wqh);
 
        INIT_LIST_HEAD(&adapter->port_list_head);
@@ -502,20 +539,14 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 
        spin_lock_init(&adapter->req_list_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);
-       spin_lock_init(&adapter->req_q_lock);
-       spin_lock_init(&adapter->qdio_stat_lock);
-
        rwlock_init(&adapter->erp_lock);
        rwlock_init(&adapter->abort_lock);
 
-       sema_init(&adapter->erp_ready_sem, 0);
+       if (zfcp_erp_thread_setup(adapter))
+               goto erp_thread_failed;
 
        INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
-       INIT_WORK(&adapter->scan_work, _zfcp_scan_ports_later);
+       INIT_WORK(&adapter->scan_work, _zfcp_fc_scan_ports_later);
 
        adapter->service_level.seq_print = zfcp_print_sl;
 
@@ -529,20 +560,25 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
                goto sysfs_failed;
 
        atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
-       zfcp_fc_wka_ports_init(adapter);
 
        if (!zfcp_adapter_scsi_register(adapter))
                return 0;
 
 sysfs_failed:
-       zfcp_adapter_debug_unregister(adapter);
+       zfcp_erp_thread_kill(adapter);
+erp_thread_failed:
+       zfcp_fc_gs_destroy(adapter);
+generic_services_failed:
+       zfcp_destroy_adapter_work_queue(adapter);
+work_queue_failed:
+       zfcp_dbf_adapter_unregister(adapter->dbf);
 debug_register_failed:
        dev_set_drvdata(&ccw_device->dev, NULL);
        kfree(adapter->req_list);
-failed_low_mem_buffers:
+low_mem_buffers_failed:
        zfcp_free_low_mem_buffers(adapter);
-qdio_allocate_failed:
-       zfcp_qdio_free(adapter);
+qdio_failed:
+       zfcp_qdio_destroy(adapter->qdio);
        kfree(adapter);
        return -ENOMEM;
 }
@@ -559,6 +595,7 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
 
        cancel_work_sync(&adapter->scan_work);
        cancel_work_sync(&adapter->stat_work);
+       zfcp_fc_wka_ports_force_offline(adapter->gs);
        zfcp_adapter_scsi_unregister(adapter);
        sysfs_remove_group(&adapter->ccw_device->dev.kobj,
                           &zfcp_sysfs_adapter_attrs);
@@ -570,13 +607,15 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
        if (!retval)
                return;
 
-       zfcp_adapter_debug_unregister(adapter);
-       zfcp_qdio_free(adapter);
+       zfcp_fc_gs_destroy(adapter);
+       zfcp_erp_thread_kill(adapter);
+       zfcp_destroy_adapter_work_queue(adapter);
+       zfcp_dbf_adapter_unregister(adapter->dbf);
        zfcp_free_low_mem_buffers(adapter);
+       zfcp_qdio_destroy(adapter->qdio);
        kfree(adapter->req_list);
        kfree(adapter->fc_stats);
        kfree(adapter->stats_reset_data);
-       kfree(adapter->gs);
        kfree(adapter);
 }
 
@@ -592,7 +631,7 @@ static void zfcp_sysfs_port_release(struct device *dev)
  * @status: initial status for the port
  * @d_id: destination id of the remote port to be enqueued
  * Returns: pointer to enqueued port on success, ERR_PTR on error
- * Locks: config_sema must be held to serialize changes to the port list
+ * Locks: config_mutex must be held to serialize changes to the port list
  *
  * All port internal structures are set up and the sysfs entry is generated.
  * d_id is used to enqueue ports with a well known address like the Directory
@@ -602,7 +641,13 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
                                     u32 status, u32 d_id)
 {
        struct zfcp_port *port;
-       int retval;
+
+       read_lock_irq(&zfcp_data.config_lock);
+       if (zfcp_get_port_by_wwpn(adapter, wwpn)) {
+               read_unlock_irq(&zfcp_data.config_lock);
+               return ERR_PTR(-EINVAL);
+       }
+       read_unlock_irq(&zfcp_data.config_lock);
 
        port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
        if (!port)
@@ -610,7 +655,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
 
        init_waitqueue_head(&port->remove_wq);
        INIT_LIST_HEAD(&port->unit_list_head);
-       INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup);
+       INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
        INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
        INIT_WORK(&port->rport_work, zfcp_scsi_rport_work);
 
@@ -623,29 +668,24 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
        atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
        atomic_set(&port->refcount, 0);
 
-       dev_set_name(&port->sysfs_device, "0x%016llx",
-                    (unsigned long long)wwpn);
+       if (dev_set_name(&port->sysfs_device, "0x%016llx",
+                        (unsigned long long)wwpn)) {
+               kfree(port);
+               return ERR_PTR(-ENOMEM);
+       }
        port->sysfs_device.parent = &adapter->ccw_device->dev;
-
        port->sysfs_device.release = zfcp_sysfs_port_release;
        dev_set_drvdata(&port->sysfs_device, port);
 
-       read_lock_irq(&zfcp_data.config_lock);
-       if (zfcp_get_port_by_wwpn(adapter, wwpn)) {
-               read_unlock_irq(&zfcp_data.config_lock);
-               goto err_out_free;
+       if (device_register(&port->sysfs_device)) {
+               put_device(&port->sysfs_device);
+               return ERR_PTR(-EINVAL);
        }
-       read_unlock_irq(&zfcp_data.config_lock);
 
-       if (device_register(&port->sysfs_device))
-               goto err_out_free;
-
-       retval = sysfs_create_group(&port->sysfs_device.kobj,
-                                   &zfcp_sysfs_port_attrs);
-
-       if (retval) {
+       if (sysfs_create_group(&port->sysfs_device.kobj,
+                              &zfcp_sysfs_port_attrs)) {
                device_unregister(&port->sysfs_device);
-               goto err_out;
+               return ERR_PTR(-EINVAL);
        }
 
        zfcp_port_get(port);
@@ -659,11 +699,6 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
 
        zfcp_adapter_get(adapter);
        return port;
-
-err_out_free:
-       kfree(port);
-err_out:
-       return ERR_PTR(-EINVAL);
 }
 
 /**
@@ -672,12 +707,11 @@ err_out:
  */
 void zfcp_port_dequeue(struct zfcp_port *port)
 {
-       wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
        write_lock_irq(&zfcp_data.config_lock);
        list_del(&port->list);
        write_unlock_irq(&zfcp_data.config_lock);
-       if (port->rport)
-               port->rport->dd_data = NULL;
+       wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
+       cancel_work_sync(&port->rport_work); /* usually not necessary */
        zfcp_adapter_put(port->adapter);
        sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
        device_unregister(&port->sysfs_device);
index d9da5c4..0c90f8e 100644 (file)
@@ -18,12 +18,15 @@ static int zfcp_ccw_suspend(struct ccw_device *cdev)
 {
        struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
 
-       down(&zfcp_data.config_sema);
+       if (!adapter)
+               return 0;
+
+       mutex_lock(&zfcp_data.config_mutex);
 
        zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL);
        zfcp_erp_wait(adapter);
 
-       up(&zfcp_data.config_sema);
+       mutex_unlock(&zfcp_data.config_mutex);
 
        return 0;
 }
@@ -33,6 +36,9 @@ static int zfcp_ccw_activate(struct ccw_device *cdev)
 {
        struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
 
+       if (!adapter)
+               return 0;
+
        zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL,
                                       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
        zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -63,25 +69,14 @@ int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter)
  * zfcp_ccw_probe - probe function of zfcp driver
  * @ccw_device: pointer to belonging ccw device
  *
- * This function gets called by the common i/o layer and sets up the initial
- * data structures for each fcp adapter, which was detected by the system.
- * Also the sysfs files for this adapter will be created by this function.
- * In addition the nameserver port will be added to the ports of the adapter
- * and its sysfs representation will be created too.
+ * This function gets called by the common i/o layer for each FCP
+ * device found on the current system. This is only a stub to make cio
+ * work: To only allocate adapter resources for devices actually used,
+ * the allocation is deferred to the first call to ccw_set_online.
  */
 static int zfcp_ccw_probe(struct ccw_device *ccw_device)
 {
-       int retval = 0;
-
-       down(&zfcp_data.config_sema);
-       if (zfcp_adapter_enqueue(ccw_device)) {
-               dev_err(&ccw_device->dev,
-                       "Setting up data structures for the "
-                       "FCP adapter failed\n");
-               retval = -EINVAL;
-       }
-       up(&zfcp_data.config_sema);
-       return retval;
+       return 0;
 }
 
 /**
@@ -102,8 +97,11 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
        LIST_HEAD(port_remove_lh);
 
        ccw_device_set_offline(ccw_device);
-       down(&zfcp_data.config_sema);
+
+       mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&ccw_device->dev);
+       if (!adapter)
+               goto out;
 
        write_lock_irq(&zfcp_data.config_lock);
        list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
@@ -129,29 +127,41 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
        wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
        zfcp_adapter_dequeue(adapter);
 
-       up(&zfcp_data.config_sema);
+out:
+       mutex_unlock(&zfcp_data.config_mutex);
 }
 
 /**
  * zfcp_ccw_set_online - set_online function of zfcp driver
  * @ccw_device: pointer to belonging ccw device
  *
- * This function gets called by the common i/o layer and sets an adapter
- * into state online. Setting an fcp device online means that it will be
- * registered with the SCSI stack, that the QDIO queues will be set up
- * and that the adapter will be opened (asynchronously).
+ * This function gets called by the common i/o layer and sets an
+ * adapter into state online.  The first call will allocate all
+ * adapter resources that will be retained until the device is removed
+ * via zfcp_ccw_remove.
+ *
+ * Setting an fcp device online means that it will be registered with
+ * the SCSI stack, that the QDIO queues will be set up and that the
+ * adapter will be opened.
  */
 static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
 {
        struct zfcp_adapter *adapter;
-       int retval;
+       int ret = 0;
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&ccw_device->dev);
 
-       retval = zfcp_erp_thread_setup(adapter);
-       if (retval)
-               goto out;
+       if (!adapter) {
+               ret = zfcp_adapter_enqueue(ccw_device);
+               if (ret) {
+                       dev_err(&ccw_device->dev,
+                               "Setting up data structures for the "
+                               "FCP adapter failed\n");
+                       goto out;
+               }
+               adapter = dev_get_drvdata(&ccw_device->dev);
+       }
 
        /* initialize request counter */
        BUG_ON(!zfcp_reqlist_isempty(adapter));
@@ -162,13 +172,11 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
        zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
                                "ccsonl2", NULL);
        zfcp_erp_wait(adapter);
-       up(&zfcp_data.config_sema);
-       flush_work(&adapter->scan_work);
-       return 0;
-
- out:
-       up(&zfcp_data.config_sema);
-       return retval;
+out:
+       mutex_unlock(&zfcp_data.config_mutex);
+       if (!ret)
+               flush_work(&adapter->scan_work);
+       return ret;
 }
 
 /**
@@ -182,12 +190,15 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 {
        struct zfcp_adapter *adapter;
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&ccw_device->dev);
+       if (!adapter)
+               goto out;
+
        zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
        zfcp_erp_wait(adapter);
-       zfcp_erp_thread_kill(adapter);
-       up(&zfcp_data.config_sema);
+       mutex_unlock(&zfcp_data.config_mutex);
+out:
        return 0;
 }
 
@@ -240,11 +251,12 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev)
 {
        struct zfcp_adapter *adapter;
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        adapter = dev_get_drvdata(&cdev->dev);
        zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
        zfcp_erp_wait(adapter);
-       up(&zfcp_data.config_sema);
+       zfcp_erp_thread_kill(adapter);
+       mutex_unlock(&zfcp_data.config_mutex);
 }
 
 static struct ccw_driver zfcp_ccw_driver = {
index b99b87c..215b707 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Debug traces for zfcp.
  *
- * Copyright IBM Corporation 2002, 2008
+ * Copyright IBM Corporation 2002, 2009
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -11,6 +11,7 @@
 
 #include <linux/ctype.h>
 #include <asm/debug.h>
+#include "zfcp_dbf.h"
 #include "zfcp_ext.h"
 
 static u32 dbfsize = 4;
@@ -37,19 +38,6 @@ static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len,
        }
 }
 
-/* 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;
-
-       stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
-       sec = stck >> 12;
-       do_div(sec, 1000000);
-       time->tv_sec = sec;
-       stck -= (sec * 1000000) << 12;
-       time->tv_nsec = ((stck * 1000) >> 12);
-}
-
 static void zfcp_dbf_tag(char **p, const char *label, const char *tag)
 {
        int i;
@@ -106,7 +94,7 @@ static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view,
        char *p = out_buf;
 
        if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) {
-               zfcp_dbf_timestamp(entry->id.stck, &t);
+               stck_to_timespec(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);
@@ -119,13 +107,10 @@ static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view,
        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)
+void _zfcp_dbf_hba_fsf_response(const char *tag2, int level,
+                               struct zfcp_fsf_req *fsf_req,
+                               struct zfcp_dbf *dbf)
 {
-       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;
@@ -134,33 +119,14 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
        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->u.response;
-       int level;
+       struct zfcp_dbf_hba_record *rec = &dbf->hba_buf;
+       struct zfcp_dbf_hba_record_response *response = &rec->u.response;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->hba_lock, flags);
        memset(rec, 0, sizeof(*rec));
        strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE);
-
-       if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
-           (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
-               strncpy(rec->tag2, "perr", ZFCP_DBF_TAG_SIZE);
-               level = 1;
-       } else if (qtcb->header.fsf_status != FSF_GOOD) {
-               strncpy(rec->tag2, "ferr", ZFCP_DBF_TAG_SIZE);
-               level = 1;
-       } else if ((fsf_req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
-                  (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;
-       }
+       strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
 
        response->fsf_command = fsf_req->fsf_command;
        response->fsf_reqid = fsf_req->req_id;
@@ -173,9 +139,9 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
        memcpy(response->fsf_status_qual,
               fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE);
        response->fsf_req_status = fsf_req->status;
-       response->sbal_first = fsf_req->sbal_first;
-       response->sbal_last = fsf_req->sbal_last;
-       response->sbal_response = fsf_req->sbal_response;
+       response->sbal_first = fsf_req->queue_req.sbal_first;
+       response->sbal_last = fsf_req->queue_req.sbal_last;
+       response->sbal_response = fsf_req->queue_req.sbal_response;
        response->pool = fsf_req->pool != NULL;
        response->erp_action = (unsigned long)fsf_req->erp_action;
 
@@ -224,7 +190,7 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
                break;
        }
 
-       debug_event(adapter->hba_dbf, level, rec, sizeof(*rec));
+       debug_event(dbf->hba, level, rec, sizeof(*rec));
 
        /* have fcp channel microcode fixed to use as little as possible */
        if (fsf_req->fsf_command != FSF_QTCB_FCP_CMND) {
@@ -232,31 +198,25 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
                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);
+               zfcp_dbf_hexdump(dbf->hba, rec, sizeof(*rec), level, buf,
+                                len);
        }
 
-       spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+       spin_unlock_irqrestore(&dbf->hba_lock, flags);
 }
 
-/**
- * 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)
+void _zfcp_dbf_hba_fsf_unsol(const char *tag, int level, struct zfcp_dbf *dbf,
+                            struct fsf_status_read_buffer *status_buffer)
 {
-       struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+       struct zfcp_dbf_hba_record *rec = &dbf->hba_buf;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->hba_lock, flags);
        memset(rec, 0, sizeof(*rec));
        strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE);
        strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE);
 
-       rec->u.status.failed = atomic_read(&adapter->stat_miss);
+       rec->u.status.failed = atomic_read(&dbf->adapter->stat_miss);
        if (status_buffer != NULL) {
                rec->u.status.status_type = status_buffer->status_type;
                rec->u.status.status_subtype = status_buffer->status_subtype;
@@ -293,63 +253,61 @@ void zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
                       &status_buffer->payload, rec->u.status.payload_size);
        }
 
-       debug_event(adapter->hba_dbf, 2, rec, sizeof(*rec));
-       spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+       debug_event(dbf->hba, level, rec, sizeof(*rec));
+       spin_unlock_irqrestore(&dbf->hba_lock, flags);
 }
 
 /**
- * zfcp_hba_dbf_event_qdio - trace event for QDIO related failure
- * @adapter: adapter affected by this QDIO related event
+ * zfcp_dbf_hba_qdio - trace event for QDIO related failure
+ * @qdio: qdio structure affected by this QDIO related event
  * @qdio_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 qdio_error, int sbal_index,
-                            int sbal_count)
+void zfcp_dbf_hba_qdio(struct zfcp_dbf *dbf, unsigned int qdio_error,
+                      int sbal_index, int sbal_count)
 {
-       struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
+       struct zfcp_dbf_hba_record *r = &dbf->hba_buf;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->hba_lock, flags);
        memset(r, 0, sizeof(*r));
        strncpy(r->tag, "qdio", ZFCP_DBF_TAG_SIZE);
        r->u.qdio.qdio_error = qdio_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);
+       debug_event(dbf->hba, 0, r, sizeof(*r));
+       spin_unlock_irqrestore(&dbf->hba_lock, flags);
 }
 
 /**
- * zfcp_hba_dbf_event_berr - trace event for bit error threshold
- * @adapter: adapter affected by this QDIO related event
+ * zfcp_dbf_hba_berr - trace event for bit error threshold
+ * @dbf: dbf structure affected by this QDIO related event
  * @req: fsf request
  */
-void zfcp_hba_dbf_event_berr(struct zfcp_adapter *adapter,
-                            struct zfcp_fsf_req *req)
+void zfcp_dbf_hba_berr(struct zfcp_dbf *dbf, struct zfcp_fsf_req *req)
 {
-       struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
+       struct zfcp_dbf_hba_record *r = &dbf->hba_buf;
        struct fsf_status_read_buffer *sr_buf = req->data;
        struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->hba_lock, flags);
        memset(r, 0, sizeof(*r));
        strncpy(r->tag, "berr", ZFCP_DBF_TAG_SIZE);
        memcpy(&r->u.berr, err, sizeof(struct fsf_bit_error_payload));
-       debug_event(adapter->hba_dbf, 0, r, sizeof(*r));
-       spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+       debug_event(dbf->hba, 0, r, sizeof(*r));
+       spin_unlock_irqrestore(&dbf->hba_lock, flags);
 }
-static void zfcp_hba_dbf_view_response(char **p,
-                                      struct zfcp_hba_dbf_record_response *r)
+static void zfcp_dbf_hba_view_response(char **p,
+                                      struct zfcp_dbf_hba_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);
+       stck_to_timespec(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);
@@ -403,8 +361,8 @@ static void zfcp_hba_dbf_view_response(char **p,
        }
 }
 
-static void zfcp_hba_dbf_view_status(char **p,
-                                    struct zfcp_hba_dbf_record_status *r)
+static void zfcp_dbf_hba_view_status(char **p,
+                                    struct zfcp_dbf_hba_record_status *r)
 {
        zfcp_dbf_out(p, "failed", "0x%02x", r->failed);
        zfcp_dbf_out(p, "status_type", "0x%08x", r->status_type);
@@ -416,14 +374,14 @@ static void zfcp_hba_dbf_view_status(char **p,
                      r->payload_size);
 }
 
-static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r)
+static void zfcp_dbf_hba_view_qdio(char **p, struct zfcp_dbf_hba_record_qdio *r)
 {
        zfcp_dbf_out(p, "qdio_error", "0x%08x", r->qdio_error);
        zfcp_dbf_out(p, "sbal_index", "0x%02x", r->sbal_index);
        zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count);
 }
 
-static void zfcp_hba_dbf_view_berr(char **p, struct fsf_bit_error_payload *r)
+static void zfcp_dbf_hba_view_berr(char **p, struct fsf_bit_error_payload *r)
 {
        zfcp_dbf_out(p, "link_failures", "%d", r->link_failure_error_count);
        zfcp_dbf_out(p, "loss_of_sync_err", "%d", r->loss_of_sync_error_count);
@@ -447,10 +405,10 @@ static void zfcp_hba_dbf_view_berr(char **p, struct fsf_bit_error_payload *r)
                     r->current_transmit_b2b_credit);
 }
 
-static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
+static int zfcp_dbf_hba_view_format(debug_info_t *id, struct debug_view *view,
                                    char *out_buf, const char *in_buf)
 {
-       struct zfcp_hba_dbf_record *r = (struct zfcp_hba_dbf_record *)in_buf;
+       struct zfcp_dbf_hba_record *r = (struct zfcp_dbf_hba_record *)in_buf;
        char *p = out_buf;
 
        if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
@@ -461,45 +419,42 @@ static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
                zfcp_dbf_tag(&p, "tag2", r->tag2);
 
        if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
-               zfcp_hba_dbf_view_response(&p, &r->u.response);
+               zfcp_dbf_hba_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);
+               zfcp_dbf_hba_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);
+               zfcp_dbf_hba_view_qdio(&p, &r->u.qdio);
        else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0)
-               zfcp_hba_dbf_view_berr(&p, &r->u.berr);
+               zfcp_dbf_hba_view_berr(&p, &r->u.berr);
 
        if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) != 0)
                p += sprintf(p, "\n");
        return p - out_buf;
 }
 
-static struct debug_view zfcp_hba_dbf_view = {
-       "structured",
-       NULL,
-       &zfcp_dbf_view_header,
-       &zfcp_hba_dbf_view_format,
-       NULL,
-       NULL
+static struct debug_view zfcp_dbf_hba_view = {
+       .name = "structured",
+       .header_proc = zfcp_dbf_view_header,
+       .format_proc = zfcp_dbf_hba_view_format,
 };
 
-static const char *zfcp_rec_dbf_tags[] = {
+static const char *zfcp_dbf_rec_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 int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
+static int zfcp_dbf_rec_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;
+       struct zfcp_dbf_rec_record *r = (struct zfcp_dbf_rec_record *)_rec;
        char *p = buf;
        char hint[ZFCP_DBF_ID_SIZE + 1];
 
        memcpy(hint, r->id2, ZFCP_DBF_ID_SIZE);
        hint[ZFCP_DBF_ID_SIZE] = 0;
-       zfcp_dbf_outs(&p, "tag", zfcp_rec_dbf_tags[r->id]);
+       zfcp_dbf_outs(&p, "tag", zfcp_dbf_rec_tags[r->id]);
        zfcp_dbf_outs(&p, "hint", hint);
        switch (r->id) {
        case ZFCP_REC_DBF_ID_THREAD:
@@ -537,24 +492,22 @@ static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
        return p - buf;
 }
 
-static struct debug_view zfcp_rec_dbf_view = {
-       "structured",
-       NULL,
-       &zfcp_dbf_view_header,
-       &zfcp_rec_dbf_view_format,
-       NULL,
-       NULL
+static struct debug_view zfcp_dbf_rec_view = {
+       .name = "structured",
+       .header_proc = zfcp_dbf_view_header,
+       .format_proc = zfcp_dbf_rec_view_format,
 };
 
 /**
- * zfcp_rec_dbf_event_thread - trace event related to recovery thread operation
+ * zfcp_dbf_rec_thread - trace event related to recovery thread operation
  * @id2: identifier for event
- * @adapter: adapter
+ * @dbf: reference to dbf structure
  * This function assumes that the caller is holding erp_lock.
  */
-void zfcp_rec_dbf_event_thread(char *id2, struct zfcp_adapter *adapter)
+void zfcp_dbf_rec_thread(char *id2, struct zfcp_dbf *dbf)
 {
-       struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+       struct zfcp_adapter *adapter = dbf->adapter;
+       struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
        unsigned long flags = 0;
        struct list_head *entry;
        unsigned ready = 0, running = 0, total;
@@ -565,41 +518,41 @@ void zfcp_rec_dbf_event_thread(char *id2, struct zfcp_adapter *adapter)
                running++;
        total = adapter->erp_total_count;
 
-       spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->rec_lock, flags);
        memset(r, 0, sizeof(*r));
        r->id = ZFCP_REC_DBF_ID_THREAD;
        memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
        r->u.thread.total = total;
        r->u.thread.ready = ready;
        r->u.thread.running = running;
-       debug_event(adapter->rec_dbf, 6, r, sizeof(*r));
-       spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+       debug_event(dbf->rec, 6, r, sizeof(*r));
+       spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
 
 /**
- * zfcp_rec_dbf_event_thread - trace event related to recovery thread operation
+ * zfcp_dbf_rec_thread - trace event related to recovery thread operation
  * @id2: identifier for event
  * @adapter: adapter
  * This function assumes that the caller does not hold erp_lock.
  */
-void zfcp_rec_dbf_event_thread_lock(char *id2, struct zfcp_adapter *adapter)
+void zfcp_dbf_rec_thread_lock(char *id2, struct zfcp_dbf *dbf)
 {
+       struct zfcp_adapter *adapter = dbf->adapter;
        unsigned long flags;
 
        read_lock_irqsave(&adapter->erp_lock, flags);
-       zfcp_rec_dbf_event_thread(id2, adapter);
+       zfcp_dbf_rec_thread(id2, dbf);
        read_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
-static void zfcp_rec_dbf_event_target(char *id2, void *ref,
-                                     struct zfcp_adapter *adapter,
-                                     atomic_t *status, atomic_t *erp_count,
-                                     u64 wwpn, u32 d_id, u64 fcp_lun)
+static void zfcp_dbf_rec_target(char *id2, void *ref, struct zfcp_dbf *dbf,
+                               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;
+       struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->rec_lock, flags);
        memset(r, 0, sizeof(*r));
        r->id = ZFCP_REC_DBF_ID_TARGET;
        memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
@@ -609,56 +562,57 @@ static void zfcp_rec_dbf_event_target(char *id2, void *ref,
        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);
+       debug_event(dbf->rec, 3, r, sizeof(*r));
+       spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
 
 /**
- * zfcp_rec_dbf_event_adapter - trace event for adapter state change
+ * zfcp_dbf_rec_adapter - trace event for adapter state change
  * @id: identifier for trigger of state change
  * @ref: additional reference (e.g. request)
- * @adapter: adapter
+ * @dbf: reference to dbf structure
  */
-void zfcp_rec_dbf_event_adapter(char *id, void *ref,
-                               struct zfcp_adapter *adapter)
+void zfcp_dbf_rec_adapter(char *id, void *ref, struct zfcp_dbf *dbf)
 {
-       zfcp_rec_dbf_event_target(id, ref, adapter, &adapter->status,
+       struct zfcp_adapter *adapter = dbf->adapter;
+
+       zfcp_dbf_rec_target(id, ref, dbf, &adapter->status,
                                  &adapter->erp_counter, 0, 0, 0);
 }
 
 /**
- * zfcp_rec_dbf_event_port - trace event for port state change
+ * zfcp_dbf_rec_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(char *id, void *ref, struct zfcp_port *port)
+void zfcp_dbf_rec_port(char *id, void *ref, struct zfcp_port *port)
 {
-       struct zfcp_adapter *adapter = port->adapter;
+       struct zfcp_dbf *dbf = port->adapter->dbf;
 
-       zfcp_rec_dbf_event_target(id, ref, adapter, &port->status,
+       zfcp_dbf_rec_target(id, ref, dbf, &port->status,
                                  &port->erp_counter, port->wwpn, port->d_id,
                                  0);
 }
 
 /**
- * zfcp_rec_dbf_event_unit - trace event for unit state change
+ * zfcp_dbf_rec_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(char *id, void *ref, struct zfcp_unit *unit)
+void zfcp_dbf_rec_unit(char *id, void *ref, struct zfcp_unit *unit)
 {
        struct zfcp_port *port = unit->port;
-       struct zfcp_adapter *adapter = port->adapter;
+       struct zfcp_dbf *dbf = port->adapter->dbf;
 
-       zfcp_rec_dbf_event_target(id, ref, adapter, &unit->status,
+       zfcp_dbf_rec_target(id, ref, dbf, &unit->status,
                                  &unit->erp_counter, port->wwpn, port->d_id,
                                  unit->fcp_lun);
 }
 
 /**
- * zfcp_rec_dbf_event_trigger - trace event for triggered error recovery
+ * zfcp_dbf_rec_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
@@ -668,14 +622,15 @@ void zfcp_rec_dbf_event_unit(char *id, void *ref, struct zfcp_unit *unit)
  * @port: port
  * @unit: unit
  */
-void zfcp_rec_dbf_event_trigger(char *id2, void *ref, u8 want, u8 need,
-                               void *action, struct zfcp_adapter *adapter,
-                               struct zfcp_port *port, struct zfcp_unit *unit)
+void zfcp_dbf_rec_trigger(char *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;
+       struct zfcp_dbf *dbf = adapter->dbf;
+       struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->rec_lock, flags);
        memset(r, 0, sizeof(*r));
        r->id = ZFCP_REC_DBF_ID_TRIGGER;
        memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
@@ -692,22 +647,22 @@ void zfcp_rec_dbf_event_trigger(char *id2, void *ref, u8 want, u8 need,
                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);
+       debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r));
+       spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
 
 /**
- * zfcp_rec_dbf_event_action - trace event showing progress of recovery action
+ * zfcp_dbf_rec_action - trace event showing progress of recovery action
  * @id2: identifier
  * @erp_action: error recovery action struct pointer
  */
-void zfcp_rec_dbf_event_action(char *id2, struct zfcp_erp_action *erp_action)
+void zfcp_dbf_rec_action(char *id2, struct zfcp_erp_action *erp_action)
 {
-       struct zfcp_adapter *adapter = erp_action->adapter;
-       struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+       struct zfcp_dbf *dbf = erp_action->adapter->dbf;
+       struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->rec_lock, flags);
        memset(r, 0, sizeof(*r));
        r->id = ZFCP_REC_DBF_ID_ACTION;
        memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE);
@@ -715,26 +670,27 @@ void zfcp_rec_dbf_event_action(char *id2, struct zfcp_erp_action *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, 5, r, sizeof(*r));
-       spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+       debug_event(dbf->rec, 5, r, sizeof(*r));
+       spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
 
 /**
- * zfcp_san_dbf_event_ct_request - trace event for issued CT request
+ * zfcp_dbf_san_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)
+void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
        struct zfcp_wka_port *wka_port = ct->wka_port;
        struct zfcp_adapter *adapter = wka_port->adapter;
+       struct zfcp_dbf *dbf = adapter->dbf;
        struct ct_hdr *hdr = sg_virt(ct->req);
-       struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
-       struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req;
+       struct zfcp_dbf_san_record *r = &dbf->san_buf;
+       struct zfcp_dbf_san_record_ct_request *oct = &r->u.ct_req;
        int level = 3;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->san_lock, flags);
        memset(r, 0, sizeof(*r));
        strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE);
        r->fsf_reqid = fsf_req->req_id;
@@ -749,28 +705,29 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
        oct->max_res_size = hdr->max_res_size;
        oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr),
                       ZFCP_DBF_SAN_MAX_PAYLOAD);
-       debug_event(adapter->san_dbf, level, r, sizeof(*r));
-       zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level,
+       debug_event(dbf->san, level, r, sizeof(*r));
+       zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level,
                         (void *)hdr + sizeof(struct ct_hdr), oct->len);
-       spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+       spin_unlock_irqrestore(&dbf->san_lock, flags);
 }
 
 /**
- * zfcp_san_dbf_event_ct_response - trace event for completion of CT request
+ * zfcp_dbf_san_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)
+void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
        struct zfcp_wka_port *wka_port = ct->wka_port;
        struct zfcp_adapter *adapter = wka_port->adapter;
        struct ct_hdr *hdr = sg_virt(ct->resp);
-       struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
-       struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp;
+       struct zfcp_dbf *dbf = adapter->dbf;
+       struct zfcp_dbf_san_record *r = &dbf->san_buf;
+       struct zfcp_dbf_san_record_ct_response *rct = &r->u.ct_resp;
        int level = 3;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->san_lock, flags);
        memset(r, 0, sizeof(*r));
        strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE);
        r->fsf_reqid = fsf_req->req_id;
@@ -785,22 +742,22 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
        rct->max_res_size = hdr->max_res_size;
        rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
                       ZFCP_DBF_SAN_MAX_PAYLOAD);
-       debug_event(adapter->san_dbf, level, r, sizeof(*r));
-       zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level,
+       debug_event(dbf->san, level, r, sizeof(*r));
+       zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level,
                         (void *)hdr + sizeof(struct ct_hdr), rct->len);
-       spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+       spin_unlock_irqrestore(&dbf->san_lock, flags);
 }
 
-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)
+static void zfcp_dbf_san_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 *dbf = adapter->dbf;
+       struct zfcp_dbf_san_record *rec = &dbf->san_buf;
        unsigned long flags;
 
-       spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->san_lock, flags);
        memset(rec, 0, sizeof(*rec));
        strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
        rec->fsf_reqid = fsf_req->req_id;
@@ -808,45 +765,45 @@ static void zfcp_san_dbf_event_els(const char *tag, int level,
        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,
+       debug_event(dbf->san, level, rec, sizeof(*rec));
+       zfcp_dbf_hexdump(dbf->san, rec, sizeof(*rec), level,
                         buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD));
-       spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+       spin_unlock_irqrestore(&dbf->san_lock, flags);
 }
 
 /**
- * zfcp_san_dbf_event_els_request - trace event for issued ELS
+ * zfcp_dbf_san_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)
+void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
 
-       zfcp_san_dbf_event_els("oels", 2, fsf_req,
+       zfcp_dbf_san_els("oels", 2, fsf_req,
                               fc_host_port_id(els->adapter->scsi_host),
                               els->d_id, *(u8 *) sg_virt(els->req),
                               sg_virt(els->req), els->req->length);
 }
 
 /**
- * zfcp_san_dbf_event_els_response - trace event for completed ELS
+ * zfcp_dbf_san_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)
+void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
 
-       zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id,
+       zfcp_dbf_san_els("rels", 2, fsf_req, els->d_id,
                               fc_host_port_id(els->adapter->scsi_host),
                               *(u8 *)sg_virt(els->req), sg_virt(els->resp),
                               els->resp->length);
 }
 
 /**
- * zfcp_san_dbf_event_incoming_els - trace event for incomig ELS
+ * zfcp_dbf_san_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)
+void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_adapter *adapter = fsf_req->adapter;
        struct fsf_status_read_buffer *buf =
@@ -854,16 +811,16 @@ void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
        int length = (int)buf->length -
                     (int)((void *)&buf->payload - (void *)buf);
 
-       zfcp_san_dbf_event_els("iels", 1, fsf_req, buf->d_id,
+       zfcp_dbf_san_els("iels", 1, fsf_req, buf->d_id,
                               fc_host_port_id(adapter->scsi_host),
                               buf->payload.data[0], (void *)buf->payload.data,
                               length);
 }
 
-static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
+static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view,
                                    char *out_buf, const char *in_buf)
 {
-       struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf;
+       struct zfcp_dbf_san_record *r = (struct zfcp_dbf_san_record *)in_buf;
        char *p = out_buf;
 
        if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
@@ -876,7 +833,7 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
        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;
+               struct zfcp_dbf_san_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);
@@ -884,7 +841,7 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
                zfcp_dbf_out(&p, "options", "0x%02x", ct->options);
                zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
        } else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
-               struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp;
+               struct zfcp_dbf_san_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);
@@ -894,35 +851,30 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
        } 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;
+               struct zfcp_dbf_san_record_els *els = &r->u.els;
                zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code);
        }
        return p - out_buf;
 }
 
-static struct debug_view zfcp_san_dbf_view = {
-       "structured",
-       NULL,
-       &zfcp_dbf_view_header,
-       &zfcp_san_dbf_view_format,
-       NULL,
-       NULL
+static struct debug_view zfcp_dbf_san_view = {
+       .name = "structured",
+       .header_proc = zfcp_dbf_view_header,
+       .format_proc = zfcp_dbf_san_view_format,
 };
 
-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)
+void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
+                   struct zfcp_dbf *dbf, 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_scsi_record *rec = &dbf->scsi_buf;
        struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
        unsigned long flags;
        struct fcp_rsp_iu *fcp_rsp;
        char *fcp_rsp_info = NULL, *fcp_sns_info = NULL;
        int offset = 0, buflen = 0;
 
-       spin_lock_irqsave(&adapter->scsi_dbf_lock, flags);
+       spin_lock_irqsave(&dbf->scsi_lock, flags);
        do {
                memset(rec, 0, sizeof(*rec));
                if (offset == 0) {
@@ -976,68 +928,20 @@ static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
                        dump->offset = offset;
                        dump->size = min(buflen - offset,
                                         (int)sizeof(struct
-                                                    zfcp_scsi_dbf_record) -
+                                                    zfcp_dbf_scsi_record) -
                                         (int)sizeof(struct zfcp_dbf_dump));
                        memcpy(dump->data, fcp_sns_info + offset, dump->size);
                        offset += dump->size;
                }
-               debug_event(adapter->scsi_dbf, level, rec, sizeof(*rec));
+               debug_event(dbf->scsi, level, rec, sizeof(*rec));
        } while (offset < buflen);
-       spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
-}
-
-/**
- * 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("rslt", tag, level, adapter, scsi_cmnd, fsf_req, 0);
+       spin_unlock_irqrestore(&dbf->scsi_lock, flags);
 }
 
-/**
- * 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("abrt", tag, 1, adapter, scsi_cmnd, new_fsf_req,
-                           old_req_id);
-}
-
-/**
- * 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)
-{
-       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,
+static int zfcp_dbf_scsi_view_format(debug_info_t *id, struct debug_view *view,
                                     char *out_buf, const char *in_buf)
 {
-       struct zfcp_scsi_dbf_record *r = (struct zfcp_scsi_dbf_record *)in_buf;
+       struct zfcp_dbf_scsi_record *r = (struct zfcp_dbf_scsi_record *)in_buf;
        struct timespec t;
        char *p = out_buf;
 
@@ -1059,7 +963,7 @@ static int zfcp_scsi_dbf_view_format(debug_info_t *id, struct debug_view *view,
                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);
+       stck_to_timespec(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) {
@@ -1078,84 +982,96 @@ static int zfcp_scsi_dbf_view_format(debug_info_t *id, struct debug_view *view,
        return p - out_buf;
 }
 
-static struct debug_view zfcp_scsi_dbf_view = {
-       "structured",
-       NULL,
-       &zfcp_dbf_view_header,
-       &zfcp_scsi_dbf_view_format,
-       NULL,
-       NULL
+static struct debug_view zfcp_dbf_scsi_view = {
+       .name = "structured",
+       .header_proc = zfcp_dbf_view_header,
+       .format_proc = zfcp_dbf_scsi_view_format,
 };
 
+static debug_info_t *zfcp_dbf_reg(const char *name, int level,
+                                 struct debug_view *view, int size)
+{
+       struct debug_info *d;
+
+       d = debug_register(name, dbfsize, level, size);
+       if (!d)
+               return NULL;
+
+       debug_register_view(d, &debug_hex_ascii_view);
+       debug_register_view(d, view);
+       debug_set_level(d, level);
+
+       return d;
+}
+
 /**
  * zfcp_adapter_debug_register - registers debug feature for an adapter
  * @adapter: pointer to adapter for which debug features should be registered
  * return: -ENOMEM on error, 0 otherwise
  */
-int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
+int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter)
 {
        char dbf_name[DEBUG_MAX_NAME_LEN];
+       struct zfcp_dbf *dbf;
+
+       dbf = kmalloc(sizeof(struct zfcp_dbf), GFP_KERNEL);
+       if (!dbf)
+               return -ENOMEM;
+
+       dbf->adapter = adapter;
+
+       spin_lock_init(&dbf->hba_lock);
+       spin_lock_init(&dbf->san_lock);
+       spin_lock_init(&dbf->scsi_lock);
+       spin_lock_init(&dbf->rec_lock);
 
        /* debug feature area which records recovery activity */
        sprintf(dbf_name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev));
-       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->rec_dbf, &debug_hex_ascii_view);
-       debug_register_view(adapter->rec_dbf, &zfcp_rec_dbf_view);
-       debug_set_level(adapter->rec_dbf, 3);
+       dbf->rec = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_rec_view,
+                               sizeof(struct zfcp_dbf_rec_record));
+       if (!dbf->rec)
+               goto err_out;
 
        /* debug feature area which records HBA (FSF and QDIO) conditions */
        sprintf(dbf_name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev));
-       adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1,
-                                         sizeof(struct zfcp_hba_dbf_record));
-       if (!adapter->hba_dbf)
-               goto failed;
-       debug_register_view(adapter->hba_dbf, &debug_hex_ascii_view);
-       debug_register_view(adapter->hba_dbf, &zfcp_hba_dbf_view);
-       debug_set_level(adapter->hba_dbf, 3);
+       dbf->hba = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_hba_view,
+                               sizeof(struct zfcp_dbf_hba_record));
+       if (!dbf->hba)
+               goto err_out;
 
        /* debug feature area which records SAN command failures and recovery */
        sprintf(dbf_name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev));
-       adapter->san_dbf = debug_register(dbf_name, dbfsize, 1,
-                                         sizeof(struct zfcp_san_dbf_record));
-       if (!adapter->san_dbf)
-               goto failed;
-       debug_register_view(adapter->san_dbf, &debug_hex_ascii_view);
-       debug_register_view(adapter->san_dbf, &zfcp_san_dbf_view);
-       debug_set_level(adapter->san_dbf, 6);
+       dbf->san = zfcp_dbf_reg(dbf_name, 6, &zfcp_dbf_san_view,
+                               sizeof(struct zfcp_dbf_san_record));
+       if (!dbf->san)
+               goto err_out;
 
        /* debug feature area which records SCSI command failures and recovery */
        sprintf(dbf_name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev));
-       adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1,
-                                          sizeof(struct zfcp_scsi_dbf_record));
-       if (!adapter->scsi_dbf)
-               goto failed;
-       debug_register_view(adapter->scsi_dbf, &debug_hex_ascii_view);
-       debug_register_view(adapter->scsi_dbf, &zfcp_scsi_dbf_view);
-       debug_set_level(adapter->scsi_dbf, 3);
+       dbf->scsi = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_scsi_view,
+                                sizeof(struct zfcp_dbf_scsi_record));
+       if (!dbf->scsi)
+               goto err_out;
 
+       adapter->dbf = dbf;
        return 0;
 
- failed:
-       zfcp_adapter_debug_unregister(adapter);
-
+err_out:
+       zfcp_dbf_adapter_unregister(dbf);
        return -ENOMEM;
 }
 
 /**
  * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter
- * @adapter: pointer to adapter for which debug features should be unregistered
+ * @dbf: pointer to dbf for which debug features should be unregistered
  */
-void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
+void zfcp_dbf_adapter_unregister(struct zfcp_dbf *dbf)
 {
-       debug_unregister(adapter->scsi_dbf);
-       debug_unregister(adapter->san_dbf);
-       debug_unregister(adapter->hba_dbf);
-       debug_unregister(adapter->rec_dbf);
-       adapter->scsi_dbf = NULL;
-       adapter->san_dbf = NULL;
-       adapter->hba_dbf = NULL;
-       adapter->rec_dbf = NULL;
+       debug_unregister(dbf->scsi);
+       debug_unregister(dbf->san);
+       debug_unregister(dbf->hba);
+       debug_unregister(dbf->rec);
+       dbf->adapter->dbf = NULL;
+       kfree(dbf);
 }
+
index a573f73..6b1461e 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the zfcp device driver for
  * FCP adapters for IBM System z9 and zSeries.
  *
- * Copyright IBM Corp. 2008, 2008
+ * Copyright IBM Corp. 2008, 2009
  *
  * 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
@@ -22,7 +22,9 @@
 #ifndef ZFCP_DBF_H
 #define ZFCP_DBF_H
 
+#include "zfcp_ext.h"
 #include "zfcp_fsf.h"
+#include "zfcp_def.h"
 
 #define ZFCP_DBF_TAG_SIZE      4
 #define ZFCP_DBF_ID_SIZE       7
@@ -35,13 +37,13 @@ struct zfcp_dbf_dump {
        u8 data[];              /* dump data */
 } __attribute__ ((packed));
 
-struct zfcp_rec_dbf_record_thread {
+struct zfcp_dbf_rec_record_thread {
        u32 total;
        u32 ready;
        u32 running;
 };
 
-struct zfcp_rec_dbf_record_target {
+struct zfcp_dbf_rec_record_target {
        u64 ref;
        u32 status;
        u32 d_id;
@@ -50,7 +52,7 @@ struct zfcp_rec_dbf_record_target {
        u32 erp_count;
 };
 
-struct zfcp_rec_dbf_record_trigger {
+struct zfcp_dbf_rec_record_trigger {
        u8 want;
        u8 need;
        u32 as;
@@ -62,21 +64,21 @@ struct zfcp_rec_dbf_record_trigger {
        u64 fcp_lun;
 };
 
-struct zfcp_rec_dbf_record_action {
+struct zfcp_dbf_rec_record_action {
        u32 status;
        u32 step;
        u64 action;
        u64 fsf_req;
 };
 
-struct zfcp_rec_dbf_record {
+struct zfcp_dbf_rec_record {
        u8 id;
        char id2[7];
        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;
+               struct zfcp_dbf_rec_record_action action;
+               struct zfcp_dbf_rec_record_thread thread;
+               struct zfcp_dbf_rec_record_target target;
+               struct zfcp_dbf_rec_record_trigger trigger;
        } u;
 };
 
@@ -87,7 +89,7 @@ enum {
        ZFCP_REC_DBF_ID_TRIGGER,
 };
 
-struct zfcp_hba_dbf_record_response {
+struct zfcp_dbf_hba_record_response {
        u32 fsf_command;
        u64 fsf_reqid;
        u32 fsf_seqno;
@@ -125,7 +127,7 @@ struct zfcp_hba_dbf_record_response {
        } u;
 } __attribute__ ((packed));
 
-struct zfcp_hba_dbf_record_status {
+struct zfcp_dbf_hba_record_status {
        u8 failed;
        u32 status_type;
        u32 status_subtype;
@@ -139,24 +141,24 @@ struct zfcp_hba_dbf_record_status {
        u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
 } __attribute__ ((packed));
 
-struct zfcp_hba_dbf_record_qdio {
+struct zfcp_dbf_hba_record_qdio {
        u32 qdio_error;
        u8 sbal_index;
        u8 sbal_count;
 } __attribute__ ((packed));
 
-struct zfcp_hba_dbf_record {
+struct zfcp_dbf_hba_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;
+               struct zfcp_dbf_hba_record_response response;
+               struct zfcp_dbf_hba_record_status status;
+               struct zfcp_dbf_hba_record_qdio qdio;
                struct fsf_bit_error_payload berr;
        } u;
 } __attribute__ ((packed));
 
-struct zfcp_san_dbf_record_ct_request {
+struct zfcp_dbf_san_record_ct_request {
        u16 cmd_req_code;
        u8 revision;
        u8 gs_type;
@@ -166,7 +168,7 @@ struct zfcp_san_dbf_record_ct_request {
        u32 len;
 } __attribute__ ((packed));
 
-struct zfcp_san_dbf_record_ct_response {
+struct zfcp_dbf_san_record_ct_response {
        u16 cmd_rsp_code;
        u8 revision;
        u8 reason_code;
@@ -176,27 +178,27 @@ struct zfcp_san_dbf_record_ct_response {
        u32 len;
 } __attribute__ ((packed));
 
-struct zfcp_san_dbf_record_els {
+struct zfcp_dbf_san_record_els {
        u8 ls_code;
        u32 len;
 } __attribute__ ((packed));
 
-struct zfcp_san_dbf_record {
+struct zfcp_dbf_san_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;
+               struct zfcp_dbf_san_record_ct_request ct_req;
+               struct zfcp_dbf_san_record_ct_response ct_resp;
+               struct zfcp_dbf_san_record_els els;
        } u;
 #define ZFCP_DBF_SAN_MAX_PAYLOAD 1024
        u8 payload[32];
 } __attribute__ ((packed));
 
-struct zfcp_scsi_dbf_record {
+struct zfcp_dbf_scsi_record {
        u8 tag[ZFCP_DBF_TAG_SIZE];
        u8 tag2[ZFCP_DBF_TAG_SIZE];
        u32 scsi_id;
@@ -222,4 +224,127 @@ struct zfcp_scsi_dbf_record {
        u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
 } __attribute__ ((packed));
 
+struct zfcp_dbf {
+       debug_info_t                    *rec;
+       debug_info_t                    *hba;
+       debug_info_t                    *san;
+       debug_info_t                    *scsi;
+       spinlock_t                      rec_lock;
+       spinlock_t                      hba_lock;
+       spinlock_t                      san_lock;
+       spinlock_t                      scsi_lock;
+       struct zfcp_dbf_rec_record      rec_buf;
+       struct zfcp_dbf_hba_record      hba_buf;
+       struct zfcp_dbf_san_record      san_buf;
+       struct zfcp_dbf_scsi_record     scsi_buf;
+       struct zfcp_adapter             *adapter;
+};
+
+static inline
+void zfcp_dbf_hba_fsf_resp(const char *tag2, int level,
+                          struct zfcp_fsf_req *req, struct zfcp_dbf *dbf)
+{
+       if (level <= dbf->hba->level)
+               _zfcp_dbf_hba_fsf_response(tag2, level, req, dbf);
+}
+
+/**
+ * zfcp_dbf_hba_fsf_response - trace event for request completion
+ * @fsf_req: request that has been completed
+ */
+static inline void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req)
+{
+       struct zfcp_dbf *dbf = req->adapter->dbf;
+       struct fsf_qtcb *qtcb = req->qtcb;
+
+       if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
+           (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
+               zfcp_dbf_hba_fsf_resp("perr", 1, req, dbf);
+
+       } else if (qtcb->header.fsf_status != FSF_GOOD) {
+               zfcp_dbf_hba_fsf_resp("ferr", 1, req, dbf);
+
+       } else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
+                  (req->fsf_command == FSF_QTCB_OPEN_LUN)) {
+               zfcp_dbf_hba_fsf_resp("open", 4, req, dbf);
+
+       } else if (qtcb->header.log_length) {
+               zfcp_dbf_hba_fsf_resp("qtcb", 5, req, dbf);
+
+       } else {
+               zfcp_dbf_hba_fsf_resp("norm", 6, req, dbf);
+       }
+ }
+
+/**
+ * zfcp_dbf_hba_fsf_unsol - trace event for an unsolicited status buffer
+ * @tag: tag indicating which kind of unsolicited status has been received
+ * @dbf: reference to dbf structure
+ * @status_buffer: buffer containing payload of unsolicited status
+ */
+static inline
+void zfcp_dbf_hba_fsf_unsol(const char *tag, struct zfcp_dbf *dbf,
+                           struct fsf_status_read_buffer *buf)
+{
+       int level = 2;
+
+       if (level <= dbf->hba->level)
+               _zfcp_dbf_hba_fsf_unsol(tag, level, dbf, buf);
+}
+
+static inline
+void zfcp_dbf_scsi(const char *tag, const char *tag2, int level,
+                  struct zfcp_dbf *dbf, struct scsi_cmnd *scmd,
+                  struct zfcp_fsf_req *req, unsigned long old_id)
+{
+       if (level <= dbf->scsi->level)
+               _zfcp_dbf_scsi(tag, tag2, level, dbf, scmd, req, old_id);
+}
+
+/**
+ * zfcp_dbf_scsi_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
+ * @scmd: SCSI command pointer
+ * @fsf_req: request used to issue SCSI command (might be NULL)
+ */
+static inline
+void zfcp_dbf_scsi_result(const char *tag, int level, struct zfcp_dbf *dbf,
+                         struct scsi_cmnd *scmd, struct zfcp_fsf_req *fsf_req)
+{
+       zfcp_dbf_scsi("rslt", tag, level, dbf, scmd, fsf_req, 0);
+}
+
+/**
+ * zfcp_dbf_scsi_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
+ * @scmd: SCSI command to be aborted
+ * @new_req: request containing abort (might be NULL)
+ * @old_id: identifier of request containg SCSI command to be aborted
+ */
+static inline
+void zfcp_dbf_scsi_abort(const char *tag, struct zfcp_dbf *dbf,
+                        struct scsi_cmnd *scmd, struct zfcp_fsf_req *new_req,
+                        unsigned long old_id)
+{
+       zfcp_dbf_scsi("abrt", tag, 1, dbf, scmd, new_req, old_id);
+}
+
+/**
+ * zfcp_dbf_scsi_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
+ */
+static inline
+void zfcp_dbf_scsi_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
+                           struct scsi_cmnd *scsi_cmnd)
+{
+       zfcp_dbf_scsi(flag == FCP_TARGET_RESET ? "trst" : "lrst", tag, 1,
+                           unit->port->adapter->dbf, scsi_cmnd, NULL, 0);
+}
+
 #endif /* ZFCP_DBF_H */
index 49d0532..7da2fad 100644 (file)
 #include <asm/debug.h>
 #include <asm/ebcdic.h>
 #include <asm/sysinfo.h>
-#include "zfcp_dbf.h"
 #include "zfcp_fsf.h"
 
-
 /********************* GENERAL DEFINES *********************************/
 
 #define REQUEST_LIST_SIZE 128
@@ -75,9 +73,6 @@
 
 /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
 
-/* timeout for name-server lookup (in seconds) */
-#define ZFCP_NS_GID_PN_TIMEOUT         10
-
 /* task attribute values in FCP-2 FCP_CMND IU */
 #define SIMPLE_Q       0
 #define HEAD_OF_Q      1
@@ -224,8 +219,6 @@ struct zfcp_ls_adisc {
 #define ZFCP_STATUS_ADAPTER_QDIOUP             0x00000002
 #define ZFCP_STATUS_ADAPTER_XCONFIG_OK         0x00000008
 #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT      0x00000010
-#define ZFCP_STATUS_ADAPTER_ERP_THREAD_UP      0x00000020
-#define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL    0x00000080
 #define ZFCP_STATUS_ADAPTER_ERP_PENDING                0x00000100
 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED     0x00000200
 
@@ -234,6 +227,7 @@ struct zfcp_ls_adisc {
 
 /* remote port status */
 #define ZFCP_STATUS_PORT_PHYS_OPEN             0x00000001
+#define ZFCP_STATUS_PORT_LINK_TEST             0x00000002
 
 /* well known address (WKA) port status*/
 enum zfcp_wka_status {
@@ -249,7 +243,6 @@ enum zfcp_wka_status {
 
 /* FSF request status (this does not have a common part) */
 #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT     0x00000002
-#define ZFCP_STATUS_FSFREQ_COMPLETED           0x00000004
 #define ZFCP_STATUS_FSFREQ_ERROR               0x00000008
 #define ZFCP_STATUS_FSFREQ_CLEANUP             0x00000010
 #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED      0x00000040
@@ -266,12 +259,14 @@ struct zfcp_fsf_req;
 
 /* holds various memory pools of an adapter */
 struct zfcp_adapter_mempool {
-       mempool_t *fsf_req_erp;
-       mempool_t *fsf_req_scsi;
-       mempool_t *fsf_req_abort;
-       mempool_t *fsf_req_status_read;
-       mempool_t *data_status_read;
-       mempool_t *data_gid_pn;
+       mempool_t *erp_req;
+       mempool_t *gid_pn_req;
+       mempool_t *scsi_req;
+       mempool_t *scsi_abort;
+       mempool_t *status_read_req;
+       mempool_t *status_read_data;
+       mempool_t *gid_pn_data;
+       mempool_t *qtcb_pool;
 };
 
 /*
@@ -305,6 +300,15 @@ struct ct_iu_gid_pn_resp {
        u32 d_id;
 } __attribute__ ((packed));
 
+struct ct_iu_gpn_ft_req {
+       struct ct_hdr header;
+       u8 flags;
+       u8 domain_id_scope;
+       u8 area_id_scope;
+       u8 fc4_type;
+} __attribute__ ((packed));
+
+
 /**
  * struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct
  * @wka_port: port where the request is sent to
@@ -312,7 +316,6 @@ struct ct_iu_gid_pn_resp {
  * @resp: scatter-gather list for response
  * @handler: handler function (called for response to the request)
  * @handler_data: data passed to handler function
- * @timeout: FSF timeout for this request
  * @completion: completion for synchronization purposes
  * @status: used to pass error status to calling function
  */
@@ -322,7 +325,6 @@ struct zfcp_send_ct {
        struct scatterlist *resp;
        void (*handler)(unsigned long);
        unsigned long handler_data;
-       int timeout;
        struct completion *completion;
        int status;
 };
@@ -420,6 +422,29 @@ struct zfcp_latencies {
        spinlock_t lock;
 };
 
+/** struct zfcp_qdio - basic QDIO data structure
+ * @resp_q: response queue
+ * @req_q: request queue
+ * @stat_lock: lock to protect req_q_util and req_q_time
+ * @req_q_lock; lock to serialize access to request queue
+ * @req_q_time: time of last fill level change
+ * @req_q_util: used for accounting
+ * @req_q_full: queue full incidents
+ * @req_q_wq: used to wait for SBAL availability
+ * @adapter: adapter used in conjunction with this QDIO structure
+ */
+struct zfcp_qdio {
+       struct zfcp_qdio_queue  resp_q;
+       struct zfcp_qdio_queue  req_q;
+       spinlock_t              stat_lock;
+       spinlock_t              req_q_lock;
+       unsigned long long      req_q_time;
+       u64                     req_q_util;
+       atomic_t                req_q_full;
+       wait_queue_head_t       req_q_wq;
+       struct zfcp_adapter     *adapter;
+};
+
 struct zfcp_adapter {
        atomic_t                refcount;          /* reference count */
        wait_queue_head_t       remove_wq;         /* can be used to wait for
@@ -428,6 +453,7 @@ struct zfcp_adapter {
        u64                     peer_wwpn;         /* P2P peer WWPN */
        u32                     peer_d_id;         /* P2P peer D_ID */
        struct ccw_device       *ccw_device;       /* S/390 ccw device */
+       struct zfcp_qdio        *qdio;
        u32                     hydra_version;     /* Hydra version */
        u32                     fsf_lic_version;
        u32                     adapter_features;  /* FCP channel features */
@@ -439,15 +465,7 @@ struct zfcp_adapter {
        unsigned long           req_no;            /* unique FSF req number */
        struct list_head        *req_list;         /* list of pending reqs */
        spinlock_t              req_list_lock;     /* request list lock */
-       struct zfcp_qdio_queue  req_q;             /* request queue */
-       spinlock_t              req_q_lock;        /* for operations on queue */
-       ktime_t                 req_q_time; /* time of last fill level change */
-       u64                     req_q_util; /* for accounting */
-       spinlock_t              qdio_stat_lock;
        u32                     fsf_req_seq_no;    /* FSF cmnd seq number */
-       wait_queue_head_t       request_wq;        /* can be used to wait for
-                                                     more avaliable SBALs */
-       struct zfcp_qdio_queue  resp_q;    /* response queue */
        rwlock_t                abort_lock;        /* Protects against SCSI
                                                      stack abort/command
                                                      completion races */
@@ -456,10 +474,9 @@ struct zfcp_adapter {
        atomic_t                status;            /* status of this adapter */
        struct list_head        erp_ready_head;    /* error recovery for this
                                                      adapter/devices */
+       wait_queue_head_t       erp_ready_wq;
        struct list_head        erp_running_head;
        rwlock_t                erp_lock;
-       struct semaphore        erp_ready_sem;
-       wait_queue_head_t       erp_thread_wqh;
        wait_queue_head_t       erp_done_wqh;
        struct zfcp_erp_action  erp_action;        /* pending error recovery */
         atomic_t                erp_counter;
@@ -467,27 +484,16 @@ struct zfcp_adapter {
                                                      actions */
        u32                     erp_low_mem_count; /* nr of erp actions waiting
                                                      for memory */
+       struct task_struct      *erp_thread;
        struct zfcp_wka_ports   *gs;               /* generic services */
-       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              rec_dbf_lock;
-       spinlock_t              hba_dbf_lock;
-       spinlock_t              san_dbf_lock;
-       spinlock_t              scsi_dbf_lock;
-       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;
+       struct zfcp_dbf         *dbf;              /* debug traces */
        struct zfcp_adapter_mempool     pool;      /* Adapter memory pools */
-       struct qdio_initialize  qdio_init_data;    /* for qdio_establish */
        struct fc_host_statistics *fc_stats;
        struct fsf_qtcb_bottom_port *stats_reset_data;
        unsigned long           stats_reset;
        struct work_struct      scan_work;
        struct service_level    service_level;
-       atomic_t                qdio_outb_full;    /* queue full incidents */
+       struct workqueue_struct *work_queue;
 };
 
 struct zfcp_port {
@@ -531,36 +537,64 @@ struct zfcp_unit {
        struct work_struct      scsi_work;
 };
 
-/* FSF request */
+/**
+ * struct zfcp_queue_req - queue related values for a request
+ * @sbal_number: number of free SBALs
+ * @sbal_first: first SBAL for this request
+ * @sbal_last: last SBAL for this request
+ * @sbal_limit: last possible SBAL for this request
+ * @sbale_curr: current SBALE at creation of this request
+ * @sbal_response: SBAL used in interrupt
+ * @qdio_outb_usage: usage of outbound queue
+ * @qdio_inb_usage: usage of inbound queue
+ */
+struct zfcp_queue_req {
+       u8                     sbal_number;
+       u8                     sbal_first;
+       u8                     sbal_last;
+       u8                     sbal_limit;
+       u8                     sbale_curr;
+       u8                     sbal_response;
+       u16                    qdio_outb_usage;
+       u16                    qdio_inb_usage;
+};
+
+/**
+ * struct zfcp_fsf_req - basic FSF request structure
+ * @list: list of FSF requests
+ * @req_id: unique request ID
+ * @adapter: adapter this request belongs to
+ * @queue_req: queue related values
+ * @completion: used to signal the completion of the request
+ * @status: status of the request
+ * @fsf_command: FSF command issued
+ * @qtcb: associated QTCB
+ * @seq_no: sequence number of this request
+ * @data: private data
+ * @timer: timer data of this request
+ * @erp_action: reference to erp action if request issued on behalf of ERP
+ * @pool: reference to memory pool if used for this request
+ * @issued: time when request was send (STCK)
+ * @unit: reference to unit if this request is a SCSI request
+ * @handler: handler which should be called to process response
+ */
 struct zfcp_fsf_req {
-       struct list_head       list;           /* list of FSF requests */
-       unsigned long          req_id;         /* unique request ID */
-       struct zfcp_adapter    *adapter;       /* adapter request belongs to */
-       u8                     sbal_number;    /* nr of SBALs free for use */
-       u8                     sbal_first;     /* first SBAL for this request */
-       u8                     sbal_last;      /* last SBAL for this request */
-       u8                     sbal_limit;      /* last possible SBAL for
-                                                 this reuest */
-       u8                     sbale_curr;     /* current SBALE during creation
-                                                 of request */
-       u8                      sbal_response;  /* SBAL used in interrupt */
-       wait_queue_head_t      completion_wq;  /* can be used by a routine
-                                                 to wait for completion */
-       u32                     status;        /* status of this request */
-       u32                    fsf_command;    /* FSF Command copy */
-       struct fsf_qtcb        *qtcb;          /* address of associated QTCB */
-       u32                    seq_no;         /* Sequence number of request */
-       void                    *data;           /* private data of request */
-       struct timer_list     timer;           /* used for erp or scsi er */
-       struct zfcp_erp_action *erp_action;    /* used if this request is
-                                                 issued on behalf of erp */
-       mempool_t              *pool;          /* used if request was alloacted
-                                                 from emergency pool */
-       unsigned long long     issued;         /* request sent time (STCK) */
-       struct zfcp_unit       *unit;
+       struct list_head        list;
+       unsigned long           req_id;
+       struct zfcp_adapter     *adapter;
+       struct zfcp_queue_req   queue_req;
+       struct completion       completion;
+       u32                     status;
+       u32                     fsf_command;
+       struct fsf_qtcb         *qtcb;
+       u32                     seq_no;
+       void                    *data;
+       struct timer_list       timer;
+       struct zfcp_erp_action  *erp_action;
+       mempool_t               *pool;
+       unsigned long long      issued;
+       struct zfcp_unit        *unit;
        void                    (*handler)(struct zfcp_fsf_req *);
-       u16                     qdio_outb_usage;/* usage of outbound queue */
-       u16                     qdio_inb_usage; /* usage of inbound queue */
 };
 
 /* driver data */
@@ -570,18 +604,11 @@ struct zfcp_data {
        rwlock_t                config_lock;        /* serialises changes
                                                       to adapter/port/unit
                                                       lists */
-       struct semaphore        config_sema;        /* serialises configuration
-                                                      changes */
-       struct kmem_cache       *fsf_req_qtcb_cache;
+       struct mutex            config_mutex;
+       struct kmem_cache       *gpn_ft_cache;
+       struct kmem_cache       *qtcb_cache;
        struct kmem_cache       *sr_buffer_cache;
        struct kmem_cache       *gid_pn_cache;
-       struct workqueue_struct *work_queue;
-};
-
-/* struct used by memory pools for fsf_requests */
-struct zfcp_fsf_req_qtcb {
-       struct zfcp_fsf_req fsf_req;
-       struct fsf_qtcb qtcb;
 };
 
 /********************** ZFCP SPECIFIC DEFINES ********************************/
index c75d6f3..73d366b 100644 (file)
@@ -9,6 +9,7 @@
 #define KMSG_COMPONENT "zfcp"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/kthread.h>
 #include "zfcp_ext.h"
 
 #define ZFCP_MAX_ERPS                   3
@@ -26,7 +27,6 @@ enum zfcp_erp_steps {
        ZFCP_ERP_STEP_FSF_XCONFIG       = 0x0001,
        ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
        ZFCP_ERP_STEP_PORT_CLOSING      = 0x0100,
-       ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400,
        ZFCP_ERP_STEP_PORT_OPENING      = 0x0800,
        ZFCP_ERP_STEP_UNIT_CLOSING      = 0x1000,
        ZFCP_ERP_STEP_UNIT_OPENING      = 0x2000,
@@ -75,9 +75,9 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act)
        struct zfcp_adapter *adapter = act->adapter;
 
        list_move(&act->list, &act->adapter->erp_ready_head);
-       zfcp_rec_dbf_event_action("erardy1", act);
-       up(&adapter->erp_ready_sem);
-       zfcp_rec_dbf_event_thread("erardy2", adapter);
+       zfcp_dbf_rec_action("erardy1", act);
+       wake_up(&adapter->erp_ready_wq);
+       zfcp_dbf_rec_thread("erardy2", adapter->dbf);
 }
 
 static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
@@ -150,6 +150,9 @@ static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
                a_status = atomic_read(&adapter->status);
                if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE)
                        return 0;
+               if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) &&
+                   !(a_status & ZFCP_STATUS_COMMON_OPEN))
+                       return 0; /* shutdown requested for closed adapter */
        }
 
        return need;
@@ -213,8 +216,7 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
        int retval = 1, need;
        struct zfcp_erp_action *act = NULL;
 
-       if (!(atomic_read(&adapter->status) &
-             ZFCP_STATUS_ADAPTER_ERP_THREAD_UP))
+       if (!adapter->erp_thread)
                return -EIO;
 
        need = zfcp_erp_required_act(want, adapter, port, unit);
@@ -227,12 +229,11 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
                goto out;
        ++adapter->erp_total_count;
        list_add_tail(&act->list, &adapter->erp_ready_head);
-       up(&adapter->erp_ready_sem);
-       zfcp_rec_dbf_event_thread("eracte1", adapter);
+       wake_up(&adapter->erp_ready_wq);
+       zfcp_dbf_rec_thread("eracte1", adapter->dbf);
        retval = 0;
  out:
-       zfcp_rec_dbf_event_trigger(id, ref, want, need, act,
-                                  adapter, port, unit);
+       zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit);
        return retval;
 }
 
@@ -443,28 +444,28 @@ static int status_change_clear(unsigned long mask, atomic_t *status)
 static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
 {
        if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
-               zfcp_rec_dbf_event_adapter("eraubl1", NULL, adapter);
+               zfcp_dbf_rec_adapter("eraubl1", NULL, adapter->dbf);
        atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
 }
 
 static void zfcp_erp_port_unblock(struct zfcp_port *port)
 {
        if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
-               zfcp_rec_dbf_event_port("erpubl1", NULL, port);
+               zfcp_dbf_rec_port("erpubl1", NULL, port);
        atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
 }
 
 static void zfcp_erp_unit_unblock(struct zfcp_unit *unit)
 {
        if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))
-               zfcp_rec_dbf_event_unit("eruubl1", NULL, unit);
+               zfcp_dbf_rec_unit("eruubl1", NULL, unit);
        atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
 }
 
 static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
 {
        list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
-       zfcp_rec_dbf_event_action("erator1", erp_action);
+       zfcp_dbf_rec_action("erator1", erp_action);
 }
 
 static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
@@ -480,13 +481,12 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act)
                if (act->status & (ZFCP_STATUS_ERP_DISMISSED |
                                   ZFCP_STATUS_ERP_TIMEDOUT)) {
                        act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
-                       zfcp_rec_dbf_event_action("erscf_1", act);
+                       zfcp_dbf_rec_action("erscf_1", act);
                        act->fsf_req->erp_action = NULL;
                }
                if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
-                       zfcp_rec_dbf_event_action("erscf_2", act);
-               if (act->fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED |
-                                           ZFCP_STATUS_FSFREQ_DISMISSED))
+                       zfcp_dbf_rec_action("erscf_2", act);
+               if (act->fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
                        act->fsf_req = NULL;
        } else
                act->fsf_req = NULL;
@@ -604,9 +604,11 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
 
 static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act)
 {
-       if (zfcp_qdio_open(act->adapter))
+       struct zfcp_qdio *qdio = act->adapter->qdio;
+
+       if (zfcp_qdio_open(qdio))
                return ZFCP_ERP_FAILED;
-       init_waitqueue_head(&act->adapter->request_wq);
+       init_waitqueue_head(&qdio->req_q_wq);
        atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status);
        return ZFCP_ERP_SUCCEEDED;
 }
@@ -641,9 +643,10 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action)
                        return ZFCP_ERP_FAILED;
                }
 
-               zfcp_rec_dbf_event_thread_lock("erasfx1", adapter);
-               down(&adapter->erp_ready_sem);
-               zfcp_rec_dbf_event_thread_lock("erasfx2", adapter);
+               zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf);
+               wait_event(adapter->erp_ready_wq,
+                          !list_empty(&adapter->erp_ready_head));
+               zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf);
                if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT)
                        break;
 
@@ -682,9 +685,10 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
        if (ret)
                return ZFCP_ERP_FAILED;
 
-       zfcp_rec_dbf_event_thread_lock("erasox1", adapter);
-       down(&adapter->erp_ready_sem);
-       zfcp_rec_dbf_event_thread_lock("erasox2", adapter);
+       zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf);
+       wait_event(adapter->erp_ready_wq,
+                  !list_empty(&adapter->erp_ready_head));
+       zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf);
        if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
                return ZFCP_ERP_FAILED;
 
@@ -711,10 +715,10 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act)
        struct zfcp_adapter *adapter = act->adapter;
 
        /* close queues to ensure that buffers are not accessed by adapter */
-       zfcp_qdio_close(adapter);
+       zfcp_qdio_close(adapter->qdio);
        zfcp_fsf_req_dismiss_all(adapter);
        adapter->fsf_req_seq_no = 0;
-       zfcp_fc_wka_port_force_offline(&adapter->gs->ds);
+       zfcp_fc_wka_ports_force_offline(adapter->gs);
        /* all ports and units are closed */
        zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
                                       ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
@@ -841,27 +845,6 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
        return zfcp_erp_port_strategy_open_port(act);
 }
 
-void zfcp_erp_port_strategy_open_lookup(struct work_struct *work)
-{
-       int retval;
-       struct zfcp_port *port = container_of(work, struct zfcp_port,
-                                             gid_pn_work);
-
-       retval = zfcp_fc_ns_gid_pn(&port->erp_action);
-       if (!retval) {
-               port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
-               goto out;
-       }
-       if (retval == -ENOMEM) {
-               zfcp_erp_notify(&port->erp_action, ZFCP_STATUS_ERP_LOWMEM);
-               goto out;
-       }
-       /* all other error condtions */
-       zfcp_erp_notify(&port->erp_action, 0);
-out:
-       zfcp_port_put(port);
-}
-
 static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
 {
        struct zfcp_adapter *adapter = act->adapter;
@@ -876,15 +859,11 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
                        return zfcp_erp_open_ptp_port(act);
                if (!port->d_id) {
                        zfcp_port_get(port);
-                       if (!queue_work(zfcp_data.work_queue,
+                       if (!queue_work(adapter->work_queue,
                                        &port->gid_pn_work))
                                zfcp_port_put(port);
-                       return ZFCP_ERP_CONTINUES;
+                       return ZFCP_ERP_EXIT;
                }
-               /* fall through */
-       case ZFCP_ERP_STEP_NAMESERVER_LOOKUP:
-               if (!port->d_id)
-                       return ZFCP_ERP_FAILED;
                return zfcp_erp_port_strategy_open_port(act);
 
        case ZFCP_ERP_STEP_PORT_OPENING:
@@ -1163,7 +1142,7 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
        }
 
        list_del(&erp_action->list);
-       zfcp_rec_dbf_event_action("eractd1", erp_action);
+       zfcp_dbf_rec_action("eractd1", erp_action);
 
        switch (erp_action->action) {
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
@@ -1311,20 +1290,16 @@ static int zfcp_erp_thread(void *data)
        struct list_head *next;
        struct zfcp_erp_action *act;
        unsigned long flags;
-       int ignore;
-
-       daemonize("zfcperp%s", dev_name(&adapter->ccw_device->dev));
-       /* Block all signals */
-       siginitsetinv(&current->blocked, 0);
-       atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
-       wake_up(&adapter->erp_thread_wqh);
 
-       while (!(atomic_read(&adapter->status) &
-                ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) {
+       for (;;) {
+               zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf);
+               wait_event_interruptible(adapter->erp_ready_wq,
+                          !list_empty(&adapter->erp_ready_head) ||
+                          kthread_should_stop());
+               zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf);
 
-               zfcp_rec_dbf_event_thread_lock("erthrd1", adapter);
-               ignore = down_interruptible(&adapter->erp_ready_sem);
-               zfcp_rec_dbf_event_thread_lock("erthrd2", adapter);
+               if (kthread_should_stop())
+                       break;
 
                write_lock_irqsave(&adapter->erp_lock, flags);
                next = adapter->erp_ready_head.next;
@@ -1339,9 +1314,6 @@ static int zfcp_erp_thread(void *data)
                }
        }
 
-       atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
-       wake_up(&adapter->erp_thread_wqh);
-
        return 0;
 }
 
@@ -1353,18 +1325,17 @@ static int zfcp_erp_thread(void *data)
  */
 int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
 {
-       int retval;
+       struct task_struct *thread;
 
-       atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
-       retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
-       if (retval < 0) {
+       thread = kthread_run(zfcp_erp_thread, adapter, "zfcperp%s",
+                            dev_name(&adapter->ccw_device->dev));
+       if (IS_ERR(thread)) {
                dev_err(&adapter->ccw_device->dev,
                        "Creating an ERP thread for the FCP device failed.\n");
-               return retval;
+               return PTR_ERR(thread);
        }
-       wait_event(adapter->erp_thread_wqh,
-                  atomic_read(&adapter->status) &
-                       ZFCP_STATUS_ADAPTER_ERP_THREAD_UP);
+
+       adapter->erp_thread = thread;
        return 0;
 }
 
@@ -1379,16 +1350,10 @@ int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
  */
 void 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_lock("erthrk1", adapter);
-
-       wait_event(adapter->erp_thread_wqh,
-                  !(atomic_read(&adapter->status) &
-                               ZFCP_STATUS_ADAPTER_ERP_THREAD_UP));
-
-       atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
-                         &adapter->status);
+       kthread_stop(adapter->erp_thread);
+       adapter->erp_thread = NULL;
+       WARN_ON(!list_empty(&adapter->erp_ready_head));
+       WARN_ON(!list_empty(&adapter->erp_running_head));
 }
 
 /**
@@ -1456,11 +1421,11 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
 
        if (set_or_clear == ZFCP_SET) {
                if (status_change_set(mask, &adapter->status))
-                       zfcp_rec_dbf_event_adapter(id, ref, adapter);
+                       zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
                atomic_set_mask(mask, &adapter->status);
        } else {
                if (status_change_clear(mask, &adapter->status))
-                       zfcp_rec_dbf_event_adapter(id, ref, adapter);
+                       zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
                atomic_clear_mask(mask, &adapter->status);
                if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
                        atomic_set(&adapter->erp_counter, 0);
@@ -1490,11 +1455,11 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
 
        if (set_or_clear == ZFCP_SET) {
                if (status_change_set(mask, &port->status))
-                       zfcp_rec_dbf_event_port(id, ref, port);
+                       zfcp_dbf_rec_port(id, ref, port);
                atomic_set_mask(mask, &port->status);
        } else {
                if (status_change_clear(mask, &port->status))
-                       zfcp_rec_dbf_event_port(id, ref, port);
+                       zfcp_dbf_rec_port(id, ref, port);
                atomic_clear_mask(mask, &port->status);
                if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
                        atomic_set(&port->erp_counter, 0);
@@ -1519,11 +1484,11 @@ void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref,
 {
        if (set_or_clear == ZFCP_SET) {
                if (status_change_set(mask, &unit->status))
-                       zfcp_rec_dbf_event_unit(id, ref, unit);
+                       zfcp_dbf_rec_unit(id, ref, unit);
                atomic_set_mask(mask, &unit->status);
        } else {
                if (status_change_clear(mask, &unit->status))
-                       zfcp_rec_dbf_event_unit(id, ref, unit);
+                       zfcp_dbf_rec_unit(id, ref, unit);
                atomic_clear_mask(mask, &unit->status);
                if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
                        atomic_set(&unit->erp_counter, 0);
index 3044c60..36935bc 100644 (file)
@@ -34,37 +34,31 @@ extern struct zfcp_adapter *zfcp_get_adapter_by_busid(char *);
 extern struct miscdevice zfcp_cfdc_misc;
 
 /* zfcp_dbf.c */
-extern int zfcp_adapter_debug_register(struct zfcp_adapter *);
-extern void zfcp_adapter_debug_unregister(struct zfcp_adapter *);
-extern void zfcp_rec_dbf_event_thread(char *, struct zfcp_adapter *);
-extern void zfcp_rec_dbf_event_thread_lock(char *, struct zfcp_adapter *);
-extern void zfcp_rec_dbf_event_adapter(char *, void *, struct zfcp_adapter *);
-extern void zfcp_rec_dbf_event_port(char *, void *, struct zfcp_port *);
-extern void zfcp_rec_dbf_event_unit(char *, void *, struct zfcp_unit *);
-extern void zfcp_rec_dbf_event_trigger(char *, void *, u8, u8, void *,
-                                      struct zfcp_adapter *,
-                                      struct zfcp_port *, struct zfcp_unit *);
-extern void zfcp_rec_dbf_event_action(char *, 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 *);
-extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, unsigned int, int,
-                                   int);
-extern void zfcp_hba_dbf_event_berr(struct zfcp_adapter *,
-                                   struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *);
-extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *);
-extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
-                                      struct scsi_cmnd *,
-                                      struct zfcp_fsf_req *);
-extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
-                                     struct scsi_cmnd *, struct zfcp_fsf_req *,
-                                     unsigned long);
-extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
-                                        struct scsi_cmnd *);
+extern int zfcp_dbf_adapter_register(struct zfcp_adapter *);
+extern void zfcp_dbf_adapter_unregister(struct zfcp_dbf *);
+extern void zfcp_dbf_rec_thread(char *, struct zfcp_dbf *);
+extern void zfcp_dbf_rec_thread_lock(char *, struct zfcp_dbf *);
+extern void zfcp_dbf_rec_adapter(char *, void *, struct zfcp_dbf *);
+extern void zfcp_dbf_rec_port(char *, void *, struct zfcp_port *);
+extern void zfcp_dbf_rec_unit(char *, void *, struct zfcp_unit *);
+extern void zfcp_dbf_rec_trigger(char *, void *, u8, u8, void *,
+                                struct zfcp_adapter *, struct zfcp_port *,
+                                struct zfcp_unit *);
+extern void zfcp_dbf_rec_action(char *, struct zfcp_erp_action *);
+extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *,
+                                      struct zfcp_dbf *);
+extern void _zfcp_dbf_hba_fsf_unsol(const char *, int level, struct zfcp_dbf *,
+                                         struct fsf_status_read_buffer *);
+extern void zfcp_dbf_hba_qdio(struct zfcp_dbf *, unsigned int, int, int);
+extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_els_request(struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_els_response(struct zfcp_fsf_req *);
+extern void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *);
+extern void _zfcp_dbf_scsi(const char *, const char *, int, struct zfcp_dbf *,
+                          struct scsi_cmnd *, struct zfcp_fsf_req *,
+                          unsigned long);
 
 /* zfcp_erp.c */
 extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, char *,
@@ -96,22 +90,20 @@ extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, char *, void *);
 extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *,
                                            void *);
 extern void zfcp_erp_timeout_handler(unsigned long);
-extern void zfcp_erp_port_strategy_open_lookup(struct work_struct *);
 
 /* zfcp_fc.c */
-extern int zfcp_scan_ports(struct zfcp_adapter *);
-extern void _zfcp_scan_ports_later(struct work_struct *);
+extern int zfcp_fc_scan_ports(struct zfcp_adapter *);
+extern void _zfcp_fc_scan_ports_later(struct work_struct *);
 extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
-extern int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *);
+extern void zfcp_fc_port_did_lookup(struct work_struct *);
 extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
-extern void zfcp_test_link(struct zfcp_port *);
+extern void zfcp_fc_test_link(struct zfcp_port *);
 extern void zfcp_fc_link_test_work(struct work_struct *);
-extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *);
-extern void zfcp_fc_wka_ports_init(struct zfcp_adapter *);
+extern void zfcp_fc_wka_ports_force_offline(struct zfcp_wka_ports *);
+extern int zfcp_fc_gs_setup(struct zfcp_adapter *);
+extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
 extern int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *);
 extern int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *);
-extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *);
-
 
 /* zfcp_fsf.c */
 extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
@@ -122,37 +114,39 @@ extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *);
 extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
 extern int zfcp_fsf_close_unit(struct zfcp_erp_action *);
 extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
-extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *,
+extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *,
                                              struct fsf_qtcb_bottom_config *);
 extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *);
-extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *,
+extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *,
                                            struct fsf_qtcb_bottom_port *);
 extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *,
                                                  struct zfcp_fsf_cfdc *);
 extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
-extern int zfcp_fsf_status_read(struct zfcp_adapter *);
+extern int zfcp_fsf_status_read(struct zfcp_qdio *);
 extern int zfcp_status_read_refill(struct zfcp_adapter *adapter);
-extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
-                           struct zfcp_erp_action *);
+extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *);
 extern int zfcp_fsf_send_els(struct zfcp_send_els *);
 extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
                                          struct scsi_cmnd *);
-extern void zfcp_fsf_req_complete(struct zfcp_fsf_req *);
 extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
 extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8);
 extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
                                                       struct zfcp_unit *);
+extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
 
 /* zfcp_qdio.c */
-extern int zfcp_qdio_allocate(struct zfcp_adapter *);
-extern void zfcp_qdio_free(struct zfcp_adapter *);
-extern int zfcp_qdio_send(struct zfcp_fsf_req *);
-extern struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *);
-extern struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *);
-extern int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *, unsigned long,
+extern int zfcp_qdio_setup(struct zfcp_adapter *);
+extern void zfcp_qdio_destroy(struct zfcp_qdio *);
+extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_queue_req *);
+extern struct qdio_buffer_element
+       *zfcp_qdio_sbale_req(struct zfcp_qdio *, struct zfcp_queue_req *);
+extern struct qdio_buffer_element
+       *zfcp_qdio_sbale_curr(struct zfcp_qdio *, struct zfcp_queue_req *);
+extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *,
+                                  struct zfcp_queue_req *, unsigned long,
                                   struct scatterlist *, int);
-extern int zfcp_qdio_open(struct zfcp_adapter *);
-extern void zfcp_qdio_close(struct zfcp_adapter *);
+extern int zfcp_qdio_open(struct zfcp_qdio *);
+extern void zfcp_qdio_close(struct zfcp_qdio *);
 
 /* zfcp_scsi.c */
 extern struct zfcp_data zfcp_data;
index 47daebf..722f22d 100644 (file)
@@ -25,14 +25,6 @@ static u32 rscn_range_mask[] = {
        [RSCN_FABRIC_ADDRESS]           = 0x000000,
 };
 
-struct ct_iu_gpn_ft_req {
-       struct ct_hdr header;
-       u8 flags;
-       u8 domain_id_scope;
-       u8 area_id_scope;
-       u8 fc4_type;
-} __attribute__ ((packed));
-
 struct gpn_ft_resp_acc {
        u8 control;
        u8 port_id[3];
@@ -65,7 +57,7 @@ struct zfcp_fc_ns_handler_data {
        unsigned long handler_data;
 };
 
-static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)
+static int zfcp_fc_wka_port_get(struct zfcp_wka_port *wka_port)
 {
        if (mutex_lock_interruptible(&wka_port->mutex))
                return -ERESTARTSYS;
@@ -90,7 +82,7 @@ static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)
        return -EIO;
 }
 
-static void zfcp_wka_port_offline(struct work_struct *work)
+static void zfcp_fc_wka_port_offline(struct work_struct *work)
 {
        struct delayed_work *dw = to_delayed_work(work);
        struct zfcp_wka_port *wka_port =
@@ -110,7 +102,7 @@ out:
        mutex_unlock(&wka_port->mutex);
 }
 
-static void zfcp_wka_port_put(struct zfcp_wka_port *wka_port)
+static void zfcp_fc_wka_port_put(struct zfcp_wka_port *wka_port)
 {
        if (atomic_dec_return(&wka_port->refcount) != 0)
                return;
@@ -129,10 +121,10 @@ static void zfcp_fc_wka_port_init(struct zfcp_wka_port *wka_port, u32 d_id,
        wka_port->status = ZFCP_WKA_PORT_OFFLINE;
        atomic_set(&wka_port->refcount, 0);
        mutex_init(&wka_port->mutex);
-       INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline);
+       INIT_DELAYED_WORK(&wka_port->work, zfcp_fc_wka_port_offline);
 }
 
-void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka)
+static void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka)
 {
        cancel_delayed_work_sync(&wka->work);
        mutex_lock(&wka->mutex);
@@ -140,15 +132,13 @@ void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka)
        mutex_unlock(&wka->mutex);
 }
 
-void zfcp_fc_wka_ports_init(struct zfcp_adapter *adapter)
+void zfcp_fc_wka_ports_force_offline(struct zfcp_wka_ports *gs)
 {
-       struct zfcp_wka_ports *gs = adapter->gs;
-
-       zfcp_fc_wka_port_init(&gs->ms, FC_FID_MGMT_SERV, adapter);
-       zfcp_fc_wka_port_init(&gs->ts, FC_FID_TIME_SERV, adapter);
-       zfcp_fc_wka_port_init(&gs->ds, FC_FID_DIR_SERV, adapter);
-       zfcp_fc_wka_port_init(&gs->as, FC_FID_ALIASES, adapter);
-       zfcp_fc_wka_port_init(&gs->ks, FC_FID_SEC_KEY, adapter);
+       zfcp_fc_wka_port_force_offline(&gs->ms);
+       zfcp_fc_wka_port_force_offline(&gs->ts);
+       zfcp_fc_wka_port_force_offline(&gs->ds);
+       zfcp_fc_wka_port_force_offline(&gs->as);
+       zfcp_fc_wka_port_force_offline(&gs->ks);
 }
 
 static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
@@ -160,7 +150,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
        read_lock_irqsave(&zfcp_data.config_lock, flags);
        list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) {
                if ((port->d_id & range) == (elem->nport_did & range))
-                       zfcp_test_link(port);
+                       zfcp_fc_test_link(port);
                if (!port->d_id)
                        zfcp_erp_port_reopen(port,
                                             ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -241,7 +231,7 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req)
                (struct fsf_status_read_buffer *) fsf_req->data;
        unsigned int els_type = status_buffer->payload.data[0];
 
-       zfcp_san_dbf_event_incoming_els(fsf_req);
+       zfcp_dbf_san_incoming_els(fsf_req);
        if (els_type == LS_PLOGI)
                zfcp_fc_incoming_plogi(fsf_req);
        else if (els_type == LS_LOGO)
@@ -281,19 +271,18 @@ static void zfcp_fc_ns_gid_pn_eval(unsigned long data)
        port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
 }
 
-int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
+static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port,
                                     struct zfcp_gid_pn_data *gid_pn)
 {
-       struct zfcp_adapter *adapter = erp_action->adapter;
+       struct zfcp_adapter *adapter = port->adapter;
        struct zfcp_fc_ns_handler_data compl_rec;
        int ret;
 
        /* setup parameters for send generic command */
-       gid_pn->port = erp_action->port;
+       gid_pn->port = port;
        gid_pn->ct.wka_port = &adapter->gs->ds;
        gid_pn->ct.handler = zfcp_fc_ns_handler;
        gid_pn->ct.handler_data = (unsigned long) &compl_rec;
-       gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
        gid_pn->ct.req = &gid_pn->req;
        gid_pn->ct.resp = &gid_pn->resp;
        sg_init_one(&gid_pn->req, &gid_pn->ct_iu_req,
@@ -308,13 +297,12 @@ int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
        gid_pn->ct_iu_req.header.options = ZFCP_CT_SYNCHRONOUS;
        gid_pn->ct_iu_req.header.cmd_rsp_code = ZFCP_CT_GID_PN;
        gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_SIZE_ONE_PAGE / 4;
-       gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn;
+       gid_pn->ct_iu_req.wwpn = port->wwpn;
 
        init_completion(&compl_rec.done);
        compl_rec.handler = zfcp_fc_ns_gid_pn_eval;
        compl_rec.handler_data = (unsigned long) gid_pn;
-       ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,
-                              erp_action);
+       ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.gid_pn_req);
        if (!ret)
                wait_for_completion(&compl_rec.done);
        return ret;
@@ -322,33 +310,56 @@ int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
 
 /**
  * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request
- * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed
+ * @port: port where GID_PN request is needed
  * return: -ENOMEM on error, 0 otherwise
  */
-int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *erp_action)
+static int zfcp_fc_ns_gid_pn(struct zfcp_port *port)
 {
        int ret;
        struct zfcp_gid_pn_data *gid_pn;
-       struct zfcp_adapter *adapter = erp_action->adapter;
+       struct zfcp_adapter *adapter = port->adapter;
 
-       gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC);
+       gid_pn = mempool_alloc(adapter->pool.gid_pn_data, GFP_ATOMIC);
        if (!gid_pn)
                return -ENOMEM;
 
        memset(gid_pn, 0, sizeof(*gid_pn));
 
-       ret = zfcp_wka_port_get(&adapter->gs->ds);
+       ret = zfcp_fc_wka_port_get(&adapter->gs->ds);
        if (ret)
                goto out;
 
-       ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn);
+       ret = zfcp_fc_ns_gid_pn_request(port, gid_pn);
 
-       zfcp_wka_port_put(&adapter->gs->ds);
+       zfcp_fc_wka_port_put(&adapter->gs->ds);
 out:
-       mempool_free(gid_pn, adapter->pool.data_gid_pn);
+       mempool_free(gid_pn, adapter->pool.gid_pn_data);
        return ret;
 }
 
+void zfcp_fc_port_did_lookup(struct work_struct *work)
+{
+       int ret;
+       struct zfcp_port *port = container_of(work, struct zfcp_port,
+                                             gid_pn_work);
+
+       ret = zfcp_fc_ns_gid_pn(port);
+       if (ret) {
+               /* could not issue gid_pn for some reason */
+               zfcp_erp_adapter_reopen(port->adapter, 0, "fcgpn_1", NULL);
+               goto out;
+       }
+
+       if (!port->d_id) {
+               zfcp_erp_port_failed(port, "fcgpn_2", NULL);
+               goto out;
+       }
+
+       zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL);
+out:
+       zfcp_port_put(port);
+}
+
 /**
  * zfcp_fc_plogi_evaluate - evaluate PLOGI playload
  * @port: zfcp_port structure
@@ -404,6 +415,7 @@ static void zfcp_fc_adisc_handler(unsigned long data)
        /* port is good, unblock rport without going through erp */
        zfcp_scsi_schedule_rport_register(port);
  out:
+       atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
        zfcp_port_put(port);
        kfree(adisc);
 }
@@ -450,28 +462,36 @@ void zfcp_fc_link_test_work(struct work_struct *work)
        port->rport_task = RPORT_DEL;
        zfcp_scsi_rport_work(&port->rport_work);
 
+       /* only issue one test command at one time per port */
+       if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST)
+               goto out;
+
+       atomic_set_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
+
        retval = zfcp_fc_adisc(port);
        if (retval == 0)
                return;
 
        /* send of ADISC was not possible */
+       atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
        zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL);
 
+out:
        zfcp_port_put(port);
 }
 
 /**
- * zfcp_test_link - lightweight link test procedure
+ * zfcp_fc_test_link - lightweight link test procedure
  * @port: port to be tested
  *
  * Test status of a link to a remote port using the ELS command ADISC.
  * If there is a problem with the remote port, error recovery steps
  * will be triggered.
  */
-void zfcp_test_link(struct zfcp_port *port)
+void zfcp_fc_test_link(struct zfcp_port *port)
 {
        zfcp_port_get(port);
-       if (!queue_work(zfcp_data.work_queue, &port->test_link_work))
+       if (!queue_work(port->adapter->work_queue, &port->test_link_work))
                zfcp_port_put(port);
 }
 
@@ -479,7 +499,7 @@ static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft, int buf_num)
 {
        struct scatterlist *sg = &gpn_ft->sg_req;
 
-       kfree(sg_virt(sg)); /* free request buffer */
+       kmem_cache_free(zfcp_data.gpn_ft_cache, sg_virt(sg));
        zfcp_sg_free_table(gpn_ft->sg_resp, buf_num);
 
        kfree(gpn_ft);
@@ -494,7 +514,7 @@ static struct zfcp_gpn_ft *zfcp_alloc_sg_env(int buf_num)
        if (!gpn_ft)
                return NULL;
 
-       req = kzalloc(sizeof(struct ct_iu_gpn_ft_req), GFP_KERNEL);
+       req = kmem_cache_alloc(zfcp_data.gpn_ft_cache, GFP_KERNEL);
        if (!req) {
                kfree(gpn_ft);
                gpn_ft = NULL;
@@ -511,9 +531,8 @@ out:
 }
 
 
-static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
-                                 struct zfcp_adapter *adapter,
-                                 int max_bytes)
+static int zfcp_fc_send_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
+                              struct zfcp_adapter *adapter, int max_bytes)
 {
        struct zfcp_send_ct *ct = &gpn_ft->ct;
        struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req);
@@ -536,19 +555,18 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
        ct->wka_port = &adapter->gs->ds;
        ct->handler = zfcp_fc_ns_handler;
        ct->handler_data = (unsigned long)&compl_rec;
-       ct->timeout = 10;
        ct->req = &gpn_ft->sg_req;
        ct->resp = gpn_ft->sg_resp;
 
        init_completion(&compl_rec.done);
        compl_rec.handler = NULL;
-       ret = zfcp_fsf_send_ct(ct, NULL, NULL);
+       ret = zfcp_fsf_send_ct(ct, NULL);
        if (!ret)
                wait_for_completion(&compl_rec.done);
        return ret;
 }
 
-static void zfcp_validate_port(struct zfcp_port *port)
+static void zfcp_fc_validate_port(struct zfcp_port *port)
 {
        struct zfcp_adapter *adapter = port->adapter;
 
@@ -568,7 +586,7 @@ static void zfcp_validate_port(struct zfcp_port *port)
        zfcp_port_dequeue(port);
 }
 
-static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
+static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
 {
        struct zfcp_send_ct *ct = &gpn_ft->ct;
        struct scatterlist *sg = gpn_ft->sg_resp;
@@ -595,7 +613,7 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
                return -E2BIG;
        }
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
 
        /* first entry is the header */
        for (x = 1; x < max_entries && !last; x++) {
@@ -628,16 +646,16 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
 
        zfcp_erp_wait(adapter);
        list_for_each_entry_safe(port, tmp, &adapter->port_list_head, list)
-               zfcp_validate_port(port);
-       up(&zfcp_data.config_sema);
+               zfcp_fc_validate_port(port);
+       mutex_unlock(&zfcp_data.config_mutex);
        return ret;
 }
 
 /**
- * zfcp_scan_ports - scan remote ports and attach new ports
+ * zfcp_fc_scan_ports - scan remote ports and attach new ports
  * @adapter: pointer to struct zfcp_adapter
  */
-int zfcp_scan_ports(struct zfcp_adapter *adapter)
+int zfcp_fc_scan_ports(struct zfcp_adapter *adapter)
 {
        int ret, i;
        struct zfcp_gpn_ft *gpn_ft;
@@ -652,7 +670,7 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
            fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
                return 0;
 
-       ret = zfcp_wka_port_get(&adapter->gs->ds);
+       ret = zfcp_fc_wka_port_get(&adapter->gs->ds);
        if (ret)
                return ret;
 
@@ -663,9 +681,9 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
        }
 
        for (i = 0; i < 3; i++) {
-               ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter, max_bytes);
+               ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes);
                if (!ret) {
-                       ret = zfcp_scan_eval_gpn_ft(gpn_ft, max_entries);
+                       ret = zfcp_fc_eval_gpn_ft(gpn_ft, max_entries);
                        if (ret == -EAGAIN)
                                ssleep(1);
                        else
@@ -674,14 +692,14 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
        }
        zfcp_free_sg_env(gpn_ft, buf_num);
 out:
-       zfcp_wka_port_put(&adapter->gs->ds);
+       zfcp_fc_wka_port_put(&adapter->gs->ds);
        return ret;
 }
 
 
-void _zfcp_scan_ports_later(struct work_struct *work)
+void _zfcp_fc_scan_ports_later(struct work_struct *work)
 {
-       zfcp_scan_ports(container_of(work, struct zfcp_adapter, scan_work));
+       zfcp_fc_scan_ports(container_of(work, struct zfcp_adapter, scan_work));
 }
 
 struct zfcp_els_fc_job {
@@ -732,7 +750,7 @@ int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *job)
        els_fc_job->els.adapter = adapter;
        if (rport) {
                read_lock_irq(&zfcp_data.config_lock);
-               port = rport->dd_data;
+               port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
                if (port)
                        els_fc_job->els.d_id = port->d_id;
                read_unlock_irq(&zfcp_data.config_lock);
@@ -771,7 +789,7 @@ static void zfcp_fc_generic_ct_handler(unsigned long data)
        job->state_flags = FC_RQST_STATE_DONE;
        job->job_done(job);
 
-       zfcp_wka_port_put(ct_fc_job->ct.wka_port);
+       zfcp_fc_wka_port_put(ct_fc_job->ct.wka_port);
 
        kfree(ct_fc_job);
 }
@@ -817,7 +835,7 @@ int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *job)
                return -EINVAL; /* no such service */
        }
 
-       ret = zfcp_wka_port_get(ct_fc_job->ct.wka_port);
+       ret = zfcp_fc_wka_port_get(ct_fc_job->ct.wka_port);
        if (ret) {
                kfree(ct_fc_job);
                return ret;
@@ -825,16 +843,40 @@ int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *job)
 
        ct_fc_job->ct.req = job->request_payload.sg_list;
        ct_fc_job->ct.resp = job->reply_payload.sg_list;
-       ct_fc_job->ct.timeout = ZFCP_FSF_REQUEST_TIMEOUT;
        ct_fc_job->ct.handler = zfcp_fc_generic_ct_handler;
        ct_fc_job->ct.handler_data = (unsigned long) ct_fc_job;
        ct_fc_job->ct.completion = NULL;
        ct_fc_job->job = job;
 
-       ret = zfcp_fsf_send_ct(&ct_fc_job->ct, NULL, NULL);
+       ret = zfcp_fsf_send_ct(&ct_fc_job->ct, NULL);
        if (ret) {
                kfree(ct_fc_job);
-               zfcp_wka_port_put(ct_fc_job->ct.wka_port);
+               zfcp_fc_wka_port_put(ct_fc_job->ct.wka_port);
        }
        return ret;
 }
+
+int zfcp_fc_gs_setup(struct zfcp_adapter *adapter)
+{
+       struct zfcp_wka_ports *wka_ports;
+
+       wka_ports = kzalloc(sizeof(struct zfcp_wka_ports), GFP_KERNEL);
+       if (!wka_ports)
+               return -ENOMEM;
+
+       adapter->gs = wka_ports;
+       zfcp_fc_wka_port_init(&wka_ports->ms, FC_FID_MGMT_SERV, adapter);
+       zfcp_fc_wka_port_init(&wka_ports->ts, FC_FID_TIME_SERV, adapter);
+       zfcp_fc_wka_port_init(&wka_ports->ds, FC_FID_DIR_SERV, adapter);
+       zfcp_fc_wka_port_init(&wka_ports->as, FC_FID_ALIASES, adapter);
+       zfcp_fc_wka_port_init(&wka_ports->ks, FC_FID_SEC_KEY, adapter);
+
+       return 0;
+}
+
+void zfcp_fc_gs_destroy(struct zfcp_adapter *adapter)
+{
+       kfree(adapter->gs);
+       adapter->gs = NULL;
+}
+
index 47795fb..f09c863 100644 (file)
@@ -11,9 +11,7 @@
 
 #include <linux/blktrace_api.h>
 #include "zfcp_ext.h"
-
-#define ZFCP_REQ_AUTO_CLEANUP  0x00000002
-#define ZFCP_REQ_NO_QTCB       0x00000008
+#include "zfcp_dbf.h"
 
 static void zfcp_fsf_request_timeout_handler(unsigned long data)
 {
@@ -111,43 +109,15 @@ static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
 void zfcp_fsf_req_free(struct zfcp_fsf_req *req)
 {
        if (likely(req->pool)) {
+               if (likely(req->qtcb))
+                       mempool_free(req->qtcb, req->adapter->pool.qtcb_pool);
                mempool_free(req, req->pool);
                return;
        }
 
-       if (req->qtcb) {
-               kmem_cache_free(zfcp_data.fsf_req_qtcb_cache, req);
-               return;
-       }
-}
-
-/**
- * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
- * @adapter: pointer to struct zfcp_adapter
- *
- * Never ever call this without shutting down the adapter first.
- * Otherwise the adapter would continue using and corrupting s390 storage.
- * Included BUG_ON() call to ensure this is done.
- * ERP is supposed to be the only user of this function.
- */
-void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
-{
-       struct zfcp_fsf_req *req, *tmp;
-       unsigned long flags;
-       LIST_HEAD(remove_queue);
-       unsigned int i;
-
-       BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
-       spin_lock_irqsave(&adapter->req_list_lock, flags);
-       for (i = 0; i < REQUEST_LIST_SIZE; i++)
-               list_splice_init(&adapter->req_list[i], &remove_queue);
-       spin_unlock_irqrestore(&adapter->req_list_lock, flags);
-
-       list_for_each_entry_safe(req, tmp, &remove_queue, list) {
-               list_del(&req->list);
-               req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
-               zfcp_fsf_req_complete(req);
-       }
+       if (likely(req->qtcb))
+               kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb);
+       kfree(req);
 }
 
 static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
@@ -278,13 +248,13 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
        struct fsf_status_read_buffer *sr_buf = req->data;
 
        if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
-               zfcp_hba_dbf_event_fsf_unsol("dism", adapter, sr_buf);
-               mempool_free(sr_buf, adapter->pool.data_status_read);
+               zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf);
+               mempool_free(sr_buf, adapter->pool.status_read_data);
                zfcp_fsf_req_free(req);
                return;
        }
 
-       zfcp_hba_dbf_event_fsf_unsol("read", adapter, sr_buf);
+       zfcp_dbf_hba_fsf_unsol("read", adapter->dbf, sr_buf);
 
        switch (sr_buf->status_type) {
        case FSF_STATUS_READ_PORT_CLOSED:
@@ -299,7 +269,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
                dev_warn(&adapter->ccw_device->dev,
                         "The error threshold for checksum statistics "
                         "has been exceeded\n");
-               zfcp_hba_dbf_event_berr(adapter, req);
+               zfcp_dbf_hba_berr(adapter->dbf, req);
                break;
        case FSF_STATUS_READ_LINK_DOWN:
                zfcp_fsf_status_read_link_down(req);
@@ -331,11 +301,11 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
                break;
        }
 
-       mempool_free(sr_buf, adapter->pool.data_status_read);
+       mempool_free(sr_buf, adapter->pool.status_read_data);
        zfcp_fsf_req_free(req);
 
        atomic_inc(&adapter->stat_miss);
-       queue_work(zfcp_data.work_queue, &adapter->stat_work);
+       queue_work(adapter->work_queue, &adapter->stat_work);
 }
 
 static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
@@ -385,7 +355,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
        struct fsf_qtcb *qtcb = req->qtcb;
        union fsf_prot_status_qual *psq = &qtcb->prefix.prot_status_qual;
 
-       zfcp_hba_dbf_event_fsf_response(req);
+       zfcp_dbf_hba_fsf_response(req);
 
        if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
                req->status |= ZFCP_STATUS_FSFREQ_ERROR |
@@ -458,7 +428,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
  * is called to process the completion status and trigger further
  * events related to the FSF request.
  */
-void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
+static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
 {
        if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
                zfcp_fsf_status_read_handler(req);
@@ -472,23 +442,40 @@ void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
 
        if (req->erp_action)
                zfcp_erp_notify(req->erp_action, 0);
-       req->status |= ZFCP_STATUS_FSFREQ_COMPLETED;
 
        if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
                zfcp_fsf_req_free(req);
        else
-       /* notify initiator waiting for the requests completion */
-       /*
-        * FIXME: Race! We must not access fsf_req here as it might have been
-        * cleaned up already due to the set ZFCP_STATUS_FSFREQ_COMPLETED
-        * flag. It's an improbable case. But, we have the same paranoia for
-        * the cleanup flag already.
-        * Might better be handled using complete()?
-        * (setting the flag and doing wakeup ought to be atomic
-        *  with regard to checking the flag as long as waitqueue is
-        *  part of the to be released structure)
-        */
-               wake_up(&req->completion_wq);
+               complete(&req->completion);
+}
+
+/**
+ * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
+ * @adapter: pointer to struct zfcp_adapter
+ *
+ * Never ever call this without shutting down the adapter first.
+ * Otherwise the adapter would continue using and corrupting s390 storage.
+ * Included BUG_ON() call to ensure this is done.
+ * ERP is supposed to be the only user of this function.
+ */
+void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
+{
+       struct zfcp_fsf_req *req, *tmp;
+       unsigned long flags;
+       LIST_HEAD(remove_queue);
+       unsigned int i;
+
+       BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
+       spin_lock_irqsave(&adapter->req_list_lock, flags);
+       for (i = 0; i < REQUEST_LIST_SIZE; i++)
+               list_splice_init(&adapter->req_list[i], &remove_queue);
+       spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+
+       list_for_each_entry_safe(req, tmp, &remove_queue, list) {
+               list_del(&req->list);
+               req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
+               zfcp_fsf_req_complete(req);
+       }
 }
 
 static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
@@ -650,79 +637,77 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
        }
 }
 
-static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter)
+static int zfcp_fsf_sbal_check(struct zfcp_qdio *qdio)
 {
-       struct zfcp_qdio_queue *req_q = &adapter->req_q;
+       struct zfcp_qdio_queue *req_q = &qdio->req_q;
 
-       spin_lock_bh(&adapter->req_q_lock);
+       spin_lock_bh(&qdio->req_q_lock);
        if (atomic_read(&req_q->count))
                return 1;
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return 0;
 }
 
-static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
+static int zfcp_fsf_req_sbal_get(struct zfcp_qdio *qdio)
 {
+       struct zfcp_adapter *adapter = qdio->adapter;
        long ret;
 
-       spin_unlock_bh(&adapter->req_q_lock);
-       ret = wait_event_interruptible_timeout(adapter->request_wq,
-                              zfcp_fsf_sbal_check(adapter), 5 * HZ);
+       spin_unlock_bh(&qdio->req_q_lock);
+       ret = wait_event_interruptible_timeout(qdio->req_q_wq,
+                              zfcp_fsf_sbal_check(qdio), 5 * HZ);
        if (ret > 0)
                return 0;
        if (!ret) {
-               atomic_inc(&adapter->qdio_outb_full);
+               atomic_inc(&qdio->req_q_full);
                /* assume hanging outbound queue, try queue recovery */
                zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL);
        }
 
-       spin_lock_bh(&adapter->req_q_lock);
+       spin_lock_bh(&qdio->req_q_lock);
        return -EIO;
 }
 
-static struct zfcp_fsf_req *zfcp_fsf_alloc_noqtcb(mempool_t *pool)
+static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
 {
        struct zfcp_fsf_req *req;
-       req = mempool_alloc(pool, GFP_ATOMIC);
-       if (!req)
+
+       if (likely(pool))
+               req = mempool_alloc(pool, GFP_ATOMIC);
+       else
+               req = kmalloc(sizeof(*req), GFP_ATOMIC);
+
+       if (unlikely(!req))
                return NULL;
+
        memset(req, 0, sizeof(*req));
        req->pool = pool;
        return req;
 }
 
-static struct zfcp_fsf_req *zfcp_fsf_alloc_qtcb(mempool_t *pool)
+static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
 {
-       struct zfcp_fsf_req_qtcb *qtcb;
+       struct fsf_qtcb *qtcb;
 
        if (likely(pool))
                qtcb = mempool_alloc(pool, GFP_ATOMIC);
        else
-               qtcb = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache,
-                                       GFP_ATOMIC);
+               qtcb = kmem_cache_alloc(zfcp_data.qtcb_cache, GFP_ATOMIC);
+
        if (unlikely(!qtcb))
                return NULL;
 
        memset(qtcb, 0, sizeof(*qtcb));
-       qtcb->fsf_req.qtcb = &qtcb->qtcb;
-       qtcb->fsf_req.pool = pool;
-
-       return &qtcb->fsf_req;
+       return qtcb;
 }
 
-static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
-                                               u32 fsf_cmd, int req_flags,
-                                               mempool_t *pool)
+static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
+                                               u32 fsf_cmd, mempool_t *pool)
 {
        struct qdio_buffer_element *sbale;
-
-       struct zfcp_fsf_req *req;
-       struct zfcp_qdio_queue *req_q = &adapter->req_q;
-
-       if (req_flags & ZFCP_REQ_NO_QTCB)
-               req = zfcp_fsf_alloc_noqtcb(pool);
-       else
-               req = zfcp_fsf_alloc_qtcb(pool);
+       struct zfcp_qdio_queue *req_q = &qdio->req_q;
+       struct zfcp_adapter *adapter = qdio->adapter;
+       struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
 
        if (unlikely(!req))
                return ERR_PTR(-ENOMEM);
@@ -732,22 +717,32 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
 
        INIT_LIST_HEAD(&req->list);
        init_timer(&req->timer);
-       init_waitqueue_head(&req->completion_wq);
+       init_completion(&req->completion);
 
        req->adapter = adapter;
        req->fsf_command = fsf_cmd;
        req->req_id = adapter->req_no;
-       req->sbal_number = 1;
-       req->sbal_first = req_q->first;
-       req->sbal_last = req_q->first;
-       req->sbale_curr = 1;
+       req->queue_req.sbal_number = 1;
+       req->queue_req.sbal_first = req_q->first;
+       req->queue_req.sbal_last = req_q->first;
+       req->queue_req.sbale_curr = 1;
 
-       sbale = zfcp_qdio_sbale_req(req);
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].addr = (void *) req->req_id;
        sbale[0].flags |= SBAL_FLAGS0_COMMAND;
 
-       if (likely(req->qtcb)) {
-               req->qtcb->prefix.req_seq_no = req->adapter->fsf_req_seq_no;
+       if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
+               if (likely(pool))
+                       req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool);
+               else
+                       req->qtcb = zfcp_qtcb_alloc(NULL);
+
+               if (unlikely(!req->qtcb)) {
+                       zfcp_fsf_req_free(req);
+                       return ERR_PTR(-ENOMEM);
+               }
+
+               req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
                req->qtcb->prefix.req_id = req->req_id;
                req->qtcb->prefix.ulp_info = 26;
                req->qtcb->prefix.qtcb_type = fsf_qtcb_type[req->fsf_command];
@@ -765,15 +760,13 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
                return ERR_PTR(-EIO);
        }
 
-       if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP))
-               req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-
        return req;
 }
 
 static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
 {
        struct zfcp_adapter *adapter = req->adapter;
+       struct zfcp_qdio *qdio = adapter->qdio;
        unsigned long        flags;
        int                  idx;
        int                  with_qtcb = (req->qtcb != NULL);
@@ -784,9 +777,9 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
        list_add_tail(&req->list, &adapter->req_list[idx]);
        spin_unlock_irqrestore(&adapter->req_list_lock, flags);
 
-       req->qdio_outb_usage = atomic_read(&adapter->req_q.count);
+       req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count);
        req->issued = get_clock();
-       if (zfcp_qdio_send(req)) {
+       if (zfcp_qdio_send(qdio, &req->queue_req)) {
                del_timer(&req->timer);
                spin_lock_irqsave(&adapter->req_list_lock, flags);
                /* lookup request again, list might have changed */
@@ -811,38 +804,37 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
  * @req_flags: request flags
  * Returns: 0 on success, ERROR otherwise
  */
-int zfcp_fsf_status_read(struct zfcp_adapter *adapter)
+int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
 {
+       struct zfcp_adapter *adapter = qdio->adapter;
        struct zfcp_fsf_req *req;
        struct fsf_status_read_buffer *sr_buf;
        struct qdio_buffer_element *sbale;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS,
-                                 ZFCP_REQ_NO_QTCB,
-                                 adapter->pool.fsf_req_status_read);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS,
+                                 adapter->pool.status_read_req);
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_STATUS;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
-       req->sbale_curr = 2;
+       req->queue_req.sbale_curr = 2;
 
-       sr_buf = mempool_alloc(adapter->pool.data_status_read, GFP_ATOMIC);
+       sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
        if (!sr_buf) {
                retval = -ENOMEM;
                goto failed_buf;
        }
        memset(sr_buf, 0, sizeof(*sr_buf));
        req->data = sr_buf;
-       sbale = zfcp_qdio_sbale_curr(req);
+       sbale = zfcp_qdio_sbale_curr(qdio, &req->queue_req);
        sbale->addr = (void *) sr_buf;
        sbale->length = sizeof(*sr_buf);
 
@@ -853,12 +845,12 @@ int zfcp_fsf_status_read(struct zfcp_adapter *adapter)
        goto out;
 
 failed_req_send:
-       mempool_free(sr_buf, adapter->pool.data_status_read);
+       mempool_free(sr_buf, adapter->pool.status_read_data);
 failed_buf:
        zfcp_fsf_req_free(req);
-       zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL);
+       zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -900,7 +892,7 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (fsq->word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       zfcp_test_link(unit->port);
+                       zfcp_fc_test_link(unit->port);
                        /* fall through */
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -925,13 +917,13 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
 {
        struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *req = NULL;
-       struct zfcp_adapter *adapter = unit->port->adapter;
+       struct zfcp_qdio *qdio = unit->port->adapter->qdio;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
-                                 0, adapter->pool.fsf_req_abort);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
+                                 qdio->adapter->pool.scsi_abort);
        if (IS_ERR(req)) {
                req = NULL;
                goto out;
@@ -941,7 +933,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
                       ZFCP_STATUS_COMMON_UNBLOCKED)))
                goto out_error_free;
 
-       sbale = zfcp_qdio_sbale_req(req);
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -959,7 +951,7 @@ out_error_free:
        zfcp_fsf_req_free(req);
        req = NULL;
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return req;
 }
 
@@ -976,7 +968,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
 
        switch (header->fsf_status) {
         case FSF_GOOD:
-               zfcp_san_dbf_event_ct_response(req);
+               zfcp_dbf_san_ct_response(req);
                send_ct->status = 0;
                break;
         case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -1035,8 +1027,10 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
                                       struct scatterlist *sg_resp,
                                       int max_sbals)
 {
-       struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(req);
-       u32 feat = req->adapter->adapter_features;
+       struct zfcp_adapter *adapter = req->adapter;
+       struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio,
+                                                              &req->queue_req);
+       u32 feat = adapter->adapter_features;
        int bytes;
 
        if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
@@ -1053,18 +1047,25 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
                return 0;
        }
 
-       bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
+       bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
+                                       SBAL_FLAGS0_TYPE_WRITE_READ,
                                        sg_req, max_sbals);
        if (bytes <= 0)
                return -EIO;
        req->qtcb->bottom.support.req_buf_length = bytes;
-       req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
+       req->queue_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
 
-       bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
+       bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
+                                       SBAL_FLAGS0_TYPE_WRITE_READ,
                                        sg_resp, max_sbals);
        if (bytes <= 0)
                return -EIO;
+
+       /* common settings for ct/gs and els requests */
        req->qtcb->bottom.support.resp_buf_length = bytes;
+       req->qtcb->bottom.support.service_class = FSF_CLASS_3;
+       req->qtcb->bottom.support.timeout = 2 * R_A_TOV;
+       zfcp_fsf_start_timer(req, 2 * R_A_TOV + 10);
 
        return 0;
 }
@@ -1073,27 +1074,26 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
  * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS)
  * @ct: pointer to struct zfcp_send_ct with data for request
  * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req
- * @erp_action: if non-null the Generic Service request sent within ERP
  */
-int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
-                    struct zfcp_erp_action *erp_action)
+int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool)
 {
        struct zfcp_wka_port *wka_port = ct->wka_port;
-       struct zfcp_adapter *adapter = wka_port->adapter;
+       struct zfcp_qdio *qdio = wka_port->adapter->qdio;
        struct zfcp_fsf_req *req;
        int ret = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC,
-                                 ZFCP_REQ_AUTO_CLEANUP, pool);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, pool);
+
        if (IS_ERR(req)) {
                ret = PTR_ERR(req);
                goto out;
        }
 
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
        ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp,
                                          FSF_MAX_SBALS_PER_REQ);
        if (ret)
@@ -1101,18 +1101,9 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
 
        req->handler = zfcp_fsf_send_ct_handler;
        req->qtcb->header.port_handle = wka_port->handle;
-       req->qtcb->bottom.support.service_class = FSF_CLASS_3;
-       req->qtcb->bottom.support.timeout = ct->timeout;
        req->data = ct;
 
-       zfcp_san_dbf_event_ct_request(req);
-
-       if (erp_action) {
-               erp_action->fsf_req = req;
-               req->erp_action = erp_action;
-               zfcp_fsf_start_erp_timer(req);
-       } else
-               zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
+       zfcp_dbf_san_ct_request(req);
 
        ret = zfcp_fsf_req_send(req);
        if (ret)
@@ -1122,10 +1113,8 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
 
 failed_send:
        zfcp_fsf_req_free(req);
-       if (erp_action)
-               erp_action->fsf_req = NULL;
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return ret;
 }
 
@@ -1142,7 +1131,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
 
        switch (header->fsf_status) {
        case FSF_GOOD:
-               zfcp_san_dbf_event_els_response(req);
+               zfcp_dbf_san_els_response(req);
                send_els->status = 0;
                break;
        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -1152,7 +1141,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
                switch (header->fsf_status_qual.word[0]){
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
                        if (port && (send_els->ls_code != ZFCP_LS_ADISC))
-                               zfcp_test_link(port);
+                               zfcp_fc_test_link(port);
                        /*fall through */
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                case FSF_SQ_RETRY_IF_POSSIBLE:
@@ -1188,35 +1177,32 @@ skip_fsfstatus:
 int zfcp_fsf_send_els(struct zfcp_send_els *els)
 {
        struct zfcp_fsf_req *req;
-       struct zfcp_adapter *adapter = els->adapter;
-       struct fsf_qtcb_bottom_support *bottom;
+       struct zfcp_qdio *qdio = els->adapter->qdio;
        int ret = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS,
-                                 ZFCP_REQ_AUTO_CLEANUP, NULL);
+
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, NULL);
+
        if (IS_ERR(req)) {
                ret = PTR_ERR(req);
                goto out;
        }
 
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
        ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2);
 
        if (ret)
                goto failed_send;
 
-       bottom = &req->qtcb->bottom.support;
+       req->qtcb->bottom.support.d_id = els->d_id;
        req->handler = zfcp_fsf_send_els_handler;
-       bottom->d_id = els->d_id;
-       bottom->service_class = FSF_CLASS_3;
-       bottom->timeout = 2 * R_A_TOV;
        req->data = els;
 
-       zfcp_san_dbf_event_els_request(req);
+       zfcp_dbf_san_els_request(req);
 
-       zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
        ret = zfcp_fsf_req_send(req);
        if (ret)
                goto failed_send;
@@ -1226,7 +1212,7 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
 failed_send:
        zfcp_fsf_req_free(req);
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return ret;
 }
 
@@ -1234,22 +1220,23 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
 {
        struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *req;
-       struct zfcp_adapter *adapter = erp_action->adapter;
+       struct zfcp_qdio *qdio = erp_action->adapter->qdio;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
-       req = zfcp_fsf_req_create(adapter,
-                                 FSF_QTCB_EXCHANGE_CONFIG_DATA,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_erp);
+
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
+                                 qdio->adapter->pool.erp_req);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -1269,29 +1256,29 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req = NULL;
        }
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
-int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
+int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
                                       struct fsf_qtcb_bottom_config *data)
 {
        struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *req = NULL;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out_unlock;
 
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
-                                 0, NULL);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, NULL);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out_unlock;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
        req->handler = zfcp_fsf_exchange_config_data_handler;
@@ -1307,16 +1294,15 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
 
        zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
        retval = zfcp_fsf_req_send(req);
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        if (!retval)
-               wait_event(req->completion_wq,
-                          req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+               wait_for_completion(&req->completion);
 
        zfcp_fsf_req_free(req);
        return retval;
 
 out_unlock:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1327,26 +1313,28 @@ out_unlock:
  */
 int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
 {
+       struct zfcp_qdio *qdio = erp_action->adapter->qdio;
        struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *req;
-       struct zfcp_adapter *adapter = erp_action->adapter;
        int retval = -EIO;
 
-       if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
+       if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
                return -EOPNOTSUPP;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_erp);
+
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
+                                 qdio->adapter->pool.erp_req);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -1361,32 +1349,32 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req = NULL;
        }
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
 /**
  * zfcp_fsf_exchange_port_data_sync - request information about local port
- * @adapter: pointer to struct zfcp_adapter
+ * @qdio: pointer to struct zfcp_qdio
  * @data: pointer to struct fsf_qtcb_bottom_port
  * Returns: 0 on success, error otherwise
  */
-int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
+int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
                                     struct fsf_qtcb_bottom_port *data)
 {
        struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *req = NULL;
        int retval = -EIO;
 
-       if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
+       if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
                return -EOPNOTSUPP;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out_unlock;
 
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0,
-                                 NULL);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, NULL);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out_unlock;
@@ -1395,24 +1383,24 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
        if (data)
                req->data = data;
 
-       sbale = zfcp_qdio_sbale_req(req);
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
        req->handler = zfcp_fsf_exchange_port_data_handler;
        zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
        retval = zfcp_fsf_req_send(req);
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
 
        if (!retval)
-               wait_event(req->completion_wq,
-                          req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+               wait_for_completion(&req->completion);
+
        zfcp_fsf_req_free(req);
 
        return retval;
 
 out_unlock:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1498,25 +1486,25 @@ out:
 int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
 {
        struct qdio_buffer_element *sbale;
-       struct zfcp_adapter *adapter = erp_action->adapter;
-       struct zfcp_fsf_req *req;
+       struct zfcp_qdio *qdio = erp_action->adapter->qdio;
        struct zfcp_port *port = erp_action->port;
+       struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(adapter,
-                                 FSF_QTCB_OPEN_PORT_WITH_DID,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_erp);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
+                                 qdio->adapter->pool.erp_req);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
         sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
         sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -1535,7 +1523,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
                zfcp_port_put(port);
        }
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1569,23 +1557,24 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
 int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
 {
        struct qdio_buffer_element *sbale;
-       struct zfcp_adapter *adapter = erp_action->adapter;
+       struct zfcp_qdio *qdio = erp_action->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_erp);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
+                                 qdio->adapter->pool.erp_req);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -1602,7 +1591,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req = NULL;
        }
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1645,24 +1634,24 @@ out:
 int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
 {
        struct qdio_buffer_element *sbale;
-       struct zfcp_adapter *adapter = wka_port->adapter;
+       struct zfcp_qdio *qdio = wka_port->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(adapter,
-                                 FSF_QTCB_OPEN_PORT_WITH_DID,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_erp);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
+                                 qdio->adapter->pool.erp_req);
+
        if (unlikely(IS_ERR(req))) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -1675,7 +1664,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
        if (retval)
                zfcp_fsf_req_free(req);
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1700,23 +1689,24 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
 int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
 {
        struct qdio_buffer_element *sbale;
-       struct zfcp_adapter *adapter = wka_port->adapter;
+       struct zfcp_qdio *qdio = wka_port->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_erp);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
+                                 qdio->adapter->pool.erp_req);
+
        if (unlikely(IS_ERR(req))) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -1729,7 +1719,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
        if (retval)
                zfcp_fsf_req_free(req);
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1791,23 +1781,24 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
 int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
 {
        struct qdio_buffer_element *sbale;
-       struct zfcp_adapter *adapter = erp_action->adapter;
+       struct zfcp_qdio *qdio = erp_action->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PHYSICAL_PORT,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_erp);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
+                                 qdio->adapter->pool.erp_req);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -1824,7 +1815,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req = NULL;
        }
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -1895,7 +1886,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (header->fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       zfcp_test_link(unit->port);
+                       zfcp_fc_test_link(unit->port);
                        /* fall through */
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1964,22 +1955,24 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
 {
        struct qdio_buffer_element *sbale;
        struct zfcp_adapter *adapter = erp_action->adapter;
+       struct zfcp_qdio *qdio = adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_OPEN_LUN,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_erp);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
+                                 adapter->pool.erp_req);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
         sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
         sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -2000,7 +1993,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req = NULL;
        }
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -2028,7 +2021,7 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (req->qtcb->header.fsf_status_qual.word[0]) {
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-                       zfcp_test_link(unit->port);
+                       zfcp_fc_test_link(unit->port);
                        /* fall through */
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
                        req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -2049,22 +2042,24 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
 int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
 {
        struct qdio_buffer_element *sbale;
-       struct zfcp_adapter *adapter = erp_action->adapter;
+       struct zfcp_qdio *qdio = erp_action->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_erp);
+
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
+                                 qdio->adapter->pool.erp_req);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(req);
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -2082,7 +2077,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
                erp_action->fsf_req = NULL;
        }
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return retval;
 }
 
@@ -2141,8 +2136,8 @@ static void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
        }
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
                trace.flags |= ZFCP_BLK_REQ_ERROR;
-       trace.inb_usage = fsf_req->qdio_inb_usage;
-       trace.outb_usage = fsf_req->qdio_outb_usage;
+       trace.inb_usage = fsf_req->queue_req.qdio_inb_usage;
+       trace.outb_usage = fsf_req->queue_req.qdio_outb_usage;
 
        blk_add_driver_data(req->q, req, &trace, sizeof(trace));
 }
@@ -2215,11 +2210,11 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
        }
 skip_fsfstatus:
        if (scpnt->result != 0)
-               zfcp_scsi_dbf_event_result("erro", 3, req->adapter, scpnt, req);
+               zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req);
        else if (scpnt->retries > 0)
-               zfcp_scsi_dbf_event_result("retr", 4, req->adapter, scpnt, req);
+               zfcp_dbf_scsi_result("retr", 4, req->adapter->dbf, scpnt, req);
        else
-               zfcp_scsi_dbf_event_result("norm", 6, req->adapter, scpnt, req);
+               zfcp_dbf_scsi_result("norm", 6, req->adapter->dbf, scpnt, req);
 
        scpnt->host_scribble = NULL;
        (scpnt->scsi_done) (scpnt);
@@ -2309,7 +2304,7 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
        case FSF_ADAPTER_STATUS_AVAILABLE:
                if (header->fsf_status_qual.word[0] ==
                    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
-                       zfcp_test_link(unit->port);
+                       zfcp_fc_test_link(unit->port);
                req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                break;
        }
@@ -2350,24 +2345,27 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
        unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
        int real_bytes, retval = -EIO;
        struct zfcp_adapter *adapter = unit->port->adapter;
+       struct zfcp_qdio *qdio = adapter->qdio;
 
        if (unlikely(!(atomic_read(&unit->status) &
                       ZFCP_STATUS_COMMON_UNBLOCKED)))
                return -EBUSY;
 
-       spin_lock(&adapter->req_q_lock);
-       if (atomic_read(&adapter->req_q.count) <= 0) {
-               atomic_inc(&adapter->qdio_outb_full);
+       spin_lock(&qdio->req_q_lock);
+       if (atomic_read(&qdio->req_q.count) <= 0) {
+               atomic_inc(&qdio->req_q_full);
                goto out;
        }
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND,
-                                 ZFCP_REQ_AUTO_CLEANUP,
-                                 adapter->pool.fsf_req_scsi);
+
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
+                                 adapter->pool.scsi_req);
+
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
+       req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
        zfcp_unit_get(unit);
        req->unit = unit;
        req->data = scsi_cmnd;
@@ -2419,11 +2417,11 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
        req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
                fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32);
 
-       real_bytes = zfcp_qdio_sbals_from_sg(req, sbtype,
+       real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype,
                                             scsi_sglist(scsi_cmnd),
                                             FSF_MAX_SBALS_PER_REQ);
        if (unlikely(real_bytes < 0)) {
-               if (req->sbal_number >= FSF_MAX_SBALS_PER_REQ) {
+               if (req->queue_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) {
                        dev_err(&adapter->ccw_device->dev,
                                "Oversize data package, unit 0x%016Lx "
                                "on port 0x%016Lx closed\n",
@@ -2448,7 +2446,7 @@ failed_scsi_cmnd:
        zfcp_fsf_req_free(req);
        scsi_cmnd->host_scribble = NULL;
 out:
-       spin_unlock(&adapter->req_q_lock);
+       spin_unlock(&qdio->req_q_lock);
        return retval;
 }
 
@@ -2463,17 +2461,19 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
        struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *req = NULL;
        struct fcp_cmnd_iu *fcp_cmnd_iu;
-       struct zfcp_adapter *adapter = unit->port->adapter;
+       struct zfcp_qdio *qdio = unit->port->adapter->qdio;
 
        if (unlikely(!(atomic_read(&unit->status) &
                       ZFCP_STATUS_COMMON_UNBLOCKED)))
                return NULL;
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
-       req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, 0,
-                                 adapter->pool.fsf_req_scsi);
+
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
+                                 qdio->adapter->pool.scsi_req);
+
        if (IS_ERR(req)) {
                req = NULL;
                goto out;
@@ -2489,7 +2489,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
        req->qtcb->bottom.io.fcp_cmnd_length =  sizeof(struct fcp_cmnd_iu) +
                                                sizeof(u32);
 
-       sbale = zfcp_qdio_sbale_req(req);
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
@@ -2504,7 +2504,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
        zfcp_fsf_req_free(req);
        req = NULL;
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
        return req;
 }
 
@@ -2522,6 +2522,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
                                           struct zfcp_fsf_cfdc *fsf_cfdc)
 {
        struct qdio_buffer_element *sbale;
+       struct zfcp_qdio *qdio = adapter->qdio;
        struct zfcp_fsf_req *req = NULL;
        struct fsf_qtcb_bottom_support *bottom;
        int direction, retval = -EIO, bytes;
@@ -2540,11 +2541,11 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
                return ERR_PTR(-EINVAL);
        }
 
-       spin_lock_bh(&adapter->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(adapter))
+       spin_lock_bh(&qdio->req_q_lock);
+       if (zfcp_fsf_req_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(adapter, fsf_cfdc->command, 0, NULL);
+       req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, NULL);
        if (IS_ERR(req)) {
                retval = -EPERM;
                goto out;
@@ -2552,14 +2553,15 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
 
        req->handler = zfcp_fsf_control_file_handler;
 
-       sbale = zfcp_qdio_sbale_req(req);
+       sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
        sbale[0].flags |= direction;
 
        bottom = &req->qtcb->bottom.support;
        bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
        bottom->option = fsf_cfdc->option;
 
-       bytes = zfcp_qdio_sbals_from_sg(req, direction, fsf_cfdc->sg,
+       bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req,
+                                       direction, fsf_cfdc->sg,
                                        FSF_MAX_SBALS_PER_REQ);
        if (bytes != ZFCP_CFDC_MAX_SIZE) {
                zfcp_fsf_req_free(req);
@@ -2569,12 +2571,53 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
        zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
        retval = zfcp_fsf_req_send(req);
 out:
-       spin_unlock_bh(&adapter->req_q_lock);
+       spin_unlock_bh(&qdio->req_q_lock);
 
        if (!retval) {
-               wait_event(req->completion_wq,
-                          req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+               wait_for_completion(&req->completion);
                return req;
        }
        return ERR_PTR(retval);
 }
+
+/**
+ * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO
+ * @adapter: pointer to struct zfcp_adapter
+ * @sbal_idx: response queue index of SBAL to be processed
+ */
+void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
+{
+       struct zfcp_adapter *adapter = qdio->adapter;
+       struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx];
+       struct qdio_buffer_element *sbale;
+       struct zfcp_fsf_req *fsf_req;
+       unsigned long flags, req_id;
+       int idx;
+
+       for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {
+
+               sbale = &sbal->element[idx];
+               req_id = (unsigned long) sbale->addr;
+               spin_lock_irqsave(&adapter->req_list_lock, flags);
+               fsf_req = zfcp_reqlist_find(adapter, req_id);
+
+               if (!fsf_req)
+                       /*
+                        * Unknown request means that we have potentially memory
+                        * corruption and must stop the machine immediately.
+                        */
+                       panic("error: unknown req_id (%lx) on adapter %s.\n",
+                             req_id, dev_name(&adapter->ccw_device->dev));
+
+               list_del(&fsf_req->list);
+               spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+
+               fsf_req->queue_req.sbal_response = sbal_idx;
+               fsf_req->queue_req.qdio_inb_usage =
+                       atomic_read(&qdio->resp_q.count);
+               zfcp_fsf_req_complete(fsf_req);
+
+               if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
+                       break;
+       }
+}
index df7f232..dcc7c1d 100644 (file)
@@ -3,13 +3,14 @@
  *
  * Interface to the FSF support functions.
  *
- * Copyright IBM Corporation 2002, 2008
+ * Copyright IBM Corporation 2002, 2009
  */
 
 #ifndef FSF_H
 #define FSF_H
 
 #include <linux/pfn.h>
+#include <linux/scatterlist.h>
 
 #define FSF_QTCB_CURRENT_VERSION               0x00000001
 
index e0a2153..6c5228b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Setup and helper functions to access QDIO.
  *
- * Copyright IBM Corporation 2002, 2008
+ * Copyright IBM Corporation 2002, 2009
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -34,29 +34,10 @@ zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx)
        return &q->sbal[sbal_idx]->element[sbale_idx];
 }
 
-/**
- * zfcp_qdio_free - free memory used by request- and resposne queue
- * @adapter: pointer to the zfcp_adapter structure
- */
-void zfcp_qdio_free(struct zfcp_adapter *adapter)
+static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id)
 {
-       struct qdio_buffer **sbal_req, **sbal_resp;
-       int p;
-
-       if (adapter->ccw_device)
-               qdio_free(adapter->ccw_device);
-
-       sbal_req = adapter->req_q.sbal;
-       sbal_resp = adapter->resp_q.sbal;
-
-       for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
-               free_page((unsigned long) sbal_req[p]);
-               free_page((unsigned long) sbal_resp[p]);
-       }
-}
+       struct zfcp_adapter *adapter = qdio->adapter;
 
-static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, char *id)
-{
        dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
 
        zfcp_erp_adapter_reopen(adapter,
@@ -75,72 +56,47 @@ static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt)
 }
 
 /* this needs to be called prior to updating the queue fill level */
-static void zfcp_qdio_account(struct zfcp_adapter *adapter)
+static inline void zfcp_qdio_account(struct zfcp_qdio *qdio)
 {
-       ktime_t now;
-       s64 span;
+       unsigned long long now, span;
        int free, used;
 
-       spin_lock(&adapter->qdio_stat_lock);
-       now = ktime_get();
-       span = ktime_us_delta(now, adapter->req_q_time);
-       free = max(0, atomic_read(&adapter->req_q.count));
+       spin_lock(&qdio->stat_lock);
+       now = get_clock_monotonic();
+       span = (now - qdio->req_q_time) >> 12;
+       free = atomic_read(&qdio->req_q.count);
        used = QDIO_MAX_BUFFERS_PER_Q - free;
-       adapter->req_q_util += used * span;
-       adapter->req_q_time = now;
-       spin_unlock(&adapter->qdio_stat_lock);
+       qdio->req_q_util += used * span;
+       qdio->req_q_time = now;
+       spin_unlock(&qdio->stat_lock);
 }
 
 static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
                              int queue_no, int first, int count,
                              unsigned long parm)
 {
-       struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
-       struct zfcp_qdio_queue *queue = &adapter->req_q;
+       struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
+       struct zfcp_qdio_queue *queue = &qdio->req_q;
 
        if (unlikely(qdio_err)) {
-               zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count);
-               zfcp_qdio_handler_error(adapter, "qdireq1");
+               zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, first,
+                                       count);
+               zfcp_qdio_handler_error(qdio, "qdireq1");
                return;
        }
 
        /* cleanup all SBALs being program-owned now */
        zfcp_qdio_zero_sbals(queue->sbal, first, count);
 
-       zfcp_qdio_account(adapter);
+       zfcp_qdio_account(qdio);
        atomic_add(count, &queue->count);
-       wake_up(&adapter->request_wq);
-}
-
-static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
-                                 unsigned long req_id, int sbal_idx)
-{
-       struct zfcp_fsf_req *fsf_req;
-       unsigned long flags;
-
-       spin_lock_irqsave(&adapter->req_list_lock, flags);
-       fsf_req = zfcp_reqlist_find(adapter, req_id);
-
-       if (!fsf_req)
-               /*
-                * Unknown request means that we have potentially memory
-                * corruption and must stop the machine immediatly.
-                */
-               panic("error: unknown request id (%lx) on adapter %s.\n",
-                     req_id, dev_name(&adapter->ccw_device->dev));
-
-       zfcp_reqlist_remove(adapter, fsf_req);
-       spin_unlock_irqrestore(&adapter->req_list_lock, flags);
-
-       fsf_req->sbal_response = sbal_idx;
-       fsf_req->qdio_inb_usage = atomic_read(&adapter->resp_q.count);
-       zfcp_fsf_req_complete(fsf_req);
+       wake_up(&qdio->req_q_wq);
 }
 
-static void zfcp_qdio_resp_put_back(struct zfcp_adapter *adapter, int processed)
+static void zfcp_qdio_resp_put_back(struct zfcp_qdio *qdio, int processed)
 {
-       struct zfcp_qdio_queue *queue = &adapter->resp_q;
-       struct ccw_device *cdev = adapter->ccw_device;
+       struct zfcp_qdio_queue *queue = &qdio->resp_q;
+       struct ccw_device *cdev = qdio->adapter->ccw_device;
        u8 count, start = queue->first;
        unsigned int retval;
 
@@ -162,14 +118,13 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
                               int queue_no, int first, int count,
                               unsigned long parm)
 {
-       struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
-       struct zfcp_qdio_queue *queue = &adapter->resp_q;
-       struct qdio_buffer_element *sbale;
-       int sbal_idx, sbale_idx, sbal_no;
+       struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
+       int sbal_idx, sbal_no;
 
        if (unlikely(qdio_err)) {
-               zfcp_hba_dbf_event_qdio(adapter, qdio_err, first, count);
-               zfcp_qdio_handler_error(adapter, "qdires1");
+               zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, first,
+                                       count);
+               zfcp_qdio_handler_error(qdio, "qdires1");
                return;
        }
 
@@ -179,39 +134,27 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
         */
        for (sbal_no = 0; sbal_no < count; sbal_no++) {
                sbal_idx = (first + sbal_no) % QDIO_MAX_BUFFERS_PER_Q;
-
                /* go through all SBALEs of SBAL */
-               for (sbale_idx = 0; sbale_idx < QDIO_MAX_ELEMENTS_PER_BUFFER;
-                    sbale_idx++) {
-                       sbale = zfcp_qdio_sbale(queue, sbal_idx, sbale_idx);
-                       zfcp_qdio_reqid_check(adapter,
-                                             (unsigned long) sbale->addr,
-                                             sbal_idx);
-                       if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
-                               break;
-               };
-
-               if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY)))
-                       dev_warn(&adapter->ccw_device->dev,
-                                "A QDIO protocol error occurred, "
-                                "operations continue\n");
+               zfcp_fsf_reqid_check(qdio, sbal_idx);
        }
 
        /*
         * put range of SBALs back to response queue
         * (including SBALs which have already been free before)
         */
-       zfcp_qdio_resp_put_back(adapter, count);
+       zfcp_qdio_resp_put_back(qdio, count);
 }
 
 /**
  * zfcp_qdio_sbale_req - return ptr to SBALE of req_q for a struct zfcp_fsf_req
- * @fsf_req: pointer to struct fsf_req
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_rec: pointer to struct zfcp_queue_rec
  * Returns: pointer to qdio_buffer_element (SBALE) structure
  */
-struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_qdio *qdio,
+                                               struct zfcp_queue_req *q_req)
 {
-       return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, 0);
+       return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last, 0);
 }
 
 /**
@@ -219,74 +162,80 @@ struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
  * @fsf_req: pointer to struct fsf_req
  * Returns: pointer to qdio_buffer_element (SBALE) structure
  */
-struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio,
+                                                struct zfcp_queue_req *q_req)
 {
-       return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last,
-                              req->sbale_curr);
+       return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last,
+                              q_req->sbale_curr);
 }
 
-static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
+static void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio,
+                                struct zfcp_queue_req *q_req, int max_sbals)
 {
-       int count = atomic_read(&fsf_req->adapter->req_q.count);
+       int count = atomic_read(&qdio->req_q.count);
        count = min(count, max_sbals);
-       fsf_req->sbal_limit = (fsf_req->sbal_first + count - 1)
+       q_req->sbal_limit = (q_req->sbal_first + count - 1)
                                        % QDIO_MAX_BUFFERS_PER_Q;
 }
 
 static struct qdio_buffer_element *
-zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
+zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req,
+                    unsigned long sbtype)
 {
        struct qdio_buffer_element *sbale;
 
        /* set last entry flag in current SBALE of current SBAL */
-       sbale = zfcp_qdio_sbale_curr(fsf_req);
+       sbale = zfcp_qdio_sbale_curr(qdio, q_req);
        sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
 
        /* don't exceed last allowed SBAL */
-       if (fsf_req->sbal_last == fsf_req->sbal_limit)
+       if (q_req->sbal_last == q_req->sbal_limit)
                return NULL;
 
        /* set chaining flag in first SBALE of current SBAL */
-       sbale = zfcp_qdio_sbale_req(fsf_req);
+       sbale = zfcp_qdio_sbale_req(qdio, q_req);
        sbale->flags |= SBAL_FLAGS0_MORE_SBALS;
 
        /* calculate index of next SBAL */
-       fsf_req->sbal_last++;
-       fsf_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q;
+       q_req->sbal_last++;
+       q_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q;
 
        /* keep this requests number of SBALs up-to-date */
-       fsf_req->sbal_number++;
+       q_req->sbal_number++;
 
        /* start at first SBALE of new SBAL */
-       fsf_req->sbale_curr = 0;
+       q_req->sbale_curr = 0;
 
        /* set storage-block type for new SBAL */
-       sbale = zfcp_qdio_sbale_curr(fsf_req);
+       sbale = zfcp_qdio_sbale_curr(qdio, q_req);
        sbale->flags |= sbtype;
 
        return sbale;
 }
 
 static struct qdio_buffer_element *
-zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
+zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req,
+                    unsigned int sbtype)
 {
-       if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
-               return zfcp_qdio_sbal_chain(fsf_req, sbtype);
-       fsf_req->sbale_curr++;
-       return zfcp_qdio_sbale_curr(fsf_req);
+       if (q_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
+               return zfcp_qdio_sbal_chain(qdio, q_req, sbtype);
+       q_req->sbale_curr++;
+       return zfcp_qdio_sbale_curr(qdio, q_req);
 }
 
-static void zfcp_qdio_undo_sbals(struct zfcp_fsf_req *fsf_req)
+static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio,
+                                struct zfcp_queue_req *q_req)
 {
-       struct qdio_buffer **sbal = fsf_req->adapter->req_q.sbal;
-       int first = fsf_req->sbal_first;
-       int last = fsf_req->sbal_last;
+       struct qdio_buffer **sbal = qdio->req_q.sbal;
+       int first = q_req->sbal_first;
+       int last = q_req->sbal_last;
        int count = (last - first + QDIO_MAX_BUFFERS_PER_Q) %
                QDIO_MAX_BUFFERS_PER_Q + 1;
        zfcp_qdio_zero_sbals(sbal, first, count);
 }
 
-static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
+static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio,
+                               struct zfcp_queue_req *q_req,
                                unsigned int sbtype, void *start_addr,
                                unsigned int total_length)
 {
@@ -297,10 +246,10 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
        /* split segment up */
        for (addr = start_addr, remaining = total_length; remaining > 0;
             addr += length, remaining -= length) {
-               sbale = zfcp_qdio_sbale_next(fsf_req, sbtype);
+               sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
                if (!sbale) {
-                       atomic_inc(&fsf_req->adapter->qdio_outb_full);
-                       zfcp_qdio_undo_sbals(fsf_req);
+                       atomic_inc(&qdio->req_q_full);
+                       zfcp_qdio_undo_sbals(qdio, q_req);
                        return -EINVAL;
                }
 
@@ -322,29 +271,31 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
  * @max_sbals: upper bound for number of SBALs to be used
  * Returns: number of bytes, or error (negativ)
  */
-int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
-                           struct scatterlist *sg, int max_sbals)
+int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio,
+                           struct zfcp_queue_req *q_req,
+                           unsigned long sbtype, struct scatterlist *sg,
+                           int max_sbals)
 {
        struct qdio_buffer_element *sbale;
        int retval, bytes = 0;
 
        /* figure out last allowed SBAL */
-       zfcp_qdio_sbal_limit(fsf_req, max_sbals);
+       zfcp_qdio_sbal_limit(qdio, q_req, max_sbals);
 
        /* set storage-block type for this request */
-       sbale = zfcp_qdio_sbale_req(fsf_req);
+       sbale = zfcp_qdio_sbale_req(qdio, q_req);
        sbale->flags |= sbtype;
 
        for (; sg; sg = sg_next(sg)) {
-               retval = zfcp_qdio_fill_sbals(fsf_req, sbtype, sg_virt(sg),
-                                             sg->length);
+               retval = zfcp_qdio_fill_sbals(qdio, q_req, sbtype,
+                                             sg_virt(sg), sg->length);
                if (retval < 0)
                        return retval;
                bytes += sg->length;
        }
 
        /* assume that no other SBALEs are to follow in the same SBAL */
-       sbale = zfcp_qdio_sbale_curr(fsf_req);
+       sbale = zfcp_qdio_sbale_curr(qdio, q_req);
        sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
 
        return bytes;
@@ -352,21 +303,22 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
 
 /**
  * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO
- * @fsf_req: pointer to struct zfcp_fsf_req
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_req: pointer to struct zfcp_queue_req
  * Returns: 0 on success, error otherwise
  */
-int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
+int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req)
 {
-       struct zfcp_adapter *adapter = fsf_req->adapter;
-       struct zfcp_qdio_queue *req_q = &adapter->req_q;
-       int first = fsf_req->sbal_first;
-       int count = fsf_req->sbal_number;
+       struct zfcp_qdio_queue *req_q = &qdio->req_q;
+       int first = q_req->sbal_first;
+       int count = q_req->sbal_number;
        int retval;
        unsigned int qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
 
-       zfcp_qdio_account(adapter);
+       zfcp_qdio_account(qdio);
 
-       retval = do_QDIO(adapter->ccw_device, qdio_flags, 0, first, count);
+       retval = do_QDIO(qdio->adapter->ccw_device, qdio_flags, 0, first,
+                        count);
        if (unlikely(retval)) {
                zfcp_qdio_zero_sbals(req_q->sbal, first, count);
                return retval;
@@ -379,63 +331,69 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
        return 0;
 }
 
+
+static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
+                                     struct zfcp_qdio *qdio)
+{
+
+       id->cdev = qdio->adapter->ccw_device;
+       id->q_format = QDIO_ZFCP_QFMT;
+       memcpy(id->adapter_name, dev_name(&id->cdev->dev), 8);
+       ASCEBC(id->adapter_name, 8);
+       id->qib_param_field_format = 0;
+       id->qib_param_field = NULL;
+       id->input_slib_elements = NULL;
+       id->output_slib_elements = NULL;
+       id->no_input_qs = 1;
+       id->no_output_qs = 1;
+       id->input_handler = zfcp_qdio_int_resp;
+       id->output_handler = zfcp_qdio_int_req;
+       id->int_parm = (unsigned long) qdio;
+       id->flags = QDIO_INBOUND_0COPY_SBALS |
+                   QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS;
+       id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal);
+       id->output_sbal_addr_array = (void **) (qdio->req_q.sbal);
+
+}
 /**
  * zfcp_qdio_allocate - allocate queue memory and initialize QDIO data
  * @adapter: pointer to struct zfcp_adapter
  * Returns: -ENOMEM on memory allocation error or return value from
  *          qdio_allocate
  */
-int zfcp_qdio_allocate(struct zfcp_adapter *adapter)
+static int zfcp_qdio_allocate(struct zfcp_qdio *qdio)
 {
-       struct qdio_initialize *init_data;
+       struct qdio_initialize init_data;
 
-       if (zfcp_qdio_buffers_enqueue(adapter->req_q.sbal) ||
-                  zfcp_qdio_buffers_enqueue(adapter->resp_q.sbal))
+       if (zfcp_qdio_buffers_enqueue(qdio->req_q.sbal) ||
+           zfcp_qdio_buffers_enqueue(qdio->resp_q.sbal))
                return -ENOMEM;
 
-       init_data = &adapter->qdio_init_data;
-
-       init_data->cdev = adapter->ccw_device;
-       init_data->q_format = QDIO_ZFCP_QFMT;
-       memcpy(init_data->adapter_name, dev_name(&adapter->ccw_device->dev), 8);
-       ASCEBC(init_data->adapter_name, 8);
-       init_data->qib_param_field_format = 0;
-       init_data->qib_param_field = NULL;
-       init_data->input_slib_elements = NULL;
-       init_data->output_slib_elements = NULL;
-       init_data->no_input_qs = 1;
-       init_data->no_output_qs = 1;
-       init_data->input_handler = zfcp_qdio_int_resp;
-       init_data->output_handler = zfcp_qdio_int_req;
-       init_data->int_parm = (unsigned long) adapter;
-       init_data->flags = QDIO_INBOUND_0COPY_SBALS |
-                       QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS;
-       init_data->input_sbal_addr_array =
-                       (void **) (adapter->resp_q.sbal);
-       init_data->output_sbal_addr_array =
-                       (void **) (adapter->req_q.sbal);
-
-       return qdio_allocate(init_data);
+       zfcp_qdio_setup_init_data(&init_data, qdio);
+
+       return qdio_allocate(&init_data);
 }
 
 /**
  * zfcp_close_qdio - close qdio queues for an adapter
+ * @qdio: pointer to structure zfcp_qdio
  */
-void zfcp_qdio_close(struct zfcp_adapter *adapter)
+void zfcp_qdio_close(struct zfcp_qdio *qdio)
 {
        struct zfcp_qdio_queue *req_q;
        int first, count;
 
-       if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
+       if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
                return;
 
        /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
-       req_q = &adapter->req_q;
-       spin_lock_bh(&adapter->req_q_lock);
-       atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
-       spin_unlock_bh(&adapter->req_q_lock);
+       req_q = &qdio->req_q;
+       spin_lock_bh(&qdio->req_q_lock);
+       atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
+       spin_unlock_bh(&qdio->req_q_lock);
 
-       qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
+       qdio_shutdown(qdio->adapter->ccw_device,
+                     QDIO_FLAG_CLEANUP_USING_CLEAR);
 
        /* cleanup used outbound sbals */
        count = atomic_read(&req_q->count);
@@ -446,50 +404,99 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
        }
        req_q->first = 0;
        atomic_set(&req_q->count, 0);
-       adapter->resp_q.first = 0;
-       atomic_set(&adapter->resp_q.count, 0);
+       qdio->resp_q.first = 0;
+       atomic_set(&qdio->resp_q.count, 0);
 }
 
 /**
  * zfcp_qdio_open - prepare and initialize response queue
- * @adapter: pointer to struct zfcp_adapter
+ * @qdio: pointer to struct zfcp_qdio
  * Returns: 0 on success, otherwise -EIO
  */
-int zfcp_qdio_open(struct zfcp_adapter *adapter)
+int zfcp_qdio_open(struct zfcp_qdio *qdio)
 {
        struct qdio_buffer_element *sbale;
+       struct qdio_initialize init_data;
+       struct ccw_device *cdev = qdio->adapter->ccw_device;
        int cc;
 
-       if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
+       if (atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
                return -EIO;
 
-       if (qdio_establish(&adapter->qdio_init_data))
+       zfcp_qdio_setup_init_data(&init_data, qdio);
+
+       if (qdio_establish(&init_data))
                goto failed_establish;
 
-       if (qdio_activate(adapter->ccw_device))
+       if (qdio_activate(cdev))
                goto failed_qdio;
 
        for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
-               sbale = &(adapter->resp_q.sbal[cc]->element[0]);
+               sbale = &(qdio->resp_q.sbal[cc]->element[0]);
                sbale->length = 0;
                sbale->flags = SBAL_FLAGS_LAST_ENTRY;
                sbale->addr = NULL;
        }
 
-       if (do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0,
+       if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0,
                     QDIO_MAX_BUFFERS_PER_Q))
                goto failed_qdio;
 
        /* set index of first avalable SBALS / number of available SBALS */
-       adapter->req_q.first = 0;
-       atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q);
+       qdio->req_q.first = 0;
+       atomic_set(&qdio->req_q.count, QDIO_MAX_BUFFERS_PER_Q);
 
        return 0;
 
 failed_qdio:
-       qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
+       qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
 failed_establish:
-       dev_err(&adapter->ccw_device->dev,
+       dev_err(&cdev->dev,
                "Setting up the QDIO connection to the FCP adapter failed\n");
        return -EIO;
 }
+
+void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
+{
+       struct qdio_buffer **sbal_req, **sbal_resp;
+       int p;
+
+       if (!qdio)
+               return;
+
+       if (qdio->adapter->ccw_device)
+               qdio_free(qdio->adapter->ccw_device);
+
+       sbal_req = qdio->req_q.sbal;
+       sbal_resp = qdio->resp_q.sbal;
+
+       for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
+               free_page((unsigned long) sbal_req[p]);
+               free_page((unsigned long) sbal_resp[p]);
+       }
+
+       kfree(qdio);
+}
+
+int zfcp_qdio_setup(struct zfcp_adapter *adapter)
+{
+       struct zfcp_qdio *qdio;
+
+       qdio = kzalloc(sizeof(struct zfcp_qdio), GFP_KERNEL);
+       if (!qdio)
+               return -ENOMEM;
+
+       qdio->adapter = adapter;
+
+       if (zfcp_qdio_allocate(qdio)) {
+               zfcp_qdio_destroy(qdio);
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&qdio->req_q_lock);
+       spin_lock_init(&qdio->stat_lock);
+
+       adapter->qdio = qdio;
+       return 0;
+}
+
index 6925a17..3ff726a 100644 (file)
@@ -9,8 +9,9 @@
 #define KMSG_COMPONENT "zfcp"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
-#include "zfcp_ext.h"
 #include <asm/atomic.h>
+#include "zfcp_ext.h"
+#include "zfcp_dbf.h"
 
 static unsigned int default_depth = 32;
 module_param_named(queue_depth, default_depth, uint, 0600);
@@ -52,11 +53,11 @@ static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
 
 static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
 {
+       struct zfcp_adapter *adapter =
+               (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
        set_host_byte(scpnt, result);
        if ((scpnt->device != NULL) && (scpnt->device->host != NULL))
-               zfcp_scsi_dbf_event_result("fail", 4,
-                       (struct zfcp_adapter*) scpnt->device->host->hostdata[0],
-                       scpnt, NULL);
+               zfcp_dbf_scsi_result("fail", 4, adapter->dbf, scpnt, NULL);
        /* return directly */
        scpnt->scsi_done(scpnt);
 }
@@ -92,7 +93,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
        scsi_result = fc_remote_port_chkready(rport);
        if (unlikely(scsi_result)) {
                scpnt->result = scsi_result;
-               zfcp_scsi_dbf_event_result("fail", 4, adapter, scpnt, NULL);
+               zfcp_dbf_scsi_result("fail", 4, adapter->dbf, scpnt, NULL);
                scpnt->scsi_done(scpnt);
                return 0;
        }
@@ -180,8 +181,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        spin_unlock(&adapter->req_list_lock);
        if (!old_req) {
                write_unlock_irqrestore(&adapter->abort_lock, flags);
-               zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
-                                         old_reqid);
+               zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL,
+                                   old_reqid);
                return FAILED; /* completion could be in progress */
        }
        old_req->data = NULL;
@@ -197,16 +198,15 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
                zfcp_erp_wait(adapter);
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING)) {
-                       zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
-                                                 old_reqid);
+                       zfcp_dbf_scsi_abort("nres", adapter->dbf, scpnt, NULL,
+                                           old_reqid);
                        return SUCCESS;
                }
        }
        if (!abrt_req)
                return FAILED;
 
-       wait_event(abrt_req->completion_wq,
-                  abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+       wait_for_completion(&abrt_req->completion);
 
        if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
                dbf_tag = "okay";
@@ -216,7 +216,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
                dbf_tag = "fail";
                retval = FAILED;
        }
-       zfcp_scsi_dbf_event_abort(dbf_tag, adapter, scpnt, abrt_req, old_reqid);
+       zfcp_dbf_scsi_abort(dbf_tag, adapter->dbf, scpnt, abrt_req, old_reqid);
        zfcp_fsf_req_free(abrt_req);
        return retval;
 }
@@ -225,7 +225,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 {
        struct zfcp_unit *unit = scpnt->device->hostdata;
        struct zfcp_adapter *adapter = unit->port->adapter;
-       struct zfcp_fsf_req *fsf_req;
+       struct zfcp_fsf_req *fsf_req = NULL;
        int retval = SUCCESS;
        int retry = 3;
 
@@ -237,25 +237,23 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
                zfcp_erp_wait(adapter);
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING)) {
-                       zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit,
-                                                    scpnt);
+                       zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt);
                        return SUCCESS;
                }
        }
        if (!fsf_req)
                return FAILED;
 
-       wait_event(fsf_req->completion_wq,
-                  fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+       wait_for_completion(&fsf_req->completion);
 
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
-               zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt);
+               zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt);
                retval = FAILED;
        } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) {
-               zfcp_scsi_dbf_event_devreset("nsup", tm_flags, unit, scpnt);
+               zfcp_dbf_scsi_devreset("nsup", tm_flags, unit, scpnt);
                retval = FAILED;
        } else
-               zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt);
+               zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt);
 
        zfcp_fsf_req_free(fsf_req);
        return retval;
@@ -430,7 +428,7 @@ static struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *host)
        if (!data)
                return NULL;
 
-       ret = zfcp_fsf_exchange_port_data_sync(adapter, data);
+       ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
        if (ret) {
                kfree(data);
                return NULL;
@@ -459,7 +457,7 @@ static void zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
        if (!data)
                return;
 
-       ret = zfcp_fsf_exchange_port_data_sync(adapter, data);
+       ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
        if (ret)
                kfree(data);
        else {
@@ -493,21 +491,6 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
 }
 
 /**
- * zfcp_scsi_dev_loss_tmo_callbk - Free any reference to rport
- * @rport: The rport that is about to be deleted.
- */
-static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
-{
-       struct zfcp_port *port;
-
-       write_lock_irq(&zfcp_data.config_lock);
-       port = rport->dd_data;
-       if (port)
-               port->rport = NULL;
-       write_unlock_irq(&zfcp_data.config_lock);
-}
-
-/**
  * zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport
  * @rport: The FC rport where to teminate I/O
  *
@@ -518,9 +501,12 @@ static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
 static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
 {
        struct zfcp_port *port;
+       struct Scsi_Host *shost = rport_to_shost(rport);
+       struct zfcp_adapter *adapter =
+               (struct zfcp_adapter *)shost->hostdata[0];
 
        write_lock_irq(&zfcp_data.config_lock);
-       port = rport->dd_data;
+       port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
        if (port)
                zfcp_port_get(port);
        write_unlock_irq(&zfcp_data.config_lock);
@@ -552,7 +538,6 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
                return;
        }
 
-       rport->dd_data = port;
        rport->maxframe_size = port->maxframe_size;
        rport->supported_classes = port->supported_classes;
        port->rport = rport;
@@ -573,7 +558,7 @@ void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
        zfcp_port_get(port);
        port->rport_task = RPORT_ADD;
 
-       if (!queue_work(zfcp_data.work_queue, &port->rport_work))
+       if (!queue_work(port->adapter->work_queue, &port->rport_work))
                zfcp_port_put(port);
 }
 
@@ -582,8 +567,11 @@ void zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
        zfcp_port_get(port);
        port->rport_task = RPORT_DEL;
 
-       if (!queue_work(zfcp_data.work_queue, &port->rport_work))
-               zfcp_port_put(port);
+       if (port->rport && queue_work(port->adapter->work_queue,
+                                     &port->rport_work))
+               return;
+
+       zfcp_port_put(port);
 }
 
 void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
@@ -662,7 +650,6 @@ struct fc_function_template zfcp_transport_functions = {
        .reset_fc_host_stats = zfcp_reset_fc_host_stats,
        .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
        .get_host_port_state = zfcp_get_host_port_state,
-       .dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk,
        .terminate_rport_io = zfcp_scsi_terminate_rport_io,
        .show_host_port_state = 1,
        .bsg_request = zfcp_execute_fc_job,
index 0fe5cce..079a8cf 100644 (file)
@@ -88,7 +88,7 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev,         \
        unsigned long val;                                                     \
        int retval = 0;                                                        \
                                                                               \
-       down(&zfcp_data.config_sema);                                          \
+       mutex_lock(&zfcp_data.config_mutex);                                   \
        if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) {         \
                retval = -EBUSY;                                               \
                goto out;                                                      \
@@ -105,7 +105,7 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev,               \
                                  _reopen_id, NULL);                           \
        zfcp_erp_wait(_adapter);                                               \
 out:                                                                          \
-       up(&zfcp_data.config_sema);                                            \
+       mutex_unlock(&zfcp_data.config_mutex);                                 \
        return retval ? retval : (ssize_t) count;                              \
 }                                                                             \
 static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO,                        \
@@ -126,7 +126,7 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
        if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE)
                return -EBUSY;
 
-       ret = zfcp_scan_ports(adapter);
+       ret = zfcp_fc_scan_ports(adapter);
        return ret ? ret : (ssize_t) count;
 }
 static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
@@ -142,7 +142,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
        int retval = 0;
        LIST_HEAD(port_remove_lh);
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
                retval = -EBUSY;
                goto out;
@@ -173,7 +173,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
        zfcp_port_put(port);
        zfcp_port_dequeue(port);
  out:
-       up(&zfcp_data.config_sema);
+       mutex_unlock(&zfcp_data.config_mutex);
        return retval ? retval : (ssize_t) count;
 }
 static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
@@ -207,7 +207,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
        u64 fcp_lun;
        int retval = -EINVAL;
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
                retval = -EBUSY;
                goto out;
@@ -226,7 +226,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
        zfcp_erp_wait(unit->port->adapter);
        zfcp_unit_put(unit);
 out:
-       up(&zfcp_data.config_sema);
+       mutex_unlock(&zfcp_data.config_mutex);
        return retval ? retval : (ssize_t) count;
 }
 static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
@@ -241,7 +241,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
        int retval = 0;
        LIST_HEAD(unit_remove_lh);
 
-       down(&zfcp_data.config_sema);
+       mutex_lock(&zfcp_data.config_mutex);
        if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
                retval = -EBUSY;
                goto out;
@@ -282,7 +282,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
        zfcp_unit_put(unit);
        zfcp_unit_dequeue(unit);
 out:
-       up(&zfcp_data.config_sema);
+       mutex_unlock(&zfcp_data.config_mutex);
        return retval ? retval : (ssize_t) count;
 }
 static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
@@ -425,7 +425,7 @@ static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
        if (!qtcb_port)
                return -ENOMEM;
 
-       retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
+       retval = zfcp_fsf_exchange_port_data_sync(adapter->qdio, qtcb_port);
        if (!retval)
                retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
                                 qtcb_port->cb_util, qtcb_port->a_util);
@@ -451,7 +451,7 @@ static int zfcp_sysfs_adapter_ex_config(struct device *dev,
        if (!qtcb_config)
                return -ENOMEM;
 
-       retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
+       retval = zfcp_fsf_exchange_config_data_sync(adapter->qdio, qtcb_config);
        if (!retval)
                *stat_inf = qtcb_config->stat_info;
 
@@ -492,15 +492,15 @@ static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
                                              char *buf)
 {
        struct Scsi_Host *scsi_host = class_to_shost(dev);
-       struct zfcp_adapter *adapter =
-               (struct zfcp_adapter *) scsi_host->hostdata[0];
+       struct zfcp_qdio *qdio =
+               ((struct zfcp_adapter *) scsi_host->hostdata[0])->qdio;
        u64 util;
 
-       spin_lock_bh(&adapter->qdio_stat_lock);
-       util = adapter->req_q_util;
-       spin_unlock_bh(&adapter->qdio_stat_lock);
+       spin_lock_bh(&qdio->stat_lock);
+       util = qdio->req_q_util;
+       spin_unlock_bh(&qdio->stat_lock);
 
-       return sprintf(buf, "%d %llu\n", atomic_read(&adapter->qdio_outb_full),
+       return sprintf(buf, "%d %llu\n", atomic_read(&qdio->req_q_full),
                       (unsigned long long)util);
 }
 static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);
index 9c23122..82bb3b2 100644 (file)
@@ -1811,6 +1811,12 @@ config ZFCP
           called zfcp. If you want to compile it as a module, say M here
           and read <file:Documentation/kbuild/modules.txt>.
 
+config SCSI_PMCRAID
+       tristate "PMC SIERRA Linux MaxRAID adapter support"
+       depends on PCI && SCSI
+       ---help---
+         This driver supports the PMC SIERRA MaxRAID adapters.
+
 config SCSI_SRP
        tristate "SCSI RDMA Protocol helper library"
        depends on SCSI && PCI
index 25429ea..61a94af 100644 (file)
@@ -130,6 +130,7 @@ obj-$(CONFIG_SCSI_MVSAS)    += mvsas/
 obj-$(CONFIG_PS3_ROM)          += ps3rom.o
 obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/
 obj-$(CONFIG_SCSI_BNX2_ISCSI)  += libiscsi.o bnx2i/
+obj-$(CONFIG_SCSI_PMCRAID)     += pmcraid.o
 
 obj-$(CONFIG_ARM)              += arm/
 
index ae4b2d5..0c4210d 100644 (file)
 
 static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
 static u32 adapter_count;
-static int bnx2i_reg_device;
 
 #define DRV_MODULE_NAME                "bnx2i"
-#define DRV_MODULE_VERSION     "2.0.1d"
-#define DRV_MODULE_RELDATE     "Mar 25, 2009"
+#define DRV_MODULE_VERSION     "2.0.1e"
+#define DRV_MODULE_RELDATE     "June 22, 2009"
 
 static char version[] __devinitdata =
                "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -31,7 +30,7 @@ MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709 iSCSI Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
-static DEFINE_RWLOCK(bnx2i_dev_lock);
+static DEFINE_MUTEX(bnx2i_dev_lock);
 
 unsigned int event_coal_div = 1;
 module_param(event_coal_div, int, 0664);
@@ -100,14 +99,14 @@ struct bnx2i_hba *get_adapter_list_head(void)
        if (!adapter_count)
                goto hba_not_found;
 
-       read_lock(&bnx2i_dev_lock);
+       mutex_lock(&bnx2i_dev_lock);
        list_for_each_entry(tmp_hba, &adapter_list, link) {
                if (tmp_hba->cnic && tmp_hba->cnic->cm_select_dev) {
                        hba = tmp_hba;
                        break;
                }
        }
-       read_unlock(&bnx2i_dev_lock);
+       mutex_unlock(&bnx2i_dev_lock);
 hba_not_found:
        return hba;
 }
@@ -122,14 +121,14 @@ struct bnx2i_hba *bnx2i_find_hba_for_cnic(struct cnic_dev *cnic)
 {
        struct bnx2i_hba *hba, *temp;
 
-       read_lock(&bnx2i_dev_lock);
+       mutex_lock(&bnx2i_dev_lock);
        list_for_each_entry_safe(hba, temp, &adapter_list, link) {
                if (hba->cnic == cnic) {
-                       read_unlock(&bnx2i_dev_lock);
+                       mutex_unlock(&bnx2i_dev_lock);
                        return hba;
                }
        }
-       read_unlock(&bnx2i_dev_lock);
+       mutex_unlock(&bnx2i_dev_lock);
        return NULL;
 }
 
@@ -186,18 +185,17 @@ void bnx2i_stop(void *handle)
  */
 void bnx2i_register_device(struct bnx2i_hba *hba)
 {
+       int rc;
+
        if (test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state) ||
            test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
                return;
        }
 
-       hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba);
+       rc = hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba);
 
-       spin_lock(&hba->lock);
-       bnx2i_reg_device++;
-       spin_unlock(&hba->lock);
-
-       set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
+       if (!rc)
+               set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
 }
 
 
@@