Merge ../linux-2.6

This commit is contained in:
James Bottomley
2006-06-10 13:47:26 -05:00
1551 changed files with 37163 additions and 20091 deletions
+58 -32
View 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.
@@ -1569,6 +1568,21 @@ mpt_resume(struct pci_dev *pdev)
}
#endif
static int
mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
{
if ((MptDriverClass[index] == MPTSPI_DRIVER &&
ioc->bus_type != SPI) ||
(MptDriverClass[index] == MPTFC_DRIVER &&
ioc->bus_type != FC) ||
(MptDriverClass[index] == MPTSAS_DRIVER &&
ioc->bus_type != SAS))
/* make sure we only call the relevant reset handler
* for the bus */
return 0;
return (MptResetHandlers[index])(ioc, reset_phase);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_do_ioc_recovery - Initialize or recover MPT adapter.
@@ -1892,14 +1906,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if ((ret == 0) && MptResetHandlers[ii]) {
dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
ioc->name, ii));
rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
handlers++;
}
if (alt_ioc_ready && MptResetHandlers[ii]) {
drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
ioc->name, ioc->alt_ioc->name, ii));
rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
handlers++;
}
}
@@ -3280,11 +3294,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
if (MptResetHandlers[ii]) {
dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
ioc->name, ii));
r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
if (ioc->alt_ioc) {
dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
ioc->name, ioc->alt_ioc->name, ii));
r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
}
}
}
@@ -5719,11 +5733,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
if (MptResetHandlers[ii]) {
dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
ioc->name, ii));
r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
if (ioc->alt_ioc) {
dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
ioc->name, ioc->alt_ioc->name, ii));
r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
}
}
}
@@ -5748,11 +5762,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:
@@ -5789,9 +5805,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";
@@ -5853,27 +5869,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:
@@ -5890,41 +5911,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:
@@ -5933,9 +5959,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:
@@ -5988,7 +6013,8 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr)
ds = "Unknown";
break;
}
strcpy(evStr,ds);
if (ds)
strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -6010,7 +6036,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;
/*
+4 -6
View 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;
/*
+84 -52
View 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;
}
ri = *((struct mptfc_rport_info **)rport->dd_data);
if (unlikely(ri->remap_needed))
return SCSI_MLQUEUE_HOST_BUSY;
return mptscsih_qcmd(SCpnt,done);
/* dd_data is null until finished adding target */
ri = *((struct mptfc_rport_info **)rport->dd_data);
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;
}
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);
+71 -28
View 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;
+27 -23
View 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;
/*
+66 -2
View 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"));
}