aboutsummaryrefslogtreecommitdiff
path: root/drivers/message/fusion
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-02-26 16:55:27 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2010-02-26 16:55:27 -0800
commit654451748b779b28077d9058442d0f354251870d (patch)
treeff889a2f6226e16b1121789f809927666a9ccf13 /drivers/message/fusion
parent64d497f55379b1e320a08ec2426468d96f5642ec (diff)
parent77c9cfc51b0d732b2524799810fb30018074fd60 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (158 commits) [SCSI] Fix printing of failed 32-byte commands [SCSI] Fix printing of variable length commands [SCSI] libsrp: fix bug in ADDITIONAL CDB LENGTH interpretation [SCSI] scsi_dh_alua: Add IBM Power Virtual SCSI ALUA device to dev list [SCSI] scsi_dh_alua: add netapp to dev list [SCSI] qla2xxx: Update version number to 8.03.02-k1. [SCSI] qla2xxx: EEH: Restore PCI saved state during pci slot reset. [SCSI] qla2xxx: Add firmware ETS burst support. [SCSI] qla2xxx: Correct loop-resync issues during SNS scans. [SCSI] qla2xxx: Correct use-after-free issue in terminate_rport_io callback. [SCSI] qla2xxx: Correct EH bus-reset handling. [SCSI] qla2xxx: Proper clean-up of BSG requests when request times out. [SCSI] qla2xxx: Initialize payload receive length in failure path of vendor commands [SCSI] fix duplicate removal on error path in scsi_sysfs_add_sdev [SCSI] fix refcounting bug in scsi_get_host_dev [SCSI] fix memory leak in scsi_report_lun_scan [SCSI] lpfc: correct PPC build failure [SCSI] raid_class: add raid1e [SCSI] mpt2sas: Do not call sas_is_tlr_enabled for RAID volumes. [SCSI] zfcp: Introduce header file for qdio structs and inline functions ...
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r--drivers/message/fusion/mptbase.c5
-rw-r--r--drivers/message/fusion/mptbase.h4
-rw-r--r--drivers/message/fusion/mptctl.c4
-rw-r--r--drivers/message/fusion/mptfc.c17
-rw-r--r--drivers/message/fusion/mptsas.c211
-rw-r--r--drivers/message/fusion/mptscsih.c9
6 files changed, 231 insertions, 19 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 44d2037e9e5..5382b5a44af 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -126,8 +126,6 @@ static int mfcounter = 0;
* Public data...
*/
-static struct proc_dir_entry *mpt_proc_root_dir;
-
#define WHOINIT_UNKNOWN 0xAA
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -146,6 +144,9 @@ static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *mpt_proc_root_dir;
+#endif
/*
* Driver Callback Index's
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index b4948671eb9..9718c8f2e95 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.04.13"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.13"
+#define MPT_LINUX_VERSION_COMMON "3.04.14"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.14"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 352acd05c46..caa8f568a41 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -360,8 +360,8 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
u16 iocstatus;
/* bus reset is only good for SCSI IO, RAID PASSTHRU */
- if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) ||
- (function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
+ if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
+ function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
"TaskMgmt, not SCSI_IO!!\n", ioc->name));
return -EPERM;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index ebf6ae024da..612ab3c51a6 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -195,29 +195,34 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
unsigned long flags;
int ready;
MPT_ADAPTER *ioc;
+ int loops = 40; /* seconds */
hd = shost_priv(SCpnt->device->host);
ioc = hd->ioc;
spin_lock_irqsave(shost->host_lock, flags);
- while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
+ while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY
+ || (loops > 0 && ioc->active == 0)) {
spin_unlock_irqrestore(shost->host_lock, flags);
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
"mptfc_block_error_handler.%d: %d:%d, port status is "
- "DID_IMM_RETRY, deferring %s recovery.\n",
+ "%x, active flag %d, deferring %s recovery.\n",
ioc->name, ioc->sh->host_no,
- SCpnt->device->id, SCpnt->device->lun, caller));
+ SCpnt->device->id, SCpnt->device->lun,
+ ready, ioc->active, caller));
msleep(1000);
spin_lock_irqsave(shost->host_lock, flags);
+ loops --;
}
spin_unlock_irqrestore(shost->host_lock, flags);
- if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) {
+ if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata
+ || ioc->active == 0) {
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
"%s.%d: %d:%d, failing recovery, "
- "port state %d, vdevice %p.\n", caller,
+ "port state %x, active %d, vdevice %p.\n", caller,
ioc->name, ioc->sh->host_no,
SCpnt->device->id, SCpnt->device->lun, ready,
- SCpnt->device->hostdata));
+ ioc->active, SCpnt->device->hostdata));
return FAILED;
}
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 83873e3d0ce..c20bbe45da8 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1075,6 +1075,19 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
return 0;
}
+static void
+mptsas_block_io_sdev(struct scsi_device *sdev, void *data)
+{
+ scsi_device_set_state(sdev, SDEV_BLOCK);
+}
+
+static void
+mptsas_block_io_starget(struct scsi_target *starget)
+{
+ if (starget)
+ starget_for_each_device(starget, NULL, mptsas_block_io_sdev);
+}
+
/**
* mptsas_target_reset_queue
*
@@ -1098,10 +1111,11 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,
id = sas_event_data->TargetID;
channel = sas_event_data->Bus;
- if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
- return;
-
- vtarget->deleted = 1; /* block IO */
+ vtarget = mptsas_find_vtarget(ioc, channel, id);
+ if (vtarget) {
+ mptsas_block_io_starget(vtarget->starget);
+ vtarget->deleted = 1; /* block IO */
+ }
target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
GFP_ATOMIC);
@@ -1868,7 +1882,8 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
if (ioc->sas_discovery_quiesce_io)
return SCSI_MLQUEUE_HOST_BUSY;
-// scsi_print_command(SCpnt);
+ if (ioc->debug_level & MPT_DEBUG_SCSI)
+ scsi_print_command(SCpnt);
return mptscsih_qcmd(SCpnt,done);
}
@@ -2686,6 +2701,187 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
return error;
}
+struct rep_manu_request{
+ u8 smp_frame_type;
+ u8 function;
+ u8 reserved;
+ u8 request_length;
+};
+
+struct rep_manu_reply{
+ u8 smp_frame_type; /* 0x41 */
+ u8 function; /* 0x01 */
+ u8 function_result;
+ u8 response_length;
+ u16 expander_change_count;
+ u8 reserved0[2];
+ u8 sas_format:1;
+ u8 reserved1:7;
+ u8 reserved2[3];
+ u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
+ u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
+ u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
+ u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
+ u16 component_id;
+ u8 component_revision_id;
+ u8 reserved3;
+ u8 vendor_specific[8];
+};
+
+/**
+ * mptsas_exp_repmanufacture_info -
+ * @ioc: per adapter object
+ * @sas_address: expander sas address
+ * @edev: the sas_expander_device object
+ *
+ * Fills in the sas_expander_device object when SMP port is created.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,
+ u64 sas_address, struct sas_expander_device *edev)
+{
+ MPT_FRAME_HDR *mf;
+ SmpPassthroughRequest_t *smpreq;
+ SmpPassthroughReply_t *smprep;
+ struct rep_manu_reply *manufacture_reply;
+ struct rep_manu_request *manufacture_request;
+ int ret;
+ int flagsLength;
+ unsigned long timeleft;
+ char *psge;
+ unsigned long flags;
+ void *data_out = NULL;
+ dma_addr_t data_out_dma = 0;
+ u32 sz;
+
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+ if (ioc->ioc_reset_in_progress) {
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+ printk(MYIOC_s_INFO_FMT "%s: host reset in progress!\n",
+ __func__, ioc->name);
+ return -EFAULT;
+ }
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+
+ ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
+ if (ret)
+ goto out;
+
+ mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
+ if (!mf) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+
+ smpreq = (SmpPassthroughRequest_t *)mf;
+ memset(smpreq, 0, sizeof(*smpreq));
+
+ sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
+
+ data_out = pci_alloc_consistent(ioc->pcidev, sz, &data_out_dma);
+ if (!data_out) {
+ printk(KERN_ERR "Memory allocation failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ ret = -ENOMEM;
+ goto put_mf;
+ }
+
+ manufacture_request = data_out;
+ manufacture_request->smp_frame_type = 0x40;
+ manufacture_request->function = 1;
+ manufacture_request->reserved = 0;
+ manufacture_request->request_length = 0;
+
+ smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
+ smpreq->PhysicalPort = 0xFF;
+ *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
+ smpreq->RequestDataLength = sizeof(struct rep_manu_request);
+
+ psge = (char *)
+ (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
+
+ flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+ MPI_SGE_FLAGS_HOST_TO_IOC |
+ MPI_SGE_FLAGS_END_OF_BUFFER;
+ flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
+ flagsLength |= sizeof(struct rep_manu_request);
+
+ ioc->add_sge(psge, flagsLength, data_out_dma);
+ psge += ioc->SGE_size;
+
+ flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI_SGE_FLAGS_SYSTEM_ADDRESS |
+ MPI_SGE_FLAGS_IOC_TO_HOST |
+ MPI_SGE_FLAGS_END_OF_BUFFER;
+ flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
+ flagsLength |= sizeof(struct rep_manu_reply);
+ ioc->add_sge(psge, flagsLength, data_out_dma +
+ sizeof(struct rep_manu_request));
+
+ INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
+ mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
+
+ timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
+ if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+ ret = -ETIME;
+ mpt_free_msg_frame(ioc, mf);
+ mf = NULL;
+ if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
+ goto out_free;
+ if (!timeleft)
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
+ goto out_free;
+ }
+
+ mf = NULL;
+
+ if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
+ u8 *tmp;
+
+ smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
+ if (le16_to_cpu(smprep->ResponseDataLength) !=
+ sizeof(struct rep_manu_reply))
+ goto out_free;
+
+ manufacture_reply = data_out + sizeof(struct rep_manu_request);
+ strncpy(edev->vendor_id, manufacture_reply->vendor_id,
+ SAS_EXPANDER_VENDOR_ID_LEN);
+ strncpy(edev->product_id, manufacture_reply->product_id,
+ SAS_EXPANDER_PRODUCT_ID_LEN);
+ strncpy(edev->product_rev, manufacture_reply->product_rev,
+ SAS_EXPANDER_PRODUCT_REV_LEN);
+ edev->level = manufacture_reply->sas_format;
+ if (manufacture_reply->sas_format) {
+ strncpy(edev->component_vendor_id,
+ manufacture_reply->component_vendor_id,
+ SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
+ tmp = (u8 *)&manufacture_reply->component_id;
+ edev->component_id = tmp[0] << 8 | tmp[1];
+ edev->component_revision_id =
+ manufacture_reply->component_revision_id;
+ }
+ } else {
+ printk(MYIOC_s_ERR_FMT
+ "%s: smp passthru reply failed to be returned\n",
+ ioc->name, __func__);
+ ret = -ENXIO;
+ }
+out_free:
+ if (data_out_dma)
+ pci_free_consistent(ioc->pcidev, sz, data_out, data_out_dma);
+put_mf:
+ if (mf)
+ mpt_free_msg_frame(ioc, mf);
+out_unlock:
+ CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
+ mutex_unlock(&ioc->sas_mgmt.mutex);
+out:
+ return ret;
+ }
+
static void
mptsas_parse_device_info(struct sas_identify *identify,
struct mptsas_devinfo *device_info)
@@ -2967,6 +3163,11 @@ static int mptsas_probe_one_phy(struct device *dev,
goto out;
}
mptsas_set_rphy(ioc, phy_info, rphy);
+ if (identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
+ identify.device_type == SAS_FANOUT_EXPANDER_DEVICE)
+ mptsas_exp_repmanufacture_info(ioc,
+ identify.sas_address,
+ rphy_to_expander_device(rphy));
}
out:
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 81279b3d694..4a7d1afcb66 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1438,9 +1438,14 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
&& (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
&& (SCpnt->device->tagged_supported)) {
scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
- } else {
+ if (SCpnt->request && SCpnt->request->ioprio) {
+ if (((SCpnt->request->ioprio & 0x7) == 1) ||
+ !(SCpnt->request->ioprio & 0x7))
+ scsictl |= MPI_SCSIIO_CONTROL_HEADOFQ;
+ }
+ } else
scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
- }
+
/* Use the above information to set up the message frame
*/