Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 11 May 2006 22:34:33 +0000 (15:34 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 11 May 2006 22:34:33 +0000 (15:34 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6: (25 commits)
  [SCSI] mptfc: race between mptfc_register_dev and mptfc_target_alloc
  [SCSI] lpfc 8.1.6 : Fix Data Corruption in Bus Reset Path
  [SCSI] mptspi: revalidate negotiation parameters after host reset and resume
  [SCSI] srp.h: avoid padding of structs
  [SCSI] ibmvscsi: fix leak when failing to send srp event
  [SCSI] qla2xxx: Correct eh_abort recovery logic.
  [SCSI] megaraid_{mm,mbox}: fix a bug in reset handler
  [SCSI] fusion - bug fix stack overflow in mptbase
  [SCSI] scsi: Add IBM 2104-DU3 to blist
  [SCSI] Fix DVD burning issues.
  [SCSI] SCSI: aic7xxx_osm_pci resource leak fix.
  [SCSI] - fusion - mptfc bug fix's to prevent deadlock situations
  [SCSI] mptfusion: bug fix's for raid components adding/deleting
  [SCSI] aic7xxx: ahc_pci_write_config() fix
  [SCSI] megaraid: unused variable
  [SCSI] qla2xxx: only free_irq() after request_irq() succeeds
  [SCSI] Overrun in drivers/scsi/sim710.c
  [SCSI] lpfc 8.1.5 : Change version number to 8.1.5
  [SCSI] lpfc 8.1.5 : Misc small fixes
  [SCSI] lpfc 8.1.5 : Additional fixes to LOGO, PLOGI, and RSCN processing
  ...

29 files changed:
Documentation/scsi/ChangeLog.megaraid
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptspi.c
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
drivers/scsi/aic7xxx/aic7xxx_pci.c
drivers/scsi/ibmvscsi/ibmvscsi.c
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_init.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_mbox.h
drivers/scsi/megaraid/megaraid_mm.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_lib.c
drivers/scsi/sim710.c
include/scsi/srp.h

index 09f6300..c173806 100644 (file)
@@ -1,3 +1,28 @@
+Release Date   : Mon Apr 11 12:27:22 EST 2006 - Seokmann Ju <sju@lsil.com>
+Current Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
+Older Version  : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
+
+1.     Fixed a bug in megaraid_reset_handler().
+       Customer reported "Unable to handle kernel NULL pointer dereference
+       at virtual address 00000000" when system goes to reset condition
+       for some reason. It happened randomly.
+       Root Cause: in the megaraid_reset_handler(), there is possibility not
+       returning pending packets in the pend_list if there are multiple
+       pending packets.
+       Fix: Made the change in the driver so that it will return all packets
+       in the pend_list.
+
+2.     Added change request.
+       As found in the following URL, rmb() only didn't help the
+       problem. I had to increase the loop counter to 0xFFFFFF. (6 F's)
+       http://marc.theaimsgroup.com/?l=linux-scsi&m=110971060502497&w=2
+
+       I attached a patch for your reference, too.
+       Could you check and get this fix in your driver?
+
+       Best Regards,
+       Jun'ichi Nomura
+
 Release Date   : Fri Nov 11 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
 Current Version : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
 Older Version  : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
index 266414c..9080853 100644 (file)
@@ -1189,7 +1189,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        ioc->diagPending = 0;
        spin_lock_init(&ioc->diagLock);
        spin_lock_init(&ioc->fc_rescan_work_lock);
-       spin_lock_init(&ioc->fc_rport_lock);
        spin_lock_init(&ioc->initializing_hba_lock);
 
        /* Initialize the event logging.
@@ -5736,11 +5735,13 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
        return rc;
 }
 
+# define EVENT_DESCR_STR_SZ            100
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static void
 EventDescriptionStr(u8 event, u32 evData0, char *evStr)
 {
-       char *ds;
+       char *ds = NULL;
 
        switch(event) {
        case MPI_EVENT_NONE:
@@ -5777,9 +5778,9 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
                if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
                        ds = "Loop State(LIP) Change";
                else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
-                       ds = "Loop State(LPE) Change";                  /* ??? */
+                       ds = "Loop State(LPE) Change";          /* ??? */
                else
-                       ds = "Loop State(LPB) Change";                  /* ??? */
+                       ds = "Loop State(LPB) Change";          /* ??? */
                break;
        case MPI_EVENT_LOGOUT:
                ds = "Logout";
@@ -5841,27 +5842,32 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
                break;
        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
        {
-               char buf[50];
                u8 id = (u8)(evData0);
                u8 ReasonCode = (u8)(evData0 >> 16);
                switch (ReasonCode) {
                case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
-                       sprintf(buf,"SAS Device Status Change: Added: id=%d", id);
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: Added: id=%d", id);
                        break;
                case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
-                       sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id);
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: Deleted: id=%d", id);
                        break;
                case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
-                       sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id);
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: SMART Data: id=%d",
+                           id);
                        break;
                case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
-                       sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id);
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: No Persistancy "
+                           "Added: id=%d", id);
                        break;
                default:
-                       sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id);
-               break;
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                           "SAS Device Status Change: Unknown: id=%d", id);
+                       break;
                }
-               ds = buf;
                break;
        }
        case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
@@ -5878,41 +5884,46 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
                break;
        case MPI_EVENT_SAS_PHY_LINK_STATUS:
        {
-               char buf[50];
                u8 LinkRates = (u8)(evData0 >> 8);
                u8 PhyNumber = (u8)(evData0);
                LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
                        MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
                switch (LinkRates) {
                case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
-                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
                           " Rate Unknown",PhyNumber);
                        break;
                case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
-                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
                           " Phy Disabled",PhyNumber);
                        break;
                case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
-                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
                           " Failed Speed Nego",PhyNumber);
                        break;
                case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
-                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
                           " Sata OOB Completed",PhyNumber);
                        break;
                case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
-                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
                           " Rate 1.5 Gbps",PhyNumber);
                        break;
                case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
-                       sprintf(buf,"SAS PHY Link Status: Phy=%d:"
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d:"
                           " Rate 3.0 Gpbs",PhyNumber);
                        break;
                default:
-                       sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber);
+                       snprintf(evStr, EVENT_DESCR_STR_SZ,
+                          "SAS PHY Link Status: Phy=%d", PhyNumber);
                        break;
                }
-               ds = buf;
                break;
        }
        case MPI_EVENT_SAS_DISCOVERY_ERROR:
@@ -5921,9 +5932,8 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
        case MPI_EVENT_IR_RESYNC_UPDATE:
        {
                u8 resync_complete = (u8)(evData0 >> 16);
-               char buf[40];
-               sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete);
-               ds = buf;
+               snprintf(evStr, EVENT_DESCR_STR_SZ,
+                   "IR Resync Update: Complete = %d:",resync_complete);
                break;
        }
        case MPI_EVENT_IR2:
@@ -5976,7 +5986,8 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
                ds = "Unknown";
                break;
        }
-       strcpy(evStr,ds);
+       if (ds)
+               strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5998,7 +6009,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
        int ii;
        int r = 0;
        int handlers = 0;
-       char evStr[100];
+       char evStr[EVENT_DESCR_STR_SZ];
        u8 event;
 
        /*
index be7e850..f673cca 100644 (file)
@@ -76,8 +76,8 @@
 #define COPYRIGHT      "Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON       "3.03.08"
-#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.03.08"
+#define MPT_LINUX_VERSION_COMMON       "3.03.09"
+#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.03.09"
 #define WHAT_MAGIC_STRING              "@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -489,7 +489,6 @@ typedef     struct _RaidCfgData {
 
 #define MPT_RPORT_INFO_FLAGS_REGISTERED        0x01    /* rport registered */
 #define MPT_RPORT_INFO_FLAGS_MISSING   0x02    /* missing from DevPage0 scan */
-#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04  /* target mapped in vdev */
 
 /*
  * data allocated for each fc rport device
@@ -501,7 +500,6 @@ struct mptfc_rport_info
        struct scsi_target *starget;
        FCDevicePage0_t pg0;
        u8              flags;
-       u8              remap_needed;
 };
 
 /*
@@ -628,11 +626,11 @@ typedef struct _MPT_ADAPTER
        struct work_struct       mptscsih_persistTask;
 
        struct list_head         fc_rports;
-       spinlock_t               fc_rport_lock; /* list and ri flags */
        spinlock_t               fc_rescan_work_lock;
        int                      fc_rescan_work_count;
        struct work_struct       fc_rescan_work;
-
+       char                     fc_rescan_work_q_name[KOBJ_NAME_LEN];
+       struct workqueue_struct *fc_rescan_work_q;
 } MPT_ADAPTER;
 
 /*
index b343f2a..8564877 100644 (file)
@@ -341,9 +341,6 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
        rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
        rid->port_id =   pg0->PortIdentifier;
        rid->roles = FC_RPORT_ROLE_UNKNOWN;
-       rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
-       if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
-               rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
 
        return 0;
 }
@@ -355,15 +352,18 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
        struct fc_rport         *rport;
        struct mptfc_rport_info *ri;
        int                     new_ri = 1;
-       u64                     pn;
-       unsigned long           flags;
+       u64                     pn, nn;
        VirtTarget              *vtarget;
+       u32                     roles = FC_RPORT_ROLE_UNKNOWN;
 
        if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
                return;
 
+       roles |= FC_RPORT_ROLE_FCP_TARGET;
+       if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
+               roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
        /* scan list looking for a match */
-       spin_lock_irqsave(&ioc->fc_rport_lock, flags);
        list_for_each_entry(ri, &ioc->fc_rports, list) {
                pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
                if (pn == rport_ids.port_name) {        /* match */
@@ -373,11 +373,9 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
                }
        }
        if (new_ri) {   /* allocate one */
-               spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
                ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
                if (!ri)
                        return;
-               spin_lock_irqsave(&ioc->fc_rport_lock, flags);
                list_add_tail(&ri->list, &ioc->fc_rports);
        }
 
@@ -387,14 +385,11 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
        /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
        if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
                ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
-               spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
                rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
-               spin_lock_irqsave(&ioc->fc_rport_lock, flags);
                if (rport) {
                        ri->rport = rport;
                        if (new_ri) /* may have been reset by user */
                                rport->dev_loss_tmo = mptfc_dev_loss_tmo;
-                       *((struct mptfc_rport_info **)rport->dd_data) = ri;
                        /*
                         * if already mapped, remap here.  If not mapped,
                         * target_alloc will allocate vtarget and map,
@@ -406,16 +401,21 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
                                        vtarget->target_id = pg0->CurrentTargetID;
                                        vtarget->bus_id = pg0->CurrentBus;
                                }
-                               ri->remap_needed = 0;
                        }
+                       *((struct mptfc_rport_info **)rport->dd_data) = ri;
+                       /* scan will be scheduled once rport becomes a target */
+                       fc_remote_port_rolechg(rport,roles);
+
+                       pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+                       nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
                        dfcprintk ((MYIOC_s_INFO_FMT
                                "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
                                "rport tid %d, tmo %d\n",
                                        ioc->name,
                                        ioc->sh->host_no,
                                        pg0->PortIdentifier,
-                                       pg0->WWNN,
-                                       pg0->WWPN,
+                                       (unsigned long long)nn,
+                                       (unsigned long long)pn,
                                        pg0->CurrentTargetID,
                                        ri->rport->scsi_target_id,
                                        ri->rport->dev_loss_tmo));
@@ -425,8 +425,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
                        ri = NULL;
                }
        }
-       spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
-
 }
 
 /*
@@ -476,7 +474,6 @@ mptfc_target_alloc(struct scsi_target *starget)
                        vtarget->target_id = ri->pg0.CurrentTargetID;
                        vtarget->bus_id = ri->pg0.CurrentBus;
                        ri->starget = starget;
-                       ri->remap_needed = 0;
                        rc = 0;
                }
        }
@@ -502,10 +499,10 @@ mptfc_slave_alloc(struct scsi_device *sdev)
        VirtDevice              *vdev;
        struct scsi_target      *starget;
        struct fc_rport         *rport;
-       unsigned long           flags;
 
 
-       rport = starget_to_rport(scsi_target(sdev));
+       starget = scsi_target(sdev);
+       rport = starget_to_rport(starget);
 
        if (!rport || fc_remote_port_chkready(rport))
                return -ENXIO;
@@ -519,10 +516,8 @@ mptfc_slave_alloc(struct scsi_device *sdev)
                return -ENOMEM;
        }
 
-       spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
 
        sdev->hostdata = vdev;
-       starget = scsi_target(sdev);
        vtarget = starget->hostdata;
 
        if (vtarget->num_luns == 0) {
@@ -535,14 +530,16 @@ mptfc_slave_alloc(struct scsi_device *sdev)
        vdev->vtarget = vtarget;
        vdev->lun = sdev->lun;
 
-       spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
-
        vtarget->num_luns++;
 
+
 #ifdef DMPT_DEBUG_FC
-        {
+       {
+       u64 nn, pn;
        struct mptfc_rport_info *ri;
        ri = *((struct mptfc_rport_info **)rport->dd_data);
+       pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+       nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
        dfcprintk ((MYIOC_s_INFO_FMT
                "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
                "CurrentTargetID %d, %x %llx %llx\n",
@@ -550,7 +547,9 @@ mptfc_slave_alloc(struct scsi_device *sdev)
                sdev->host->host_no,
                vtarget->num_luns,
                sdev->id, ri->pg0.CurrentTargetID,
-               ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
+               ri->pg0.PortIdentifier,
+               (unsigned long long)pn,
+               (unsigned long long)nn));
        }
 #endif
 
@@ -570,11 +569,31 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
                done(SCpnt);
                return 0;
        }
+
+       /* dd_data is null until finished adding target */
        ri = *((struct mptfc_rport_info **)rport->dd_data);
-       if (unlikely(ri->remap_needed))
-               return SCSI_MLQUEUE_HOST_BUSY;
+       if (unlikely(!ri)) {
+               dfcprintk ((MYIOC_s_INFO_FMT
+                       "mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
+                       ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
+                       ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
+                       SCpnt->device->id,SCpnt->device->lun));
+               SCpnt->result = DID_IMM_RETRY << 16;
+               done(SCpnt);
+               return 0;
+       }
 
-       return mptscsih_qcmd(SCpnt,done);
+       err = mptscsih_qcmd(SCpnt,done);
+#ifdef DMPT_DEBUG_FC
+       if (unlikely(err)) {
+               dfcprintk ((MYIOC_s_INFO_FMT
+                       "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n",
+                       ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
+                       ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
+                       SCpnt->device->id,SCpnt->device->lun));
+       }
+#endif
+       return err;
 }
 
 static void
@@ -615,18 +634,17 @@ mptfc_rescan_devices(void *arg)
        MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
        int                     ii;
        int                     work_to_do;
+       u64                     pn;
        unsigned long           flags;
        struct mptfc_rport_info *ri;
 
        do {
                /* start by tagging all ports as missing */
-               spin_lock_irqsave(&ioc->fc_rport_lock,flags);
                list_for_each_entry(ri, &ioc->fc_rports, list) {
                        if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
                                ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
                        }
                }
-               spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
 
                /*
                 * now rescan devices known to adapter,
@@ -639,33 +657,24 @@ mptfc_rescan_devices(void *arg)
                }
 
                /* delete devices still missing */
-               spin_lock_irqsave(&ioc->fc_rport_lock, flags);
                list_for_each_entry(ri, &ioc->fc_rports, list) {
                        /* if newly missing, delete it */
-                       if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
-                                         MPT_RPORT_INFO_FLAGS_MISSING))
-                         == (MPT_RPORT_INFO_FLAGS_REGISTERED |
-                             MPT_RPORT_INFO_FLAGS_MISSING)) {
+                       if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
 
                                ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
                                               MPT_RPORT_INFO_FLAGS_MISSING);
-                               ri->remap_needed = 1;
-                               fc_remote_port_delete(ri->rport);
-                               /*
-                                * remote port not really deleted 'cause
-                                * binding is by WWPN and driver only
-                                * registers FCP_TARGETs but cannot trust
-                                * data structures.
-                                */
+                               fc_remote_port_delete(ri->rport);       /* won't sleep */
                                ri->rport = NULL;
+
+                               pn = (u64)ri->pg0.WWPN.High << 32 |
+                                    (u64)ri->pg0.WWPN.Low;
                                dfcprintk ((MYIOC_s_INFO_FMT
                                        "mptfc_rescan.%d: %llx deleted\n",
                                        ioc->name,
                                        ioc->sh->host_no,
-                                       ri->pg0.WWPN));
+                                       (unsigned long long)pn));
                        }
                }
-               spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
 
                /*
                 * allow multiple passes as target state
@@ -870,10 +879,23 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto out_mptfc_probe;
        }
 
-       for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-               mptfc_init_host_attr(ioc,ii);
-               mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
-       }
+       /* initialize workqueue */
+
+       snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
+               sh->host_no);
+       ioc->fc_rescan_work_q =
+               create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
+       if (!ioc->fc_rescan_work_q)
+               goto out_mptfc_probe;
+
+       /*
+        * scan for rports -
+        *      by doing it via the workqueue, some locking is eliminated
+        */
+
+       ioc->fc_rescan_work_count = 1;
+       queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
+       flush_workqueue(ioc->fc_rescan_work_q);
 
        return 0;
 
@@ -949,8 +971,18 @@ mptfc_init(void)
 static void __devexit
 mptfc_remove(struct pci_dev *pdev)
 {
-       MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
-       struct mptfc_rport_info *p, *n;
+       MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
+       struct mptfc_rport_info *p, *n;
+       struct workqueue_struct *work_q;
+       unsigned long           flags;
+
+       /* destroy workqueue */
+       if ((work_q=ioc->fc_rescan_work_q)) {
+               spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+               ioc->fc_rescan_work_q = NULL;
+               spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+               destroy_workqueue(work_q);
+       }
 
        fc_remove_host(ioc->sh);
 
index e9716b1..af6ec55 100644 (file)
@@ -91,6 +91,7 @@ enum mptsas_hotplug_action {
        MPTSAS_DEL_DEVICE,
        MPTSAS_ADD_RAID,
        MPTSAS_DEL_RAID,
+       MPTSAS_IGNORE_EVENT,
 };
 
 struct mptsas_hotplug_event {
@@ -298,6 +299,26 @@ mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
        return rc;
 }
 
+/*
+ * Returns true if there is a scsi end device
+ */
+static inline int
+mptsas_is_end_device(struct mptsas_devinfo * attached)
+{
+       if ((attached->handle) &&
+           (attached->device_info &
+           MPI_SAS_DEVICE_INFO_END_DEVICE) &&
+           ((attached->device_info &
+           MPI_SAS_DEVICE_INFO_SSP_TARGET) |
+           (attached->device_info &
+           MPI_SAS_DEVICE_INFO_STP_TARGET) |
+           (attached->device_info &
+           MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
+               return 1;
+       else
+               return 0;
+}
+
 static int
 mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
                u32 form, u32 form_specific)
@@ -872,7 +893,11 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
        SasDevicePage0_t *buffer;
        dma_addr_t dma_handle;
        __le64 sas_address;
-       int error;
+       int error=0;
+
+       if (ioc->sas_discovery_runtime &&
+               mptsas_is_end_device(device_info))
+                       goto out;
 
        hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
        hdr.ExtPageLength = 0;
@@ -1009,7 +1034,11 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
        CONFIGPARMS cfg;
        SasExpanderPage1_t *buffer;
        dma_addr_t dma_handle;
-       int error;
+       int error=0;
+
+       if (ioc->sas_discovery_runtime &&
+               mptsas_is_end_device(&phy_info->attached))
+                       goto out;
 
        hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
        hdr.ExtPageLength = 0;
@@ -1068,26 +1097,6 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
        return error;
 }
 
-/*
- * Returns true if there is a scsi end device
- */
-static inline int
-mptsas_is_end_device(struct mptsas_devinfo * attached)
-{
-       if ((attached->handle) &&
-           (attached->device_info &
-           MPI_SAS_DEVICE_INFO_END_DEVICE) &&
-           ((attached->device_info &
-           MPI_SAS_DEVICE_INFO_SSP_TARGET) |
-           (attached->device_info &
-           MPI_SAS_DEVICE_INFO_STP_TARGET) |
-           (attached->device_info &
-           MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
-               return 1;
-       else
-               return 0;
-}
-
 static void
 mptsas_parse_device_info(struct sas_identify *identify,
                struct mptsas_devinfo *device_info)
@@ -1737,6 +1746,9 @@ mptsas_hotplug_work(void *arg)
                break;
        case MPTSAS_ADD_DEVICE:
 
+               if (ev->phys_disk_num_valid)
+                       mpt_findImVolumes(ioc);
+
                /*
                 * Refresh sas device pg0 data
                 */
@@ -1868,6 +1880,9 @@ mptsas_hotplug_work(void *arg)
                scsi_device_put(sdev);
                mpt_findImVolumes(ioc);
                break;
+       case MPTSAS_IGNORE_EVENT:
+       default:
+               break;
        }
 
        kfree(ev);
@@ -1940,7 +1955,8 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
                EVENT_DATA_RAID *raid_event_data)
 {
        struct mptsas_hotplug_event *ev;
-       RAID_VOL0_STATUS * volumeStatus;
+       int status = le32_to_cpu(raid_event_data->SettingsStatus);
+       int state = (status >> 8) & 0xff;
 
        if (ioc->bus_type != SAS)
                return;
@@ -1955,6 +1971,7 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
        INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
        ev->ioc = ioc;
        ev->id = raid_event_data->VolumeID;
+       ev->event_type = MPTSAS_IGNORE_EVENT;
 
        switch (raid_event_data->ReasonCode) {
        case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
@@ -1966,6 +1983,25 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
                ev->phys_disk_num = raid_event_data->PhysDiskNum;
                ev->event_type = MPTSAS_DEL_DEVICE;
                break;
+       case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
+               switch (state) {
+               case MPI_PD_STATE_ONLINE:
+                       ioc->raid_data.isRaid = 1;
+                       ev->phys_disk_num_valid = 1;
+                       ev->phys_disk_num = raid_event_data->PhysDiskNum;
+                       ev->event_type = MPTSAS_ADD_DEVICE;
+                       break;
+               case MPI_PD_STATE_MISSING:
+               case MPI_PD_STATE_NOT_COMPATIBLE:
+               case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
+               case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
+               case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
+                       ev->event_type = MPTSAS_DEL_DEVICE;
+                       break;
+               default:
+                       break;
+               }
+               break;
        case MPI_EVENT_RAID_RC_VOLUME_DELETED:
                ev->event_type = MPTSAS_DEL_RAID;
                break;
@@ -1973,11 +2009,18 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
                ev->event_type = MPTSAS_ADD_RAID;
                break;
        case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
-               volumeStatus = (RAID_VOL0_STATUS *) &
-                   raid_event_data->SettingsStatus;
-               ev->event_type = (volumeStatus->State ==
-                   MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
-                   MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
+               switch (state) {
+               case MPI_RAIDVOL0_STATUS_STATE_FAILED:
+               case MPI_RAIDVOL0_STATUS_STATE_MISSING:
+                       ev->event_type = MPTSAS_DEL_RAID;
+                       break;
+               case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
+               case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
+                       ev->event_type = MPTSAS_ADD_RAID;
+                       break;
+               default:
+                       break;
+               }
                break;
        default:
                break;
index 3729062..84fa271 100644 (file)
@@ -632,7 +632,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
                case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
                        /* Spoof to SCSI Selection Timeout! */
-                       sc->result = DID_NO_CONNECT << 16;
+                       if (ioc->bus_type != FC)
+                               sc->result = DID_NO_CONNECT << 16;
+                       /* else fibre, just stall until rescan event */
+                       else
+                               sc->result = DID_REQUEUE << 16;
 
                        if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
                                hd->sel_timeout[pScsiReq->TargetID]++;
@@ -877,7 +881,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
        struct scsi_cmnd *sc;
 
        dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
-                       vdevice->target_id, vdevice->lun, max));
+                       vdevice->vtarget->target_id, vdevice->lun, max));
 
        for (ii=0; ii < max; ii++) {
                if ((sc = hd->ScsiLookup[ii]) != NULL) {
@@ -1645,7 +1649,6 @@ int
 mptscsih_abort(struct scsi_cmnd * SCpnt)
 {
        MPT_SCSI_HOST   *hd;
-       MPT_ADAPTER     *ioc;
        MPT_FRAME_HDR   *mf;
        u32              ctx2abort;
        int              scpnt_idx;
@@ -1663,14 +1666,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
                return FAILED;
        }
 
-       ioc = hd->ioc;
-       if (hd->resetPending) {
-               return FAILED;
-       }
-
-       if (hd->timeouts < -1)
-               hd->timeouts++;
-
        /* Find this command
         */
        if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
@@ -1684,6 +1679,13 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
                return SUCCESS;
        }
 
+       if (hd->resetPending) {
+               return FAILED;
+       }
+
+       if (hd->timeouts < -1)
+               hd->timeouts++;
+
        printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
               hd->ioc->name, SCpnt);
        scsi_print_command(SCpnt);
@@ -1703,7 +1705,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
        vdev = SCpnt->device->hostdata;
        retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
                vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun,
-               ctx2abort, mptscsih_get_tm_timeout(ioc));
+               ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
 
        printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
                hd->ioc->name,
@@ -2521,15 +2523,15 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
                /* 7. FC: Rescan for blocked rports which might have returned.
                 */
-               else if (ioc->bus_type == FC) {
-                       int work_count;
-                       unsigned long flags;
-
+               if (ioc->bus_type == FC) {
                        spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
-                       work_count = ++ioc->fc_rescan_work_count;
+                       if (ioc->fc_rescan_work_q) {
+                               if (ioc->fc_rescan_work_count++ == 0) {
+                                       queue_work(ioc->fc_rescan_work_q,
+                                                  &ioc->fc_rescan_work);
+                               }
+                       }
                        spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
-                       if (work_count == 1)
-                               schedule_work(&ioc->fc_rescan_work);
                }
                dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
 
@@ -2544,7 +2546,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
        MPT_SCSI_HOST *hd;
        u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
-       int work_count;
        unsigned long flags;
 
        devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
@@ -2569,10 +2570,13 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 
        case MPI_EVENT_RESCAN:                          /* 06 */
                spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
-               work_count = ++ioc->fc_rescan_work_count;
+               if (ioc->fc_rescan_work_q) {
+                       if (ioc->fc_rescan_work_count++ == 0) {
+                               queue_work(ioc->fc_rescan_work_q,
+                                          &ioc->fc_rescan_work);
+                       }
+               }
                spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
-               if (work_count == 1)
-                       schedule_work(&ioc->fc_rescan_work);
                break;
 
                /*
index 09c745b..f2a4d38 100644 (file)
@@ -783,6 +783,70 @@ static struct pci_device_id mptspi_pci_table[] = {
 };
 MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
 
+
+/*
+ * renegotiate for a given target
+ */
+static void
+mptspi_dv_renegotiate_work(void *data)
+{
+       struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+       struct _MPT_SCSI_HOST *hd = wqw->hd;
+       struct scsi_device *sdev;
+
+       kfree(wqw);
+
+       shost_for_each_device(sdev, hd->ioc->sh)
+               mptspi_dv_device(hd, sdev);
+}
+
+static void
+mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
+{
+       struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC);
+
+       if (!wqw)
+               return;
+
+       INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work, wqw);
+       wqw->hd = hd;
+
+       schedule_work(&wqw->work);
+}
+
+/*
+ * spi module reset handler
+ */
+static int
+mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+{
+       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+       int rc;
+
+       rc = mptscsih_ioc_reset(ioc, reset_phase);
+
+       if (reset_phase == MPT_IOC_POST_RESET)
+               mptspi_dv_renegotiate(hd);
+
+       return rc;
+}
+
+/*
+ * spi module resume handler
+ */
+static int
+mptspi_resume(struct pci_dev *pdev)
+{
+       MPT_ADAPTER     *ioc = pci_get_drvdata(pdev);
+       struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata;
+       int rc;
+
+       rc = mptscsih_resume(pdev);
+       mptspi_dv_renegotiate(hd);
+
+       return rc;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -1032,7 +1096,7 @@ static struct pci_driver mptspi_driver = {
        .shutdown       = mptscsih_shutdown,
 #ifdef CONFIG_PM
        .suspend        = mptscsih_suspend,
-       .resume         = mptscsih_resume,
+       .resume         = mptspi_resume,
 #endif
 };
 
@@ -1061,7 +1125,7 @@ mptspi_init(void)
                  ": Registered for IOC event notifications\n"));
        }
 
-       if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) {
+       if (mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset) == 0) {
                dprintk((KERN_INFO MYNAM
                  ": Registered for IOC reset notifications\n"));
        }
index cb30d9c..0c9c2f4 100644 (file)
@@ -219,6 +219,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                ahc->flags |= AHC_39BIT_ADDRESSING;
        } else {
                if (dma_set_mask(dev, DMA_32BIT_MASK)) {
+                       ahc_free(ahc);
                        printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
                        return (-ENODEV);
                }
index 5f58614..3adecef 100644 (file)
@@ -2036,12 +2036,12 @@ ahc_pci_resume(struct ahc_softc *ahc)
         * that the OS doesn't know about and rely on our chip
         * reset handler to handle the rest.
         */
-       ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4,
-                            ahc->bus_softc.pci_softc.devconfig);
-       ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1,
-                            ahc->bus_softc.pci_softc.command);
-       ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1,
-                            ahc->bus_softc.pci_softc.csize_lattime);
+       ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
+                            ahc->bus_softc.pci_softc.devconfig, /*bytes*/4);
+       ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
+                            ahc->bus_softc.pci_softc.command, /*bytes*/1);
+       ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
+                            ahc->bus_softc.pci_softc.csize_lattime, /*bytes*/1);
        if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
                struct  seeprom_descriptor sd;
                u_int   sxfrctl1;
index 0a8ad37..2e9be83 100644 (file)
@@ -739,7 +739,8 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
 {
        struct viosrp_adapter_info *req;
        struct srp_event_struct *evt_struct;
-       
+       dma_addr_t addr;
+
        evt_struct = get_event_struct(&hostdata->pool);
        if (!evt_struct) {
                printk(KERN_ERR "ibmvscsi: couldn't allocate an event "
@@ -757,10 +758,10 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
        
        req->common.type = VIOSRP_ADAPTER_INFO_TYPE;
        req->common.length = sizeof(hostdata->madapter_info);
-       req->buffer = dma_map_single(hostdata->dev,
-                                    &hostdata->madapter_info,
-                                    sizeof(hostdata->madapter_info),
-                                    DMA_BIDIRECTIONAL);
+       req->buffer = addr = dma_map_single(hostdata->dev,
+                                           &hostdata->madapter_info,
+                                           sizeof(hostdata->madapter_info),
+                                           DMA_BIDIRECTIONAL);
 
        if (dma_mapping_error(req->buffer)) {
                printk(KERN_ERR
@@ -770,8 +771,13 @@ static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
                return;
        }
        
-       if (ibmvscsi_send_srp_event(evt_struct, hostdata))
+       if (ibmvscsi_send_srp_event(evt_struct, hostdata)) {
                printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");
+               dma_unmap_single(hostdata->dev,
+                                addr,
+                                sizeof(hostdata->madapter_info),
+                                DMA_BIDIRECTIONAL);
+       }
 };
 
 /**
@@ -1259,6 +1265,7 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
 {
        struct viosrp_host_config *host_config;
        struct srp_event_struct *evt_struct;
+       dma_addr_t addr;
        int rc;
 
        evt_struct = get_event_struct(&hostdata->pool);
@@ -1279,8 +1286,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
        memset(host_config, 0x00, sizeof(*host_config));
        host_config->common.type = VIOSRP_HOST_CONFIG_TYPE;
        host_config->common.length = length;
-       host_config->buffer = dma_map_single(hostdata->dev, buffer, length,
-                                           DMA_BIDIRECTIONAL);
+       host_config->buffer = addr = dma_map_single(hostdata->dev, buffer,
+                                                   length,
+                                                   DMA_BIDIRECTIONAL);
 
        if (dma_mapping_error(host_config->buffer)) {
                printk(KERN_ERR
@@ -1291,11 +1299,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
 
        init_completion(&evt_struct->comp);
        rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
-       if (rc == 0) {
+       if (rc == 0)
                wait_for_completion(&evt_struct->comp);
-               dma_unmap_single(hostdata->dev, host_config->buffer,
-                                length, DMA_BIDIRECTIONAL);
-       }
+       dma_unmap_single(hostdata->dev, addr, length, DMA_BIDIRECTIONAL);
 
        return rc;
 }
index fad607b..ee22173 100644 (file)
@@ -27,7 +27,6 @@ void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
-void lpfc_set_slim(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
 int lpfc_reg_login(struct lpfc_hba *, uint32_t, uint8_t *, LPFC_MBOXQ_t *,
                   uint32_t);
 void lpfc_unreg_login(struct lpfc_hba *, uint32_t, LPFC_MBOXQ_t *);
index 8932b1b..41cf5d3 100644 (file)
@@ -113,6 +113,7 @@ struct lpfc_nodelist {
 #define NLP_NPR_ADISC      0x2000000   /* Issue ADISC when dq'ed from
                                           NPR list */
 #define NLP_DELAY_REMOVE   0x4000000   /* Defer removal till end of DSM */
+#define NLP_NODEV_REMOVE   0x8000000   /* Defer removal till discovery ends */
 
 /* Defines for list searchs */
 #define NLP_SEARCH_MAPPED    0x1       /* search mapped */
index 4813bea..283b7d8 100644 (file)
@@ -302,10 +302,6 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
        if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0))
                goto fail_free_mbox;
 
-       /*
-        * set_slim mailbox command needs to execute first,
-        * queue this command to be processed later.
-        */
        mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
        mbox->context2 = ndlp;
 
@@ -781,25 +777,26 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
        if (disc && phba->num_disc_nodes) {
                /* Check to see if there are more PLOGIs to be sent */
                lpfc_more_plogi(phba);
-       }
 
-       if (phba->num_disc_nodes == 0) {
-               spin_lock_irq(phba->host->host_lock);
-               phba->fc_flag &= ~FC_NDISC_ACTIVE;
-               spin_unlock_irq(phba->host->host_lock);
+               if (phba->num_disc_nodes == 0) {
+                       spin_lock_irq(phba->host->host_lock);
+                       phba->fc_flag &= ~FC_NDISC_ACTIVE;
+                       spin_unlock_irq(phba->host->host_lock);
 
-               lpfc_can_disctmo(phba);
-               if (phba->fc_flag & FC_RSCN_MODE) {
-                       /* Check to see if more RSCNs came in while we were
-                        * processing this one.
-                        */
-                       if ((phba->fc_rscn_id_cnt == 0) &&
-                           (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
-                               spin_lock_irq(phba->host->host_lock);
-                               phba->fc_flag &= ~FC_RSCN_MODE;
-                               spin_unlock_irq(phba->host->host_lock);
-                       } else {
-                               lpfc_els_handle_rscn(phba);
+                       lpfc_can_disctmo(phba);
+                       if (phba->fc_flag & FC_RSCN_MODE) {
+                               /*
+                                * Check to see if more RSCNs came in while
+                                * we were processing this one.
+                                */
+                               if ((phba->fc_rscn_id_cnt == 0) &&
+                               (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
+                                       spin_lock_irq(phba->host->host_lock);
+                                       phba->fc_flag &= ~FC_RSCN_MODE;
+                                       spin_unlock_irq(phba->host->host_lock);
+                               } else {
+                                       lpfc_els_handle_rscn(phba);
+                               }
                        }
                }
        }
@@ -1263,7 +1260,7 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
        psli = &phba->sli;
        pring = &psli->ring[LPFC_ELS_RING];
 
-       cmdsize = 2 * (sizeof (uint32_t) + sizeof (struct lpfc_name));
+       cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name);
        elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
                                                ndlp->nlp_DID, ELS_CMD_LOGO);
        if (!elsiocb)
@@ -1451,22 +1448,23 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
                         * PLOGIs to be sent
                         */
                        lpfc_more_plogi(phba);
-               }
 
-               if (phba->num_disc_nodes == 0) {
-                       phba->fc_flag &= ~FC_NDISC_ACTIVE;
-                       lpfc_can_disctmo(phba);
-                       if (phba->fc_flag & FC_RSCN_MODE) {
-                               /* Check to see if more RSCNs
-                                * came in while we were
-                                * processing this one.
-                                */
-                               if((phba->fc_rscn_id_cnt==0) &&
-                                  (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
-                                       phba->fc_flag &= ~FC_RSCN_MODE;
-                               }
-                               else {
-                                       lpfc_els_handle_rscn(phba);
+                       if (phba->num_disc_nodes == 0) {
+                               phba->fc_flag &= ~FC_NDISC_ACTIVE;
+                               lpfc_can_disctmo(phba);
+                               if (phba->fc_flag & FC_RSCN_MODE) {
+                                       /*
+                                        * Check to see if more RSCNs
+                                        * came in while we were
+                                        * processing this one.
+                                        */
+                                       if((phba->fc_rscn_id_cnt==0) &&
+                                        !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
+                                               phba->fc_flag &= ~FC_RSCN_MODE;
+                                       }
+                                       else {
+                                               lpfc_els_handle_rscn(phba);
+                                       }
                                }
                        }
                }
@@ -1872,9 +1870,6 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
        if (mbox) {
                if ((rspiocb->iocb.ulpStatus == 0)
                    && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
-                       /* set_slim mailbox command needs to execute first,
-                        * queue this command to be processed later.
-                        */
                        lpfc_unreg_rpi(phba, ndlp);
                        mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
                        mbox->context2 = ndlp;
@@ -1920,6 +1915,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
        uint8_t *pcmd;
        uint16_t cmdsize;
        int rc;
+       ELS_PKT *els_pkt_ptr;
 
        psli = &phba->sli;
        pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
@@ -1958,6 +1954,23 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
                pcmd += sizeof (uint32_t);
                memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
                break;
+       case ELS_CMD_PRLO:
+               cmdsize = sizeof (uint32_t) + sizeof (PRLO);
+               elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
+                                            ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
+               if (!elsiocb)
+                       return 1;
+
+               icmd = &elsiocb->iocb;
+               icmd->ulpContext = oldcmd->ulpContext; /* Xri */
+               pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+
+               memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
+                      sizeof (uint32_t) + sizeof (PRLO));
+               *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
+               els_pkt_ptr = (ELS_PKT *) pcmd;
+               els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
+               break;
        default:
                return 1;
        }
@@ -2498,7 +2511,7 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba,
        /* If we are about to begin discovery, just ACC the RSCN.
         * Discovery processing will satisfy it.
         */
-       if (phba->hba_state < LPFC_NS_QRY) {
+       if (phba->hba_state <= LPFC_NS_QRY) {
                lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
                                                                newnode);
                return 0;
index 6721e67..adb0860 100644 (file)
@@ -311,8 +311,8 @@ lpfc_workq_post_event(struct lpfc_hba * phba, void *arg1, void *arg2,
        evtp->evt_arg2  = arg2;
        evtp->evt       = evt;
 
-       list_add_tail(&evtp->evt_listp, &phba->work_list);
        spin_lock_irq(phba->host->host_lock);
+       list_add_tail(&evtp->evt_listp, &phba->work_list);
        if (phba->work_wait)
                wake_up(phba->work_wait);
        spin_unlock_irq(phba->host->host_lock);
@@ -1071,10 +1071,6 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
        /* initialize static port data */
        rport->maxframe_size = ndlp->nlp_maxframe;
        rport->supported_classes = ndlp->nlp_class_sup;
-       if ((rport->scsi_target_id != -1) &&
-               (rport->scsi_target_id < MAX_FCP_TARGET)) {
-               ndlp->nlp_sid = rport->scsi_target_id;
-       }
        rdata = rport->dd_data;
        rdata->pnode = ndlp;
 
@@ -1087,6 +1083,10 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
        if (rport_ids.roles !=  FC_RPORT_ROLE_UNKNOWN)
                fc_remote_port_rolechg(rport, rport_ids.roles);
 
+       if ((rport->scsi_target_id != -1) &&
+               (rport->scsi_target_id < MAX_FCP_TARGET)) {
+               ndlp->nlp_sid = rport->scsi_target_id;
+       }
 
        return;
 }
@@ -1238,6 +1238,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
                                                evt_listp);
 
                }
+               nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
                nlp->nlp_type |= NLP_FC_NODE;
                break;
        case NLP_MAPPED_LIST:
@@ -1258,6 +1259,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
                                                evt_listp);
 
                }
+               nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
                break;
        case NLP_NPR_LIST:
                nlp->nlp_flag |= list;
@@ -1402,6 +1404,8 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba,
                        if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi)
                                return 1;
                case CMD_ELS_REQUEST64_CR:
+                       if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID)
+                               return 1;
                case CMD_XMIT_ELS_RSP64_CX:
                        if (iocb->context1 == (uint8_t *) ndlp)
                                return 1;
@@ -1901,10 +1905,8 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
                         */
                        if (ndlp->nlp_flag & NLP_DELAY_TMO)
                                lpfc_cancel_retry_delay_tmo(phba, ndlp);
-               } else {
-                       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+               } else
                        ndlp = NULL;
-               }
        } else {
                flg = ndlp->nlp_flag & NLP_LIST_MASK;
                if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST))
index 54d0418..eedf988 100644 (file)
@@ -449,6 +449,7 @@ struct serv_parm {  /* Structure is in Big Endian format */
 #define ELS_CMD_RRQ       0x12000000
 #define ELS_CMD_PRLI      0x20100014
 #define ELS_CMD_PRLO      0x21100014
+#define ELS_CMD_PRLO_ACC  0x02100014
 #define ELS_CMD_PDISC     0x50000000
 #define ELS_CMD_FDISC     0x51000000
 #define ELS_CMD_ADISC     0x52000000
@@ -484,6 +485,7 @@ struct serv_parm {  /* Structure is in Big Endian format */
 #define ELS_CMD_RRQ       0x12
 #define ELS_CMD_PRLI      0x14001020
 #define ELS_CMD_PRLO      0x14001021
+#define ELS_CMD_PRLO_ACC  0x14001002
 #define ELS_CMD_PDISC     0x50
 #define ELS_CMD_FDISC     0x51
 #define ELS_CMD_ADISC     0x52
@@ -1539,6 +1541,7 @@ typedef struct {
 
 #define FLAGS_TOPOLOGY_FAILOVER      0x0400    /* Bit 10 */
 #define FLAGS_LINK_SPEED             0x0800    /* Bit 11 */
+#define FLAGS_IMED_ABORT             0x04000   /* Bit 14 */
 
        uint32_t link_speed;
 #define LINK_SPEED_AUTO 0       /* Auto selection */
index 66d5d00..908d0f2 100644 (file)
@@ -294,15 +294,6 @@ lpfc_config_port_post(struct lpfc_hba * phba)
                }
        }
 
-       /* This should turn on DELAYED ABTS for ELS timeouts */
-       lpfc_set_slim(phba, pmb, 0x052198, 0x1);
-       if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
-               phba->hba_state = LPFC_HBA_ERROR;
-               mempool_free( pmb, phba->mbox_mem_pool);
-               return -EIO;
-       }
-
-
        lpfc_read_config(phba, pmb);
        if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
                lpfc_printf_log(phba,
@@ -804,7 +795,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
                int    max_speed;
                char * ports;
                char * bus;
-       } m;
+       } m = {"<Unknown>", 0, "", ""};
 
        pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
        ports = (hdrtype == 0x80) ? "2-port " : "";
@@ -1627,7 +1618,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 
        error = lpfc_alloc_sysfs_attr(phba);
        if (error)
-               goto out_kthread_stop;
+               goto out_remove_host;
 
        error = request_irq(phba->pcidev->irq, lpfc_intr_handler, SA_SHIRQ,
                                                        LPFC_DRIVER_NAME, phba);
@@ -1644,8 +1635,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
 
        error = lpfc_sli_hba_setup(phba);
-       if (error)
+       if (error) {
+               error = -ENODEV;
                goto out_free_irq;
+       }
 
        if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
                spin_lock_irq(phba->host->host_lock);
@@ -1700,6 +1693,9 @@ out_free_irq:
        free_irq(phba->pcidev->irq, phba);
 out_free_sysfs_attr:
        lpfc_free_sysfs_attr(phba);
+out_remove_host:
+       fc_remove_host(phba->host);
+       scsi_remove_host(phba->host);
 out_kthread_stop:
        kthread_stop(phba->worker_thread);
 out_free_iocbq:
@@ -1721,12 +1717,14 @@ out_iounmap_slim:
 out_idr_remove:
        idr_remove(&lpfc_hba_index, phba->brd_no);
 out_put_host:
+       phba->host = NULL;
        scsi_host_put(host);
 out_release_regions:
        pci_release_regions(pdev);
 out_disable_device:
        pci_disable_device(pdev);
 out:
+       pci_set_drvdata(pdev, NULL);
        return error;
 }
 
index c585e2b..e42f22a 100644 (file)
@@ -200,6 +200,9 @@ lpfc_init_link(struct lpfc_hba * phba,
                break;
        }
 
+       /* Enable asynchronous ABTS responses from firmware */
+       mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT;
+
        /* NEW_FEATURE
         * Setting up the link speed
         */
@@ -292,36 +295,6 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
        return;
 }
 
-/***********************************************/
-
-/*                  command to write slim      */
-/***********************************************/
-void
-lpfc_set_slim(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint32_t addr,
-             uint32_t value)
-{
-       MAILBOX_t *mb;
-
-       mb = &pmb->mb;
-       memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
-
-       /* addr = 0x090597 is AUTO ABTS disable for ELS commands */
-       /* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
-
-       /*
-        * Always turn on DELAYED ABTS for ELS timeouts
-        */
-       if ((addr == 0x052198) && (value == 0))
-               value = 1;
-
-       mb->un.varWords[0] = addr;
-       mb->un.varWords[1] = value;
-
-       mb->mbxCommand = MBX_SET_SLIM;
-       mb->mbxOwner = OWN_HOST;
-       return;
-}
-
 /**********************************************/
 /*  lpfc_read_nv  Issue a READ CONFIG         */
 /*                mailbox command             */
index 3d77bd9..27d60ad 100644 (file)
@@ -465,14 +465,18 @@ lpfc_rcv_padisc(struct lpfc_hba * phba,
 static int
 lpfc_rcv_logo(struct lpfc_hba * phba,
                      struct lpfc_nodelist * ndlp,
-                     struct lpfc_iocbq *cmdiocb)
+                     struct lpfc_iocbq *cmdiocb,
+                     uint32_t els_cmd)
 {
        /* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */
        /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
         * PLOGIs during LOGO storms from a device.
         */
        ndlp->nlp_flag |= NLP_LOGO_ACC;
-       lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       if (els_cmd == ELS_CMD_PRLO)
+               lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+       else
+               lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
 
        if (!(ndlp->nlp_type & NLP_FABRIC) ||
                (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
@@ -681,7 +685,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
        /* software abort outstanding PLOGI */
        lpfc_els_abort(phba, ndlp, 1);
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -788,10 +792,6 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
        if (lpfc_reg_login
            (phba, irsp->un.elsreq64.remoteID,
             (uint8_t *) sp, mbox, 0) == 0) {
-               /* set_slim mailbox command needs to
-                * execute first, queue this command to
-                * be processed later.
-                */
                switch (ndlp->nlp_DID) {
                case NameServer_DID:
                        mbox->mbox_cmpl =
@@ -832,11 +832,17 @@ static uint32_t
 lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
                           struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
-       /* software abort outstanding PLOGI */
-       lpfc_els_abort(phba, ndlp, 1);
+       if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+               return ndlp->nlp_state;
+       }
+       else {
+               /* software abort outstanding PLOGI */
+               lpfc_els_abort(phba, ndlp, 1);
 
-       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-       return NLP_STE_FREED_NODE;
+               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               return NLP_STE_FREED_NODE;
+       }
 }
 
 static uint32_t
@@ -851,7 +857,7 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
        ndlp->nlp_state = NLP_STE_NPR_NODE;
        lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
        spin_lock_irq(phba->host->host_lock);
-       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        spin_unlock_irq(phba->host->host_lock);
 
        return ndlp->nlp_state;
@@ -905,7 +911,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
        /* software abort outstanding ADISC */
        lpfc_els_abort(phba, ndlp, 0);
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -932,7 +938,7 @@ lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,
        cmdiocb = (struct lpfc_iocbq *) arg;
 
        /* Treat like rcv logo */
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
        return ndlp->nlp_state;
 }
 
@@ -987,11 +993,17 @@ lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
                            struct lpfc_nodelist * ndlp, void *arg,
                            uint32_t evt)
 {
-       /* software abort outstanding ADISC */
-       lpfc_els_abort(phba, ndlp, 1);
+       if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+               return ndlp->nlp_state;
+       }
+       else {
+               /* software abort outstanding ADISC */
+               lpfc_els_abort(phba, ndlp, 1);
 
-       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-       return NLP_STE_FREED_NODE;
+               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               return NLP_STE_FREED_NODE;
+       }
 }
 
 static uint32_t
@@ -1006,7 +1018,7 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
        ndlp->nlp_state = NLP_STE_NPR_NODE;
        lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
        spin_lock_irq(phba->host->host_lock);
-       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        ndlp->nlp_flag |= NLP_NPR_ADISC;
        spin_unlock_irq(phba->host->host_lock);
 
@@ -1048,7 +1060,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -1073,7 +1085,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba,
        struct lpfc_iocbq *cmdiocb;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
-       lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
        return ndlp->nlp_state;
 }
 
@@ -1133,8 +1145,14 @@ lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba,
                              struct lpfc_nodelist * ndlp, void *arg,
                              uint32_t evt)
 {
-       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-       return NLP_STE_FREED_NODE;
+       if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+               return ndlp->nlp_state;
+       }
+       else {
+               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               return NLP_STE_FREED_NODE;
+       }
 }
 
 static uint32_t
@@ -1146,7 +1164,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba,
        ndlp->nlp_state = NLP_STE_NPR_NODE;
        lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
        spin_lock_irq(phba->host->host_lock);
-       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        spin_unlock_irq(phba->host->host_lock);
        return ndlp->nlp_state;
 }
@@ -1186,7 +1204,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
        /* Software abort outstanding PRLI before sending acc */
        lpfc_els_abort(phba, ndlp, 1);
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -1214,7 +1232,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba,
        struct lpfc_iocbq *cmdiocb;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
-       lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
        return ndlp->nlp_state;
 }
 
@@ -1278,11 +1296,17 @@ static uint32_t
 lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
                          struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
-       /* software abort outstanding PRLI */
-       lpfc_els_abort(phba, ndlp, 1);
+       if(ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+               return ndlp->nlp_state;
+       }
+       else {
+               /* software abort outstanding PLOGI */
+               lpfc_els_abort(phba, ndlp, 1);
 
-       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-       return NLP_STE_FREED_NODE;
+               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               return NLP_STE_FREED_NODE;
+       }
 }
 
 
@@ -1313,7 +1337,7 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
        ndlp->nlp_state = NLP_STE_NPR_NODE;
        lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
        spin_lock_irq(phba->host->host_lock);
-       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        spin_unlock_irq(phba->host->host_lock);
        return ndlp->nlp_state;
 }
@@ -1351,7 +1375,7 @@ lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -1375,7 +1399,7 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
        return ndlp->nlp_state;
 }
 
@@ -1386,7 +1410,7 @@ lpfc_device_recov_unmap_node(struct lpfc_hba * phba,
        ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
        ndlp->nlp_state = NLP_STE_NPR_NODE;
        lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
-       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        lpfc_disc_set_adisc(phba, ndlp);
 
        return ndlp->nlp_state;
@@ -1424,7 +1448,7 @@ lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -1456,7 +1480,7 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba,
        spin_unlock_irq(phba->host->host_lock);
 
        /* Treat like rcv logo */
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
        return ndlp->nlp_state;
 }
 
@@ -1469,7 +1493,7 @@ lpfc_device_recov_mapped_node(struct lpfc_hba * phba,
        ndlp->nlp_state = NLP_STE_NPR_NODE;
        lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
        spin_lock_irq(phba->host->host_lock);
-       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        spin_unlock_irq(phba->host->host_lock);
        lpfc_disc_set_adisc(phba, ndlp);
        return ndlp->nlp_state;
@@ -1551,7 +1575,7 @@ lpfc_rcv_logo_npr_node(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -1617,9 +1641,16 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
                          struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
        struct lpfc_iocbq *cmdiocb, *rspiocb;
+       IOCB_t *irsp;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        rspiocb = cmdiocb->context_un.rsp_iocb;
+
+       irsp = &rspiocb->iocb;
+       if (irsp->ulpStatus) {
+               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               return NLP_STE_FREED_NODE;
+       }
        return ndlp->nlp_state;
 }
 
@@ -1628,9 +1659,16 @@ lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
                          struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
 {
        struct lpfc_iocbq *cmdiocb, *rspiocb;
+       IOCB_t *irsp;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        rspiocb = cmdiocb->context_un.rsp_iocb;
+
+       irsp = &rspiocb->iocb;
+       if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               return NLP_STE_FREED_NODE;
+       }
        return ndlp->nlp_state;
 }
 
@@ -1649,9 +1687,16 @@ lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
                            uint32_t evt)
 {
        struct lpfc_iocbq *cmdiocb, *rspiocb;
+       IOCB_t *irsp;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
        rspiocb = cmdiocb->context_un.rsp_iocb;
+
+       irsp = &rspiocb->iocb;
+       if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
+               lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+               return NLP_STE_FREED_NODE;
+       }
        return ndlp->nlp_state;
 }
 
@@ -1668,7 +1713,12 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
 
        if (!mb->mbxStatus)
                ndlp->nlp_rpi = mb->un.varWords[0];
-
+       else {
+               if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
+                       lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+                       return NLP_STE_FREED_NODE;
+               }
+       }
        return ndlp->nlp_state;
 }
 
@@ -1677,6 +1727,10 @@ lpfc_device_rm_npr_node(struct lpfc_hba * phba,
                            struct lpfc_nodelist * ndlp, void *arg,
                            uint32_t evt)
 {
+       if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
+               ndlp->nlp_flag |= NLP_NODEV_REMOVE;
+               return ndlp->nlp_state;
+       }
        lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
        return NLP_STE_FREED_NODE;
 }
@@ -1687,7 +1741,7 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba,
                            uint32_t evt)
 {
        spin_lock_irq(phba->host->host_lock);
-       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+       ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
        spin_unlock_irq(phba->host->host_lock);
        if (ndlp->nlp_flag & NLP_DELAY_TMO) {
                lpfc_cancel_retry_delay_tmo(phba, ndlp);
index f937998..7dc4c2e 100644 (file)
@@ -629,8 +629,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
        struct lpfc_iocbq *piocbq;
        IOCB_t *piocb;
        struct fcp_cmnd *fcp_cmnd;
-       struct scsi_device *scsi_dev = lpfc_cmd->pCmd->device;
-       struct lpfc_rport_data *rdata = scsi_dev->hostdata;
+       struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
        struct lpfc_nodelist *ndlp = rdata->pnode;
 
        if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
@@ -665,56 +664,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
                piocb->ulpTimeout = lpfc_cmd->timeout;
        }
 
-       lpfc_cmd->rdata = rdata;
-
-       switch (task_mgmt_cmd) {
-       case FCP_LUN_RESET:
-               /* Issue LUN Reset to TGT <num> LUN <num> */
-               lpfc_printf_log(phba,
-                               KERN_INFO,
-                               LOG_FCP,
-                               "%d:0703 Issue LUN Reset to TGT %d LUN %d "
-                               "Data: x%x x%x\n",
-                               phba->brd_no,
-                               scsi_dev->id, scsi_dev->lun,
-                               ndlp->nlp_rpi, ndlp->nlp_flag);
-
-               break;
-       case FCP_ABORT_TASK_SET:
-               /* Issue Abort Task Set to TGT <num> LUN <num> */
-               lpfc_printf_log(phba,
-                               KERN_INFO,
-                               LOG_FCP,
-                               "%d:0701 Issue Abort Task Set to TGT %d LUN %d "
-                               "Data: x%x x%x\n",
-                               phba->brd_no,
-                               scsi_dev->id, scsi_dev->lun,
-                               ndlp->nlp_rpi, ndlp->nlp_flag);
-
-               break;
-       case FCP_TARGET_RESET:
-               /* Issue Target Reset to TGT <num> */
-               lpfc_printf_log(phba,
-                               KERN_INFO,
-                               LOG_FCP,
-                               "%d:0702 Issue Target Reset to TGT %d "
-                               "Data: x%x x%x\n",
-                               phba->brd_no,
-                               scsi_dev->id, ndlp->nlp_rpi,
-                               ndlp->nlp_flag);
-               break;
-       }
-
        return (1);
 }
 
 static int
-lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
+lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
+                   unsigned  tgt_id, struct lpfc_rport_data *rdata)
 {
        struct lpfc_iocbq *iocbq;
        struct lpfc_iocbq *iocbqrsp;
        int ret;
 
+       lpfc_cmd->rdata = rdata;
        ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_TARGET_RESET);
        if (!ret)
                return FAILED;
@@ -726,6 +687,13 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba)
        if (!iocbqrsp)
                return FAILED;
 
+       /* Issue Target Reset to TGT <num> */
+       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+                       "%d:0702 Issue Target Reset to TGT %d "
+                       "Data: x%x x%x\n",
+                       phba->brd_no, tgt_id, rdata->pnode->nlp_rpi,
+                       rdata->pnode->nlp_flag);
+
        ret = lpfc_sli_issue_iocb_wait(phba,
                                       &phba->sli.ring[phba->sli.fcp_ring],
                                       iocbq, iocbqrsp, lpfc_cmd->timeout);
@@ -1021,6 +989,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
        lpfc_cmd->pCmd = cmnd;
        lpfc_cmd->timeout = 60;
        lpfc_cmd->scsi_hba = phba;
+       lpfc_cmd->rdata = rdata;
 
        ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, FCP_LUN_RESET);
        if (!ret)
@@ -1033,6 +1002,11 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
        if (iocbqrsp == NULL)
                goto out_free_scsi_buf;
 
+       lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+                       "%d:0703 Issue LUN Reset to TGT %d LUN %d "
+                       "Data: x%x x%x\n", phba->brd_no, cmnd->device->id,
+                       cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
+
        ret = lpfc_sli_issue_iocb_wait(phba,
                                       &phba->sli.ring[phba->sli.fcp_ring],
                                       iocbq, iocbqrsp, lpfc_cmd->timeout);
@@ -1104,7 +1078,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
        int match;
        int ret = FAILED, i, err_count = 0;
        int cnt, loopcnt;
-       unsigned int midlayer_id = 0;
        struct lpfc_scsi_buf * lpfc_cmd;
 
        lpfc_block_requests(phba);
@@ -1124,7 +1097,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
         * targets known to the driver.  Should any target reset
         * fail, this routine returns failure to the midlayer.
         */
-       midlayer_id = cmnd->device->id;
        for (i = 0; i < MAX_FCP_TARGET; i++) {
                /* Search the mapped list for this target ID */
                match = 0;
@@ -1137,9 +1109,8 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
                if (!match)
                        continue;
 
-               lpfc_cmd->pCmd->device->id = i;
-               lpfc_cmd->pCmd->device->hostdata = ndlp->rport->dd_data;
-               ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba);
+               ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba,
+                                         i, ndlp->rport->dd_data);
                if (ret != SUCCESS) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
                                "%d:0713 Bus Reset on target %d failed\n",
@@ -1158,7 +1129,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
         * the targets.  Unfortunately, some targets do not abide by
         * this forcing the driver to double check.
         */
-       cmnd->device->id = midlayer_id;
        cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
                                0, 0, LPFC_CTX_HOST);
        if (cnt)
index 4cf1366..6b73756 100644 (file)
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.1.4"
+#define LPFC_DRIVER_VERSION "8.1.6"
 
 #define LPFC_DRIVER_NAME "lpfc"
 
index 80b68a2..de35ffe 100644 (file)
@@ -4471,7 +4471,6 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
 {
        Scsi_Cmnd       *scmd;
        struct  scsi_device *sdev;
-       unsigned long   flags = 0;
        scb_t   *scb;
        int     rval;
 
index c11e5ce..bec1424 100644 (file)
@@ -10,7 +10,7 @@
  *        2 of the License, or (at your option) any later version.
  *
  * FILE                : megaraid_mbox.c
- * Version     : v2.20.4.7 (Nov 14 2005)
+ * Version     : v2.20.4.8 (Apr 11 2006)
  *
  * Authors:
  *     Atul Mukker             <Atul.Mukker@lsil.com>
@@ -2278,6 +2278,7 @@ megaraid_mbox_dpc(unsigned long devp)
        unsigned long           flags;
        uint8_t                 c;
        int                     status;
+       uioc_t                  *kioc;
 
 
        if (!adapter) return;
@@ -2320,6 +2321,9 @@ megaraid_mbox_dpc(unsigned long devp)
                        // remove from local clist
                        list_del_init(&scb->list);
 
+                       kioc                    = (uioc_t *)scb->gp;
+                       kioc->status            = 0;
+
                        megaraid_mbox_mm_done(adapter, scb);
 
                        continue;
@@ -2636,6 +2640,7 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
        int             recovery_window;
        int             recovering;
        int             i;
+       uioc_t          *kioc;
 
        adapter         = SCP2ADAPTER(scp);
        raid_dev        = ADAP2RAIDDEV(adapter);
@@ -2655,32 +2660,51 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
        // Also, reset all the commands currently owned by the driver
        spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
        list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
-
                list_del_init(&scb->list);      // from pending list
 
-               con_log(CL_ANN, (KERN_WARNING
-                       "megaraid: %ld:%d[%d:%d], reset from pending list\n",
-                               scp->serial_number, scb->sno,
-                               scb->dev_channel, scb->dev_target));
+               if (scb->sno >= MBOX_MAX_SCSI_CMDS) {
+                       con_log(CL_ANN, (KERN_WARNING
+                       "megaraid: IOCTL packet with %d[%d:%d] being reset\n",
+                       scb->sno, scb->dev_channel, scb->dev_target));
 
-               scp->result = (DID_RESET << 16);
-               scp->scsi_done(scp);
+                       scb->status = -1;
 
-               megaraid_dealloc_scb(adapter, scb);
+                       kioc                    = (uioc_t *)scb->gp;
+                       kioc->status            = -EFAULT;
+
+                       megaraid_mbox_mm_done(adapter, scb);
+               } else {
+                       if (scb->scp == scp) {  // Found command
+                               con_log(CL_ANN, (KERN_WARNING
+                                       "megaraid: %ld:%d[%d:%d], reset from pending list\n",
+                                       scp->serial_number, scb->sno,
+                                       scb->dev_channel, scb->dev_target));
+                       } else {
+                               con_log(CL_ANN, (KERN_WARNING
+                               "megaraid: IO packet with %d[%d:%d] being reset\n",
+                               scb->sno, scb->dev_channel, scb->dev_target));
+                       }
+
+                       scb->scp->result = (DID_RESET << 16);
+                       scb->scp->scsi_done(scb->scp);
+
+                       megaraid_dealloc_scb(adapter, scb);
+               }
        }
        spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
 
        if (adapter->outstanding_cmds) {
                con_log(CL_ANN, (KERN_NOTICE
                        "megaraid: %d outstanding commands. Max wait %d sec\n",
-                       adapter->outstanding_cmds, MBOX_RESET_WAIT));
+                       adapter->outstanding_cmds,
+                       (MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT)));
        }
 
        recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
 
        recovering = adapter->outstanding_cmds;
 
-       for (i = 0; i < recovery_window && adapter->outstanding_cmds; i++) {
+       for (i = 0; i < recovery_window; i++) {
 
                megaraid_ack_sequence(adapter);
 
@@ -2689,12 +2713,11 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
                        con_log(CL_ANN, (
                        "megaraid mbox: Wait for %d commands to complete:%d\n",
                                adapter->outstanding_cmds,
-                               MBOX_RESET_WAIT - i));
+                               (MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT) - i));
                }
 
                // bailout if no recovery happended in reset time
-               if ((i == MBOX_RESET_WAIT) &&
-                       (recovering == adapter->outstanding_cmds)) {
+               if (adapter->outstanding_cmds == 0) {
                        break;
                }
 
@@ -2918,12 +2941,13 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
        wmb();
        WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
 
-       for (i = 0; i < 0xFFFFF; i++) {
+       for (i = 0; i < MBOX_SYNC_WAIT_CNT; i++) {
                if (mbox->numstatus != 0xFF) break;
                rmb();
+               udelay(MBOX_SYNC_DELAY_200);
        }
 
-       if (i == 0xFFFFF) {
+       if (i == MBOX_SYNC_WAIT_CNT) {
                // We may need to re-calibrate the counter
                con_log(CL_ANN, (KERN_CRIT
                        "megaraid: fast sync command timed out\n"));
@@ -3475,7 +3499,7 @@ megaraid_cmm_register(adapter_t *adapter)
        adp.drvr_data           = (unsigned long)adapter;
        adp.pdev                = adapter->pdev;
        adp.issue_uioc          = megaraid_mbox_mm_handler;
-       adp.timeout             = 300;
+       adp.timeout             = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
        adp.max_kioc            = MBOX_MAX_USER_CMDS;
 
        if ((rval = mraid_mm_register_adp(&adp)) != 0) {
@@ -3702,7 +3726,6 @@ megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb)
        unsigned long           flags;
 
        kioc                    = (uioc_t *)scb->gp;
-       kioc->status            = 0;
        mbox64                  = (mbox64_t *)(unsigned long)kioc->cmdbuf;
        mbox64->mbox32.status   = scb->status;
        raw_mbox                = (uint8_t *)&mbox64->mbox32;
index 882fb1a..868fb0e 100644 (file)
@@ -21,8 +21,8 @@
 #include "megaraid_ioctl.h"
 
 
-#define MEGARAID_VERSION       "2.20.4.7"
-#define MEGARAID_EXT_VERSION   "(Release Date: Mon Nov 14 12:27:22 EST 2005)"
+#define MEGARAID_VERSION       "2.20.4.8"
+#define MEGARAID_EXT_VERSION   "(Release Date: Mon Apr 11 12:27:22 EST 2006)"
 
 
 /*
 #define MBOX_BUSY_WAIT         10      // max usec to wait for busy mailbox
 #define MBOX_RESET_WAIT                180     // wait these many seconds in reset
 #define MBOX_RESET_EXT_WAIT    120     // extended wait reset
+#define MBOX_SYNC_WAIT_CNT     0xFFFF  // wait loop index for synchronous mode
+
+#define MBOX_SYNC_DELAY_200    200     // 200 micro-seconds
 
 /*
  * maximum transfer that can happen through the firmware commands issued
index 8f3ce04..e8f534f 100644 (file)
@@ -898,10 +898,8 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
 
        adapter = kmalloc(sizeof(mraid_mmadp_t), GFP_KERNEL);
 
-       if (!adapter) {
-               rval = -ENOMEM;
-               goto memalloc_error;
-       }
+       if (!adapter)
+               return -ENOMEM;
 
        memset(adapter, 0, sizeof(mraid_mmadp_t));
 
index 017729c..584fe5d 100644 (file)
@@ -599,6 +599,7 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
 *    Either SUCCESS or FAILED.
 *
 * Note:
+*    Only return FAILED if command not returned by firmware.
 **************************************************************************/
 int
 qla2xxx_eh_abort(struct scsi_cmnd *cmd)
@@ -609,11 +610,12 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
        unsigned int id, lun;
        unsigned long serial;
        unsigned long flags;
+       int wait = 0;
 
        if (!CMD_SP(cmd))
-               return FAILED;
+               return SUCCESS;
 
-       ret = FAILED;
+       ret = SUCCESS;
 
        id = cmd->device->id;
        lun = cmd->device->lun;
@@ -642,7 +644,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
                } else {
                        DEBUG3(printk("%s(%ld): abort_command "
                            "mbx success.\n", __func__, ha->host_no));
-                       ret = SUCCESS;
+                       wait = 1;
                }
                spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -651,17 +653,18 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        /* Wait for the command to be returned. */
-       if (ret == SUCCESS) {
+       if (wait) {
                if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
                        qla_printk(KERN_ERR, ha,
                            "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
                            "%x.\n", ha->host_no, id, lun, serial, ret);
+                       ret = FAILED;
                }
        }
 
        qla_printk(KERN_INFO, ha,
-           "scsi(%ld:%d:%d): Abort command issued -- %lx %x.\n", ha->host_no,
-           id, lun, serial, ret);
+           "scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n",
+           ha->host_no, id, lun, wait, serial, ret);
 
        return ret;
 }
@@ -1700,8 +1703,8 @@ qla2x00_free_device(scsi_qla_host_t *ha)
        ha->flags.online = 0;
 
        /* Detach interrupts */
-       if (ha->pdev->irq)
-               free_irq(ha->pdev->irq, ha);
+       if (ha->host->irq)
+               free_irq(ha->host->irq, ha);
 
        /* release io space registers  */
        if (ha->iobase)
index c750d33..941c1e1 100644 (file)
@@ -56,6 +56,8 @@ static struct {
        {"DENON", "DRD-25X", "V", BLIST_NOLUN},                 /* locks up */
        {"HITACHI", "DK312C", "CM81", BLIST_NOLUN},     /* responds to all lun */
        {"HITACHI", "DK314C", "CR21", BLIST_NOLUN},     /* responds to all lun */
+       {"IBM", "2104-DU3", NULL, BLIST_NOLUN},         /* locks up */
+       {"IBM", "2104-TU3", NULL, BLIST_NOLUN},         /* locks up */
        {"IMS", "CDD521/10", "2.06", BLIST_NOLUN},      /* locks up */
        {"MAXTOR", "XT-3280", "PR02", BLIST_NOLUN},     /* locks up */
        {"MAXTOR", "XT-4380S", "B3C", BLIST_NOLUN},     /* locks up */
index 7b0f9a3..764a8b3 100644 (file)
@@ -1067,16 +1067,29 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
                        break;
                case NOT_READY:
                        /*
-                        * If the device is in the process of becoming ready,
-                        * retry.
+                        * If the device is in the process of becoming
+                        * ready, or has a temporary blockage, retry.
                         */
-                       if (sshdr.asc == 0x04 && sshdr.ascq == 0x01) {
-                               scsi_requeue_command(q, cmd);
-                               return;
+                       if (sshdr.asc == 0x04) {
+                               switch (sshdr.ascq) {
+                               case 0x01: /* becoming ready */
+                               case 0x04: /* format in progress */
+                               case 0x05: /* rebuild in progress */
+                               case 0x06: /* recalculation in progress */
+                               case 0x07: /* operation in progress */
+                               case 0x08: /* Long write in progress */
+                               case 0x09: /* self test in progress */
+                                       scsi_requeue_command(q, cmd);
+                                       return;
+                               default:
+                                       break;
+                               }
                        }
-                       if (!(req->flags & REQ_QUIET))
+                       if (!(req->flags & REQ_QUIET)) {
                                scmd_printk(KERN_INFO, cmd,
-                                          "Device not ready.\n");
+                                          "Device not ready: ");
+                               scsi_print_sense_hdr("", &sshdr);
+                       }
                        scsi_end_request(cmd, 0, this_count, 1);
                        return;
                case VOLUME_OVERFLOW:
index 3274ab7..255886a 100644 (file)
@@ -75,7 +75,7 @@ param_setup(char *str)
                else if(!strncmp(pos, "id:", 3)) {
                        if(slot == -1) {
                                printk(KERN_WARNING "sim710: Must specify slot for id parameter\n");
-                       } else if(slot > MAX_SLOTS) {
+                       } else if(slot >= MAX_SLOTS) {
                                printk(KERN_WARNING "sim710: Illegal slot %d for id %d\n", slot, val);
                        } else {
                                id_array[slot] = val;
index 6c2681d..637f77e 100644 (file)
@@ -95,14 +95,15 @@ struct srp_direct_buf {
 
 /*
  * We need the packed attribute because the SRP spec puts the list of
- * descriptors at an offset of 20, which is not aligned to the size
- * of struct srp_direct_buf.
+ * descriptors at an offset of 20, which is not aligned to the size of
+ * struct srp_direct_buf.  The whole structure must be packed to avoid
+ * having the 20-byte structure padded to 24 bytes on 64-bit architectures.
  */
 struct srp_indirect_buf {
        struct srp_direct_buf   table_desc;
        __be32                  len;
-       struct srp_direct_buf   desc_list[0] __attribute__((packed));
-};
+       struct srp_direct_buf   desc_list[0];
+} __attribute__((packed));
 
 enum {
        SRP_MULTICHAN_SINGLE = 0,
@@ -122,6 +123,11 @@ struct srp_login_req {
        u8      target_port_id[16];
 };
 
+/*
+ * The SRP spec defines the size of the LOGIN_RSP structure to be 52
+ * bytes, so it needs to be packed to avoid having it padded to 56
+ * bytes on 64-bit architectures.
+ */
 struct srp_login_rsp {
        u8      opcode;
        u8      reserved1[3];
@@ -132,7 +138,7 @@ struct srp_login_rsp {
        __be16  buf_fmt;
        u8      rsp_flags;
        u8      reserved2[25];
-};
+} __attribute__((packed));
 
 struct srp_login_rej {
        u8      opcode;
@@ -207,6 +213,11 @@ enum {
        SRP_RSP_FLAG_DIUNDER  = 1 << 5
 };
 
+/*
+ * The SRP spec defines the size of the RSP structure to be 36 bytes,
+ * so it needs to be packed to avoid having it padded to 40 bytes on
+ * 64-bit architectures.
+ */
 struct srp_rsp {
        u8      opcode;
        u8      sol_not;
@@ -221,6 +232,6 @@ struct srp_rsp {
        __be32  sense_data_len;
        __be32  resp_data_len;
        u8      data[0];
-};
+} __attribute__((packed));
 
 #endif /* SCSI_SRP_H */