Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
Linus Torvalds [Fri, 21 May 2010 14:19:18 +0000 (07:19 -0700)]
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (182 commits)
  [SCSI] aacraid: add an ifdef'd device delete case instead of taking the device offline
  [SCSI] aacraid: prohibit access to array container space
  [SCSI] aacraid: add support for handling ATA pass-through commands.
  [SCSI] aacraid: expose physical devices for models with newer firmware
  [SCSI] aacraid: respond automatically to volumes added by config tool
  [SCSI] fcoe: fix fcoe module ref counting
  [SCSI] libfcoe: FIP Keep-Alive messages for VPorts are sent with incorrect port_id and wwn
  [SCSI] libfcoe: Fix incorrect MAC address clearing
  [SCSI] fcoe: fix a circular locking issue with rtnl and sysfs mutex
  [SCSI] libfc: Move the port_id into lport
  [SCSI] fcoe: move link speed checking into its own routine
  [SCSI] libfc: Remove extra pointer check
  [SCSI] libfc: Remove unused fc_get_host_port_type
  [SCSI] fcoe: fixes wrong error exit in fcoe_create
  [SCSI] libfc: set seq_id for incoming sequence
  [SCSI] qla2xxx: Updates to ISP82xx support.
  [SCSI] qla2xxx: Optionally disable target reset.
  [SCSI] qla2xxx: ensure flash operation and host reset via sg_reset are mutually exclusive
  [SCSI] qla2xxx: Silence bogus warning by gcc for wrap and did.
  [SCSI] qla2xxx: T10 DIF support added.
  ...

161 files changed:
MAINTAINERS
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptsas.h
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptspi.c
drivers/s390/scsi/zfcp_aux.c
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_qdio.h
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-9xxx.h
drivers/scsi/3w-xxxx.c
drivers/scsi/3w-xxxx.h
drivers/scsi/Makefile
drivers/scsi/a2091.c
drivers/scsi/a2091.h
drivers/scsi/a3000.c
drivers/scsi/a3000.h
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/commsup.c
drivers/scsi/bfa/bfa_cb_ioim_macros.h
drivers/scsi/bfa/bfa_ioim.c
drivers/scsi/bfa/bfa_os_inc.h
drivers/scsi/bfa/bfad.c
drivers/scsi/bfa/bfad_attr.c
drivers/scsi/bfa/bfad_drv.h
drivers/scsi/bfa/bfad_im.c
drivers/scsi/bfa/bfad_im.h
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/bnx2i/bnx2i_init.c
drivers/scsi/cxgb3i/cxgb3i_init.c
drivers/scsi/device_handler/scsi_dh_emc.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/libfcoe.c
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_fcs.c
drivers/scsi/fnic/fnic_main.c
drivers/scsi/gdth.c
drivers/scsi/gvp11.c
drivers/scsi/gvp11.h
drivers/scsi/hpsa.c
drivers/scsi/hpsa_cmd.h
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvfc.h
drivers/scsi/iscsi_tcp.c
drivers/scsi/iscsi_tcp.h
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_libfc.h
drivers/scsi/libfc/fc_lport.c
drivers/scsi/libfc/fc_npiv.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/libiscsi_tcp.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_bsg.h
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_disc.h
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_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli.h
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/lpfc/lpfc_vport.c
drivers/scsi/mpt2sas/Kconfig
drivers/scsi/mpt2sas/mpi/mpi2.h
drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
drivers/scsi/mpt2sas/mpi/mpi2_history.txt
drivers/scsi/mpt2sas/mpi/mpi2_init.h
drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
drivers/scsi/mpt2sas/mpi/mpi2_tool.h
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_ctl.h
drivers/scsi/mpt2sas/mpt2sas_debug.h
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mpt2sas/mpt2sas_transport.c
drivers/scsi/mvme147.c
drivers/scsi/mvme147.h
drivers/scsi/mvsas/mv_64xx.c
drivers/scsi/mvsas/mv_94xx.c
drivers/scsi/mvsas/mv_init.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/mvsas/mv_sas.h
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pmcraid.c
drivers/scsi/qla2xxx/Makefile
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_bsg.c [new file with mode: 0644]
drivers/scsi/qla2xxx/qla_bsg.h [new file with mode: 0644]
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_dbg.h
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_inline.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_nx.c [new file with mode: 0644]
drivers/scsi/qla2xxx/qla_nx.h [new file with mode: 0644]
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla4xxx/ql4_def.h
drivers/scsi/qla4xxx/ql4_fw.h
drivers/scsi/qla4xxx/ql4_glbl.h
drivers/scsi/qla4xxx/ql4_init.c
drivers/scsi/qla4xxx/ql4_iocb.c
drivers/scsi/qla4xxx/ql4_isr.c
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/qla4xxx/ql4_version.h
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_trace.c [new file with mode: 0644]
drivers/scsi/scsi_transport_fc.c
drivers/scsi/sd.c
drivers/scsi/wd33c93.c
drivers/scsi/wd33c93.h
include/linux/ftrace_event.h
include/scsi/Kbuild
include/scsi/fc/fc_fcp.h
include/scsi/fc_encode.h
include/scsi/libfc.h
include/scsi/libfcoe.h
include/scsi/scsi.h
include/scsi/scsi_transport_fc.h
include/trace/events/scsi.h [new file with mode: 0644]
include/trace/ftrace.h
kernel/trace/trace_output.c

index 22a49e6..601ede3 100644 (file)
@@ -131,19 +131,12 @@ L:        netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/typhoon*
 
-3W-9XXX SATA-RAID CONTROLLER DRIVER
-M:     Adam Radford <linuxraid@amcc.com>
+3WARE SAS/SATA-RAID SCSI DRIVERS (3W-XXXX, 3W-9XXX, 3W-SAS)
+M:     Adam Radford <linuxraid@lsi.com>
 L:     linux-scsi@vger.kernel.org
-W:     http://www.amcc.com
+W:     http://www.lsi.com
 S:     Supported
-F:     drivers/scsi/3w-9xxx*
-
-3W-XXXX ATA-RAID CONTROLLER DRIVER
-M:     Adam Radford <linuxraid@amcc.com>
-L:     linux-scsi@vger.kernel.org
-W:     http://www.amcc.com
-S:     Supported
-F:     drivers/scsi/3w-xxxx*
+F:     drivers/scsi/3w-*
 
 53C700 AND 53C700-66 SCSI DRIVER
 M:     "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
@@ -4621,6 +4614,14 @@ S:       Supported
 F:     Documentation/scsi/LICENSE.qla2xxx
 F:     drivers/scsi/qla2xxx/
 
+QLOGIC QLA4XXX iSCSI DRIVER
+M:     Ravi Anand <ravi.anand@qlogic.com>
+M:     Vikas Chaudhary <vikas.chaudhary@qlogic.com>
+M:     iscsi-driver@qlogic.com
+L:     linux-scsi@vger.kernel.org
+S:     Supported
+F:     drivers/scsi/qla4xxx/
+
 QLOGIC QLA3XXX NETWORK DRIVER
 M:     Ron Mercer <ron.mercer@qlogic.com>
 M:     linux-driver@qlogic.com
index 5382b5a..a6a5701 100644 (file)
@@ -5064,7 +5064,7 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
                if (!timeleft) {
                        printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n",
                            ioc->name, __func__);
-                       mpt_HardResetHandler(ioc, CAN_SLEEP);
+                       mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
                        mpt_free_msg_frame(ioc, mf);
                }
                goto out;
@@ -6456,10 +6456,15 @@ out:
                issue_hard_reset = 0;
                printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
                    ioc->name, __func__);
-               mpt_HardResetHandler(ioc, CAN_SLEEP);
+               if (retry_count == 0) {
+                       if (mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP) != 0)
+                               retry_count++;
+               } else
+                       mpt_HardResetHandler(ioc, CAN_SLEEP);
+
                mpt_free_msg_frame(ioc, mf);
                /* attempt one retry for a timed out command */
-               if (!retry_count) {
+               if (retry_count < 2) {
                        printk(MYIOC_s_INFO_FMT
                            "Attempting Retry Config request"
                            " type 0x%x, page 0x%x,"
@@ -6904,6 +6909,172 @@ mpt_halt_firmware(MPT_ADAPTER *ioc)
 }
 EXPORT_SYMBOL(mpt_halt_firmware);
 
+/**
+ *     mpt_SoftResetHandler - Issues a less expensive reset
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *     @sleepFlag: Indicates if sleep or schedule must be called.
+
+ *
+ *     Returns 0 for SUCCESS or -1 if FAILED.
+ *
+ *     Message Unit Reset - instructs the IOC to reset the Reply Post and
+ *     Free FIFO's. All the Message Frames on Reply Free FIFO are discarded.
+ *     All posted buffers are freed, and event notification is turned off.
+ *     IOC doesnt reply to any outstanding request. This will transfer IOC
+ *     to READY state.
+ **/
+int
+mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
+{
+       int              rc;
+       int              ii;
+       u8               cb_idx;
+       unsigned long    flags;
+       u32              ioc_state;
+       unsigned long    time_count;
+
+       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n",
+               ioc->name));
+
+       ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
+
+       if (mpt_fwfault_debug)
+               mpt_halt_firmware(ioc);
+
+       if (ioc_state == MPI_IOC_STATE_FAULT ||
+           ioc_state == MPI_IOC_STATE_RESET) {
+               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                   "skipping, either in FAULT or RESET state!\n", ioc->name));
+               return -1;
+       }
+
+       if (ioc->bus_type == FC) {
+               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                   "skipping, because the bus type is FC!\n", ioc->name));
+               return -1;
+       }
+
+       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+       if (ioc->ioc_reset_in_progress) {
+               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+               return -1;
+       }
+       ioc->ioc_reset_in_progress = 1;
+       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+
+       rc = -1;
+
+       for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
+               if (MptResetHandlers[cb_idx])
+                       mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
+       }
+
+       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+       if (ioc->taskmgmt_in_progress) {
+               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+               return -1;
+       }
+       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+       /* Disable reply interrupts (also blocks FreeQ) */
+       CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+       ioc->active = 0;
+       time_count = jiffies;
+
+       rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
+
+       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 (rc)
+               goto out;
+
+       ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
+       if (ioc_state != MPI_IOC_STATE_READY)
+               goto out;
+
+       for (ii = 0; ii < 5; ii++) {
+               /* Get IOC facts! Allow 5 retries */
+               rc = GetIocFacts(ioc, sleepFlag,
+                       MPT_HOSTEVENT_IOC_RECOVER);
+               if (rc == 0)
+                       break;
+               if (sleepFlag == CAN_SLEEP)
+                       msleep(100);
+               else
+                       mdelay(100);
+       }
+       if (ii == 5)
+               goto out;
+
+       rc = PrimeIocFifos(ioc);
+       if (rc != 0)
+               goto out;
+
+       rc = SendIocInit(ioc, sleepFlag);
+       if (rc != 0)
+               goto out;
+
+       rc = SendEventNotification(ioc, 1, sleepFlag);
+       if (rc != 0)
+               goto out;
+
+       if (ioc->hard_resets < -1)
+               ioc->hard_resets++;
+
+       /*
+        * At this point, we know soft reset succeeded.
+        */
+
+       ioc->active = 1;
+       CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
+
+ out:
+       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+       ioc->ioc_reset_in_progress = 0;
+       ioc->taskmgmt_quiesce_io = 0;
+       ioc->taskmgmt_in_progress = 0;
+       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+
+       if (ioc->active) {      /* otherwise, hard reset coming */
+               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);
+               }
+       }
+
+       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+               "SoftResetHandler: completed (%d seconds): %s\n",
+               ioc->name, jiffies_to_msecs(jiffies - time_count)/1000,
+               ((rc == 0) ? "SUCCESS" : "FAILED")));
+
+       return rc;
+}
+
+/**
+ *     mpt_Soft_Hard_ResetHandler - Try less expensive reset
+ *     @ioc: Pointer to MPT_ADAPTER structure
+ *     @sleepFlag: Indicates if sleep or schedule must be called.
+
+ *
+ *     Returns 0 for SUCCESS or -1 if FAILED.
+ *     Try for softreset first, only if it fails go for expensive
+ *     HardReset.
+ **/
+int
+mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag) {
+       int ret = -1;
+
+       ret = mpt_SoftResetHandler(ioc, sleepFlag);
+       if (ret == 0)
+               return ret;
+       ret = mpt_HardResetHandler(ioc, sleepFlag);
+       return ret;
+}
+EXPORT_SYMBOL(mpt_Soft_Hard_ResetHandler);
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     Reset Handling
index 9718c8f..b613eb3 100644 (file)
@@ -76,8 +76,8 @@
 #define COPYRIGHT      "Copyright (c) 1999-2008 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON       "3.04.14"
-#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.04.14"
+#define MPT_LINUX_VERSION_COMMON       "3.04.15"
+#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.04.15"
 #define WHAT_MAGIC_STRING              "@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -940,6 +940,7 @@ extern int   mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
 extern u32      mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
 extern void     mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
 extern int      mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
+extern int      mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
 extern int      mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
 extern int      mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
 extern void     mpt_free_fw_memory(MPT_ADAPTER *ioc);
index caa8f56..f06b291 100644 (file)
@@ -128,7 +128,6 @@ static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags
                struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
 static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
                struct buflist *buflist, MPT_ADAPTER *ioc);
-static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function);
 
 /*
  * Reset Handler cleanup function
@@ -275,45 +274,6 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
        return 1;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_timeout_expired
- *
- * Expecting an interrupt, however timed out.
- *
- */
-static void
-mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
-{
-       unsigned long flags;
-
-       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n",
-               ioc->name, __func__));
-
-       if (mpt_fwfault_debug)
-               mpt_halt_firmware(ioc);
-
-       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
-       if (ioc->ioc_reset_in_progress) {
-               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
-               CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
-               mpt_free_msg_frame(ioc, mf);
-               return;
-       }
-       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
-
-
-       if (!mptctl_bus_reset(ioc, mf->u.hdr.Function))
-               return;
-
-       /* Issue a reset for this device.
-        * The IOC is not responding.
-        */
-       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
-                ioc->name));
-       CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
-       mpt_HardResetHandler(ioc, CAN_SLEEP);
-       mpt_free_msg_frame(ioc, mf);
-}
 
 static int
 mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
@@ -343,12 +303,8 @@ mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
        return 0;
 }
 
-/* mptctl_bus_reset
- *
- * Bus reset code.
- *
- */
-static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
+static int
+mptctl_do_taskmgmt(MPT_ADAPTER *ioc, u8 tm_type, u8 bus_id, u8 target_id)
 {
        MPT_FRAME_HDR   *mf;
        SCSITaskMgmt_t  *pScsiTm;
@@ -359,13 +315,6 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
        unsigned long    time_count;
        u16              iocstatus;
 
-       /* bus reset is only good for SCSI IO, RAID PASSTHRU */
-       if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
-               function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
-               dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
-                       "TaskMgmt, not SCSI_IO!!\n", ioc->name));
-               return -EPERM;
-       }
 
        mutex_lock(&ioc->taskmgmt_cmds.mutex);
        if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
@@ -375,15 +324,14 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
 
        retval = 0;
 
-       /* Send request
-        */
        mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc);
        if (mf == NULL) {
-               dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
-                       "TaskMgmt, no msg frames!!\n", ioc->name));
+               dtmprintk(ioc,
+                       printk(MYIOC_s_WARN_FMT "TaskMgmt, no msg frames!!\n",
+                       ioc->name));
                mpt_clear_taskmgmt_in_progress_flag(ioc);
                retval = -ENOMEM;
-               goto mptctl_bus_reset_done;
+               goto tm_done;
        }
 
        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
@@ -392,10 +340,13 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
        pScsiTm = (SCSITaskMgmt_t *) mf;
        memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
        pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
-       pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
-       pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
-       pScsiTm->TargetID = 0;
-       pScsiTm->Bus = 0;
+       pScsiTm->TaskType = tm_type;
+       if ((tm_type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) &&
+               (ioc->bus_type == FC))
+               pScsiTm->MsgFlags =
+                               MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
+       pScsiTm->TargetID = target_id;
+       pScsiTm->Bus = bus_id;
        pScsiTm->ChainOffset = 0;
        pScsiTm->Reserved = 0;
        pScsiTm->Reserved1 = 0;
@@ -413,17 +364,16 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
                timeout = 30;
                break;
        case SPI:
-       default:
-               timeout = 2;
+               default:
+               timeout = 10;
                break;
        }
 
-       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-               "TaskMgmt type=%d timeout=%ld\n",
-               ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout));
+       dtmprintk(ioc,
+               printk(MYIOC_s_DEBUG_FMT "TaskMgmt type=%d timeout=%ld\n",
+               ioc->name, tm_type, timeout));
 
        INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
-       CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
        time_count = jiffies;
        if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
            (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
@@ -432,17 +382,20 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
                retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc,
                    sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP);
                if (retval != 0) {
-                       dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
+                       dfailprintk(ioc,
+                               printk(MYIOC_s_ERR_FMT
                                "TaskMgmt send_handshake FAILED!"
                                " (ioc %p, mf %p, rc=%d) \n", ioc->name,
                                ioc, mf, retval));
+                       mpt_free_msg_frame(ioc, mf);
                        mpt_clear_taskmgmt_in_progress_flag(ioc);
-                       goto mptctl_bus_reset_done;
+                       goto tm_done;
                }
        }
 
        /* Now wait for the command to complete */
        ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
+
        if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                    "TaskMgmt failed\n", ioc->name));
@@ -452,14 +405,14 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
                        retval = 0;
                else
                        retval = -1; /* return failure */
-               goto mptctl_bus_reset_done;
+               goto tm_done;
        }
 
        if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
                    "TaskMgmt failed\n", ioc->name));
                retval = -1; /* return failure */
-               goto mptctl_bus_reset_done;
+               goto tm_done;
        }
 
        pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
@@ -467,7 +420,7 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
            "TaskMgmt fw_channel = %d, fw_id = %d, task_type=0x%02X, "
            "iocstatus=0x%04X\n\tloginfo=0x%08X, response_code=0x%02X, "
            "term_cmnds=%d\n", ioc->name, pScsiTmReply->Bus,
-           pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+           pScsiTmReply->TargetID, tm_type,
            le16_to_cpu(pScsiTmReply->IOCStatus),
            le32_to_cpu(pScsiTmReply->IOCLogInfo),
            pScsiTmReply->ResponseCode,
@@ -485,13 +438,71 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
                retval = -1; /* return failure */
        }
 
-
- mptctl_bus_reset_done:
+ tm_done:
        mutex_unlock(&ioc->taskmgmt_cmds.mutex);
        CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
        return retval;
 }
 
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* mptctl_timeout_expired
+ *
+ * Expecting an interrupt, however timed out.
+ *
+ */
+static void
+mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
+{
+       unsigned long flags;
+       int ret_val = -1;
+       SCSIIORequest_t *scsi_req = (SCSIIORequest_t *) mf;
+       u8 function = mf->u.hdr.Function;
+
+       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n",
+               ioc->name, __func__));
+
+       if (mpt_fwfault_debug)
+               mpt_halt_firmware(ioc);
+
+       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+       if (ioc->ioc_reset_in_progress) {
+               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+               CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
+               mpt_free_msg_frame(ioc, mf);
+               return;
+       }
+       spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+
+
+       CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
+
+       if (ioc->bus_type == SAS) {
+               if (function == MPI_FUNCTION_SCSI_IO_REQUEST)
+                       ret_val = mptctl_do_taskmgmt(ioc,
+                               MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
+                               scsi_req->Bus, scsi_req->TargetID);
+               else if (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
+                       ret_val = mptctl_do_taskmgmt(ioc,
+                               MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+                               scsi_req->Bus, 0);
+               if (!ret_val)
+                       return;
+       } else {
+               if ((function == MPI_FUNCTION_SCSI_IO_REQUEST) ||
+                       (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH))
+                       ret_val = mptctl_do_taskmgmt(ioc,
+                               MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
+                               scsi_req->Bus, 0);
+               if (!ret_val)
+                       return;
+       }
+
+       dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling Reset! \n",
+                ioc->name));
+       mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
+       mpt_free_msg_frame(ioc, mf);
+}
+
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /* mptctl_ioc_reset
@@ -1318,6 +1329,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
        if (ioc->sh) {
                shost_for_each_device(sdev, ioc->sh) {
                        vdevice = sdev->hostdata;
+                       if (vdevice == NULL || vdevice->vtarget == NULL)
+                               continue;
                        if (vdevice->vtarget->tflags &
                            MPT_TARGET_FLAGS_RAID_COMPONENT)
                                continue;
@@ -1439,6 +1452,8 @@ mptctl_gettargetinfo (unsigned long arg)
                        if (!maxWordsLeft)
                                continue;
                        vdevice = sdev->hostdata;
+                       if (vdevice == NULL || vdevice->vtarget == NULL)
+                               continue;
                        if (vdevice->vtarget->tflags &
                            MPT_TARGET_FLAGS_RAID_COMPONENT)
                                continue;
@@ -1967,6 +1982,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
                                struct scsi_target *starget = scsi_target(sdev);
                                VirtTarget *vtarget = starget->hostdata;
 
+                               if (vtarget == NULL)
+                                       continue;
+
                                if ((pScsiReq->TargetID == vtarget->id) &&
                                    (pScsiReq->Bus == vtarget->channel) &&
                                    (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
@@ -2991,6 +3009,14 @@ static int __init mptctl_init(void)
        }
 
        mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER);
+       if (!mptctl_taskmgmt_id || mptctl_taskmgmt_id >= MPT_MAX_PROTOCOL_DRIVERS) {
+               printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n");
+               mpt_deregister(mptctl_id);
+               misc_deregister(&mptctl_miscdev);
+               err = -EBUSY;
+               goto out_fail;
+       }
+
        mpt_reset_register(mptctl_id, mptctl_ioc_reset);
        mpt_event_register(mptctl_id, mptctl_event_process);
 
@@ -3010,12 +3036,15 @@ static void mptctl_exit(void)
        printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",
                         mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
 
+       /* De-register event handler from base module */
+       mpt_event_deregister(mptctl_id);
+
        /* De-register reset handler from base module */
        mpt_reset_deregister(mptctl_id);
 
        /* De-register callback handler from base module */
+       mpt_deregister(mptctl_taskmgmt_id);
        mpt_deregister(mptctl_id);
-       mpt_reset_deregister(mptctl_taskmgmt_id);
 
         mpt_device_driver_deregister(MPTCTL_DRIVER);
 
index 33f7256..b5f03ad 100644 (file)
@@ -482,6 +482,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
                                if (vtarget) {
                                        vtarget->id = pg0->CurrentTargetID;
                                        vtarget->channel = pg0->CurrentBus;
+                                       vtarget->deleted = 0;
                                }
                        }
                        *((struct mptfc_rport_info **)rport->dd_data) = ri;
@@ -1092,6 +1093,8 @@ mptfc_setup_reset(struct work_struct *work)
                container_of(work, MPT_ADAPTER, fc_setup_reset_work);
        u64                     pn;
        struct mptfc_rport_info *ri;
+       struct scsi_target      *starget;
+       VirtTarget              *vtarget;
 
        /* reset about to happen, delete (block) all rports */
        list_for_each_entry(ri, &ioc->fc_rports, list) {
@@ -1099,6 +1102,12 @@ mptfc_setup_reset(struct work_struct *work)
                        ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
                        fc_remote_port_delete(ri->rport);       /* won't sleep */
                        ri->rport = NULL;
+                       starget = ri->starget;
+                       if (starget) {
+                               vtarget = starget->hostdata;
+                               if (vtarget)
+                                       vtarget->deleted = 1;
+                       }
 
                        pn = (u64)ri->pg0.WWPN.High << 32 |
                             (u64)ri->pg0.WWPN.Low;
@@ -1119,6 +1128,8 @@ mptfc_rescan_devices(struct work_struct *work)
        int                     ii;
        u64                     pn;
        struct mptfc_rport_info *ri;
+       struct scsi_target      *starget;
+       VirtTarget              *vtarget;
 
        /* start by tagging all ports as missing */
        list_for_each_entry(ri, &ioc->fc_rports, list) {
@@ -1146,6 +1157,12 @@ mptfc_rescan_devices(struct work_struct *work)
                                       MPT_RPORT_INFO_FLAGS_MISSING);
                        fc_remote_port_delete(ri->rport);       /* won't sleep */
                        ri->rport = NULL;
+                       starget = ri->starget;
+                       if (starget) {
+                               vtarget = starget->hostdata;
+                               if (vtarget)
+                                       vtarget->deleted = 1;
+                       }
 
                        pn = (u64)ri->pg0.WWPN.High << 32 |
                             (u64)ri->pg0.WWPN.Low;
@@ -1358,6 +1375,9 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
        unsigned long flags;
        int rc=1;
 
+       if (ioc->bus_type != FC)
+               return 0;
+
        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
                        ioc->name, event));
 
@@ -1396,7 +1416,7 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
        unsigned long   flags;
 
        rc = mptscsih_ioc_reset(ioc,reset_phase);
-       if (rc == 0)
+       if ((ioc->bus_type != FC) || (!rc))
                return rc;
 
 
index 7668712..ac000e8 100644 (file)
@@ -1894,7 +1894,7 @@ static struct scsi_host_template mptsas_driver_template = {
        .module                         = THIS_MODULE,
        .proc_name                      = "mptsas",
        .proc_info                      = mptscsih_proc_info,
-       .name                           = "MPT SPI Host",
+       .name                           = "MPT SAS Host",
        .info                           = mptscsih_info,
        .queuecommand                   = mptsas_qcmd,
        .target_alloc                   = mptsas_target_alloc,
@@ -2038,11 +2038,13 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
 
        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
                        10 * HZ);
-       if (!timeleft) {
-               /* On timeout reset the board */
+       if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+               error = -ETIME;
                mpt_free_msg_frame(ioc, mf);
-               mpt_HardResetHandler(ioc, CAN_SLEEP);
-               error = -ETIMEDOUT;
+               if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
+                       goto out_unlock;
+               if (!timeleft)
+                       mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
                goto out_unlock;
        }
 
@@ -2223,11 +2225,14 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
 
        timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
-       if (!timeleft) {
-               printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
-               /* On timeout reset the board */
-               mpt_HardResetHandler(ioc, CAN_SLEEP);
-               ret = -ETIMEDOUT;
+       if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+               ret = -ETIME;
+               mpt_free_msg_frame(ioc, mf);
+               mf = NULL;
+               if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
+                       goto unmap;
+               if (!timeleft)
+                       mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
                goto unmap;
        }
        mf = NULL;
@@ -2518,6 +2523,12 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 
        error = mpt_config(ioc, &cfg);
+
+       if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
+               error = -ENODEV;
+               goto out_free_consistent;
+       }
+
        if (error)
                goto out_free_consistent;
 
@@ -2594,14 +2605,14 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
 
        error = mpt_config(ioc, &cfg);
-       if (error)
-               goto out_free_consistent;
-
-       if (!buffer->NumPhys) {
+       if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
                error = -ENODEV;
                goto out_free_consistent;
        }
 
+       if (error)
+               goto out_free_consistent;
+
        /* save config data */
        port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
        port_info->phy_info = kcalloc(port_info->num_phys,
@@ -2677,7 +2688,7 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
 
        if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
                error = -ENODEV;
-               goto out;
+               goto out_free_consistent;
        }
 
        if (error)
@@ -2833,7 +2844,7 @@ mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,
                if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
                        goto out_free;
                if (!timeleft)
-                       mpt_HardResetHandler(ioc, CAN_SLEEP);
+                       mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
                goto out_free;
        }
 
@@ -4098,6 +4109,7 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
        cfg.pageAddr = (channel << 8) + id;
        cfg.cfghdr.hdr = &hdr;
        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+       cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
 
        if (mpt_config(ioc, &cfg) != 0)
                goto out;
@@ -4717,7 +4729,7 @@ mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
        if (issue_reset) {
                printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
                    ioc->name, __func__);
-               mpt_HardResetHandler(ioc, CAN_SLEEP);
+               mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
        }
        mptsas_free_fw_event(ioc, fw_event);
 }
@@ -4779,6 +4791,9 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
        struct fw_event_work *fw_event;
        unsigned long delay;
 
+       if (ioc->bus_type != SAS)
+               return 0;
+
        /* events turned off due to host reset or driver unloading */
        if (ioc->fw_events_off)
                return 0;
@@ -5073,6 +5088,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
        struct mptsas_portinfo *p, *n;
        int i;
 
+       if (!ioc->sh) {
+               printk(MYIOC_s_INFO_FMT "IOC is in Target mode\n", ioc->name);
+               mpt_detach(pdev);
+               return;
+       }
+
        mptsas_shutdown(pdev);
 
        mptsas_del_device_components(ioc);
index 953c2bf..7b249ed 100644 (file)
@@ -110,7 +110,7 @@ struct fw_event_work {
        MPT_ADAPTER     *ioc;
        u32                     event;
        u8                      retries;
-       u8                      event_data[1];
+       u8                      __attribute__((aligned(4))) event_data[1];
 };
 
 struct mptsas_discovery_event {
index 6796597..7bd4c0f 100644 (file)
@@ -1149,11 +1149,6 @@ mptscsih_remove(struct pci_dev *pdev)
        MPT_SCSI_HOST           *hd;
        int sz1;
 
-       if(!host) {
-               mpt_detach(pdev);
-               return;
-       }
-
        scsi_remove_host(host);
 
        if((hd = shost_priv(host)) == NULL)
@@ -1711,7 +1706,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
        if (issue_hard_reset) {
                printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
                        ioc->name, __func__);
-               retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
+               retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
                mpt_free_msg_frame(ioc, mf);
        }
 
@@ -1728,6 +1723,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
        case FC:
                return 40;
        case SAS:
+               return 30;
        case SPI:
        default:
                return 10;
@@ -1777,7 +1773,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
                    ioc->name, SCpnt));
                SCpnt->result = DID_NO_CONNECT << 16;
                SCpnt->scsi_done(SCpnt);
-               retval = 0;
+               retval = SUCCESS;
                goto out;
        }
 
@@ -1792,6 +1788,17 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
                goto out;
        }
 
+       /* Task aborts are not supported for volumes.
+        */
+       if (vdevice->vtarget->raidVolume) {
+               dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+                   "task abort: raid volume (sc=%p)\n",
+                   ioc->name, SCpnt));
+               SCpnt->result = DID_RESET << 16;
+               retval = FAILED;
+               goto out;
+       }
+
        /* Find this command
         */
        if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
@@ -1991,7 +1998,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
        /*  If our attempts to reset the host failed, then return a failed
         *  status.  The host will be taken off line by the SCSI mid-layer.
         */
-    retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
+    retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
        if (retval < 0)
                status = FAILED;
        else
@@ -2344,6 +2351,8 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
        starget = scsi_target(sdev);
        vtarget = starget->hostdata;
        vdevice = sdev->hostdata;
+       if (!vdevice)
+               return;
 
        mptscsih_search_running_cmds(hd, vdevice);
        vtarget->num_luns--;
@@ -3040,7 +3049,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
                if (!timeleft) {
                        printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
                            ioc->name, __func__);
-                       mpt_HardResetHandler(ioc, CAN_SLEEP);
+                       mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
                        mpt_free_msg_frame(ioc, mf);
                }
                goto out;
index e443651..1abaa5d 100644 (file)
@@ -210,6 +210,10 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
        target->maxOffset = offset;
        target->maxWidth = width;
 
+       spi_min_period(scsi_target(sdev)) = factor;
+       spi_max_offset(scsi_target(sdev)) = offset;
+       spi_max_width(scsi_target(sdev)) = width;
+
        target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
 
        /* Disable unused features.
@@ -558,6 +562,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
        cfg.dir = 0;
        cfg.pageAddr = starget->id;
+       cfg.timeout = 60;
 
        if (mpt_config(ioc, &cfg)) {
                starget_printk(KERN_ERR, starget, MYIOC_s_FMT "mpt_config failed\n", ioc->name);
@@ -1152,6 +1157,9 @@ mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
        u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
        struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
 
+       if (ioc->bus_type != SPI)
+               return 0;
+
        if (hd && event ==  MPI_EVENT_INTEGRATED_RAID) {
                int reason
                        = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
@@ -1283,6 +1291,8 @@ mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
        int rc;
 
        rc = mptscsih_ioc_reset(ioc, reset_phase);
+       if ((ioc->bus_type != SPI) || (!rc))
+               return rc;
 
        /* only try to do a renegotiation if we're properly set up
         * if we get an ioc fault on bringup, ioc->sh will be NULL */
index 1e6183a..e331df2 100644 (file)
@@ -425,7 +425,8 @@ int zfcp_status_read_refill(struct zfcp_adapter *adapter)
 {
        while (atomic_read(&adapter->stat_miss) > 0)
                if (zfcp_fsf_status_read(adapter->qdio)) {
-                       if (atomic_read(&adapter->stat_miss) >= 16) {
+                       if (atomic_read(&adapter->stat_miss) >=
+                           adapter->stat_read_buf_num) {
                                zfcp_erp_adapter_reopen(adapter, 0, "axsref1",
                                                        NULL);
                                return 1;
@@ -545,6 +546,10 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
                               &zfcp_sysfs_adapter_attrs))
                goto failed;
 
+       /* report size limit per scatter-gather segment */
+       adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
+       adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
+
        if (!zfcp_adapter_scsi_register(adapter))
                return adapter;
 
index 7131c7d..9fa1b06 100644 (file)
@@ -44,23 +44,6 @@ struct zfcp_reqlist;
 /********************* SCSI SPECIFIC DEFINES *********************************/
 #define ZFCP_SCSI_ER_TIMEOUT                    (10*HZ)
 
-/********************* CIO/QDIO SPECIFIC DEFINES *****************************/
-
-/* DMQ bug workaround: don't use last SBALE */
-#define ZFCP_MAX_SBALES_PER_SBAL       (QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
-
-/* index of last SBALE (with respect to DMQ bug workaround) */
-#define ZFCP_LAST_SBALE_PER_SBAL       (ZFCP_MAX_SBALES_PER_SBAL - 1)
-
-/* max. number of (data buffer) SBALEs in largest SBAL chain */
-#define ZFCP_MAX_SBALES_PER_REQ                \
-       (FSF_MAX_SBALS_PER_REQ * ZFCP_MAX_SBALES_PER_SBAL - 2)
-        /* request ID + QTCB in SBALE 0 + 1 of first SBAL in chain */
-
-#define ZFCP_MAX_SECTORS (ZFCP_MAX_SBALES_PER_REQ * 8)
-        /* max. number of (data buffer) SBALEs in largest SBAL chain
-           multiplied with number of sectors per 4k block */
-
 /********************* FSF SPECIFIC DEFINES *********************************/
 
 /* ATTENTION: value must not be used by hardware */
@@ -181,6 +164,7 @@ struct zfcp_adapter {
                                                      stack abort/command
                                                      completion races */
        atomic_t                stat_miss;         /* # missing status reads*/
+       unsigned int            stat_read_buf_num;
        struct work_struct      stat_work;
        atomic_t                status;            /* status of this adapter */
        struct list_head        erp_ready_head;    /* error recovery for this
@@ -205,6 +189,7 @@ struct zfcp_adapter {
        struct work_struct      scan_work;
        struct service_level    service_level;
        struct workqueue_struct *work_queue;
+       struct device_dma_parameters dma_parms;
 };
 
 struct zfcp_port {
index 0be5e7e..e3dbeda 100644 (file)
@@ -714,7 +714,7 @@ static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)
        if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
                return ZFCP_ERP_FAILED;
 
-       atomic_set(&act->adapter->stat_miss, 16);
+       atomic_set(&act->adapter->stat_miss, act->adapter->stat_read_buf_num);
        if (zfcp_status_read_refill(act->adapter))
                return ZFCP_ERP_FAILED;
 
index 8786a79..48a8f93 100644 (file)
@@ -3,7 +3,7 @@
  *
  * External function declarations.
  *
- * Copyright IBM Corporation 2002, 2009
+ * Copyright IBM Corporation 2002, 2010
  */
 
 #ifndef ZFCP_EXT_H
@@ -143,9 +143,9 @@ extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
 /* zfcp_qdio.c */
 extern int zfcp_qdio_setup(struct zfcp_adapter *);
 extern void zfcp_qdio_destroy(struct zfcp_qdio *);
+extern int zfcp_qdio_sbal_get(struct zfcp_qdio *);
 extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_qdio_req *);
-extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *,
-                                  struct zfcp_qdio_req *, unsigned long,
+extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, struct zfcp_qdio_req *,
                                   struct scatterlist *, int);
 extern int zfcp_qdio_open(struct zfcp_qdio *);
 extern void zfcp_qdio_close(struct zfcp_qdio *);
index 2a1cbb7..6f8ab43 100644 (file)
@@ -400,7 +400,7 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
        struct zfcp_adapter *adapter = port->adapter;
        int ret;
 
-       adisc = kmem_cache_alloc(zfcp_data.adisc_cache, GFP_ATOMIC);
+       adisc = kmem_cache_zalloc(zfcp_data.adisc_cache, GFP_ATOMIC);
        if (!adisc)
                return -ENOMEM;
 
@@ -493,7 +493,7 @@ static struct zfcp_fc_gpn_ft *zfcp_alloc_sg_env(int buf_num)
        if (!gpn_ft)
                return NULL;
 
-       req = kmem_cache_alloc(zfcp_data.gpn_ft_cache, GFP_KERNEL);
+       req = kmem_cache_zalloc(zfcp_data.gpn_ft_cache, GFP_KERNEL);
        if (!req) {
                kfree(gpn_ft);
                gpn_ft = NULL;
index b3b1d2f..9ac6a6e 100644 (file)
@@ -496,6 +496,7 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
 
        adapter->hydra_version = bottom->adapter_type;
        adapter->timer_ticks = bottom->timer_interval;
+       adapter->stat_read_buf_num = max(bottom->status_read_buf_num, (u16)16);
 
        if (fc_host_permanent_port_name(shost) == -1)
                fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
@@ -640,37 +641,6 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
        }
 }
 
-static int zfcp_fsf_sbal_check(struct zfcp_qdio *qdio)
-{
-       struct zfcp_qdio_queue *req_q = &qdio->req_q;
-
-       spin_lock_bh(&qdio->req_q_lock);
-       if (atomic_read(&req_q->count))
-               return 1;
-       spin_unlock_bh(&qdio->req_q_lock);
-       return 0;
-}
-
-static int zfcp_fsf_req_sbal_get(struct zfcp_qdio *qdio)
-{
-       struct zfcp_adapter *adapter = qdio->adapter;
-       long ret;
-
-       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(&qdio->req_q_full);
-               /* assume hanging outbound queue, try queue recovery */
-               zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL);
-       }
-
-       spin_lock_bh(&qdio->req_q_lock);
-       return -EIO;
-}
-
 static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
 {
        struct zfcp_fsf_req *req;
@@ -705,10 +675,9 @@ static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
 }
 
 static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
-                                               u32 fsf_cmd, mempool_t *pool)
+                                               u32 fsf_cmd, u32 sbtype,
+                                               mempool_t *pool)
 {
-       struct qdio_buffer_element *sbale;
-       struct zfcp_qdio_queue *req_q = &qdio->req_q;
        struct zfcp_adapter *adapter = qdio->adapter;
        struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
 
@@ -725,14 +694,6 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
        req->adapter = adapter;
        req->fsf_command = fsf_cmd;
        req->req_id = adapter->req_no;
-       req->qdio_req.sbal_number = 1;
-       req->qdio_req.sbal_first = req_q->first;
-       req->qdio_req.sbal_last = req_q->first;
-       req->qdio_req.sbale_curr = 1;
-
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].addr = (void *) req->req_id;
-       sbale[0].flags |= SBAL_FLAGS0_COMMAND;
 
        if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
                if (likely(pool))
@@ -753,10 +714,11 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
                req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION;
                req->qtcb->header.req_handle = req->req_id;
                req->qtcb->header.fsf_command = req->fsf_command;
-               sbale[1].addr = (void *) req->qtcb;
-               sbale[1].length = sizeof(struct fsf_qtcb);
        }
 
+       zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype,
+                          req->qtcb, sizeof(struct fsf_qtcb));
+
        if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) {
                zfcp_fsf_req_free(req);
                return ERR_PTR(-EIO);
@@ -803,24 +765,19 @@ 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(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS,
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS, 0,
                                  adapter->pool.status_read_req);
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out;
        }
 
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
-       req->qdio_req.sbale_curr = 2;
-
        sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
        if (!sr_buf) {
                retval = -ENOMEM;
@@ -828,9 +785,9 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
        }
        memset(sr_buf, 0, sizeof(*sr_buf));
        req->data = sr_buf;
-       sbale = zfcp_qdio_sbale_curr(qdio, &req->qdio_req);
-       sbale->addr = (void *) sr_buf;
-       sbale->length = sizeof(*sr_buf);
+
+       zfcp_qdio_fill_next(qdio, &req->qdio_req, sr_buf, sizeof(*sr_buf));
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        retval = zfcp_fsf_req_send(req);
        if (retval)
@@ -907,14 +864,14 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
 struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
                                                struct zfcp_unit *unit)
 {
-       struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *req = NULL;
        struct zfcp_qdio *qdio = unit->port->adapter->qdio;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  qdio->adapter->pool.scsi_abort);
        if (IS_ERR(req)) {
                req = NULL;
@@ -925,9 +882,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(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->data = unit;
        req->handler = zfcp_fsf_abort_fcp_command_handler;
@@ -996,21 +951,14 @@ skip_fsfstatus:
                ct->handler(ct->handler_data);
 }
 
-static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale,
+static void zfcp_fsf_setup_ct_els_unchained(struct zfcp_qdio *qdio,
+                                           struct zfcp_qdio_req *q_req,
                                            struct scatterlist *sg_req,
                                            struct scatterlist *sg_resp)
 {
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
-       sbale[2].addr   = sg_virt(sg_req);
-       sbale[2].length = sg_req->length;
-       sbale[3].addr   = sg_virt(sg_resp);
-       sbale[3].length = sg_resp->length;
-       sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
-}
-
-static int zfcp_fsf_one_sbal(struct scatterlist *sg)
-{
-       return sg_is_last(sg) && sg->length <= PAGE_SIZE;
+       zfcp_qdio_fill_next(qdio, q_req, sg_virt(sg_req), sg_req->length);
+       zfcp_qdio_fill_next(qdio, q_req, sg_virt(sg_resp), sg_resp->length);
+       zfcp_qdio_set_sbale_last(qdio, q_req);
 }
 
 static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
@@ -1019,35 +967,34 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
                                       int max_sbals)
 {
        struct zfcp_adapter *adapter = req->adapter;
-       struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio,
-                                                              &req->qdio_req);
        u32 feat = adapter->adapter_features;
        int bytes;
 
        if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
-               if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp))
+               if (!zfcp_qdio_sg_one_sbale(sg_req) ||
+                   !zfcp_qdio_sg_one_sbale(sg_resp))
                        return -EOPNOTSUPP;
 
-               zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
+               zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,
+                                               sg_req, sg_resp);
                return 0;
        }
 
        /* use single, unchained SBAL if it can hold the request */
-       if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) {
-               zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
+       if (zfcp_qdio_sg_one_sbale(sg_req) || zfcp_qdio_sg_one_sbale(sg_resp)) {
+               zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,
+                                               sg_req, sg_resp);
                return 0;
        }
 
        bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req,
-                                       SBAL_FLAGS0_TYPE_WRITE_READ,
                                        sg_req, max_sbals);
        if (bytes <= 0)
                return -EIO;
        req->qtcb->bottom.support.req_buf_length = bytes;
-       req->qdio_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
+       zfcp_qdio_skip_to_last_sbale(&req->qdio_req);
 
        bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req,
-                                       SBAL_FLAGS0_TYPE_WRITE_READ,
                                        sg_resp, max_sbals);
        req->qtcb->bottom.support.resp_buf_length = bytes;
        if (bytes <= 0)
@@ -1091,10 +1038,11 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
        int ret = -EIO;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, pool);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC,
+                                 SBAL_FLAGS0_TYPE_WRITE_READ, pool);
 
        if (IS_ERR(req)) {
                ret = PTR_ERR(req);
@@ -1103,7 +1051,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
        ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp,
-                                   FSF_MAX_SBALS_PER_REQ, timeout);
+                                   ZFCP_FSF_MAX_SBALS_PER_REQ, timeout);
        if (ret)
                goto failed_send;
 
@@ -1187,10 +1135,11 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
        int ret = -EIO;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, NULL);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS,
+                                 SBAL_FLAGS0_TYPE_WRITE_READ, NULL);
 
        if (IS_ERR(req)) {
                ret = PTR_ERR(req);
@@ -1224,16 +1173,16 @@ out:
 
 int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
 {
-       struct qdio_buffer_element *sbale;
        struct zfcp_fsf_req *req;
        struct zfcp_qdio *qdio = erp_action->adapter->qdio;
        int retval = -EIO;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1242,9 +1191,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->qtcb->bottom.config.feature_selection =
                        FSF_FEATURE_CFDC |
@@ -1269,24 +1216,22 @@ out:
 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(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out_unlock;
 
-       req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, NULL);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
+                                 SBAL_FLAGS0_TYPE_READ, NULL);
 
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
                goto out_unlock;
        }
 
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
        req->handler = zfcp_fsf_exchange_config_data_handler;
 
        req->qtcb->bottom.config.feature_selection =
@@ -1320,7 +1265,6 @@ 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;
        int retval = -EIO;
 
@@ -1328,10 +1272,11 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
                return -EOPNOTSUPP;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1340,9 +1285,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->handler = zfcp_fsf_exchange_port_data_handler;
        req->erp_action = erp_action;
@@ -1368,7 +1311,6 @@ out:
 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;
 
@@ -1376,10 +1318,11 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
                return -EOPNOTSUPP;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out_unlock;
 
-       req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, NULL);
+       req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
+                                 SBAL_FLAGS0_TYPE_READ, NULL);
 
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
@@ -1389,9 +1332,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
        if (data)
                req->data = data;
 
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->handler = zfcp_fsf_exchange_port_data_handler;
        zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
@@ -1485,17 +1426,17 @@ out:
  */
 int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
 {
-       struct qdio_buffer_element *sbale;
        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(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1504,9 +1445,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->handler = zfcp_fsf_open_port_handler;
        hton24(req->qtcb->bottom.support.d_id, port->d_id);
@@ -1556,16 +1495,16 @@ 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_qdio *qdio = erp_action->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1574,9 +1513,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->handler = zfcp_fsf_close_port_handler;
        req->data = erp_action->port;
@@ -1633,16 +1570,16 @@ out:
  */
 int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
 {
-       struct qdio_buffer_element *sbale;
        struct zfcp_qdio *qdio = wka_port->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (unlikely(IS_ERR(req))) {
@@ -1651,9 +1588,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->handler = zfcp_fsf_open_wka_port_handler;
        hton24(req->qtcb->bottom.support.d_id, wka_port->d_id);
@@ -1688,16 +1623,16 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
  */
 int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
 {
-       struct qdio_buffer_element *sbale;
        struct zfcp_qdio *qdio = wka_port->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (unlikely(IS_ERR(req))) {
@@ -1706,9 +1641,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->handler = zfcp_fsf_close_wka_port_handler;
        req->data = wka_port;
@@ -1782,16 +1715,16 @@ 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_qdio *qdio = erp_action->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1800,9 +1733,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->data = erp_action->port;
        req->qtcb->header.port_handle = erp_action->port->handle;
@@ -1954,17 +1885,17 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
  */
 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(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -1973,9 +1904,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->qtcb->header.port_handle = erp_action->port->handle;
        req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
@@ -2041,16 +1970,16 @@ 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_qdio *qdio = erp_action->adapter->qdio;
        struct zfcp_fsf_req *req;
        int retval = -EIO;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
+                                 SBAL_FLAGS0_TYPE_READ,
                                  qdio->adapter->pool.erp_req);
 
        if (IS_ERR(req)) {
@@ -2059,9 +1988,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        req->qtcb->header.port_handle = erp_action->port->handle;
        req->qtcb->header.lun_handle = erp_action->unit->handle;
@@ -2289,8 +2216,11 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
                goto out;
        }
 
+       if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE)
+               sbtype = SBAL_FLAGS0_TYPE_WRITE;
+
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
-                                 adapter->pool.scsi_req);
+                                 sbtype, adapter->pool.scsi_req);
 
        if (IS_ERR(req)) {
                retval = PTR_ERR(req);
@@ -2298,7 +2228,6 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
        }
 
        req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-       get_device(&unit->dev);
        req->unit = unit;
        req->data = scsi_cmnd;
        req->handler = zfcp_fsf_send_fcp_command_handler;
@@ -2323,20 +2252,21 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
                break;
        case DMA_TO_DEVICE:
                req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
-               sbtype = SBAL_FLAGS0_TYPE_WRITE;
                break;
        case DMA_BIDIRECTIONAL:
                goto failed_scsi_cmnd;
        }
 
+       get_device(&unit->dev);
+
        fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
        zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
 
-       real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sbtype,
+       real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
                                             scsi_sglist(scsi_cmnd),
-                                            FSF_MAX_SBALS_PER_REQ);
+                                            ZFCP_FSF_MAX_SBALS_PER_REQ);
        if (unlikely(real_bytes < 0)) {
-               if (req->qdio_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) {
+               if (req->qdio_req.sbal_number >= ZFCP_FSF_MAX_SBALS_PER_REQ) {
                        dev_err(&adapter->ccw_device->dev,
                                "Oversize data package, unit 0x%016Lx "
                                "on port 0x%016Lx closed\n",
@@ -2371,7 +2301,6 @@ out:
  */
 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 *fcp_cmnd;
        struct zfcp_qdio *qdio = unit->port->adapter->qdio;
@@ -2381,10 +2310,11 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
                return NULL;
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
        req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
+                                 SBAL_FLAGS0_TYPE_WRITE,
                                  qdio->adapter->pool.scsi_req);
 
        if (IS_ERR(req)) {
@@ -2401,9 +2331,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
        req->qtcb->bottom.io.service_class = FSF_CLASS_3;
        req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
 
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req);
-       sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
-       sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+       zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
        fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
        zfcp_fc_fcp_tm(fcp_cmnd, unit->device, tm_flags);
@@ -2432,7 +2360,6 @@ static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
 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;
@@ -2453,10 +2380,10 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
        }
 
        spin_lock_bh(&qdio->req_q_lock);
-       if (zfcp_fsf_req_sbal_get(qdio))
+       if (zfcp_qdio_sbal_get(qdio))
                goto out;
 
-       req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, NULL);
+       req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, direction, NULL);
        if (IS_ERR(req)) {
                retval = -EPERM;
                goto out;
@@ -2464,16 +2391,13 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
 
        req->handler = zfcp_fsf_control_file_handler;
 
-       sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_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(qdio, &req->qdio_req,
-                                       direction, fsf_cfdc->sg,
-                                       FSF_MAX_SBALS_PER_REQ);
+                                       fsf_cfdc->sg,
+                                       ZFCP_FSF_MAX_SBALS_PER_REQ);
        if (bytes != ZFCP_CFDC_MAX_SIZE) {
                zfcp_fsf_req_free(req);
                goto out;
index b3de682..519083f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Interface to the FSF support functions.
  *
- * Copyright IBM Corporation 2002, 2009
+ * Copyright IBM Corporation 2002, 2010
  */
 
 #ifndef FSF_H
 #define FSF_CLASS_3                            0x00000003
 
 /* SBAL chaining */
-#define FSF_MAX_SBALS_PER_REQ                  36
+#define ZFCP_FSF_MAX_SBALS_PER_REQ             36
+
+/* max. number of (data buffer) SBALEs in largest SBAL chain
+ * request ID + QTCB in SBALE 0 + 1 of first SBAL in chain   */
+#define ZFCP_FSF_MAX_SBALES_PER_REQ    \
+       (ZFCP_FSF_MAX_SBALS_PER_REQ * ZFCP_QDIO_MAX_SBALES_PER_SBAL - 2)
 
 /* logging space behind QTCB */
 #define FSF_QTCB_LOG_SIZE                      1024
@@ -361,7 +366,7 @@ struct fsf_qtcb_bottom_config {
        u32 adapter_type;
        u8 res0;
        u8 peer_d_id[3];
-       u8 res1[2];
+       u16 status_read_buf_num;
        u16 timer_interval;
        u8 res2[9];
        u8 s_id[3];
index dbfa312..28117e1 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Setup and helper functions to access QDIO.
  *
- * Copyright IBM Corporation 2002, 2009
+ * Copyright IBM Corporation 2002, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -151,8 +151,7 @@ static void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio,
 }
 
 static struct qdio_buffer_element *
-zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
-                    unsigned long sbtype)
+zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
 {
        struct qdio_buffer_element *sbale;
 
@@ -180,17 +179,16 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
 
        /* set storage-block type for new SBAL */
        sbale = zfcp_qdio_sbale_curr(qdio, q_req);
-       sbale->flags |= sbtype;
+       sbale->flags |= q_req->sbtype;
 
        return sbale;
 }
 
 static struct qdio_buffer_element *
-zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
-                    unsigned int sbtype)
+zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
 {
-       if (q_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
-               return zfcp_qdio_sbal_chain(qdio, q_req, sbtype);
+       if (q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL)
+               return zfcp_qdio_sbal_chain(qdio, q_req);
        q_req->sbale_curr++;
        return zfcp_qdio_sbale_curr(qdio, q_req);
 }
@@ -206,62 +204,38 @@ static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio,
        zfcp_qdio_zero_sbals(sbal, first, count);
 }
 
-static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio,
-                               struct zfcp_qdio_req *q_req,
-                               unsigned int sbtype, void *start_addr,
-                               unsigned int total_length)
-{
-       struct qdio_buffer_element *sbale;
-       unsigned long remaining, length;
-       void *addr;
-
-       /* split segment up */
-       for (addr = start_addr, remaining = total_length; remaining > 0;
-            addr += length, remaining -= length) {
-               sbale = zfcp_qdio_sbale_next(qdio, q_req, sbtype);
-               if (!sbale) {
-                       atomic_inc(&qdio->req_q_full);
-                       zfcp_qdio_undo_sbals(qdio, q_req);
-                       return -EINVAL;
-               }
-
-               /* new piece must not exceed next page boundary */
-               length = min(remaining,
-                            (PAGE_SIZE - ((unsigned long)addr &
-                                          (PAGE_SIZE - 1))));
-               sbale->addr = addr;
-               sbale->length = length;
-       }
-       return 0;
-}
-
 /**
  * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
- * @fsf_req: request to be processed
- * @sbtype: SBALE flags
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_req: pointer to struct zfcp_qdio_req
  * @sg: scatter-gather list
  * @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_qdio *qdio, struct zfcp_qdio_req *q_req,
-                           unsigned long sbtype, struct scatterlist *sg,
-                           int max_sbals)
+                           struct scatterlist *sg, int max_sbals)
 {
        struct qdio_buffer_element *sbale;
-       int retval, bytes = 0;
+       int bytes = 0;
 
        /* figure out last allowed SBAL */
        zfcp_qdio_sbal_limit(qdio, q_req, max_sbals);
 
        /* set storage-block type for this request */
        sbale = zfcp_qdio_sbale_req(qdio, q_req);
-       sbale->flags |= sbtype;
+       sbale->flags |= q_req->sbtype;
 
        for (; sg; sg = sg_next(sg)) {
-               retval = zfcp_qdio_fill_sbals(qdio, q_req, sbtype,
-                                             sg_virt(sg), sg->length);
-               if (retval < 0)
-                       return retval;
+               sbale = zfcp_qdio_sbale_next(qdio, q_req);
+               if (!sbale) {
+                       atomic_inc(&qdio->req_q_full);
+                       zfcp_qdio_undo_sbals(qdio, q_req);
+                       return -EINVAL;
+               }
+
+               sbale->addr = sg_virt(sg);
+               sbale->length = sg->length;
+
                bytes += sg->length;
        }
 
@@ -272,6 +246,46 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
        return bytes;
 }
 
+static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
+{
+       struct zfcp_qdio_queue *req_q = &qdio->req_q;
+
+       spin_lock_bh(&qdio->req_q_lock);
+       if (atomic_read(&req_q->count))
+               return 1;
+       spin_unlock_bh(&qdio->req_q_lock);
+       return 0;
+}
+
+/**
+ * zfcp_qdio_sbal_get - get free sbal in request queue, wait if necessary
+ * @qdio: pointer to struct zfcp_qdio
+ *
+ * The req_q_lock must be held by the caller of this function, and
+ * this function may only be called from process context; it will
+ * sleep when waiting for a free sbal.
+ *
+ * Returns: 0 on success, -EIO if there is no free sbal after waiting.
+ */
+int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio)
+{
+       long ret;
+
+       spin_unlock_bh(&qdio->req_q_lock);
+       ret = wait_event_interruptible_timeout(qdio->req_q_wq,
+                              zfcp_qdio_sbal_check(qdio), 5 * HZ);
+       if (ret > 0)
+               return 0;
+       if (!ret) {
+               atomic_inc(&qdio->req_q_full);
+               /* assume hanging outbound queue, try queue recovery */
+               zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL);
+       }
+
+       spin_lock_bh(&qdio->req_q_lock);
+       return -EIO;
+}
+
 /**
  * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO
  * @qdio: pointer to struct zfcp_qdio
index 8cca546..138fba5 100644 (file)
 
 #include <asm/qdio.h>
 
+#define ZFCP_QDIO_SBALE_LEN    PAGE_SIZE
+
+/* DMQ bug workaround: don't use last SBALE */
+#define ZFCP_QDIO_MAX_SBALES_PER_SBAL  (QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
+
+/* index of last SBALE (with respect to DMQ bug workaround) */
+#define ZFCP_QDIO_LAST_SBALE_PER_SBAL  (ZFCP_QDIO_MAX_SBALES_PER_SBAL - 1)
+
 /**
  * struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count
  * @sbal: qdio buffers
@@ -49,6 +57,7 @@ struct zfcp_qdio {
 
 /**
  * struct zfcp_qdio_req - qdio queue related values for a request
+ * @sbtype: sbal type flags for sbale 0
  * @sbal_number: number of free sbals
  * @sbal_first: first sbal for this request
  * @sbal_last: last sbal for this request
@@ -59,6 +68,7 @@ struct zfcp_qdio {
  * @qdio_inb_usage: usage of inbound queue
  */
 struct zfcp_qdio_req {
+       u32     sbtype;
        u8      sbal_number;
        u8      sbal_first;
        u8      sbal_last;
@@ -106,4 +116,98 @@ zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req)
                               q_req->sbale_curr);
 }
 
+/**
+ * zfcp_qdio_req_init - initialize qdio request
+ * @qdio: request queue where to start putting the request
+ * @q_req: the qdio request to start
+ * @req_id: The request id
+ * @sbtype: type flags to set for all sbals
+ * @data: First data block
+ * @len: Length of first data block
+ *
+ * This is the start of putting the request into the queue, the last
+ * step is passing the request to zfcp_qdio_send. The request queue
+ * lock must be held during the whole process from init to send.
+ */
+static inline
+void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
+                       unsigned long req_id, u32 sbtype, void *data, u32 len)
+{
+       struct qdio_buffer_element *sbale;
+
+       q_req->sbal_first = q_req->sbal_last = qdio->req_q.first;
+       q_req->sbal_number = 1;
+       q_req->sbtype = sbtype;
+
+       sbale = zfcp_qdio_sbale_req(qdio, q_req);
+       sbale->addr = (void *) req_id;
+       sbale->flags |= SBAL_FLAGS0_COMMAND;
+       sbale->flags |= sbtype;
+
+       q_req->sbale_curr = 1;
+       sbale++;
+       sbale->addr = data;
+       if (likely(data))
+               sbale->length = len;
+}
+
+/**
+ * zfcp_qdio_fill_next - Fill next sbale, only for single sbal requests
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_req: pointer to struct zfcp_queue_req
+ *
+ * This is only required for single sbal requests, calling it when
+ * wrapping around to the next sbal is a bug.
+ */
+static inline
+void zfcp_qdio_fill_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
+                        void *data, u32 len)
+{
+       struct qdio_buffer_element *sbale;
+
+       BUG_ON(q_req->sbale_curr == ZFCP_QDIO_LAST_SBALE_PER_SBAL);
+       q_req->sbale_curr++;
+       sbale = zfcp_qdio_sbale_curr(qdio, q_req);
+       sbale->addr = data;
+       sbale->length = len;
+}
+
+/**
+ * zfcp_qdio_set_sbale_last - set last entry flag in current sbale
+ * @qdio: pointer to struct zfcp_qdio
+ * @q_req: pointer to struct zfcp_queue_req
+ */
+static inline
+void zfcp_qdio_set_sbale_last(struct zfcp_qdio *qdio,
+                             struct zfcp_qdio_req *q_req)
+{
+       struct qdio_buffer_element *sbale;
+
+       sbale = zfcp_qdio_sbale_curr(qdio, q_req);
+       sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
+}
+
+/**
+ * zfcp_qdio_sg_one_sbal - check if one sbale is enough for sg data
+ * @sg: The scatterlist where to check the data size
+ *
+ * Returns: 1 when one sbale is enough for the data in the scatterlist,
+ *         0 if not.
+ */
+static inline
+int zfcp_qdio_sg_one_sbale(struct scatterlist *sg)
+{
+       return sg_is_last(sg) && sg->length <= ZFCP_QDIO_SBALE_LEN;
+}
+
+/**
+ * zfcp_qdio_skip_to_last_sbale - skip to last sbale in sbal
+ * @q_req: The current zfcp_qdio_req
+ */
+static inline
+void zfcp_qdio_skip_to_last_sbale(struct zfcp_qdio_req *q_req)
+{
+       q_req->sbale_curr = ZFCP_QDIO_LAST_SBALE_PER_SBAL;
+}
+
 #endif /* ZFCP_QDIO_H */
index 174b6d5..be5d2c6 100644 (file)
@@ -175,7 +175,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        struct zfcp_fsf_req *old_req, *abrt_req;
        unsigned long flags;
        unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
-       int retval = SUCCESS;
+       int retval = SUCCESS, ret;
        int retry = 3;
        char *dbf_tag;
 
@@ -200,7 +200,9 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
                        break;
 
                zfcp_erp_wait(adapter);
-               fc_block_scsi_eh(scpnt);
+               ret = fc_block_scsi_eh(scpnt);
+               if (ret)
+                       return ret;
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING)) {
                        zfcp_dbf_scsi_abort("nres", adapter->dbf, scpnt, NULL,
@@ -231,7 +233,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 = NULL;
-       int retval = SUCCESS;
+       int retval = SUCCESS, ret;
        int retry = 3;
 
        while (retry--) {
@@ -240,7 +242,10 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
                        break;
 
                zfcp_erp_wait(adapter);
-               fc_block_scsi_eh(scpnt);
+               ret = fc_block_scsi_eh(scpnt);
+               if (ret)
+                       return ret;
+
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING)) {
                        zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt);
@@ -276,10 +281,13 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
        struct zfcp_unit *unit = scpnt->device->hostdata;
        struct zfcp_adapter *adapter = unit->port->adapter;
+       int ret;
 
        zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
        zfcp_erp_wait(adapter);
-       fc_block_scsi_eh(scpnt);
+       ret = fc_block_scsi_eh(scpnt);
+       if (ret)
+               return ret;
 
        return SUCCESS;
 }
@@ -669,11 +677,12 @@ struct zfcp_data zfcp_data = {
                .eh_host_reset_handler   = zfcp_scsi_eh_host_reset_handler,
                .can_queue               = 4096,
                .this_id                 = -1,
-               .sg_tablesize            = ZFCP_MAX_SBALES_PER_REQ,
+               .sg_tablesize            = ZFCP_FSF_MAX_SBALES_PER_REQ,
                .cmd_per_lun             = 1,
                .use_clustering          = 1,
                .sdev_attrs              = zfcp_sysfs_sdev_attrs,
-               .max_sectors             = (ZFCP_MAX_SBALES_PER_REQ * 8),
+               .max_sectors             = (ZFCP_FSF_MAX_SBALES_PER_REQ * 8),
+               .dma_boundary            = ZFCP_QDIO_SBALE_LEN - 1,
                .shost_attrs             = zfcp_sysfs_shost_attrs,
        },
 };
index e9788f5..1bb774b 100644 (file)
@@ -1,10 +1,11 @@
 /*
    3w-9xxx.c -- 3ware 9000 Storage Controller device driver for Linux.
 
-   Written By: Adam Radford <linuxraid@amcc.com>
-   Modifications By: Tom Couch <linuxraid@amcc.com>
+   Written By: Adam Radford <linuxraid@lsi.com>
+   Modifications By: Tom Couch <linuxraid@lsi.com>
 
    Copyright (C) 2004-2009 Applied Micro Circuits Corporation.
+   Copyright (C) 2010 LSI Corporation.
 
    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
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
    Bugs/Comments/Suggestions should be mailed to:
-   linuxraid@amcc.com
+   linuxraid@lsi.com
 
    For more information, goto:
-   http://www.amcc.com
+   http://www.lsi.com
 
    Note: This version of the driver does not contain a bundled firmware
          image.
@@ -77,6 +78,7 @@
                  Use pci_resource_len() for ioremap().
    2.26.02.012 - Add power management support.
    2.26.02.013 - Fix bug in twa_load_sgl().
+   2.26.02.014 - Force 60 second timeout default.
 */
 
 #include <linux/module.h>
 #include "3w-9xxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "2.26.02.013"
+#define TW_DRIVER_VERSION "2.26.02.014"
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
 extern struct timezone sys_tz;
 
 /* Module parameters */
-MODULE_AUTHOR ("AMCC");
+MODULE_AUTHOR ("LSI");
 MODULE_DESCRIPTION ("3ware 9000 Storage Controller Linux Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(TW_DRIVER_VERSION);
@@ -1990,6 +1992,15 @@ static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
                scsi_dma_unmap(cmd);
 } /* End twa_unmap_scsi_data() */
 
+/* This function gets called when a disk is coming on-line */
+static int twa_slave_configure(struct scsi_device *sdev)
+{
+       /* Force 60 second timeout */
+       blk_queue_rq_timeout(sdev->request_queue, 60 * HZ);
+
+       return 0;
+} /* End twa_slave_configure() */
+
 /* scsi_host_template initializer */
 static struct scsi_host_template driver_template = {
        .module                 = THIS_MODULE,
@@ -1999,6 +2010,7 @@ static struct scsi_host_template driver_template = {
        .bios_param             = twa_scsi_biosparam,
        .change_queue_depth     = twa_change_queue_depth,
        .can_queue              = TW_Q_LENGTH-2,
+       .slave_configure        = twa_slave_configure,
        .this_id                = -1,
        .sg_tablesize           = TW_APACHE_MAX_SGL_LENGTH,
        .max_sectors            = TW_MAX_SECTORS,
index 2893eec..3343824 100644 (file)
@@ -1,10 +1,11 @@
 /*
    3w-9xxx.h -- 3ware 9000 Storage Controller device driver for Linux.
 
-   Written By: Adam Radford <linuxraid@amcc.com>
-   Modifications By: Tom Couch <linuxraid@amcc.com>
+   Written By: Adam Radford <linuxraid@lsi.com>
+   Modifications By: Tom Couch <linuxraid@lsi.com>
 
    Copyright (C) 2004-2009 Applied Micro Circuits Corporation.
+   Copyright (C) 2010 LSI Corporation.
 
    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
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
    Bugs/Comments/Suggestions should be mailed to:
-   linuxraid@amcc.com
+   linuxraid@lsi.com
 
    For more information, goto:
-   http://www.amcc.com
+   http://www.lsi.com
 */
 
 #ifndef _3W_9XXX_H
index 5faf903..d119a61 100644 (file)
@@ -1,12 +1,12 @@
 /* 
    3w-xxxx.c -- 3ware Storage Controller device driver for Linux.
 
-   Written By: Adam Radford <linuxraid@amcc.com>
+   Written By: Adam Radford <linuxraid@lsi.com>
    Modifications By: Joel Jacobson <linux@3ware.com>
                     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
                      Brad Strand <linux@3ware.com>
 
-   Copyright (C) 1999-2009 3ware Inc.
+   Copyright (C) 1999-2010 3ware Inc.
 
    Kernel compatibility By:    Andre Hedrick <andre@suse.com>
    Non-Copyright (C) 2000      Andre Hedrick <andre@suse.com>
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
    Bugs/Comments/Suggestions should be mailed to:                            
-   linuxraid@amcc.com
+   linuxraid@lsi.com
 
    For more information, goto:
-   http://www.amcc.com
+   http://www.lsi.com
 
    History
    -------
    1.26.02.002 - Free irq handler in __tw_shutdown().
                  Turn on RCD bit for caching mode page.
                  Serialize reset code.
+   1.26.02.003 - Force 60 second timeout default.
 */
 
 #include <linux/module.h>
 #include "3w-xxxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "1.26.02.002"
+#define TW_DRIVER_VERSION "1.26.02.003"
 static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 static int tw_device_extension_count = 0;
 static int twe_major = -1;
 
 /* Module parameters */
-MODULE_AUTHOR("AMCC");
+MODULE_AUTHOR("LSI");
 MODULE_DESCRIPTION("3ware Storage Controller Linux Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(TW_DRIVER_VERSION);
@@ -2245,6 +2246,15 @@ static void tw_shutdown(struct pci_dev *pdev)
        __tw_shutdown(tw_dev);
 } /* End tw_shutdown() */
 
+/* This function gets called when a disk is coming online */
+static int tw_slave_configure(struct scsi_device *sdev)
+{
+       /* Force 60 second timeout */
+       blk_queue_rq_timeout(sdev->request_queue, 60 * HZ);
+
+       return 0;
+} /* End tw_slave_configure() */
+
 static struct scsi_host_template driver_template = {
        .module                 = THIS_MODULE,
        .name                   = "3ware Storage Controller",
@@ -2253,6 +2263,7 @@ static struct scsi_host_template driver_template = {
        .bios_param             = tw_scsi_biosparam,
        .change_queue_depth     = tw_change_queue_depth,
        .can_queue              = TW_Q_LENGTH-2,
+       .slave_configure        = tw_slave_configure,
        .this_id                = -1,
        .sg_tablesize           = TW_MAX_SGL_LENGTH,
        .max_sectors            = TW_MAX_SECTORS,
index a5a2ba2..8b9f9d1 100644 (file)
@@ -1,12 +1,12 @@
 /* 
    3w-xxxx.h -- 3ware Storage Controller device driver for Linux.
    
-   Written By: Adam Radford <linuxraid@amcc.com>
+   Written By: Adam Radford <linuxraid@lsi.com>
    Modifications By: Joel Jacobson <linux@3ware.com>
                     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
                      Brad Strand <linux@3ware.com>
 
-   Copyright (C) 1999-2009 3ware Inc.
+   Copyright (C) 1999-2010 3ware Inc.
 
    Kernel compatiblity By:     Andre Hedrick <andre@suse.com>
    Non-Copyright (C) 2000      Andre Hedrick <andre@suse.com>
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
    Bugs/Comments/Suggestions should be mailed to:                            
-   linuxraid@amcc.com
+   linuxraid@lsi.com
    
    For more information, goto:
-   http://www.amcc.com
+   http://www.lsi.com
 */
 
 #ifndef _3W_XXXX_H
index 92a8c50..1c7ac49 100644 (file)
@@ -162,6 +162,7 @@ scsi_mod-y                  += scsi_scan.o scsi_sysfs.o scsi_devinfo.o
 scsi_mod-$(CONFIG_SCSI_NETLINK)        += scsi_netlink.o
 scsi_mod-$(CONFIG_SYSCTL)      += scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)        += scsi_proc.o
+scsi_mod-y                     += scsi_trace.o
 
 scsi_tgt-y                     += scsi_tgt_lib.o scsi_tgt_if.o
 
index d8fe5b7..308541f 100644 (file)
 #include "wd33c93.h"
 #include "a2091.h"
 
-#include<linux/stat.h>
+#include <linux/stat.h>
 
-#define DMA(ptr) ((a2091_scsiregs *)((ptr)->base))
-#define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
 
 static int a2091_release(struct Scsi_Host *instance);
 
-static irqreturn_t a2091_intr (int irq, void *_instance)
+static irqreturn_t a2091_intr(int irq, void *data)
 {
-    unsigned long flags;
-    unsigned int status;
-    struct Scsi_Host *instance = (struct Scsi_Host *)_instance;
-
-    status = DMA(instance)->ISTR;
-    if (!(status & (ISTR_INT_F|ISTR_INT_P)) || !(status & ISTR_INTS))
-       return IRQ_NONE;
-
-    spin_lock_irqsave(instance->host_lock, flags);
-    wd33c93_intr(instance);
-    spin_unlock_irqrestore(instance->host_lock, flags);
-    return IRQ_HANDLED;
+       struct Scsi_Host *instance = data;
+       a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base);
+       unsigned int status = regs->ISTR;
+       unsigned long flags;
+
+       if (!(status & (ISTR_INT_F | ISTR_INT_P)) || !(status & ISTR_INTS))
+               return IRQ_NONE;
+
+       spin_lock_irqsave(instance->host_lock, flags);
+       wd33c93_intr(instance);
+       spin_unlock_irqrestore(instance->host_lock, flags);
+       return IRQ_HANDLED;
 }
 
 static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 {
-    unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
-    unsigned long addr = virt_to_bus(cmd->SCp.ptr);
-    struct Scsi_Host *instance = cmd->device->host;
-
-    /* don't allow DMA if the physical address is bad */
-    if (addr & A2091_XFER_MASK)
-    {
-       HDATA(instance)->dma_bounce_len = (cmd->SCp.this_residual + 511)
-           & ~0x1ff;
-       HDATA(instance)->dma_bounce_buffer =
-           kmalloc (HDATA(instance)->dma_bounce_len, GFP_KERNEL);
-       
-       /* can't allocate memory; use PIO */
-       if (!HDATA(instance)->dma_bounce_buffer) {
-           HDATA(instance)->dma_bounce_len = 0;
-           return 1;
-       }
-
-       /* get the physical address of the bounce buffer */
-       addr = virt_to_bus(HDATA(instance)->dma_bounce_buffer);
+       struct Scsi_Host *instance = cmd->device->host;
+       struct WD33C93_hostdata *hdata = shost_priv(instance);
+       a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base);
+       unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
+       unsigned long addr = virt_to_bus(cmd->SCp.ptr);
 
-       /* the bounce buffer may not be in the first 16M of physmem */
+       /* don't allow DMA if the physical address is bad */
        if (addr & A2091_XFER_MASK) {
-           /* we could use chipmem... maybe later */
-           kfree (HDATA(instance)->dma_bounce_buffer);
-           HDATA(instance)->dma_bounce_buffer = NULL;
-           HDATA(instance)->dma_bounce_len = 0;
-           return 1;
+               hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
+               hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len,
+                                                  GFP_KERNEL);
+
+               /* can't allocate memory; use PIO */
+               if (!hdata->dma_bounce_buffer) {
+                       hdata->dma_bounce_len = 0;
+                       return 1;
+               }
+
+               /* get the physical address of the bounce buffer */
+               addr = virt_to_bus(hdata->dma_bounce_buffer);
+
+               /* the bounce buffer may not be in the first 16M of physmem */
+               if (addr & A2091_XFER_MASK) {
+                       /* we could use chipmem... maybe later */
+                       kfree(hdata->dma_bounce_buffer);
+                       hdata->dma_bounce_buffer = NULL;
+                       hdata->dma_bounce_len = 0;
+                       return 1;
+               }
+
+               if (!dir_in) {
+                       /* copy to bounce buffer for a write */
+                       memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr,
+                              cmd->SCp.this_residual);
+               }
        }
 
-       if (!dir_in) {
-               /* copy to bounce buffer for a write */
-               memcpy (HDATA(instance)->dma_bounce_buffer,
-                       cmd->SCp.ptr, cmd->SCp.this_residual);
-       }
-    }
+       /* setup dma direction */
+       if (!dir_in)
+               cntr |= CNTR_DDIR;
 
-    /* setup dma direction */
-    if (!dir_in)
-       cntr |= CNTR_DDIR;
+       /* remember direction */
+       hdata->dma_dir = dir_in;
 
-    /* remember direction */
-    HDATA(cmd->device->host)->dma_dir = dir_in;
+       regs->CNTR = cntr;
 
-    DMA(cmd->device->host)->CNTR = cntr;
+       /* setup DMA *physical* address */
+       regs->ACR = addr;
 
-    /* setup DMA *physical* address */
-    DMA(cmd->device->host)->ACR = addr;
-
-    if (dir_in){
-       /* invalidate any cache */
-       cache_clear (addr, cmd->SCp.this_residual);
-    }else{
-       /* push any dirty cache */
-       cache_push (addr, cmd->SCp.this_residual);
-      }
-    /* start DMA */
-    DMA(cmd->device->host)->ST_DMA = 1;
+       if (dir_in) {
+               /* invalidate any cache */
+               cache_clear(addr, cmd->SCp.this_residual);
+       } else {
+               /* push any dirty cache */
+               cache_push(addr, cmd->SCp.this_residual);
+       }
+       /* start DMA */
+       regs->ST_DMA = 1;
 
-    /* return success */
-    return 0;
+       /* return success */
+       return 0;
 }
 
 static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
-                     int status)
+                    int status)
 {
-    /* disable SCSI interrupts */
-    unsigned short cntr = CNTR_PDMD;
-
-    if (!HDATA(instance)->dma_dir)
-           cntr |= CNTR_DDIR;
-
-    /* disable SCSI interrupts */
-    DMA(instance)->CNTR = cntr;
-
-    /* flush if we were reading */
-    if (HDATA(instance)->dma_dir) {
-       DMA(instance)->FLUSH = 1;
-       while (!(DMA(instance)->ISTR & ISTR_FE_FLG))
-           ;
-    }
-
-    /* clear a possible interrupt */
-    DMA(instance)->CINT = 1;
-
-    /* stop DMA */
-    DMA(instance)->SP_DMA = 1;
-
-    /* restore the CONTROL bits (minus the direction flag) */
-    DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
-
-    /* copy from a bounce buffer, if necessary */
-    if (status && HDATA(instance)->dma_bounce_buffer) {
-       if( HDATA(instance)->dma_dir )
-               memcpy (SCpnt->SCp.ptr, 
-                       HDATA(instance)->dma_bounce_buffer,
-                       SCpnt->SCp.this_residual);
-       kfree (HDATA(instance)->dma_bounce_buffer);
-       HDATA(instance)->dma_bounce_buffer = NULL;
-       HDATA(instance)->dma_bounce_len = 0;
-    }
+       struct WD33C93_hostdata *hdata = shost_priv(instance);
+       a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base);
+
+       /* disable SCSI interrupts */
+       unsigned short cntr = CNTR_PDMD;
+
+       if (!hdata->dma_dir)
+               cntr |= CNTR_DDIR;
+
+       /* disable SCSI interrupts */
+       regs->CNTR = cntr;
+
+       /* flush if we were reading */
+       if (hdata->dma_dir) {
+               regs->FLUSH = 1;
+               while (!(regs->ISTR & ISTR_FE_FLG))
+                       ;
+       }
+
+       /* clear a possible interrupt */
+       regs->CINT = 1;
+
+       /* stop DMA */
+       regs->SP_DMA = 1;
+
+       /* restore the CONTROL bits (minus the direction flag) */
+       regs->CNTR = CNTR_PDMD | CNTR_INTEN;
+
+       /* copy from a bounce buffer, if necessary */
+       if (status && hdata->dma_bounce_buffer) {
+               if (hdata->dma_dir)
+                       memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer,
+                              SCpnt->SCp.this_residual);
+               kfree(hdata->dma_bounce_buffer);
+               hdata->dma_bounce_buffer = NULL;
+               hdata->dma_bounce_len = 0;
+       }
 }
 
 static int __init a2091_detect(struct scsi_host_template *tpnt)
 {
-    static unsigned char called = 0;
-    struct Scsi_Host *instance;
-    unsigned long address;
-    struct zorro_dev *z = NULL;
-    wd33c93_regs regs;
-    int num_a2091 = 0;
-
-    if (!MACH_IS_AMIGA || called)
-       return 0;
-    called = 1;
-
-    tpnt->proc_name = "A2091";
-    tpnt->proc_info = &wd33c93_proc_info;
-
-    while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-       if (z->id != ZORRO_PROD_CBM_A590_A2091_1 &&
-           z->id != ZORRO_PROD_CBM_A590_A2091_2)
-           continue;
-       address = z->resource.start;
-       if (!request_mem_region(address, 256, "wd33c93"))
-           continue;
-
-       instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata));
-       if (instance == NULL)
-           goto release;
-       instance->base = ZTWO_VADDR(address);
-       instance->irq = IRQ_AMIGA_PORTS;
-       instance->unique_id = z->slotaddr;
-       DMA(instance)->DAWR = DAWR_A2091;
-       regs.SASR = &(DMA(instance)->SASR);
-       regs.SCMD = &(DMA(instance)->SCMD);
-       HDATA(instance)->no_sync = 0xff;
-       HDATA(instance)->fast = 0;
-       HDATA(instance)->dma_mode = CTRL_DMA;
-       wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
-       if (request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, "A2091 SCSI",
-                       instance))
-           goto unregister;
-       DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
-       num_a2091++;
-       continue;
+       static unsigned char called = 0;
+       struct Scsi_Host *instance;
+       unsigned long address;
+       struct zorro_dev *z = NULL;
+       wd33c93_regs wdregs;
+       a2091_scsiregs *regs;
+       struct WD33C93_hostdata *hdata;
+       int num_a2091 = 0;
+
+       if (!MACH_IS_AMIGA || called)
+               return 0;
+       called = 1;
+
+       tpnt->proc_name = "A2091";
+       tpnt->proc_info = &wd33c93_proc_info;
+
+       while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
+               if (z->id != ZORRO_PROD_CBM_A590_A2091_1 &&
+                   z->id != ZORRO_PROD_CBM_A590_A2091_2)
+                       continue;
+               address = z->resource.start;
+               if (!request_mem_region(address, 256, "wd33c93"))
+                       continue;
+
+               instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
+               if (instance == NULL)
+                       goto release;
+               instance->base = ZTWO_VADDR(address);
+               instance->irq = IRQ_AMIGA_PORTS;
+               instance->unique_id = z->slotaddr;
+               regs = (a2091_scsiregs *)(instance->base);
+               regs->DAWR = DAWR_A2091;
+               wdregs.SASR = &regs->SASR;
+               wdregs.SCMD = &regs->SCMD;
+               hdata = shost_priv(instance);
+               hdata->no_sync = 0xff;
+               hdata->fast = 0;
+               hdata->dma_mode = CTRL_DMA;
+               wd33c93_init(instance, wdregs, dma_setup, dma_stop,
+                            WD33C93_FS_8_10);
+               if (request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED,
+                               "A2091 SCSI", instance))
+                       goto unregister;
+               regs->CNTR = CNTR_PDMD | CNTR_INTEN;
+               num_a2091++;
+               continue;
 
 unregister:
-       scsi_unregister(instance);
-       wd33c93_release();
+               scsi_unregister(instance);
 release:
-       release_mem_region(address, 256);
-    }
+               release_mem_region(address, 256);
+       }
 
-    return num_a2091;
+       return num_a2091;
 }
 
 static int a2091_bus_reset(struct scsi_cmnd *cmd)
@@ -239,10 +243,11 @@ static struct scsi_host_template driver_template = {
 static int a2091_release(struct Scsi_Host *instance)
 {
 #ifdef MODULE
-       DMA(instance)->CNTR = 0;
+       a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base);
+
+       regs->CNTR = 0;
        release_mem_region(ZTWO_PADDR(instance->base), 256);
        free_irq(IRQ_AMIGA_PORTS, instance);
-       wd33c93_release();
 #endif
        return 1;
 }
index 252528f..1c3daa1 100644 (file)
 #include <linux/types.h>
 
 #ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
+#define CMD_PER_LUN            2
 #endif
 
 #ifndef CAN_QUEUE
-#define CAN_QUEUE 16
+#define CAN_QUEUE              16
 #endif
 
 /*
  * if the transfer address ANDed with this results in a non-zero
  * result, then we can't use DMA.
  */
-#define A2091_XFER_MASK  (0xff000001)
+#define A2091_XFER_MASK                (0xff000001)
 
 typedef struct {
-             unsigned char      pad1[64];
-    volatile unsigned short     ISTR;
-    volatile unsigned short     CNTR;
-             unsigned char      pad2[60];
-    volatile unsigned int       WTC;
-    volatile unsigned long      ACR;
-             unsigned char      pad3[6];
-    volatile unsigned short     DAWR;
-             unsigned char      pad4;
-    volatile unsigned char      SASR;
-             unsigned char      pad5;
-    volatile unsigned char      SCMD;
-             unsigned char      pad6[76];
-    volatile unsigned short     ST_DMA;
-    volatile unsigned short     SP_DMA;
-    volatile unsigned short     CINT;
-             unsigned char      pad7[2];
-    volatile unsigned short     FLUSH;
+                unsigned char  pad1[64];
+       volatile unsigned short ISTR;
+       volatile unsigned short CNTR;
+                unsigned char  pad2[60];
+       volatile unsigned int   WTC;
+       volatile unsigned long  ACR;
+                unsigned char  pad3[6];
+       volatile unsigned short DAWR;
+                unsigned char  pad4;
+       volatile unsigned char  SASR;
+                unsigned char  pad5;
+       volatile unsigned char  SCMD;
+                unsigned char  pad6[76];
+       volatile unsigned short ST_DMA;
+       volatile unsigned short SP_DMA;
+       volatile unsigned short CINT;
+                unsigned char  pad7[2];
+       volatile unsigned short FLUSH;
 } a2091_scsiregs;
 
 #define DAWR_A2091             (3)
index c35fc55..bc6eb69 100644 (file)
 #include "wd33c93.h"
 #include "a3000.h"
 
-#include<linux/stat.h>
+#include <linux/stat.h>
 
-#define DMA(ptr) ((a3000_scsiregs *)((ptr)->base))
-#define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
+
+#define DMA(ptr)       ((a3000_scsiregs *)((ptr)->base))
 
 static struct Scsi_Host *a3000_host = NULL;
 
 static int a3000_release(struct Scsi_Host *instance);
 
-static irqreturn_t a3000_intr (int irq, void *dummy)
+static irqreturn_t a3000_intr(int irq, void *dummy)
 {
        unsigned long flags;
        unsigned int status = DMA(a3000_host)->ISTR;
 
        if (!(status & ISTR_INT_P))
                return IRQ_NONE;
-       if (status & ISTR_INTS)
-       {
+       if (status & ISTR_INTS) {
                spin_lock_irqsave(a3000_host->host_lock, flags);
-               wd33c93_intr (a3000_host);
+               wd33c93_intr(a3000_host);
                spin_unlock_irqrestore(a3000_host->host_lock, flags);
                return IRQ_HANDLED;
        }
@@ -48,162 +47,165 @@ static irqreturn_t a3000_intr (int irq, void *dummy)
 
 static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 {
-    unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
-    unsigned long addr = virt_to_bus(cmd->SCp.ptr);
-
-    /*
-     * if the physical address has the wrong alignment, or if
-     * physical address is bad, or if it is a write and at the
-     * end of a physical memory chunk, then allocate a bounce
-     * buffer
-     */
-    if (addr & A3000_XFER_MASK)
-    {
-       HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511)
-           & ~0x1ff;
-       HDATA(a3000_host)->dma_bounce_buffer =
-           kmalloc (HDATA(a3000_host)->dma_bounce_len, GFP_KERNEL);
-       
-       /* can't allocate memory; use PIO */
-       if (!HDATA(a3000_host)->dma_bounce_buffer) {
-           HDATA(a3000_host)->dma_bounce_len = 0;
-           return 1;
-       }
-
-       if (!dir_in) {
-           /* copy to bounce buffer for a write */
-           memcpy (HDATA(a3000_host)->dma_bounce_buffer,
-               cmd->SCp.ptr, cmd->SCp.this_residual);
+       struct WD33C93_hostdata *hdata = shost_priv(a3000_host);
+       unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
+       unsigned long addr = virt_to_bus(cmd->SCp.ptr);
+
+       /*
+        * if the physical address has the wrong alignment, or if
+        * physical address is bad, or if it is a write and at the
+        * end of a physical memory chunk, then allocate a bounce
+        * buffer
+        */
+       if (addr & A3000_XFER_MASK) {
+               hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
+               hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len,
+                                                  GFP_KERNEL);
+
+               /* can't allocate memory; use PIO */
+               if (!hdata->dma_bounce_buffer) {
+                       hdata->dma_bounce_len = 0;
+                       return 1;
+               }
+
+               if (!dir_in) {
+                       /* copy to bounce buffer for a write */
+                       memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr,
+                              cmd->SCp.this_residual);
+               }
+
+               addr = virt_to_bus(hdata->dma_bounce_buffer);
        }
 
-       addr = virt_to_bus(HDATA(a3000_host)->dma_bounce_buffer);
-    }
+       /* setup dma direction */
+       if (!dir_in)
+               cntr |= CNTR_DDIR;
 
-    /* setup dma direction */
-    if (!dir_in)
-       cntr |= CNTR_DDIR;
+       /* remember direction */
+       hdata->dma_dir = dir_in;
 
-    /* remember direction */
-    HDATA(a3000_host)->dma_dir = dir_in;
+       DMA(a3000_host)->CNTR = cntr;
 
-    DMA(a3000_host)->CNTR = cntr;
+       /* setup DMA *physical* address */
+       DMA(a3000_host)->ACR = addr;
 
-    /* setup DMA *physical* address */
-    DMA(a3000_host)->ACR = addr;
-
-    if (dir_in)
-       /* invalidate any cache */
-       cache_clear (addr, cmd->SCp.this_residual);
-    else
-       /* push any dirty cache */
-       cache_push (addr, cmd->SCp.this_residual);
+       if (dir_in) {
+               /* invalidate any cache */
+               cache_clear(addr, cmd->SCp.this_residual);
+       } else {
+               /* push any dirty cache */
+               cache_push(addr, cmd->SCp.this_residual);
+       }
 
-    /* start DMA */
-    mb();                      /* make sure setup is completed */
-    DMA(a3000_host)->ST_DMA = 1;
-    mb();                      /* make sure DMA has started before next IO */
+       /* start DMA */
+       mb();                   /* make sure setup is completed */
+       DMA(a3000_host)->ST_DMA = 1;
+       mb();                   /* make sure DMA has started before next IO */
 
-    /* return success */
-    return 0;
+       /* return success */
+       return 0;
 }
 
 static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
                     int status)
 {
-    /* disable SCSI interrupts */
-    unsigned short cntr = CNTR_PDMD;
-
-    if (!HDATA(instance)->dma_dir)
-       cntr |= CNTR_DDIR;
-
-    DMA(instance)->CNTR = cntr;
-    mb();                      /* make sure CNTR is updated before next IO */
-
-    /* flush if we were reading */
-    if (HDATA(instance)->dma_dir) {
-       DMA(instance)->FLUSH = 1;
-       mb();                   /* don't allow prefetch */
-       while (!(DMA(instance)->ISTR & ISTR_FE_FLG))
-           barrier();
-       mb();                   /* no IO until FLUSH is done */
-    }
-
-    /* clear a possible interrupt */
-    /* I think that this CINT is only necessary if you are
-     * using the terminal count features.   HM 7 Mar 1994
-     */
-    DMA(instance)->CINT = 1;
-
-    /* stop DMA */
-    DMA(instance)->SP_DMA = 1;
-    mb();                      /* make sure DMA is stopped before next IO */
-
-    /* restore the CONTROL bits (minus the direction flag) */
-    DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
-    mb();                      /* make sure CNTR is updated before next IO */
-
-    /* copy from a bounce buffer, if necessary */
-    if (status && HDATA(instance)->dma_bounce_buffer) {
-       if (SCpnt) {
-           if (HDATA(instance)->dma_dir && SCpnt)
-               memcpy (SCpnt->SCp.ptr,
-                       HDATA(instance)->dma_bounce_buffer,
-                       SCpnt->SCp.this_residual);
-           kfree (HDATA(instance)->dma_bounce_buffer);
-           HDATA(instance)->dma_bounce_buffer = NULL;
-           HDATA(instance)->dma_bounce_len = 0;
-       } else {
-           kfree (HDATA(instance)->dma_bounce_buffer);
-           HDATA(instance)->dma_bounce_buffer = NULL;
-           HDATA(instance)->dma_bounce_len = 0;
+       struct WD33C93_hostdata *hdata = shost_priv(instance);
+
+       /* disable SCSI interrupts */
+       unsigned short cntr = CNTR_PDMD;
+
+       if (!hdata->dma_dir)
+               cntr |= CNTR_DDIR;
+
+       DMA(instance)->CNTR = cntr;
+       mb();                   /* make sure CNTR is updated before next IO */
+
+       /* flush if we were reading */
+       if (hdata->dma_dir) {
+               DMA(instance)->FLUSH = 1;
+               mb();           /* don't allow prefetch */
+               while (!(DMA(instance)->ISTR & ISTR_FE_FLG))
+                       barrier();
+               mb();           /* no IO until FLUSH is done */
+       }
+
+       /* clear a possible interrupt */
+       /* I think that this CINT is only necessary if you are
+        * using the terminal count features.   HM 7 Mar 1994
+        */
+       DMA(instance)->CINT = 1;
+
+       /* stop DMA */
+       DMA(instance)->SP_DMA = 1;
+       mb();                   /* make sure DMA is stopped before next IO */
+
+       /* restore the CONTROL bits (minus the direction flag) */
+       DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
+       mb();                   /* make sure CNTR is updated before next IO */
+
+       /* copy from a bounce buffer, if necessary */
+       if (status && hdata->dma_bounce_buffer) {
+               if (SCpnt) {
+                       if (hdata->dma_dir && SCpnt)
+                               memcpy(SCpnt->SCp.ptr,
+                                      hdata->dma_bounce_buffer,
+                                      SCpnt->SCp.this_residual);
+                       kfree(hdata->dma_bounce_buffer);
+                       hdata->dma_bounce_buffer = NULL;
+                       hdata->dma_bounce_len = 0;
+               } else {
+                       kfree(hdata->dma_bounce_buffer);
+                       hdata->dma_bounce_buffer = NULL;
+                       hdata->dma_bounce_len = 0;
+               }
        }
-    }
 }
 
 static int __init a3000_detect(struct scsi_host_template *tpnt)
 {
-    wd33c93_regs regs;
-
-    if  (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI))
-       return 0;
-    if (!request_mem_region(0xDD0000, 256, "wd33c93"))
-       return 0;
-
-    tpnt->proc_name = "A3000";
-    tpnt->proc_info = &wd33c93_proc_info;
-
-    a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata));
-    if (a3000_host == NULL)
-       goto fail_register;
-
-    a3000_host->base = ZTWO_VADDR(0xDD0000);
-    a3000_host->irq = IRQ_AMIGA_PORTS;
-    DMA(a3000_host)->DAWR = DAWR_A3000;
-    regs.SASR = &(DMA(a3000_host)->SASR);
-    regs.SCMD = &(DMA(a3000_host)->SCMD);
-    HDATA(a3000_host)->no_sync = 0xff;
-    HDATA(a3000_host)->fast = 0;
-    HDATA(a3000_host)->dma_mode = CTRL_DMA;
-    wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15);
-    if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI",
-                   a3000_intr))
-        goto fail_irq;
-    DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN;
-
-    return 1;
+       wd33c93_regs regs;
+       struct WD33C93_hostdata *hdata;
+
+       if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI))
+               return 0;
+       if (!request_mem_region(0xDD0000, 256, "wd33c93"))
+               return 0;
+
+       tpnt->proc_name = "A3000";
+       tpnt->proc_info = &wd33c93_proc_info;
+
+       a3000_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
+       if (a3000_host == NULL)
+               goto fail_register;
+
+       a3000_host->base = ZTWO_VADDR(0xDD0000);
+       a3000_host->irq = IRQ_AMIGA_PORTS;
+       DMA(a3000_host)->DAWR = DAWR_A3000;
+       regs.SASR = &(DMA(a3000_host)->SASR);
+       regs.SCMD = &(DMA(a3000_host)->SCMD);
+       hdata = shost_priv(a3000_host);
+       hdata->no_sync = 0xff;
+       hdata->fast = 0;
+       hdata->dma_mode = CTRL_DMA;
+       wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15);
+       if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI",
+                       a3000_intr))
+               goto fail_irq;
+       DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN;
+
+       return 1;
 
 fail_irq:
-    wd33c93_release();
-    scsi_unregister(a3000_host);
+       scsi_unregister(a3000_host);
 fail_register:
-    release_mem_region(0xDD0000, 256);
-    return 0;
+       release_mem_region(0xDD0000, 256);
+       return 0;
 }
 
 static int a3000_bus_reset(struct scsi_cmnd *cmd)
 {
        /* FIXME perform bus-specific reset */
-       
+
        /* FIXME 2: kill this entire function, which should
           cause mid-layer to call wd33c93_host_reset anyway? */
 
@@ -237,11 +239,10 @@ static struct scsi_host_template driver_template = {
 
 static int a3000_release(struct Scsi_Host *instance)
 {
-    wd33c93_release();
-    DMA(instance)->CNTR = 0;
-    release_mem_region(0xDD0000, 256);
-    free_irq(IRQ_AMIGA_PORTS, a3000_intr);
-    return 1;
+       DMA(instance)->CNTR = 0;
+       release_mem_region(0xDD0000, 256);
+       free_irq(IRQ_AMIGA_PORTS, a3000_intr);
+       return 1;
 }
 
 MODULE_LICENSE("GPL");
index c7afe16..684813e 100644 (file)
 #include <linux/types.h>
 
 #ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
+#define CMD_PER_LUN            2
 #endif
 
 #ifndef CAN_QUEUE
-#define CAN_QUEUE 16
+#define CAN_QUEUE              16
 #endif
 
 /*
  * if the transfer address ANDed with this results in a non-zero
  * result, then we can't use DMA.
  */
-#define A3000_XFER_MASK  (0x00000003)
+#define A3000_XFER_MASK                (0x00000003)
 
 typedef struct {
-             unsigned char      pad1[2];
-    volatile unsigned short     DAWR;
-    volatile unsigned int       WTC;
-             unsigned char      pad2[2];
-    volatile unsigned short     CNTR;
-    volatile unsigned long      ACR;
-             unsigned char      pad3[2];
-    volatile unsigned short     ST_DMA;
-             unsigned char      pad4[2];
-    volatile unsigned short     FLUSH;
-             unsigned char      pad5[2];
-    volatile unsigned short     CINT;
-             unsigned char      pad6[2];
-    volatile unsigned short     ISTR;
-            unsigned char      pad7[30];
-    volatile unsigned short     SP_DMA;
-             unsigned char      pad8;
-    volatile unsigned char      SASR;
-             unsigned char      pad9;
-    volatile unsigned char      SCMD;
+                unsigned char  pad1[2];
+       volatile unsigned short DAWR;
+       volatile unsigned int   WTC;
+                unsigned char  pad2[2];
+       volatile unsigned short CNTR;
+       volatile unsigned long  ACR;
+                unsigned char  pad3[2];
+       volatile unsigned short ST_DMA;
+                unsigned char  pad4[2];
+       volatile unsigned short FLUSH;
+                unsigned char  pad5[2];
+       volatile unsigned short CINT;
+                unsigned char  pad6[2];
+       volatile unsigned short ISTR;
+                unsigned char  pad7[30];
+       volatile unsigned short SP_DMA;
+                unsigned char  pad8;
+       volatile unsigned char  SASR;
+                unsigned char  pad9;
+       volatile unsigned char  SCMD;
 } a3000_scsiregs;
 
 #define DAWR_A3000             (3)
index 7e26ebc..7df2dd1 100644 (file)
@@ -328,6 +328,16 @@ int aac_get_config_status(struct aac_dev *dev, int commit_flag)
        return status;
 }
 
+static void aac_expose_phy_device(struct scsi_cmnd *scsicmd)
+{
+       char inq_data;
+       scsi_sg_copy_to_buffer(scsicmd,  &inq_data, sizeof(inq_data));
+       if ((inq_data & 0x20) && (inq_data & 0x1f) == TYPE_DISK) {
+               inq_data &= 0xdf;
+               scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
+       }
+}
+
 /**
  *     aac_get_containers      -       list containers
  *     @common: adapter to probe
@@ -1598,6 +1608,7 @@ static int aac_read(struct scsi_cmnd * scsicmd)
        int status;
        struct aac_dev *dev;
        struct fib * cmd_fibcontext;
+       int cid;
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
        /*
@@ -1647,6 +1658,22 @@ static int aac_read(struct scsi_cmnd * scsicmd)
                count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
                break;
        }
+
+       if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
+               cid = scmd_id(scsicmd);
+               dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
+                       SAM_STAT_CHECK_CONDITION;
+               set_sense(&dev->fsa_dev[cid].sense_data,
+                         HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
+                         ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
+               memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+                      min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
+                            SCSI_SENSE_BUFFERSIZE));
+               scsicmd->scsi_done(scsicmd);
+               return 1;
+       }
+
        dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
          smp_processor_id(), (unsigned long long)lba, jiffies));
        if (aac_adapter_bounds(dev,scsicmd,lba))
@@ -1688,6 +1715,7 @@ static int aac_write(struct scsi_cmnd * scsicmd)
        int status;
        struct aac_dev *dev;
        struct fib * cmd_fibcontext;
+       int cid;
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
        /*
@@ -1727,6 +1755,22 @@ static int aac_write(struct scsi_cmnd * scsicmd)
                count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
                fua = scsicmd->cmnd[1] & 0x8;
        }
+
+       if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
+               cid = scmd_id(scsicmd);
+               dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
+               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
+                       SAM_STAT_CHECK_CONDITION;
+               set_sense(&dev->fsa_dev[cid].sense_data,
+                         HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
+                         ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
+               memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
+                      min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
+                            SCSI_SENSE_BUFFERSIZE));
+               scsicmd->scsi_done(scsicmd);
+               return 1;
+       }
+
        dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
          smp_processor_id(), (unsigned long long)lba, jiffies));
        if (aac_adapter_bounds(dev,scsicmd,lba))
@@ -2573,6 +2617,11 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
 
        scsi_dma_unmap(scsicmd);
 
+       /* expose physical device if expose_physicald flag is on */
+       if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
+         && expose_physicals > 0)
+               aac_expose_phy_device(scsicmd);
+
        /*
         * First check the fib status
         */
@@ -2678,8 +2727,22 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
                        scsicmd->cmnd[0],
                        le32_to_cpu(srbreply->scsi_status));
 #endif
-               scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
-               break;
+               if ((scsicmd->cmnd[0] == ATA_12)
+                 || (scsicmd->cmnd[0] == ATA_16)) {
+                       if (scsicmd->cmnd[2] & (0x01 << 5)) {
+                               scsicmd->result = DID_OK << 16
+                                               | COMMAND_COMPLETE << 8;
+                               break;
+                       } else {
+                               scsicmd->result = DID_ERROR << 16
+                                               | COMMAND_COMPLETE << 8;
+                               break;
+                       }
+               } else {
+                       scsicmd->result = DID_ERROR << 16
+                                       | COMMAND_COMPLETE << 8;
+                       break;
+               }
        }
        if (le32_to_cpu(srbreply->scsi_status) == SAM_STAT_CHECK_CONDITION) {
                int len;
index 619c02d..4dbcc05 100644 (file)
@@ -12,7 +12,7 @@
  *----------------------------------------------------------------------------*/
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 24702
+# define AAC_DRIVER_BUILD 26400
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS 32
@@ -26,6 +26,8 @@
 #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
 #define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)256)
 
+#define AAC_DEBUG_INSTRUMENT_AIF_DELETE
+
 /*
  * These macros convert from physical channels to virtual channels
  */
index 94d2954..7007914 100644 (file)
@@ -966,6 +966,16 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
                        device_config_needed =
                          (((__le32 *)aifcmd->data)[0] ==
                            cpu_to_le32(AifEnAddJBOD)) ? ADD : DELETE;
+                       if (device_config_needed == ADD) {
+                               device = scsi_device_lookup(dev->scsi_host_ptr,
+                                       channel,
+                                       id,
+                                       lun);
+                               if (device) {
+                                       scsi_remove_device(device);
+                                       scsi_device_put(device);
+                               }
+                       }
                        break;
 
                case AifEnEnclosureManagement:
@@ -1123,6 +1133,9 @@ retry_next:
        if (device) {
                switch (device_config_needed) {
                case DELETE:
+#if (defined(AAC_DEBUG_INSTRUMENT_AIF_DELETE))
+                       scsi_remove_device(device);
+#else
                        if (scsi_device_online(device)) {
                                scsi_device_set_state(device, SDEV_OFFLINE);
                                sdev_printk(KERN_INFO, device,
@@ -1131,6 +1144,7 @@ retry_next:
                                                "array deleted" :
                                                "enclosure services event");
                        }
+#endif
                        break;
                case ADD:
                        if (!scsi_device_online(device)) {
@@ -1145,12 +1159,16 @@ retry_next:
                case CHANGE:
                        if ((channel == CONTAINER_CHANNEL)
                         && (!dev->fsa_dev[container].valid)) {
+#if (defined(AAC_DEBUG_INSTRUMENT_AIF_DELETE))
+                               scsi_remove_device(device);
+#else
                                if (!scsi_device_online(device))
                                        break;
                                scsi_device_set_state(device, SDEV_OFFLINE);
                                sdev_printk(KERN_INFO, device,
                                        "Device offlined - %s\n",
                                        "array failed");
+#endif
                                break;
                        }
                        scsi_rescan_device(&device->sdev_gendev);
index 961fe43..53a616f 100644 (file)
@@ -117,35 +117,6 @@ bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio)
 }
 
 /**
- * Get SG element for the I/O request given the SG element index
- */
-static inline union bfi_addr_u
-bfa_cb_ioim_get_sgaddr(struct bfad_ioim_s *dio, int sgeid)
-{
-       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-       struct scatterlist *sge;
-       u64        addr;
-
-       sge = (struct scatterlist *)scsi_sglist(cmnd) + sgeid;
-       addr = (u64) sg_dma_address(sge);
-
-       return *((union bfi_addr_u *) &addr);
-}
-
-static inline u32
-bfa_cb_ioim_get_sglen(struct bfad_ioim_s *dio, int sgeid)
-{
-       struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-       struct scatterlist *sge;
-       u32        len;
-
-       sge = (struct scatterlist *)scsi_sglist(cmnd) + sgeid;
-       len = sg_dma_len(sge);
-
-       return len;
-}
-
-/**
  * Get Command Reference Number for the I/O request. 0 if none.
  */
 static inline u8
index 5b107ab..687f3d6 100644 (file)
@@ -731,6 +731,9 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
        static struct fcp_cmnd_s cmnd_z0 = { 0 };
        struct bfi_sge_s      *sge;
        u32        pgdlen = 0;
+       u64 addr;
+       struct scatterlist *sg;
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
 
        /**
         * check for room in queue to send request now
@@ -754,8 +757,10 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
         */
        sge = &m->sges[0];
        if (ioim->nsges) {
-               sge->sga = bfa_cb_ioim_get_sgaddr(ioim->dio, 0);
-               pgdlen = bfa_cb_ioim_get_sglen(ioim->dio, 0);
+               sg = (struct scatterlist *)scsi_sglist(cmnd);
+               addr = bfa_os_sgaddr(sg_dma_address(sg));
+               sge->sga = *(union bfi_addr_u *) &addr;
+               pgdlen = sg_dma_len(sg);
                sge->sg_len = pgdlen;
                sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
                                        BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
@@ -868,10 +873,16 @@ bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
        struct bfi_sge_s      *sge;
        struct bfa_sgpg_s *sgpg;
        u32        pgcumsz;
+       u64        addr;
+       struct scatterlist *sg;
+       struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
 
        sgeid = BFI_SGE_INLINE;
        ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
 
+       sg = scsi_sglist(cmnd);
+       sg = sg_next(sg);
+
        do {
                sge = sgpg->sgpg->sges;
                nsges = ioim->nsges - sgeid;
@@ -879,9 +890,10 @@ bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
                        nsges = BFI_SGPG_DATA_SGES;
 
                pgcumsz = 0;
-               for (i = 0; i < nsges; i++, sge++, sgeid++) {
-                       sge->sga = bfa_cb_ioim_get_sgaddr(ioim->dio, sgeid);
-                       sge->sg_len = bfa_cb_ioim_get_sglen(ioim->dio, sgeid);
+               for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
+                       addr = bfa_os_sgaddr(sg_dma_address(sg));
+                       sge->sga = *(union bfi_addr_u *) &addr;
+                       sge->sg_len = sg_dma_len(sg);
                        pgcumsz += sge->sg_len;
 
                        /**
index 10a89f7..bd1cd3e 100644 (file)
 #include <scsi/scsi_transport_fc.h>
 #include <scsi/scsi_transport.h>
 
+#ifdef __BIG_ENDIAN
+#define __BIGENDIAN
+#endif
+
 #define BFA_ERR                        KERN_ERR
 #define BFA_WARNING            KERN_WARNING
 #define BFA_NOTICE             KERN_NOTICE
@@ -123,6 +127,15 @@ int bfa_os_MWB(void *);
        (((_x) & 0x00ff0000) >> 8)      |       \
        (((_x) & 0xff000000) >> 24))
 
+#define bfa_os_swap_sgaddr(_x) ((u64)(                                 \
+       (((u64)(_x) & (u64)0x00000000000000ffull) << 32)        |       \
+       (((u64)(_x) & (u64)0x000000000000ff00ull) << 32)        |       \
+       (((u64)(_x) & (u64)0x0000000000ff0000ull) << 32)        |       \
+       (((u64)(_x) & (u64)0x00000000ff000000ull) << 32)        |       \
+       (((u64)(_x) & (u64)0x000000ff00000000ull) >> 32)        |       \
+       (((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32)        |       \
+       (((u64)(_x) & (u64)0x00ff000000000000ull) >> 32)        |       \
+       (((u64)(_x) & (u64)0xff00000000000000ull) >> 32)))
 
 #ifndef __BIGENDIAN
 #define bfa_os_htons(_x) ((u16)((((_x) & 0xff00) >> 8) | \
@@ -133,6 +146,7 @@ int bfa_os_MWB(void *);
 #define bfa_os_hton3b(_x)      bfa_swap_3b(_x)
 
 #define bfa_os_wtole(_x)   (_x)
+#define bfa_os_sgaddr(_x)  (_x)
 
 #else
 
@@ -141,6 +155,7 @@ int bfa_os_MWB(void *);
 #define bfa_os_hton3b(_x)  (_x)
 #define bfa_os_htonll(_x)  (_x)
 #define bfa_os_wtole(_x)   bfa_os_swap32(_x)
+#define bfa_os_sgaddr(_x)  bfa_os_swap_sgaddr(_x)
 
 #endif
 
@@ -161,12 +176,12 @@ int bfa_os_MWB(void *);
 #define bfa_os_addr_t char __iomem *
 #define bfa_os_panic()
 
-#define bfa_os_reg_read(_raddr) bfa_os_wtole(readl(_raddr))
-#define bfa_os_reg_write(_raddr, _val) writel(bfa_os_wtole((_val)), (_raddr))
+#define bfa_os_reg_read(_raddr) readl(_raddr)
+#define bfa_os_reg_write(_raddr, _val) writel((_val), (_raddr))
 #define bfa_os_mem_read(_raddr, _off)                                   \
-       bfa_os_ntohl(readl(((_raddr) + (_off))))
+       bfa_os_swap32(readl(((_raddr) + (_off))))
 #define bfa_os_mem_write(_raddr, _off, _val)                            \
-       writel(bfa_os_htonl((_val)), ((_raddr) + (_off)))
+       writel(bfa_os_swap32((_val)), ((_raddr) + (_off)))
 
 #define BFA_TRC_TS(_trcm)                                              \
                        ({                                              \
index 13f5feb..d4fc428 100644 (file)
@@ -33,7 +33,7 @@
 #include <fcb/bfa_fcb.h>
 
 BFA_TRC_FILE(LDRV, BFAD);
-static DEFINE_MUTEX(bfad_mutex);
+DEFINE_MUTEX(bfad_mutex);
 LIST_HEAD(bfad_list);
 static int      bfad_inst;
 int bfad_supported_fc4s;
@@ -299,8 +299,6 @@ bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv)
                complete(vport_drv->comp_del);
                return;
        }
-
-       kfree(vport_drv);
 }
 
 /**
@@ -483,7 +481,7 @@ ext:
  */
 bfa_status_t
 bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
-                 struct bfa_port_cfg_s *port_cfg)
+                 struct bfa_port_cfg_s *port_cfg, struct device *dev)
 {
        struct bfad_vport_s *vport;
        int             rc = BFA_STATUS_OK;
@@ -506,7 +504,8 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
                goto ext_free_vport;
 
        if (port_cfg->roles & BFA_PORT_ROLE_FCP_IM) {
-               rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port);
+               rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port,
+                                                       dev);
                if (rc != BFA_STATUS_OK)
                        goto ext_free_fcs_vport;
        }
@@ -591,7 +590,6 @@ bfad_init_timer(struct bfad_s *bfad)
 int
 bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
 {
-       unsigned long   bar0_len;
        int             rc = -ENODEV;
 
        if (pci_enable_device(pdev)) {
@@ -611,9 +609,7 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
                        goto out_release_region;
                }
 
-       bfad->pci_bar0_map = pci_resource_start(pdev, 0);
-       bar0_len = pci_resource_len(pdev, 0);
-       bfad->pci_bar0_kva = ioremap(bfad->pci_bar0_map, bar0_len);
+       bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
 
        if (bfad->pci_bar0_kva == NULL) {
                BFA_PRINTF(BFA_ERR, "Fail to map bar0\n");
@@ -646,11 +642,7 @@ out:
 void
 bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad)
 {
-#if defined(__ia64__)
        pci_iounmap(pdev, bfad->pci_bar0_kva);
-#else
-       iounmap(bfad->pci_bar0_kva);
-#endif
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
@@ -848,7 +840,8 @@ bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role)
                        goto out;
                }
 
-               rc = bfad_im_scsi_host_alloc(bfad, bfad->pport.im_port);
+               rc = bfad_im_scsi_host_alloc(bfad, bfad->pport.im_port,
+                                               &bfad->pcidev->dev);
                if (rc != BFA_STATUS_OK)
                        goto out;
 
index 6a2efdd..e477bfb 100644 (file)
@@ -364,6 +364,152 @@ bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
 
 }
 
+static int
+bfad_im_vport_create(struct fc_vport *fc_vport, bool disable)
+{
+       char *vname = fc_vport->symbolic_name;
+       struct Scsi_Host *shost = fc_vport->shost;
+       struct bfad_im_port_s *im_port =
+               (struct bfad_im_port_s *) shost->hostdata[0];
+       struct bfad_s *bfad = im_port->bfad;
+       struct bfa_port_cfg_s port_cfg;
+       int status = 0, rc;
+       unsigned long flags;
+
+       memset(&port_cfg, 0, sizeof(port_cfg));
+
+       port_cfg.pwwn = wwn_to_u64((u8 *) &fc_vport->port_name);
+       port_cfg.nwwn = wwn_to_u64((u8 *) &fc_vport->node_name);
+
+       if (strlen(vname) > 0)
+               strcpy((char *)&port_cfg.sym_name, vname);
+
+       port_cfg.roles = BFA_PORT_ROLE_FCP_IM;
+       rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev);
+
+       if (rc == BFA_STATUS_OK) {
+               struct bfad_vport_s   *vport;
+               struct bfa_fcs_vport_s *fcs_vport;
+               struct Scsi_Host *vshost;
+
+               spin_lock_irqsave(&bfad->bfad_lock, flags);
+               fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0,
+                                       port_cfg.pwwn);
+               if (fcs_vport == NULL) {
+                       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+                       return VPCERR_BAD_WWN;
+               }
+
+               fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
+               if (disable) {
+                       bfa_fcs_vport_stop(fcs_vport);
+                       fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
+               }
+               spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+               vport = fcs_vport->vport_drv;
+               vshost = vport->drv_port.im_port->shost;
+               fc_host_node_name(vshost) = wwn_to_u64((u8 *) &port_cfg.nwwn);
+               fc_host_port_name(vshost) = wwn_to_u64((u8 *) &port_cfg.pwwn);
+               fc_vport->dd_data = vport;
+               vport->drv_port.im_port->fc_vport = fc_vport;
+
+       } else if (rc == BFA_STATUS_INVALID_WWN)
+               return VPCERR_BAD_WWN;
+       else if (rc == BFA_STATUS_VPORT_EXISTS)
+               return VPCERR_BAD_WWN;
+       else if (rc == BFA_STATUS_VPORT_MAX)
+               return VPCERR_NO_FABRIC_SUPP;
+       else if (rc == BFA_STATUS_VPORT_WWN_BP)
+               return VPCERR_BAD_WWN;
+        else
+               return FC_VPORT_FAILED;
+
+       return status;
+}
+
+static int
+bfad_im_vport_delete(struct fc_vport *fc_vport)
+{
+       struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data;
+       struct bfad_im_port_s *im_port =
+                       (struct bfad_im_port_s *) vport->drv_port.im_port;
+       struct bfad_s *bfad = im_port->bfad;
+       struct bfad_port_s *port;
+       struct bfa_fcs_vport_s *fcs_vport;
+       struct Scsi_Host *vshost;
+       wwn_t   pwwn;
+       int rc;
+       unsigned long flags;
+       struct completion fcomp;
+
+       if (im_port->flags & BFAD_PORT_DELETE)
+               goto free_scsi_host;
+
+       port = im_port->port;
+
+       vshost = vport->drv_port.im_port->shost;
+       pwwn = wwn_to_u64((u8 *) &fc_host_port_name(vshost));
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       if (fcs_vport == NULL)
+               return VPCERR_BAD_WWN;
+
+       vport->drv_port.flags |= BFAD_PORT_DELETE;
+
+       vport->comp_del = &fcomp;
+       init_completion(vport->comp_del);
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       rc = bfa_fcs_vport_delete(&vport->fcs_vport);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       wait_for_completion(vport->comp_del);
+
+free_scsi_host:
+       bfad_os_scsi_host_free(bfad, im_port);
+
+       kfree(vport);
+
+       return 0;
+}
+
+static int
+bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable)
+{
+       struct bfad_vport_s *vport;
+       struct bfad_s *bfad;
+       struct bfa_fcs_vport_s *fcs_vport;
+       struct Scsi_Host *vshost;
+       wwn_t   pwwn;
+       unsigned long flags;
+
+       vport = (struct bfad_vport_s *)fc_vport->dd_data;
+       bfad = vport->drv_port.bfad;
+       vshost = vport->drv_port.im_port->shost;
+       pwwn = wwn_to_u64((u8 *) &fc_vport->port_name);
+
+       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn);
+       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+       if (fcs_vport == NULL)
+               return VPCERR_BAD_WWN;
+
+       if (disable) {
+               bfa_fcs_vport_stop(fcs_vport);
+               fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
+       } else {
+               bfa_fcs_vport_start(fcs_vport);
+               fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
+       }
+
+       return 0;
+}
+
 struct fc_function_template bfad_im_fc_function_template = {
 
        /* Target dynamic attributes */
@@ -413,6 +559,61 @@ struct fc_function_template bfad_im_fc_function_template = {
        .show_rport_dev_loss_tmo = 1,
        .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
        .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
+
+       .vport_create = bfad_im_vport_create,
+       .vport_delete = bfad_im_vport_delete,
+       .vport_disable = bfad_im_vport_disable,
+};
+
+struct fc_function_template bfad_im_vport_fc_function_template = {
+
+       /* Target dynamic attributes */
+       .get_starget_port_id = bfad_im_get_starget_port_id,
+       .show_starget_port_id = 1,
+       .get_starget_node_name = bfad_im_get_starget_node_name,
+       .show_starget_node_name = 1,
+       .get_starget_port_name = bfad_im_get_starget_port_name,
+       .show_starget_port_name = 1,
+
+       /* Host dynamic attribute */
+       .get_host_port_id = bfad_im_get_host_port_id,
+       .show_host_port_id = 1,
+
+       /* Host fixed attributes */
+       .show_host_node_name = 1,
+       .show_host_port_name = 1,
+       .show_host_supported_classes = 1,
+       .show_host_supported_fc4s = 1,
+       .show_host_supported_speeds = 1,
+       .show_host_maxframe_size = 1,
+
+       /* More host dynamic attributes */
+       .show_host_port_type = 1,
+       .get_host_port_type = bfad_im_get_host_port_type,
+       .show_host_port_state = 1,
+       .get_host_port_state = bfad_im_get_host_port_state,
+       .show_host_active_fc4s = 1,
+       .get_host_active_fc4s = bfad_im_get_host_active_fc4s,
+       .show_host_speed = 1,
+       .get_host_speed = bfad_im_get_host_speed,
+       .show_host_fabric_name = 1,
+       .get_host_fabric_name = bfad_im_get_host_fabric_name,
+
+       .show_host_symbolic_name = 1,
+
+       /* Statistics */
+       .get_fc_host_stats = bfad_im_get_stats,
+       .reset_fc_host_stats = bfad_im_reset_stats,
+
+       /* Allocation length for host specific data */
+       .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *),
+
+       /* Remote port fixed attributes */
+       .show_rport_maxframe_size = 1,
+       .show_rport_supported_classes = 1,
+       .show_rport_dev_loss_tmo = 1,
+       .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo,
+       .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo,
 };
 
 /**
index 107848c..6c920c1 100644 (file)
@@ -162,7 +162,6 @@ struct bfad_s {
        const char *pci_name;
        struct bfa_pcidev_s hal_pcidev;
        struct bfa_ioc_pci_attr_s pci_attr;
-       unsigned long   pci_bar0_map;
        void __iomem   *pci_bar0_kva;
        struct completion comp;
        struct completion suspend;
@@ -254,7 +253,7 @@ do {                                                \
 
 
 bfa_status_t    bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
-                                 struct bfa_port_cfg_s *port_cfg);
+                         struct bfa_port_cfg_s *port_cfg, struct device *dev);
 bfa_status_t    bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
                               struct bfa_port_cfg_s *port_cfg);
 bfa_status_t    bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role);
@@ -294,5 +293,6 @@ extern struct list_head bfad_list;
 extern int bfa_lun_queue_depth;
 extern int bfad_supported_fc4s;
 extern int bfa_linkup_delay;
+extern struct mutex bfad_mutex;
 
 #endif /* __BFAD_DRV_H__ */
index 78f42aa..5b7cf53 100644 (file)
@@ -30,6 +30,7 @@ BFA_TRC_FILE(LDRV, IM);
 
 DEFINE_IDR(bfad_im_port_index);
 struct scsi_transport_template *bfad_im_scsi_transport_template;
+struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
 static void bfad_im_itnim_work_handler(struct work_struct *work);
 static int bfad_im_queuecommand(struct scsi_cmnd *cmnd,
                void (*done)(struct scsi_cmnd *));
@@ -252,7 +253,6 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,
        struct bfa_itnim_s *bfa_itnim;
        bfa_status_t    rc = BFA_STATUS_OK;
 
-       bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim);
        tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
        if (!tskim) {
                BFA_DEV_PRINTF(bfad, BFA_ERR,
@@ -513,11 +513,14 @@ void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim)
  * Allocate a Scsi_Host for a port.
  */
 int
-bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
+bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
+                               struct device *dev)
 {
        int error = 1;
 
+       mutex_lock(&bfad_mutex);
        if (!idr_pre_get(&bfad_im_port_index, GFP_KERNEL)) {
+               mutex_unlock(&bfad_mutex);
                printk(KERN_WARNING "idr_pre_get failure\n");
                goto out;
        }
@@ -525,10 +528,13 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
        error = idr_get_new(&bfad_im_port_index, im_port,
                                         &im_port->idr_id);
        if (error) {
+               mutex_unlock(&bfad_mutex);
                printk(KERN_WARNING "idr_get_new failure\n");
                goto out;
        }
 
+       mutex_unlock(&bfad_mutex);
+
        im_port->shost = bfad_os_scsi_host_alloc(im_port, bfad);
        if (!im_port->shost) {
                error = 1;
@@ -542,12 +548,15 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
        im_port->shost->max_lun = MAX_FCP_LUN;
        im_port->shost->max_cmd_len = 16;
        im_port->shost->can_queue = bfad->cfg_data.ioc_queue_depth;
-       im_port->shost->transportt = bfad_im_scsi_transport_template;
+       if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE)
+               im_port->shost->transportt = bfad_im_scsi_transport_template;
+       else
+               im_port->shost->transportt =
+                               bfad_im_scsi_vport_transport_template;
 
-       error = bfad_os_scsi_add_host(im_port->shost, im_port, bfad);
+       error = scsi_add_host(im_port->shost, dev);
        if (error) {
-               printk(KERN_WARNING "bfad_os_scsi_add_host failure %d\n",
-                                                       error);
+               printk(KERN_WARNING "scsi_add_host failure %d\n", error);
                goto out_fc_rel;
        }
 
@@ -559,7 +568,9 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
 out_fc_rel:
        scsi_host_put(im_port->shost);
 out_free_idr:
+       mutex_lock(&bfad_mutex);
        idr_remove(&bfad_im_port_index, im_port->idr_id);
+       mutex_unlock(&bfad_mutex);
 out:
        return error;
 }
@@ -567,8 +578,6 @@ out:
 void
 bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
 {
-       unsigned long flags;
-
        bfa_trc(bfad, bfad->inst_no);
        bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_HOST_FREE,
                        im_port->shost->host_no);
@@ -578,9 +587,9 @@ bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
        scsi_remove_host(im_port->shost);
        scsi_host_put(im_port->shost);
 
-       spin_lock_irqsave(&bfad->bfad_lock, flags);
+       mutex_lock(&bfad_mutex);
        idr_remove(&bfad_im_port_index, im_port->idr_id);
-       spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+       mutex_unlock(&bfad_mutex);
 }
 
 static void
@@ -589,9 +598,11 @@ bfad_im_port_delete_handler(struct work_struct *work)
        struct bfad_im_port_s *im_port =
                container_of(work, struct bfad_im_port_s, port_delete_work);
 
-       bfad_im_scsi_host_free(im_port->bfad, im_port);
-       bfad_im_port_clean(im_port);
-       kfree(im_port);
+       if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) {
+               im_port->flags |= BFAD_PORT_DELETE;
+               fc_vport_terminate(im_port->fc_vport);
+       }
+
 }
 
 bfa_status_t
@@ -690,23 +701,6 @@ bfad_im_probe_undo(struct bfad_s *bfad)
        }
 }
 
-
-
-
-int
-bfad_os_scsi_add_host(struct Scsi_Host *shost, struct bfad_im_port_s *im_port,
-                       struct bfad_s *bfad)
-{
-    struct device *dev;
-
-    if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE)
-               dev = &bfad->pcidev->dev;
-    else
-               dev = &bfad->pport.im_port->shost->shost_gendev;
-
-    return scsi_add_host(shost, dev);
-}
-
 struct Scsi_Host *
 bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
 {
@@ -725,7 +719,8 @@ bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
 void
 bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
 {
-       flush_workqueue(bfad->im->drv_workq);
+       if (!(im_port->flags & BFAD_PORT_DELETE))
+               flush_workqueue(bfad->im->drv_workq);
        bfad_im_scsi_host_free(im_port->bfad, im_port);
        bfad_im_port_clean(im_port);
        kfree(im_port);
@@ -830,6 +825,13 @@ bfad_im_module_init(void)
        if (!bfad_im_scsi_transport_template)
                return BFA_STATUS_ENOMEM;
 
+       bfad_im_scsi_vport_transport_template =
+               fc_attach_transport(&bfad_im_vport_fc_function_template);
+       if (!bfad_im_scsi_vport_transport_template) {
+               fc_release_transport(bfad_im_scsi_transport_template);
+               return BFA_STATUS_ENOMEM;
+       }
+
        return BFA_STATUS_OK;
 }
 
@@ -838,6 +840,8 @@ bfad_im_module_exit(void)
 {
        if (bfad_im_scsi_transport_template)
                fc_release_transport(bfad_im_scsi_transport_template);
+       if (bfad_im_scsi_vport_transport_template)
+               fc_release_transport(bfad_im_scsi_vport_transport_template);
 }
 
 void
@@ -938,6 +942,7 @@ bfad_os_fc_host_init(struct bfad_im_port_s *im_port)
                bfa_os_htonll((bfa_fcs_port_get_nwwn(port->fcs_port)));
        fc_host_port_name(host) =
                bfa_os_htonll((bfa_fcs_port_get_pwwn(port->fcs_port)));
+       fc_host_max_npiv_vports(host) = bfa_lps_get_max_vport(&bfad->bfa);
 
        fc_host_supported_classes(host) = FC_COS_CLASS3;
 
index 85ab2da..973cab4 100644 (file)
@@ -34,7 +34,7 @@ void bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port);
 void bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port);
 void bfad_im_port_clean(struct bfad_im_port_s *im_port);
 int  bfad_im_scsi_host_alloc(struct bfad_s *bfad,
-                               struct bfad_im_port_s *im_port);
+               struct bfad_im_port_s *im_port, struct device *dev);
 void bfad_im_scsi_host_free(struct bfad_s *bfad,
                                struct bfad_im_port_s *im_port);
 
@@ -64,9 +64,11 @@ struct bfad_im_port_s {
        struct work_struct port_delete_work;
        int             idr_id;
        u16        cur_scsi_id;
+       u16        flags;
        struct list_head binding_list;
        struct Scsi_Host *shost;
        struct list_head itnim_mapped_list;
+       struct fc_vport *fc_vport;
 };
 
 enum bfad_itnim_state {
@@ -140,6 +142,8 @@ void bfad_im_itnim_unmap(struct bfad_im_port_s  *im_port,
 extern struct scsi_host_template bfad_im_scsi_host_template;
 extern struct scsi_host_template bfad_im_vport_template;
 extern struct fc_function_template bfad_im_fc_function_template;
+extern struct fc_function_template bfad_im_vport_fc_function_template;
 extern struct scsi_transport_template *bfad_im_scsi_transport_template;
+extern struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
 
 #endif
index 18352ff..3a66ca2 100644 (file)
@@ -347,6 +347,7 @@ int bnx2i_send_iscsi_login(struct bnx2i_conn *bnx2i_conn,
 
        login_wqe->cmd_sn = be32_to_cpu(login_hdr->cmdsn);
        login_wqe->exp_stat_sn = be32_to_cpu(login_hdr->exp_statsn);
+       login_wqe->flags = ISCSI_LOGIN_REQUEST_UPDATE_EXP_STAT_SN;
 
        login_wqe->resp_bd_list_addr_lo = (u32) bnx2i_conn->gen_pdu.resp_bd_dma;
        login_wqe->resp_bd_list_addr_hi =
@@ -356,7 +357,6 @@ int bnx2i_send_iscsi_login(struct bnx2i_conn *bnx2i_conn,
                 (bnx2i_conn->gen_pdu.resp_buf_size <<
                  ISCSI_LOGIN_REQUEST_RESP_BUFFER_LENGTH_SHIFT));
        login_wqe->resp_buffer = dword;
-       login_wqe->flags = 0;
        login_wqe->bd_list_addr_lo = (u32) bnx2i_conn->gen_pdu.req_bd_dma;
        login_wqe->bd_list_addr_hi =
                (u32) ((u64) bnx2i_conn->gen_pdu.req_bd_dma >> 32);
index 5d9296c..af6a00a 100644 (file)
@@ -17,8 +17,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME                "bnx2i"
-#define DRV_MODULE_VERSION     "2.1.0"
-#define DRV_MODULE_RELDATE     "Dec 06, 2009"
+#define DRV_MODULE_VERSION     "2.1.1"
+#define DRV_MODULE_RELDATE     "Mar 24, 2010"
 
 static char version[] __devinitdata =
                "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -26,7 +26,8 @@ static char version[] __devinitdata =
 
 
 MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709 iSCSI Driver");
+MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711"
+                  " iSCSI Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
@@ -289,6 +290,7 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic)
        int rc;
 
        mutex_lock(&bnx2i_dev_lock);
+       hba->cnic = cnic;
        rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba);
        if (!rc) {
                hba->age++;
@@ -335,8 +337,7 @@ void bnx2i_ulp_init(struct cnic_dev *dev)
        if (bnx2i_init_one(hba, dev)) {
                printk(KERN_ERR "bnx2i - hba %p init failed\n", hba);
                bnx2i_free_hba(hba);
-       } else
-               hba->cnic = dev;
+       }
 }
 
 
index d0ab23a..685af36 100644 (file)
@@ -104,8 +104,10 @@ static int __init cxgb3i_init_module(void)
                return err;
 
        err = cxgb3i_pdu_init();
-       if (err < 0)
+       if (err < 0) {
+               cxgb3i_iscsi_cleanup();
                return err;
+       }
 
        cxgb3_register_client(&t3c_client);
 
index e8a0bc3..6faf472 100644 (file)
@@ -285,13 +285,11 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
        switch (cmd) {
        case MODE_SELECT:
                len = sizeof(short_trespass);
-               rq->cmd_flags |= REQ_RW;
                rq->cmd[1] = 0x10;
                rq->cmd[4] = len;
                break;
        case MODE_SELECT_10:
                len = sizeof(long_trespass);
-               rq->cmd_flags |= REQ_RW;
                rq->cmd[1] = 0x10;
                rq->cmd[8] = len;
                break;
index 54c870b..9276121 100644 (file)
@@ -74,6 +74,7 @@ static int fcoe_rcv(struct sk_buff *, struct net_device *,
 static int fcoe_percpu_receive_thread(void *);
 static void fcoe_clean_pending_queue(struct fc_lport *);
 static void fcoe_percpu_clean(struct fc_lport *);
+static int fcoe_link_speed_update(struct fc_lport *);
 static int fcoe_link_ok(struct fc_lport *);
 
 static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
@@ -146,6 +147,7 @@ static int fcoe_vport_destroy(struct fc_vport *);
 static int fcoe_vport_create(struct fc_vport *, bool disabled);
 static int fcoe_vport_disable(struct fc_vport *, bool disable);
 static void fcoe_set_vport_symbolic_name(struct fc_vport *);
+static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *);
 
 static struct libfc_function_template fcoe_libfc_fcn_templ = {
        .frame_send = fcoe_xmit,
@@ -153,6 +155,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
        .ddp_done = fcoe_ddp_done,
        .elsct_send = fcoe_elsct_send,
        .get_lesb = fcoe_get_lesb,
+       .lport_set_port_id = fcoe_set_port_id,
 };
 
 struct fc_function_template fcoe_transport_function = {
@@ -629,6 +632,8 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
        port->fcoe_pending_queue_active = 0;
        setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport);
 
+       fcoe_link_speed_update(lport);
+
        if (!lport->vport) {
                /*
                 * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN:
@@ -653,15 +658,13 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
 /**
  * fcoe_shost_config() - Set up the SCSI host associated with a local port
  * @lport: The local port
- * @shost: The SCSI host to associate with the local port
  * @dev:   The device associated with the SCSI host
  *
  * Must be called after fcoe_lport_config() and fcoe_netdev_config()
  *
  * Returns: 0 for success
  */
-static int fcoe_shost_config(struct fc_lport *lport, struct Scsi_Host *shost,
-                            struct device *dev)
+static int fcoe_shost_config(struct fc_lport *lport, struct device *dev)
 {
        int rc = 0;
 
@@ -669,6 +672,8 @@ static int fcoe_shost_config(struct fc_lport *lport, struct Scsi_Host *shost,
        lport->host->max_lun = FCOE_MAX_LUN;
        lport->host->max_id = FCOE_MAX_FCP_TARGET;
        lport->host->max_channel = 0;
+       lport->host->max_cmd_len = FCOE_MAX_CMD_LEN;
+
        if (lport->vport)
                lport->host->transportt = fcoe_vport_transport_template;
        else
@@ -796,6 +801,12 @@ skip_oem:
 /**
  * fcoe_if_destroy() - Tear down a SW FCoE instance
  * @lport: The local port to be destroyed
+ *
+ * Locking: must be called with the RTNL mutex held and RTNL mutex
+ * needed to be dropped by this function since not dropping RTNL
+ * would cause circular locking warning on synchronous fip worker
+ * cancelling thru fcoe_interface_put invoked by this function.
+ *
  */
 static void fcoe_if_destroy(struct fc_lport *lport)
 {
@@ -818,7 +829,6 @@ static void fcoe_if_destroy(struct fc_lport *lport)
        /* Free existing transmit skbs */
        fcoe_clean_pending_queue(lport);
 
-       rtnl_lock();
        if (!is_zero_ether_addr(port->data_src_addr))
                dev_uc_del(netdev, port->data_src_addr);
        rtnl_unlock();
@@ -841,6 +851,7 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 
        /* Release the Scsi_Host */
        scsi_host_put(lport->host);
+       module_put(THIS_MODULE);
 }
 
 /**
@@ -897,7 +908,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
        struct net_device *netdev = fcoe->netdev;
        struct fc_lport *lport = NULL;
        struct fcoe_port *port;
-       struct Scsi_Host *shost;
        int rc;
        /*
         * parent is only a vport if npiv is 1,
@@ -919,7 +929,6 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
                rc = -ENOMEM;
                goto out;
        }
-       shost = lport->host;
        port = lport_priv(lport);
        port->lport = lport;
        port->fcoe = fcoe;
@@ -934,7 +943,8 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
        }
 
        if (npiv) {
-               FCOE_NETDEV_DBG(netdev, "Setting vport names, 0x%llX 0x%llX\n",
+               FCOE_NETDEV_DBG(netdev, "Setting vport names, "
+                               "%16.16llx %16.16llx\n",
                                vport->node_name, vport->port_name);
                fc_set_wwnn(lport, vport->node_name);
                fc_set_wwpn(lport, vport->port_name);
@@ -949,7 +959,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
        }
 
        /* configure lport scsi host properties */
-       rc = fcoe_shost_config(lport, shost, parent);
+       rc = fcoe_shost_config(lport, parent);
        if (rc) {
                FCOE_NETDEV_DBG(netdev, "Could not configure shost for the "
                                "interface\n");
@@ -1073,7 +1083,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu)
        struct sk_buff *skb;
 #ifdef CONFIG_SMP
        struct fcoe_percpu_s *p0;
-       unsigned targ_cpu = smp_processor_id();
+       unsigned targ_cpu = get_cpu();
 #endif /* CONFIG_SMP */
 
        FCOE_DBG("Destroying receive thread for CPU %d\n", cpu);
@@ -1129,6 +1139,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu)
                        kfree_skb(skb);
                spin_unlock_bh(&p->fcoe_rx_list.lock);
        }
+       put_cpu();
 #else
        /*
         * This a non-SMP scenario where the singular Rx thread is
@@ -1297,8 +1308,8 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
 
        return 0;
 err:
-       fc_lport_get_stats(lport)->ErrorFrames++;
-
+       per_cpu_ptr(lport->dev_stats, get_cpu())->ErrorFrames++;
+       put_cpu();
 err2:
        kfree_skb(skb);
        return -1;
@@ -1444,7 +1455,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
                return 0;
        }
 
-       if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
+       if (unlikely(fh->fh_type == FC_TYPE_ELS) &&
            fcoe_ctlr_els_send(&fcoe->ctlr, lport, skb))
                return 0;
 
@@ -1527,9 +1538,10 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
                skb_shinfo(skb)->gso_size = 0;
        }
        /* update tx stats: regardless if LLD fails */
-       stats = fc_lport_get_stats(lport);
+       stats = per_cpu_ptr(lport->dev_stats, get_cpu());
        stats->TxFrames++;
        stats->TxWords += wlen;
+       put_cpu();
 
        /* send down to lld */
        fr_dev(fp) = lport;
@@ -1563,7 +1575,6 @@ static void fcoe_recv_frame(struct sk_buff *skb)
        struct fc_frame_header *fh;
        struct fcoe_crc_eof crc_eof;
        struct fc_frame *fp;
-       u8 *mac = NULL;
        struct fcoe_port *port;
        struct fcoe_hdr *hp;
 
@@ -1583,13 +1594,9 @@ static void fcoe_recv_frame(struct sk_buff *skb)
                        skb_end_pointer(skb), skb->csum,
                        skb->dev ? skb->dev->name : "<NULL>");
 
-       /*
-        * Save source MAC address before discarding header.
-        */
        port = lport_priv(lport);
        if (skb_is_nonlinear(skb))
                skb_linearize(skb);     /* not ideal */
-       mac = eth_hdr(skb)->h_source;
 
        /*
         * Frame length checks and setting up the header pointers
@@ -1598,7 +1605,7 @@ static void fcoe_recv_frame(struct sk_buff *skb)
        hp = (struct fcoe_hdr *) skb_network_header(skb);
        fh = (struct fc_frame_header *) skb_transport_header(skb);
 
-       stats = fc_lport_get_stats(lport);
+       stats = per_cpu_ptr(lport->dev_stats, get_cpu());
        if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
                if (stats->ErrorFrames < 5)
                        printk(KERN_WARNING "fcoe: FCoE version "
@@ -1607,9 +1614,7 @@ static void fcoe_recv_frame(struct sk_buff *skb)
                               "initiator supports version "
                               "%x\n", FC_FCOE_DECAPS_VER(hp),
                               FC_FCOE_VER);
-               stats->ErrorFrames++;
-               kfree_skb(skb);
-               return;
+               goto drop;
        }
 
        skb_pull(skb, sizeof(struct fcoe_hdr));
@@ -1624,16 +1629,12 @@ static void fcoe_recv_frame(struct sk_buff *skb)
        fr_sof(fp) = hp->fcoe_sof;
 
        /* Copy out the CRC and EOF trailer for access */
-       if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
-               kfree_skb(skb);
-               return;
-       }
+       if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof)))
+               goto drop;
        fr_eof(fp) = crc_eof.fcoe_eof;
        fr_crc(fp) = crc_eof.fcoe_crc32;
-       if (pskb_trim(skb, fr_len)) {
-               kfree_skb(skb);
-               return;
-       }
+       if (pskb_trim(skb, fr_len))
+               goto drop;
 
        /*
         * We only check CRC if no offload is available and if it is
@@ -1647,25 +1648,27 @@ static void fcoe_recv_frame(struct sk_buff *skb)
                fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
 
        fh = fc_frame_header_get(fp);
-       if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
-           fh->fh_type == FC_TYPE_FCP) {
-               fc_exch_recv(lport, fp);
-               return;
-       }
-       if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
+       if ((fh->fh_r_ctl != FC_RCTL_DD_SOL_DATA ||
+           fh->fh_type != FC_TYPE_FCP) &&
+           (fr_flags(fp) & FCPHF_CRC_UNCHECKED)) {
                if (le32_to_cpu(fr_crc(fp)) !=
                    ~crc32(~0, skb->data, fr_len)) {
                        if (stats->InvalidCRCCount < 5)
                                printk(KERN_WARNING "fcoe: dropping "
                                       "frame with CRC error\n");
                        stats->InvalidCRCCount++;
-                       stats->ErrorFrames++;
-                       fc_frame_free(fp);
-                       return;
+                       goto drop;
                }
                fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
        }
+       put_cpu();
        fc_exch_recv(lport, fp);
+       return;
+
+drop:
+       stats->ErrorFrames++;
+       put_cpu();
+       kfree_skb(skb);
 }
 
 /**
@@ -1835,11 +1838,15 @@ static int fcoe_device_notification(struct notifier_block *notifier,
                FCOE_NETDEV_DBG(netdev, "Unknown event %ld "
                                "from netdev netlink\n", event);
        }
+
+       fcoe_link_speed_update(lport);
+
        if (link_possible && !fcoe_link_ok(lport))
                fcoe_ctlr_link_up(&fcoe->ctlr);
        else if (fcoe_ctlr_link_down(&fcoe->ctlr)) {
-               stats = fc_lport_get_stats(lport);
+               stats = per_cpu_ptr(lport->dev_stats, get_cpu());
                stats->LinkFailureCount++;
+               put_cpu();
                fcoe_clean_pending_queue(lport);
        }
 out:
@@ -1901,13 +1908,19 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp)
                goto out_nodev;
        }
 
-       rtnl_lock();
+       if (!rtnl_trylock()) {
+               dev_put(netdev);
+               mutex_unlock(&fcoe_config_mutex);
+               return restart_syscall();
+       }
+
        fcoe = fcoe_hostlist_lookup_port(netdev);
        rtnl_unlock();
 
-       if (fcoe)
+       if (fcoe) {
                fc_fabric_logoff(fcoe->ctlr.lp);
-       else
+               fcoe_ctlr_link_down(&fcoe->ctlr);
+       } else
                rc = -ENODEV;
 
        dev_put(netdev);
@@ -1950,13 +1963,20 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp)
                goto out_nodev;
        }
 
-       rtnl_lock();
+       if (!rtnl_trylock()) {
+               dev_put(netdev);
+               mutex_unlock(&fcoe_config_mutex);
+               return restart_syscall();
+       }
+
        fcoe = fcoe_hostlist_lookup_port(netdev);
        rtnl_unlock();
 
-       if (fcoe)
+       if (fcoe) {
+               if (!fcoe_link_ok(fcoe->ctlr.lp))
+                       fcoe_ctlr_link_up(&fcoe->ctlr);
                rc = fc_fabric_login(fcoe->ctlr.lp);
-       else
+       } else
                rc = -ENODEV;
 
        dev_put(netdev);
@@ -1999,7 +2019,12 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
                goto out_nodev;
        }
 
-       rtnl_lock();
+       if (!rtnl_trylock()) {
+               dev_put(netdev);
+               mutex_unlock(&fcoe_config_mutex);
+               return restart_syscall();
+       }
+
        fcoe = fcoe_hostlist_lookup_port(netdev);
        if (!fcoe) {
                rtnl_unlock();
@@ -2008,9 +2033,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
        }
        list_del(&fcoe->list);
        fcoe_interface_cleanup(fcoe);
-       rtnl_unlock();
+       /* RTNL mutex is dropped by fcoe_if_destroy */
        fcoe_if_destroy(fcoe->ctlr.lp);
-       module_put(THIS_MODULE);
 
 out_putdev:
        dev_put(netdev);
@@ -2029,6 +2053,8 @@ static void fcoe_destroy_work(struct work_struct *work)
 
        port = container_of(work, struct fcoe_port, destroy_work);
        mutex_lock(&fcoe_config_mutex);
+       rtnl_lock();
+       /* RTNL mutex is dropped by fcoe_if_destroy */
        fcoe_if_destroy(port->lport);
        mutex_unlock(&fcoe_config_mutex);
 }
@@ -2050,6 +2076,12 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
        struct net_device *netdev;
 
        mutex_lock(&fcoe_config_mutex);
+
+       if (!rtnl_trylock()) {
+               mutex_unlock(&fcoe_config_mutex);
+               return restart_syscall();
+       }
+
 #ifdef CONFIG_FCOE_MODULE
        /*
         * Make sure the module has been initialized, and is not about to be
@@ -2058,7 +2090,7 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
         */
        if (THIS_MODULE->state != MODULE_STATE_LIVE) {
                rc = -ENODEV;
-               goto out_nodev;
+               goto out_nomod;
        }
 #endif
 
@@ -2067,7 +2099,6 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
                goto out_nomod;
        }
 
-       rtnl_lock();
        netdev = fcoe_if_to_netdev(buffer);
        if (!netdev) {
                rc = -ENODEV;
@@ -2122,35 +2153,27 @@ out_free:
 out_putdev:
        dev_put(netdev);
 out_nodev:
-       rtnl_unlock();
        module_put(THIS_MODULE);
 out_nomod:
+       rtnl_unlock();
        mutex_unlock(&fcoe_config_mutex);
        return rc;
 }
 
 /**
- * fcoe_link_ok() - Check if the link is OK for a local port
- * @lport: The local port to check link on
- *
- * Any permanently-disqualifying conditions have been previously checked.
- * This also updates the speed setting, which may change with link for 100/1000.
- *
- * This function should probably be checking for PAUSE support at some point
- * in the future. Currently Per-priority-pause is not determinable using
- * ethtool, so we shouldn't be restrictive until that problem is resolved.
- *
- * Returns: 0 if link is OK for use by FCoE.
+ * fcoe_link_speed_update() - Update the supported and actual link speeds
+ * @lport: The local port to update speeds for
  *
+ * Returns: 0 if the ethtool query was successful
+ *          -1 if the ethtool query failed
  */
-int fcoe_link_ok(struct fc_lport *lport)
+int fcoe_link_speed_update(struct fc_lport *lport)
 {
        struct fcoe_port *port = lport_priv(lport);
        struct net_device *netdev = port->fcoe->netdev;
        struct ethtool_cmd ecmd = { ETHTOOL_GSET };
 
-       if ((netdev->flags & IFF_UP) && netif_carrier_ok(netdev) &&
-           (!dev_ethtool_get_settings(netdev, &ecmd))) {
+       if (!dev_ethtool_get_settings(netdev, &ecmd)) {
                lport->link_supported_speeds &=
                        ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
                if (ecmd.supported & (SUPPORTED_1000baseT_Half |
@@ -2170,6 +2193,23 @@ int fcoe_link_ok(struct fc_lport *lport)
 }
 
 /**
+ * fcoe_link_ok() - Check if the link is OK for a local port
+ * @lport: The local port to check link on
+ *
+ * Returns: 0 if link is UP and OK, -1 if not
+ *
+ */
+int fcoe_link_ok(struct fc_lport *lport)
+{
+       struct fcoe_port *port = lport_priv(lport);
+       struct net_device *netdev = port->fcoe->netdev;
+
+       if (netif_oper_up(netdev))
+               return 0;
+       return -1;
+}
+
+/**
  * fcoe_percpu_clean() - Clear all pending skbs for an local port
  * @lport: The local port whose skbs are to be cleared
  *
@@ -2631,3 +2671,25 @@ static void fcoe_get_lesb(struct fc_lport *lport,
        lesb->lesb_miss_fka = htonl(mdac);
        lesb->lesb_fcs_error = htonl(dev_get_stats(netdev)->rx_crc_errors);
 }
+
+/**
+ * fcoe_set_port_id() - Callback from libfc when Port_ID is set.
+ * @lport: the local port
+ * @port_id: the port ID
+ * @fp: the received frame, if any, that caused the port_id to be set.
+ *
+ * This routine handles the case where we received a FLOGI and are
+ * entering point-to-point mode.  We need to call fcoe_ctlr_recv_flogi()
+ * so it can set the non-mapped mode and gateway address.
+ *
+ * The FLOGI LS_ACC is handled by fcoe_flogi_resp().
+ */
+static void fcoe_set_port_id(struct fc_lport *lport,
+                            u32 port_id, struct fc_frame *fp)
+{
+       struct fcoe_port *port = lport_priv(lport);
+       struct fcoe_interface *fcoe = port->fcoe;
+
+       if (fp && fc_frame_payload_op(fp) == ELS_FLOGI)
+               fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp);
+}
index 3440da4..50aaa4b 100644 (file)
@@ -51,7 +51,7 @@ MODULE_LICENSE("GPL v2");
 #define        FCOE_CTLR_DEF_FKA       FIP_DEF_FKA     /* default keep alive (mS) */
 
 static void fcoe_ctlr_timeout(unsigned long);
-static void fcoe_ctlr_link_work(struct work_struct *);
+static void fcoe_ctlr_timer_work(struct work_struct *);
 static void fcoe_ctlr_recv_work(struct work_struct *);
 
 static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
@@ -116,7 +116,7 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip)
        spin_lock_init(&fip->lock);
        fip->flogi_oxid = FC_XID_UNKNOWN;
        setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
-       INIT_WORK(&fip->link_work, fcoe_ctlr_link_work);
+       INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work);
        INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work);
        skb_queue_head_init(&fip->fip_recv_list);
 }
@@ -164,7 +164,7 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
        fcoe_ctlr_reset_fcfs(fip);
        spin_unlock_bh(&fip->lock);
        del_timer_sync(&fip->timer);
-       cancel_work_sync(&fip->link_work);
+       cancel_work_sync(&fip->timer_work);
 }
 EXPORT_SYMBOL(fcoe_ctlr_destroy);
 
@@ -257,14 +257,10 @@ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip)
 {
        spin_lock_bh(&fip->lock);
        if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) {
-               fip->last_link = 1;
-               fip->link = 1;
                spin_unlock_bh(&fip->lock);
                fc_linkup(fip->lp);
        } else if (fip->state == FIP_ST_LINK_WAIT) {
                fip->state = fip->mode;
-               fip->last_link = 1;
-               fip->link = 1;
                spin_unlock_bh(&fip->lock);
                if (fip->state == FIP_ST_AUTO)
                        LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n");
@@ -306,9 +302,7 @@ int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
        LIBFCOE_FIP_DBG(fip, "link down.\n");
        spin_lock_bh(&fip->lock);
        fcoe_ctlr_reset(fip);
-       link_dropped = fip->link;
-       fip->link = 0;
-       fip->last_link = 0;
+       link_dropped = fip->state != FIP_ST_LINK_WAIT;
        fip->state = FIP_ST_LINK_WAIT;
        spin_unlock_bh(&fip->lock);
 
@@ -349,7 +343,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
 
        fcf = fip->sel_fcf;
        lp = fip->lp;
-       if (!fcf || !fc_host_port_id(lp->host))
+       if (!fcf || !lp->port_id)
                return;
 
        len = sizeof(*kal) + ports * sizeof(*vn);
@@ -380,8 +374,8 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
                vn->fd_desc.fip_dtype = FIP_DT_VN_ID;
                vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW;
                memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
-               hton24(vn->fd_fc_id, fc_host_port_id(lp->host));
-               put_unaligned_be64(lp->wwpn, &vn->fd_wwpn);
+               hton24(vn->fd_fc_id, lport->port_id);
+               put_unaligned_be64(lport->wwpn, &vn->fd_wwpn);
        }
        skb_put(skb, len);
        skb->protocol = htons(ETH_P_FIP);
@@ -445,13 +439,18 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
        cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW;
 
        mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac));
-       memset(mac, 0, sizeof(mac));
+       memset(mac, 0, sizeof(*mac));
        mac->fd_desc.fip_dtype = FIP_DT_MAC;
        mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW;
-       if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC)
+       if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) {
                memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
-       else if (fip->spma)
+       } else if (fip_flags & FIP_FL_SPMA) {
+               LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n");
                memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN);
+       } else {
+               LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n");
+               /* FPMA only FLOGI must leave the MAC desc set to all 0s */
+       }
 
        skb->protocol = htons(ETH_P_FIP);
        skb_reset_mac_header(skb);
@@ -556,7 +555,7 @@ EXPORT_SYMBOL(fcoe_ctlr_els_send);
  * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller
  * @fip: The FCoE controller to free FCFs on
  *
- * Called with lock held.
+ * Called with lock held and preemption disabled.
  *
  * An FCF is considered old if we have missed three advertisements.
  * That is, there have been no valid advertisement from it for three
@@ -573,17 +572,20 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
        struct fcoe_fcf *next;
        unsigned long sel_time = 0;
        unsigned long mda_time = 0;
+       struct fcoe_dev_stats *stats;
 
        list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
                mda_time = fcf->fka_period + (fcf->fka_period >> 1);
                if ((fip->sel_fcf == fcf) &&
                    (time_after(jiffies, fcf->time + mda_time))) {
                        mod_timer(&fip->timer, jiffies + mda_time);
-                       fc_lport_get_stats(fip->lp)->MissDiscAdvCount++;
+                       stats = per_cpu_ptr(fip->lp->dev_stats,
+                                           smp_processor_id());
+                       stats->MissDiscAdvCount++;
                        printk(KERN_INFO "libfcoe: host%d: Missing Discovery "
-                              "Advertisement for fab %llx count %lld\n",
+                              "Advertisement for fab %16.16llx count %lld\n",
                               fip->lp->host->host_no, fcf->fabric_name,
-                              fc_lport_get_stats(fip->lp)->MissDiscAdvCount);
+                              stats->MissDiscAdvCount);
                }
                if (time_after(jiffies, fcf->time + fcf->fka_period * 3 +
                               msecs_to_jiffies(FIP_FCF_FUZZ * 3))) {
@@ -593,7 +595,9 @@ static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
                        WARN_ON(!fip->fcf_count);
                        fip->fcf_count--;
                        kfree(fcf);
-                       fc_lport_get_stats(fip->lp)->VLinkFailureCount++;
+                       stats = per_cpu_ptr(fip->lp->dev_stats,
+                                           smp_processor_id());
+                       stats->VLinkFailureCount++;
                } else if (fcoe_ctlr_mtu_valid(fcf) &&
                           (!sel_time || time_before(sel_time, fcf->time))) {
                        sel_time = fcf->time;
@@ -776,7 +780,8 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
        mtu_valid = fcoe_ctlr_mtu_valid(fcf);
        fcf->time = jiffies;
        if (!found) {
-               LIBFCOE_FIP_DBG(fip, "New FCF for fab %llx map %x val %d\n",
+               LIBFCOE_FIP_DBG(fip, "New FCF for fab %16.16llx "
+                               "map %x val %d\n",
                                fcf->fabric_name, fcf->fc_map, mtu_valid);
        }
 
@@ -906,9 +911,10 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
        fr_eof(fp) = FC_EOF_T;
        fr_dev(fp) = lport;
 
-       stats = fc_lport_get_stats(lport);
+       stats = per_cpu_ptr(lport->dev_stats, get_cpu());
        stats->RxFrames++;
        stats->RxWords += skb->len / FIP_BPW;
+       put_cpu();
 
        fc_exch_recv(lport, fp);
        return;
@@ -942,9 +948,8 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
        u32     desc_mask;
 
        LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n");
-       if (!fcf)
-               return;
-       if (!fcf || !fc_host_port_id(lport->host))
+
+       if (!fcf || !lport->port_id)
                return;
 
        /*
@@ -982,8 +987,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
                        if (compare_ether_addr(vp->fd_mac,
                                               fip->get_src_addr(lport)) == 0 &&
                            get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn &&
-                           ntoh24(vp->fd_fc_id) ==
-                           fc_host_port_id(lport->host))
+                           ntoh24(vp->fd_fc_id) == lport->port_id)
                                desc_mask &= ~BIT(FIP_DT_VN_ID);
                        break;
                default:
@@ -1006,7 +1010,8 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
                LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n");
 
                spin_lock_bh(&fip->lock);
-               fc_lport_get_stats(lport)->VLinkFailureCount++;
+               per_cpu_ptr(lport->dev_stats,
+                           smp_processor_id())->VLinkFailureCount++;
                fcoe_ctlr_reset(fip);
                spin_unlock_bh(&fip->lock);
 
@@ -1102,15 +1107,17 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
        struct fcoe_fcf *best = NULL;
 
        list_for_each_entry(fcf, &fip->fcfs, list) {
-               LIBFCOE_FIP_DBG(fip, "consider FCF for fab %llx VFID %d map %x "
-                               "val %d\n", fcf->fabric_name, fcf->vfid,
+               LIBFCOE_FIP_DBG(fip, "consider FCF for fab %16.16llx "
+                               "VFID %d map %x val %d\n",
+                               fcf->fabric_name, fcf->vfid,
                                fcf->fc_map, fcoe_ctlr_mtu_valid(fcf));
                if (!fcoe_ctlr_fcf_usable(fcf)) {
-                       LIBFCOE_FIP_DBG(fip, "FCF for fab %llx map %x %svalid "
-                                       "%savailable\n", fcf->fabric_name,
-                                       fcf->fc_map, (fcf->flags & FIP_FL_SOL)
-                                       ? "" : "in", (fcf->flags & FIP_FL_AVAIL)
-                                       ? "" : "un");
+                       LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
+                                       "map %x %svalid %savailable\n",
+                                       fcf->fabric_name, fcf->fc_map,
+                                       (fcf->flags & FIP_FL_SOL) ? "" : "in",
+                                       (fcf->flags & FIP_FL_AVAIL) ?
+                                       "" : "un");
                        continue;
                }
                if (!best) {
@@ -1175,7 +1182,7 @@ static void fcoe_ctlr_timeout(unsigned long arg)
                               "Starting FCF discovery.\n",
                               fip->lp->host->host_no);
                        fip->reset_req = 1;
-                       schedule_work(&fip->link_work);
+                       schedule_work(&fip->timer_work);
                }
        }
 
@@ -1201,43 +1208,31 @@ static void fcoe_ctlr_timeout(unsigned long arg)
                mod_timer(&fip->timer, next_timer);
        }
        if (fip->send_ctlr_ka || fip->send_port_ka)
-               schedule_work(&fip->link_work);
+               schedule_work(&fip->timer_work);
        spin_unlock_bh(&fip->lock);
 }
 
 /**
- * fcoe_ctlr_link_work() - Worker thread function for link changes
+ * fcoe_ctlr_timer_work() - Worker thread function for timer work
  * @work: Handle to a FCoE controller
  *
- * See if the link status has changed and if so, report it.
- *
- * This is here because fc_linkup() and fc_linkdown() must not
+ * Sends keep-alives and resets which must not
  * be called from the timer directly, since they use a mutex.
  */
-static void fcoe_ctlr_link_work(struct work_struct *work)
+static void fcoe_ctlr_timer_work(struct work_struct *work)
 {
        struct fcoe_ctlr *fip;
        struct fc_lport *vport;
        u8 *mac;
-       int link;
-       int last_link;
        int reset;
 
-       fip = container_of(work, struct fcoe_ctlr, link_work);
+       fip = container_of(work, struct fcoe_ctlr, timer_work);
        spin_lock_bh(&fip->lock);
-       last_link = fip->last_link;
-       link = fip->link;
-       fip->last_link = link;
        reset = fip->reset_req;
        fip->reset_req = 0;
        spin_unlock_bh(&fip->lock);
 
-       if (last_link != link) {
-               if (link)
-                       fc_linkup(fip->lp);
-               else
-                       fc_linkdown(fip->lp);
-       } else if (reset && link)
+       if (reset)
                fc_lport_reset(fip->lp);
 
        if (fip->send_ctlr_ka) {
@@ -1334,9 +1329,9 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport,
                if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) {
                        memcpy(fip->dest_addr, sa, ETH_ALEN);
                        fip->map_dest = 0;
-                       if (fip->state == FIP_ST_NON_FIP)
-                               LIBFCOE_FIP_DBG(fip, "received FLOGI REQ, "
-                                               "using non-FIP mode\n");
+                       if (fip->state == FIP_ST_AUTO)
+                               LIBFCOE_FIP_DBG(fip, "received non-FIP FLOGI. "
+                                               "Setting non-FIP mode\n");
                        fip->state = FIP_ST_NON_FIP;
                }
                spin_unlock_bh(&fip->lock);
index 3966c71..19338e0 100644 (file)
@@ -36,7 +36,7 @@
 
 #define DRV_NAME               "fnic"
 #define DRV_DESCRIPTION                "Cisco FCoE HBA Driver"
-#define DRV_VERSION            "1.4.0.98"
+#define DRV_VERSION            "1.4.0.145"
 #define PFX                    DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
@@ -45,7 +45,7 @@
 #define        FNIC_IO_LOCKS           64 /* IO locks: power of 2 */
 #define FNIC_DFLT_QUEUE_DEPTH  32
 #define        FNIC_STATS_RATE_LIMIT   4 /* limit rate at which stats are pulled up */
-#define FNIC_MAX_CMD_LEN        16 /* Supported CDB length */
+
 /*
  * Tag bits used for special requests.
  */
index 5259888..2b48d79 100644 (file)
@@ -617,7 +617,7 @@ void fnic_flush_tx(struct fnic *fnic)
        struct sk_buff *skb;
        struct fc_frame *fp;
 
-       while ((skb = skb_dequeue(&fnic->frame_queue))) {
+       while ((skb = skb_dequeue(&fnic->tx_queue))) {
                fp = (struct fc_frame *)skb;
                fnic_send_frame(fnic, fp);
        }
index 97b2125..265e73d 100644 (file)
@@ -556,7 +556,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
        }
        host->max_lun = fnic->config.luns_per_tgt;
        host->max_id = FNIC_MAX_FCP_TARGET;
-       host->max_cmd_len = FNIC_MAX_CMD_LEN;
+       host->max_cmd_len = FCOE_MAX_CMD_LEN;
 
        fnic_get_res_counts(fnic);
 
index 35a4b30..a765fe7 100644 (file)
@@ -3842,7 +3842,7 @@ int __init option_setup(char *str)
 
     TRACE2(("option_setup() str %s\n", str ? str:"NULL")); 
 
-    while (cur && isdigit(*cur) && i <= MAXHA) {
+    while (cur && isdigit(*cur) && i < MAXHA) {
         ints[i++] = simple_strtoul(cur, NULL, 0);
         if ((cur = strchr(cur, ',')) != NULL) cur++;
     }
index 48f4068..18b7102 100644 (file)
 #include "wd33c93.h"
 #include "gvp11.h"
 
-#include<linux/stat.h>
+#include <linux/stat.h>
 
-#define DMA(ptr) ((gvp11_scsiregs *)((ptr)->base))
-#define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
 
-static irqreturn_t gvp11_intr (int irq, void *_instance)
+#define DMA(ptr)       ((gvp11_scsiregs *)((ptr)->base))
+
+static irqreturn_t gvp11_intr(int irq, void *_instance)
 {
-    unsigned long flags;
-    unsigned int status;
-    struct Scsi_Host *instance = (struct Scsi_Host *)_instance;
-
-    status = DMA(instance)->CNTR;
-    if (!(status & GVP11_DMAC_INT_PENDING))
-       return IRQ_NONE;
-
-    spin_lock_irqsave(instance->host_lock, flags);
-    wd33c93_intr(instance);
-    spin_unlock_irqrestore(instance->host_lock, flags);
-    return IRQ_HANDLED;
+       unsigned long flags;
+       unsigned int status;
+       struct Scsi_Host *instance = (struct Scsi_Host *)_instance;
+
+       status = DMA(instance)->CNTR;
+       if (!(status & GVP11_DMAC_INT_PENDING))
+               return IRQ_NONE;
+
+       spin_lock_irqsave(instance->host_lock, flags);
+       wd33c93_intr(instance);
+       spin_unlock_irqrestore(instance->host_lock, flags);
+       return IRQ_HANDLED;
 }
 
 static int gvp11_xfer_mask = 0;
 
-void gvp11_setup (char *str, int *ints)
+void gvp11_setup(char *str, int *ints)
 {
-    gvp11_xfer_mask = ints[1];
+       gvp11_xfer_mask = ints[1];
 }
 
 static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 {
-    unsigned short cntr = GVP11_DMAC_INT_ENABLE;
-    unsigned long addr = virt_to_bus(cmd->SCp.ptr);
-    int bank_mask;
-    static int scsi_alloc_out_of_range = 0;
-
-    /* use bounce buffer if the physical address is bad */
-    if (addr & HDATA(cmd->device->host)->dma_xfer_mask)
-    {
-       HDATA(cmd->device->host)->dma_bounce_len = (cmd->SCp.this_residual + 511)
-           & ~0x1ff;
-
-       if( !scsi_alloc_out_of_range ) {
-           HDATA(cmd->device->host)->dma_bounce_buffer =
-               kmalloc (HDATA(cmd->device->host)->dma_bounce_len, GFP_KERNEL);
-           HDATA(cmd->device->host)->dma_buffer_pool = BUF_SCSI_ALLOCED;
-       }
+       struct Scsi_Host *instance = cmd->device->host;
+       struct WD33C93_hostdata *hdata = shost_priv(instance);
+       unsigned short cntr = GVP11_DMAC_INT_ENABLE;
+       unsigned long addr = virt_to_bus(cmd->SCp.ptr);
+       int bank_mask;
+       static int scsi_alloc_out_of_range = 0;
+
+       /* use bounce buffer if the physical address is bad */
+       if (addr & hdata->dma_xfer_mask) {
+               hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
+
+               if (!scsi_alloc_out_of_range) {
+                       hdata->dma_bounce_buffer =
+                               kmalloc(hdata->dma_bounce_len, GFP_KERNEL);
+                       hdata->dma_buffer_pool = BUF_SCSI_ALLOCED;
+               }
 
-       if (scsi_alloc_out_of_range ||
-           !HDATA(cmd->device->host)->dma_bounce_buffer) {
-           HDATA(cmd->device->host)->dma_bounce_buffer =
-               amiga_chip_alloc(HDATA(cmd->device->host)->dma_bounce_len,
-                                      "GVP II SCSI Bounce Buffer");
+               if (scsi_alloc_out_of_range ||
+                   !hdata->dma_bounce_buffer) {
+                       hdata->dma_bounce_buffer =
+                               amiga_chip_alloc(hdata->dma_bounce_len,
+                                                "GVP II SCSI Bounce Buffer");
 
-           if(!HDATA(cmd->device->host)->dma_bounce_buffer)
-           {
-               HDATA(cmd->device->host)->dma_bounce_len = 0;
-               return 1;
-           }
+                       if (!hdata->dma_bounce_buffer) {
+                               hdata->dma_bounce_len = 0;
+                               return 1;
+                       }
 
-           HDATA(cmd->device->host)->dma_buffer_pool = BUF_CHIP_ALLOCED;
-       }
+                       hdata->dma_buffer_pool = BUF_CHIP_ALLOCED;
+               }
 
-       /* check if the address of the bounce buffer is OK */
-       addr = virt_to_bus(HDATA(cmd->device->host)->dma_bounce_buffer);
-
-       if (addr & HDATA(cmd->device->host)->dma_xfer_mask) {
-           /* fall back to Chip RAM if address out of range */
-           if( HDATA(cmd->device->host)->dma_buffer_pool == BUF_SCSI_ALLOCED) {
-               kfree (HDATA(cmd->device->host)->dma_bounce_buffer);
-               scsi_alloc_out_of_range = 1;
-           } else {
-               amiga_chip_free (HDATA(cmd->device->host)->dma_bounce_buffer);
-            }
-               
-           HDATA(cmd->device->host)->dma_bounce_buffer =
-               amiga_chip_alloc(HDATA(cmd->device->host)->dma_bounce_len,
-                                      "GVP II SCSI Bounce Buffer");
-
-           if(!HDATA(cmd->device->host)->dma_bounce_buffer)
-           {
-               HDATA(cmd->device->host)->dma_bounce_len = 0;
-               return 1;
-           }
-
-           addr = virt_to_bus(HDATA(cmd->device->host)->dma_bounce_buffer);
-           HDATA(cmd->device->host)->dma_buffer_pool = BUF_CHIP_ALLOCED;
-       }
-           
-       if (!dir_in) {
-           /* copy to bounce buffer for a write */
-           memcpy (HDATA(cmd->device->host)->dma_bounce_buffer,
-                   cmd->SCp.ptr, cmd->SCp.this_residual);
+               /* check if the address of the bounce buffer is OK */
+               addr = virt_to_bus(hdata->dma_bounce_buffer);
+
+               if (addr & hdata->dma_xfer_mask) {
+                       /* fall back to Chip RAM if address out of range */
+                       if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED) {
+                               kfree(hdata->dma_bounce_buffer);
+                               scsi_alloc_out_of_range = 1;
+                       } else {
+                               amiga_chip_free(hdata->dma_bounce_buffer);
+                       }
+
+                       hdata->dma_bounce_buffer =
+                               amiga_chip_alloc(hdata->dma_bounce_len,
+                                                "GVP II SCSI Bounce Buffer");
+
+                       if (!hdata->dma_bounce_buffer) {
+                               hdata->dma_bounce_len = 0;
+                               return 1;
+                       }
+
+                       addr = virt_to_bus(hdata->dma_bounce_buffer);
+                       hdata->dma_buffer_pool = BUF_CHIP_ALLOCED;
+               }
+
+               if (!dir_in) {
+                       /* copy to bounce buffer for a write */
+                       memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr,
+                              cmd->SCp.this_residual);
+               }
        }
-    }
 
-    /* setup dma direction */
-    if (!dir_in)
-       cntr |= GVP11_DMAC_DIR_WRITE;
+       /* setup dma direction */
+       if (!dir_in)
+               cntr |= GVP11_DMAC_DIR_WRITE;
 
-    HDATA(cmd->device->host)->dma_dir = dir_in;
-    DMA(cmd->device->host)->CNTR = cntr;
+       hdata->dma_dir = dir_in;
+       DMA(cmd->device->host)->CNTR = cntr;
 
-    /* setup DMA *physical* address */
-    DMA(cmd->device->host)->ACR = addr;
+       /* setup DMA *physical* address */
+       DMA(cmd->device->host)->ACR = addr;
 
-    if (dir_in)
-       /* invalidate any cache */
-       cache_clear (addr, cmd->SCp.this_residual);
-    else
-       /* push any dirty cache */
-       cache_push (addr, cmd->SCp.this_residual);
+       if (dir_in) {
+               /* invalidate any cache */
+               cache_clear(addr, cmd->SCp.this_residual);
+       } else {
+               /* push any dirty cache */
+               cache_push(addr, cmd->SCp.this_residual);
+       }
 
-    if ((bank_mask = (~HDATA(cmd->device->host)->dma_xfer_mask >> 18) & 0x01c0))
-           DMA(cmd->device->host)->BANK = bank_mask & (addr >> 18);
+       bank_mask = (~hdata->dma_xfer_mask >> 18) & 0x01c0;
+       if (bank_mask)
+               DMA(cmd->device->host)->BANK = bank_mask & (addr >> 18);
 
-    /* start DMA */
-    DMA(cmd->device->host)->ST_DMA = 1;
+       /* start DMA */
+       DMA(cmd->device->host)->ST_DMA = 1;
 
-    /* return success */
-    return 0;
+       /* return success */
+       return 0;
 }
 
 static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
                     int status)
 {
-    /* stop DMA */
-    DMA(instance)->SP_DMA = 1;
-    /* remove write bit from CONTROL bits */
-    DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
-
-    /* copy from a bounce buffer, if necessary */
-    if (status && HDATA(instance)->dma_bounce_buffer) {
-       if (HDATA(instance)->dma_dir && SCpnt)
-           memcpy (SCpnt->SCp.ptr, 
-                   HDATA(instance)->dma_bounce_buffer,
-                   SCpnt->SCp.this_residual);
-       
-       if (HDATA(instance)->dma_buffer_pool == BUF_SCSI_ALLOCED)
-           kfree (HDATA(instance)->dma_bounce_buffer);
-       else
-           amiga_chip_free(HDATA(instance)->dma_bounce_buffer);
-       
-       HDATA(instance)->dma_bounce_buffer = NULL;
-       HDATA(instance)->dma_bounce_len = 0;
-    }
+       struct WD33C93_hostdata *hdata = shost_priv(instance);
+
+       /* stop DMA */
+       DMA(instance)->SP_DMA = 1;
+       /* remove write bit from CONTROL bits */
+       DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
+
+       /* copy from a bounce buffer, if necessary */
+       if (status && hdata->dma_bounce_buffer) {
+               if (hdata->dma_dir && SCpnt)
+                       memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer,
+                              SCpnt->SCp.this_residual);
+
+               if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED)
+                       kfree(hdata->dma_bounce_buffer);
+               else
+                       amiga_chip_free(hdata->dma_bounce_buffer);
+
+               hdata->dma_bounce_buffer = NULL;
+               hdata->dma_bounce_len = 0;
+       }
 }
 
 #define CHECK_WD33C93
 
 int __init gvp11_detect(struct scsi_host_template *tpnt)
 {
-    static unsigned char called = 0;
-    struct Scsi_Host *instance;
-    unsigned long address;
-    unsigned int epc;
-    struct zorro_dev *z = NULL;
-    unsigned int default_dma_xfer_mask;
-    wd33c93_regs regs;
-    int num_gvp11 = 0;
+       static unsigned char called = 0;
+       struct Scsi_Host *instance;
+       unsigned long address;
+       unsigned int epc;
+       struct zorro_dev *z = NULL;
+       unsigned int default_dma_xfer_mask;
+       struct WD33C93_hostdata *hdata;
+       wd33c93_regs regs;
+       int num_gvp11 = 0;
 #ifdef CHECK_WD33C93
-    volatile unsigned char *sasr_3393, *scmd_3393;
-    unsigned char save_sasr;
-    unsigned char q, qq;
+       volatile unsigned char *sasr_3393, *scmd_3393;
+       unsigned char save_sasr;
+       unsigned char q, qq;
 #endif
 
-    if (!MACH_IS_AMIGA || called)
-       return 0;
-    called = 1;
-
-    tpnt->proc_name = "GVP11";
-    tpnt->proc_info = &wd33c93_proc_info;
-
-    while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
-       /* 
-        * This should (hopefully) be the correct way to identify
-        * all the different GVP SCSI controllers (except for the
-        * SERIES I though).
-        */
-
-       if (z->id == ZORRO_PROD_GVP_COMBO_030_R3_SCSI ||
-           z->id == ZORRO_PROD_GVP_SERIES_II)
-           default_dma_xfer_mask = ~0x00ffffff;
-       else if (z->id == ZORRO_PROD_GVP_GFORCE_030_SCSI ||
-                z->id == ZORRO_PROD_GVP_A530_SCSI ||
-                z->id == ZORRO_PROD_GVP_COMBO_030_R4_SCSI)
-           default_dma_xfer_mask = ~0x01ffffff;
-       else if (z->id == ZORRO_PROD_GVP_A1291 ||
-                z->id == ZORRO_PROD_GVP_GFORCE_040_SCSI_1)
-           default_dma_xfer_mask = ~0x07ffffff;
-       else
-           continue;
-
-       /*
-        * Rumors state that some GVP ram boards use the same product
-        * code as the SCSI controllers. Therefore if the board-size
-        * is not 64KB we asume it is a ram board and bail out.
-        */
-       if (z->resource.end-z->resource.start != 0xffff)
-               continue;
-
-       address = z->resource.start;
-       if (!request_mem_region(address, 256, "wd33c93"))
-           continue;
+       if (!MACH_IS_AMIGA || called)
+               return 0;
+       called = 1;
+
+       tpnt->proc_name = "GVP11";
+       tpnt->proc_info = &wd33c93_proc_info;
+
+       while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
+               /*
+                * This should (hopefully) be the correct way to identify
+                * all the different GVP SCSI controllers (except for the
+                * SERIES I though).
+                */
+
+               if (z->id == ZORRO_PROD_GVP_COMBO_030_R3_SCSI ||
+                   z->id == ZORRO_PROD_GVP_SERIES_II)
+                       default_dma_xfer_mask = ~0x00ffffff;
+               else if (z->id == ZORRO_PROD_GVP_GFORCE_030_SCSI ||
+                        z->id == ZORRO_PROD_GVP_A530_SCSI ||
+                        z->id == ZORRO_PROD_GVP_COMBO_030_R4_SCSI)
+                       default_dma_xfer_mask = ~0x01ffffff;
+               else if (z->id == ZORRO_PROD_GVP_A1291 ||
+                        z->id == ZORRO_PROD_GVP_GFORCE_040_SCSI_1)
+                       default_dma_xfer_mask = ~0x07ffffff;
+               else
+                       continue;
+
+               /*
+                * Rumors state that some GVP ram boards use the same product
+                * code as the SCSI controllers. Therefore if the board-size
+                * is not 64KB we asume it is a ram board and bail out.
+                */
+               if (z->resource.end - z->resource.start != 0xffff)
+                       continue;
+
+               address = z->resource.start;
+               if (!request_mem_region(address, 256, "wd33c93"))
+                       continue;
 
 #ifdef CHECK_WD33C93
 
-       /*
-        * These darn GVP boards are a problem - it can be tough to tell
-        * whether or not they include a SCSI controller. This is the
-        * ultimate Yet-Another-GVP-Detection-Hack in that it actually
-        * probes for a WD33c93 chip: If we find one, it's extremely
-        * likely that this card supports SCSI, regardless of Product_
-        * Code, Board_Size, etc. 
-        */
-
-    /* Get pointers to the presumed register locations and save contents */
-
-       sasr_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SASR);
-       scmd_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SCMD);
-       save_sasr = *sasr_3393;
-
-    /* First test the AuxStatus Reg */
-
-       q = *sasr_3393;         /* read it */
-       if (q & 0x08)           /* bit 3 should always be clear */
-               goto release;
-       *sasr_3393 = WD_AUXILIARY_STATUS;        /* setup indirect address */
-       if (*sasr_3393 == WD_AUXILIARY_STATUS) { /* shouldn't retain the write */
-               *sasr_3393 = save_sasr; /* Oops - restore this byte */
-               goto release;
+               /*
+                * These darn GVP boards are a problem - it can be tough to tell
+                * whether or not they include a SCSI controller. This is the
+                * ultimate Yet-Another-GVP-Detection-Hack in that it actually
+                * probes for a WD33c93 chip: If we find one, it's extremely
+                * likely that this card supports SCSI, regardless of Product_
+                * Code, Board_Size, etc.
+                */
+
+               /* Get pointers to the presumed register locations and save contents */
+
+               sasr_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SASR);
+               scmd_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SCMD);
+               save_sasr = *sasr_3393;
+
+               /* First test the AuxStatus Reg */
+
+               q = *sasr_3393; /* read it */
+               if (q & 0x08)   /* bit 3 should always be clear */
+                       goto release;
+               *sasr_3393 = WD_AUXILIARY_STATUS;       /* setup indirect address */
+               if (*sasr_3393 == WD_AUXILIARY_STATUS) {        /* shouldn't retain the write */
+                       *sasr_3393 = save_sasr; /* Oops - restore this byte */
+                       goto release;
                }
-       if (*sasr_3393 != q) {  /* should still read the same */
-               *sasr_3393 = save_sasr; /* Oops - restore this byte */
-               goto release;
+               if (*sasr_3393 != q) {  /* should still read the same */
+                       *sasr_3393 = save_sasr; /* Oops - restore this byte */
+                       goto release;
                }
-       if (*scmd_3393 != q)    /* and so should the image at 0x1f */
-               goto release;
-
-
-    /* Ok, we probably have a wd33c93, but let's check a few other places
-     * for good measure. Make sure that this works for both 'A and 'B    
-     * chip versions.
-     */
-
-       *sasr_3393 = WD_SCSI_STATUS;
-       q = *scmd_3393;
-       *sasr_3393 = WD_SCSI_STATUS;
-       *scmd_3393 = ~q;
-       *sasr_3393 = WD_SCSI_STATUS;
-       qq = *scmd_3393;
-       *sasr_3393 = WD_SCSI_STATUS;
-       *scmd_3393 = q;
-       if (qq != q)                    /* should be read only */
-               goto release;
-       *sasr_3393 = 0x1e;      /* this register is unimplemented */
-       q = *scmd_3393;
-       *sasr_3393 = 0x1e;
-       *scmd_3393 = ~q;
-       *sasr_3393 = 0x1e;
-       qq = *scmd_3393;
-       *sasr_3393 = 0x1e;
-       *scmd_3393 = q;
-       if (qq != q || qq != 0xff)      /* should be read only, all 1's */
-               goto release;
-       *sasr_3393 = WD_TIMEOUT_PERIOD;
-       q = *scmd_3393;
-       *sasr_3393 = WD_TIMEOUT_PERIOD;
-       *scmd_3393 = ~q;
-       *sasr_3393 = WD_TIMEOUT_PERIOD;
-       qq = *scmd_3393;
-       *sasr_3393 = WD_TIMEOUT_PERIOD;
-       *scmd_3393 = q;
-       if (qq != (~q & 0xff))          /* should be read/write */
-               goto release;
+               if (*scmd_3393 != q)    /* and so should the image at 0x1f */
+                       goto release;
+
+               /*
+                * Ok, we probably have a wd33c93, but let's check a few other places
+                * for good measure. Make sure that this works for both 'A and 'B
+                * chip versions.
+                */
+
+               *sasr_3393 = WD_SCSI_STATUS;
+               q = *scmd_3393;
+               *sasr_3393 = WD_SCSI_STATUS;
+               *scmd_3393 = ~q;
+               *sasr_3393 = WD_SCSI_STATUS;
+               qq = *scmd_3393;
+               *sasr_3393 = WD_SCSI_STATUS;
+               *scmd_3393 = q;
+               if (qq != q)    /* should be read only */
+                       goto release;
+               *sasr_3393 = 0x1e;      /* this register is unimplemented */
+               q = *scmd_3393;
+               *sasr_3393 = 0x1e;
+               *scmd_3393 = ~q;
+               *sasr_3393 = 0x1e;
+               qq = *scmd_3393;
+               *sasr_3393 = 0x1e;
+               *scmd_3393 = q;
+               if (qq != q || qq != 0xff)      /* should be read only, all 1's */
+                       goto release;
+               *sasr_3393 = WD_TIMEOUT_PERIOD;
+               q = *scmd_3393;
+               *sasr_3393 = WD_TIMEOUT_PERIOD;
+               *scmd_3393 = ~q;
+               *sasr_3393 = WD_TIMEOUT_PERIOD;
+               qq = *scmd_3393;
+               *sasr_3393 = WD_TIMEOUT_PERIOD;
+               *scmd_3393 = q;
+               if (qq != (~q & 0xff))  /* should be read/write */
+                       goto release;
 #endif
 
-       instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata));
-       if(instance == NULL)
-               goto release;
-       instance->base = ZTWO_VADDR(address);
-       instance->irq = IRQ_AMIGA_PORTS;
-       instance->unique_id = z->slotaddr;
-
-       if (gvp11_xfer_mask)
-               HDATA(instance)->dma_xfer_mask = gvp11_xfer_mask;
-       else
-               HDATA(instance)->dma_xfer_mask = default_dma_xfer_mask;
-
-
-       DMA(instance)->secret2 = 1;
-       DMA(instance)->secret1 = 0;
-       DMA(instance)->secret3 = 15;
-       while (DMA(instance)->CNTR & GVP11_DMAC_BUSY) ;
-       DMA(instance)->CNTR = 0;
-
-       DMA(instance)->BANK = 0;
-
-       epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
-
-       /*
-        * Check for 14MHz SCSI clock
-        */
-       regs.SASR = &(DMA(instance)->SASR);
-       regs.SCMD = &(DMA(instance)->SCMD);
-       HDATA(instance)->no_sync = 0xff;
-       HDATA(instance)->fast = 0;
-       HDATA(instance)->dma_mode = CTRL_DMA;
-       wd33c93_init(instance, regs, dma_setup, dma_stop,
-                    (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
-                                            : WD33C93_FS_12_15);
-
-       if (request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, "GVP11 SCSI",
-                       instance))
-               goto unregister;
-       DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
-       num_gvp11++;
-       continue;
+               instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
+               if (instance == NULL)
+                       goto release;
+               instance->base = ZTWO_VADDR(address);
+               instance->irq = IRQ_AMIGA_PORTS;
+               instance->unique_id = z->slotaddr;
+
+               hdata = shost_priv(instance);
+               if (gvp11_xfer_mask)
+                       hdata->dma_xfer_mask = gvp11_xfer_mask;
+               else
+                       hdata->dma_xfer_mask = default_dma_xfer_mask;
+
+               DMA(instance)->secret2 = 1;
+               DMA(instance)->secret1 = 0;
+               DMA(instance)->secret3 = 15;
+               while (DMA(instance)->CNTR & GVP11_DMAC_BUSY)
+                       ;
+               DMA(instance)->CNTR = 0;
+
+               DMA(instance)->BANK = 0;
+
+               epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
+
+               /*
+                * Check for 14MHz SCSI clock
+                */
+               regs.SASR = &(DMA(instance)->SASR);
+               regs.SCMD = &(DMA(instance)->SCMD);
+               hdata->no_sync = 0xff;
+               hdata->fast = 0;
+               hdata->dma_mode = CTRL_DMA;
+               wd33c93_init(instance, regs, dma_setup, dma_stop,
+                            (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
+                                                    : WD33C93_FS_12_15);
+
+               if (request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED,
+                               "GVP11 SCSI", instance))
+                       goto unregister;
+               DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
+               num_gvp11++;
+               continue;
 
 unregister:
-       scsi_unregister(instance);
-       wd33c93_release();
+               scsi_unregister(instance);
 release:
-       release_mem_region(address, 256);
-    }
+               release_mem_region(address, 256);
+       }
 
-    return num_gvp11;
+       return num_gvp11;
 }
 
 static int gvp11_bus_reset(struct scsi_cmnd *cmd)
@@ -389,12 +391,11 @@ static struct scsi_host_template driver_template = {
 int gvp11_release(struct Scsi_Host *instance)
 {
 #ifdef MODULE
-    DMA(instance)->CNTR = 0;
-    release_mem_region(ZTWO_PADDR(instance->base), 256);
-    free_irq(IRQ_AMIGA_PORTS, instance);
-    wd33c93_release();
+       DMA(instance)->CNTR = 0;
+       release_mem_region(ZTWO_PADDR(instance->base), 256);
+       free_irq(IRQ_AMIGA_PORTS, instance);
 #endif
-    return 1;
+       return 1;
 }
 
 MODULE_LICENSE("GPL");
index bf22859..e2efdf9 100644 (file)
@@ -15,11 +15,11 @@ int gvp11_detect(struct scsi_host_template *);
 int gvp11_release(struct Scsi_Host *);
 
 #ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
+#define CMD_PER_LUN            2
 #endif
 
 #ifndef CAN_QUEUE
-#define CAN_QUEUE 16
+#define CAN_QUEUE              16
 #endif
 
 #ifndef HOSTS_C
@@ -28,24 +28,24 @@ int gvp11_release(struct Scsi_Host *);
  * if the transfer address ANDed with this results in a non-zero
  * result, then we can't use DMA.
  */
-#define GVP11_XFER_MASK  (0xff000001)
+#define GVP11_XFER_MASK                (0xff000001)
 
 typedef struct {
-             unsigned char      pad1[64];
-    volatile unsigned short     CNTR;
-             unsigned char      pad2[31];
-    volatile unsigned char      SASR;
-             unsigned char      pad3;
-    volatile unsigned char      SCMD;
-             unsigned char      pad4[4];
-    volatile unsigned short     BANK;
-             unsigned char      pad5[6];
-    volatile unsigned long      ACR;
-    volatile unsigned short     secret1; /* store 0 here */
-    volatile unsigned short     ST_DMA;
-    volatile unsigned short     SP_DMA;
-    volatile unsigned short     secret2; /* store 1 here */
-    volatile unsigned short     secret3; /* store 15 here */
+                unsigned char  pad1[64];
+       volatile unsigned short CNTR;
+                unsigned char  pad2[31];
+       volatile unsigned char  SASR;
+                unsigned char  pad3;
+       volatile unsigned char  SCMD;
+                unsigned char  pad4[4];
+       volatile unsigned short BANK;
+                unsigned char  pad5[6];
+       volatile unsigned long  ACR;
+       volatile unsigned short secret1; /* store 0 here */
+       volatile unsigned short ST_DMA;
+       volatile unsigned short SP_DMA;
+       volatile unsigned short secret2; /* store 1 here */
+       volatile unsigned short secret3; /* store 15 here */
 } gvp11_scsiregs;
 
 /* bits in CNTR */
index 183d3a4..c016426 100644 (file)
@@ -2708,14 +2708,6 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                        c->Request.CDB[8] = (size >> 8) & 0xFF;
                        c->Request.CDB[9] = size & 0xFF;
                        break;
-
-               case HPSA_READ_CAPACITY:
-                       c->Request.CDBLen = 10;
-                       c->Request.Type.Attribute = ATTR_SIMPLE;
-                       c->Request.Type.Direction = XFER_READ;
-                       c->Request.Timeout = 0;
-                       c->Request.CDB[0] = cmd;
-                       break;
                case HPSA_CACHE_FLUSH:
                        c->Request.CDBLen = 12;
                        c->Request.Type.Attribute = ATTR_SIMPLE;
index 56fb982..78de9b6 100644 (file)
@@ -152,21 +152,6 @@ struct SenseSubsystem_info {
        u8 reserved1[1108];
 };
 
-#define HPSA_READ_CAPACITY 0x25 /* Read Capacity */
-struct ReadCapdata {
-       u8 total_size[4];       /* Total size in blocks */
-       u8 block_size[4];       /* Size of blocks in bytes */
-};
-
-#if 0
-/* 12 byte commands not implemented in firmware yet. */
-#define HPSA_READ      0xa8
-#define HPSA_WRITE     0xaa
-#endif
-
-#define HPSA_READ   0x28    /* Read(10) */
-#define HPSA_WRITE  0x2a    /* Write(10) */
-
 /* BMIC commands */
 #define BMIC_READ 0x26
 #define BMIC_WRITE 0x27
index c2eea71..d18f45c 100644 (file)
@@ -2245,7 +2245,7 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device,
        DECLARE_COMPLETION_ONSTACK(comp);
        int wait;
        unsigned long flags;
-       signed long timeout = init_timeout * HZ;
+       signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ;
 
        ENTER;
        do {
@@ -3013,6 +3013,7 @@ static struct ibmvfc_async_crq *ibmvfc_next_async_crq(struct ibmvfc_host *vhost)
        if (crq->valid & 0x80) {
                if (++async_crq->cur == async_crq->size)
                        async_crq->cur = 0;
+               rmb();
        } else
                crq = NULL;
 
@@ -3035,6 +3036,7 @@ static struct ibmvfc_crq *ibmvfc_next_crq(struct ibmvfc_host *vhost)
        if (crq->valid & 0x80) {
                if (++queue->cur == queue->size)
                        queue->cur = 0;
+               rmb();
        } else
                crq = NULL;
 
@@ -3083,12 +3085,14 @@ static void ibmvfc_tasklet(void *data)
                while ((async = ibmvfc_next_async_crq(vhost)) != NULL) {
                        ibmvfc_handle_async(async, vhost);
                        async->valid = 0;
+                       wmb();
                }
 
                /* Pull all the valid messages off the CRQ */
                while ((crq = ibmvfc_next_crq(vhost)) != NULL) {
                        ibmvfc_handle_crq(crq, vhost);
                        crq->valid = 0;
+                       wmb();
                }
 
                vio_enable_interrupts(vdev);
@@ -3096,10 +3100,12 @@ static void ibmvfc_tasklet(void *data)
                        vio_disable_interrupts(vdev);
                        ibmvfc_handle_async(async, vhost);
                        async->valid = 0;
+                       wmb();
                } else if ((crq = ibmvfc_next_crq(vhost)) != NULL) {
                        vio_disable_interrupts(vdev);
                        ibmvfc_handle_crq(crq, vhost);
                        crq->valid = 0;
+                       wmb();
                } else
                        done = 1;
        }
index d25106a..7e97427 100644 (file)
@@ -38,6 +38,7 @@
 #define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT       \
                (IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT)
 #define IBMVFC_INIT_TIMEOUT            120
+#define IBMVFC_ABORT_WAIT_TIMEOUT      40
 #define IBMVFC_MAX_REQUESTS_DEFAULT    100
 
 #define IBMVFC_DEBUG                   0
index 9eae04a..7608310 100644 (file)
@@ -206,8 +206,10 @@ static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn)
 }
 
 static void
-iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_sw_tcp_conn *tcp_sw_conn)
+iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_conn *conn)
 {
+       struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+       struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
        struct sock *sk = tcp_sw_conn->sock->sk;
 
        /* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
@@ -555,7 +557,7 @@ static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn)
                return;
 
        sock_hold(sock->sk);
-       iscsi_sw_tcp_conn_restore_callbacks(tcp_sw_conn);
+       iscsi_sw_tcp_conn_restore_callbacks(conn);
        sock_put(sock->sk);
 
        spin_lock_bh(&session->lock);
index ca6b7bc..94644ba 100644 (file)
@@ -36,7 +36,6 @@ struct iscsi_sw_tcp_send {
 };
 
 struct iscsi_sw_tcp_conn {
-       struct iscsi_conn       *iscsi_conn;
        struct socket           *sock;
 
        struct iscsi_sw_tcp_send out;
index 1087a7f..c7985da 100644 (file)
@@ -132,7 +132,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
                switch (fmt) {
                case ELS_ADDR_FMT_PORT:
                        FC_DISC_DBG(disc, "Port address format for port "
-                                   "(%6x)\n", ntoh24(pp->rscn_fid));
+                                   "(%6.6x)\n", ntoh24(pp->rscn_fid));
                        dp = kzalloc(sizeof(*dp), GFP_KERNEL);
                        if (!dp) {
                                redisc = 1;
@@ -440,7 +440,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
                ids.port_id = ntoh24(np->fp_fid);
                ids.port_name = ntohll(np->fp_wwpn);
 
-               if (ids.port_id != fc_host_port_id(lport->host) &&
+               if (ids.port_id != lport->port_id &&
                    ids.port_name != lport->wwpn) {
                        rdata = lport->tt.rport_create(lport, ids.port_id);
                        if (rdata) {
@@ -449,7 +449,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
                        } else {
                                printk(KERN_WARNING "libfc: Failed to allocate "
                                       "memory for the newly discovered port "
-                                      "(%6x)\n", ids.port_id);
+                                      "(%6.6x)\n", ids.port_id);
                                error = -ENOMEM;
                        }
                }
@@ -607,7 +607,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
                        rdata->ids.port_name = port_name;
                else if (rdata->ids.port_name != port_name) {
                        FC_DISC_DBG(disc, "GPN_ID accepted.  WWPN changed. "
-                                   "Port-id %x wwpn %llx\n",
+                                   "Port-id %6.6x wwpn %16.16llx\n",
                                    rdata->ids.port_id, port_name);
                        lport->tt.rport_logoff(rdata);
 
index 5374872..e9412b7 100644 (file)
@@ -63,7 +63,7 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did,
                return NULL;
        }
 
-       fc_fill_fc_hdr(fp, r_ctl, did, fc_host_port_id(lport->host), fh_type,
+       fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type,
                       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
 
        return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec);
index e5df0d4..104e0fb 100644 (file)
@@ -488,7 +488,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp,
         */
        spin_lock_bh(&ep->ex_lock);
        ep->f_ctl = f_ctl & ~FC_FC_FIRST_SEQ;   /* not first seq */
-       if (f_ctl & (FC_FC_END_SEQ | FC_FC_SEQ_INIT))
+       if (f_ctl & FC_FC_SEQ_INIT)
                ep->esb_stat &= ~ESB_ST_SEQ_INIT;
        spin_unlock_bh(&ep->ex_lock);
        return error;
@@ -676,9 +676,10 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
        }
        memset(ep, 0, sizeof(*ep));
 
-       cpu = smp_processor_id();
+       cpu = get_cpu();
        pool = per_cpu_ptr(mp->pool, cpu);
        spin_lock_bh(&pool->lock);
+       put_cpu();
        index = pool->next_index;
        /* allocate new exch from pool */
        while (fc_exch_ptr_get(pool, index)) {
@@ -734,19 +735,14 @@ err:
  * EM is selected when a NULL match function pointer is encountered
  * or when a call to a match function returns true.
  */
-static struct fc_exch *fc_exch_alloc(struct fc_lport *lport,
-                                    struct fc_frame *fp)
+static inline struct fc_exch *fc_exch_alloc(struct fc_lport *lport,
+                                           struct fc_frame *fp)
 {
        struct fc_exch_mgr_anchor *ema;
-       struct fc_exch *ep;
 
-       list_for_each_entry(ema, &lport->ema_list, ema_list) {
-               if (!ema->match || ema->match(fp)) {
-                       ep = fc_exch_em_alloc(lport, ema->mp);
-                       if (ep)
-                               return ep;
-               }
-       }
+       list_for_each_entry(ema, &lport->ema_list, ema_list)
+               if (!ema->match || ema->match(fp))
+                       return fc_exch_em_alloc(lport, ema->mp);
        return NULL;
 }
 
@@ -920,13 +916,9 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport,
         * Find or create the sequence.
         */
        if (fc_sof_is_init(fr_sof(fp))) {
-               sp = fc_seq_start_next(&ep->seq);
-               if (!sp) {
-                       reject = FC_RJT_SEQ_XS; /* exchange shortage */
-                       goto rel;
-               }
-               sp->id = fh->fh_seq_id;
+               sp = &ep->seq;
                sp->ssb_stat |= SSB_ST_RESP;
+               sp->id = fh->fh_seq_id;
        } else {
                sp = &ep->seq;
                if (sp->id != fh->fh_seq_id) {
@@ -1250,9 +1242,6 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp,
        struct fc_frame_header *fh = fc_frame_header_get(fp);
        struct fc_seq *sp = NULL;
        struct fc_exch *ep = NULL;
-       enum fc_sof sof;
-       enum fc_eof eof;
-       u32 f_ctl;
        enum fc_pf_rjt_reason reject;
 
        /* We can have the wrong fc_lport at this point with NPIV, which is a
@@ -1269,9 +1258,6 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp,
        if (reject == FC_RJT_NONE) {
                sp = fr_seq(fp);        /* sequence will be held */
                ep = fc_seq_exch(sp);
-               sof = fr_sof(fp);
-               eof = fr_eof(fp);
-               f_ctl = ntoh24(fh->fh_f_ctl);
                fc_seq_send_ack(sp, fp);
 
                /*
@@ -1336,17 +1322,15 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
                goto rel;
        }
        sof = fr_sof(fp);
+       sp = &ep->seq;
        if (fc_sof_is_init(sof)) {
-               sp = fc_seq_start_next(&ep->seq);
-               sp->id = fh->fh_seq_id;
                sp->ssb_stat |= SSB_ST_RESP;
-       } else {
-               sp = &ep->seq;
-               if (sp->id != fh->fh_seq_id) {
-                       atomic_inc(&mp->stats.seq_not_found);
-                       goto rel;
-               }
+               sp->id = fh->fh_seq_id;
+       } else if (sp->id != fh->fh_seq_id) {
+               atomic_inc(&mp->stats.seq_not_found);
+               goto rel;
        }
+
        f_ctl = ntoh24(fh->fh_f_ctl);
        fr_seq(fp) = sp;
        if (f_ctl & FC_FC_SEQ_INIT)
@@ -1763,7 +1747,6 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp)
                fc_exch_done(sp);
                goto out;
        }
-       sp = fc_seq_start_next(sp);
        acc = fc_frame_payload_get(fp, sizeof(*acc));
        memset(acc, 0, sizeof(*acc));
        acc->reca_cmd = ELS_LS_ACC;
@@ -1944,7 +1927,7 @@ static void fc_exch_rrq(struct fc_exch *ep)
                did = ep->sid;
 
        fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, did,
-                      fc_host_port_id(lport->host), FC_TYPE_ELS,
+                      lport->port_id, FC_TYPE_ELS,
                       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
 
        if (fc_exch_seq_send(lport, fp, fc_exch_rrq_resp, NULL, ep,
index 17396c7..ec1f66c 100644 (file)
@@ -97,7 +97,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *, struct fc_frame *);
 static void fc_fcp_complete_locked(struct fc_fcp_pkt *);
 static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *);
 static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *);
-static void fc_timeout_error(struct fc_fcp_pkt *);
+static void fc_fcp_recovery(struct fc_fcp_pkt *);
 static void fc_fcp_timeout(unsigned long);
 static void fc_fcp_rec(struct fc_fcp_pkt *);
 static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *);
@@ -121,7 +121,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *);
 #define FC_DATA_UNDRUN         7
 #define FC_ERROR               8
 #define FC_HRD_ERROR           9
-#define FC_CMD_TIME_OUT                10
+#define FC_CMD_RECOVERY                10
 
 /*
  * Error recovery timeout values.
@@ -446,9 +446,16 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
        len = fr_len(fp) - sizeof(*fh);
        buf = fc_frame_payload_get(fp, 0);
 
-       /* if this I/O is ddped, update xfer len */
-       fc_fcp_ddp_done(fsp);
-
+       /*
+        * if this I/O is ddped then clear it
+        * and initiate recovery since data
+        * frames are expected to be placed
+        * directly in that case.
+        */
+       if (fsp->xfer_ddp != FC_XID_UNKNOWN) {
+               fc_fcp_ddp_done(fsp);
+               goto err;
+       }
        if (offset + len > fsp->data_len) {
                /* this should never happen */
                if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) &&
@@ -456,8 +463,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
                        goto crc_err;
                FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx "
                           "data_len %x\n", len, offset, fsp->data_len);
-               fc_fcp_retry_cmd(fsp);
-               return;
+               goto err;
        }
        if (offset != fsp->xfer_len)
                fsp->state |= FC_SRB_DISCONTIG;
@@ -478,13 +484,14 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 
                if (~crc != le32_to_cpu(fr_crc(fp))) {
 crc_err:
-                       stats = fc_lport_get_stats(lport);
+                       stats = per_cpu_ptr(lport->dev_stats, get_cpu());
                        stats->ErrorFrames++;
-                       /* FIXME - per cpu count, not total count! */
+                       /* per cpu count, not total count, but OK for limit */
                        if (stats->InvalidCRCCount++ < 5)
                                printk(KERN_WARNING "libfc: CRC error on data "
-                                      "frame for port (%6x)\n",
-                                 &nbs