Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6: (32 commits) [SCSI] aacraid: prevent panic on adapter resource failure [SCSI] aha152x: use data accessors and !use_sg cleanup [SCSI] aha152x: Fix check_condition code-path [SCSI] aha152x: Clean Reset path [SCSI] aha152x: preliminary fixes and some comments [SCSI] aha152x: use bounce buffer [SCSI] aha152x: fix debug mode symbol conflict [SCSI] sd: disentangle barriers in SCSI [SCSI] lpfc : scsi command accessor fix for 8.2.2 [SCSI] qlogicpti: Some cosmetic changes [SCSI] lpfc 8.2.2 : Change version number to 8.2.2 [SCSI] lpfc 8.2.2 : Style cleanups [SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes [SCSI] lpfc 8.2.2 : Miscellaneous management and logging mods [SCSI] lpfc 8.2.2 : Rework the lpfc_printf_log() macro [SCSI] lpfc 8.2.2 : Attribute and Parameter splits for vport and physical port [SCSI] lpfc 8.2.2 : Fix locking around HBA's port_list [SCSI] lpfc 8.2.2 : Error messages and debugfs updates [SCSI] initialize shost_data to zero [SCSI] mptsas: add SMP passthrough support via bsg ...
This commit is contained in:
@@ -88,7 +88,9 @@ module_param(mpt_channel_mapping, int, 0);
|
||||
MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
|
||||
|
||||
static int mpt_debug_level;
|
||||
module_param(mpt_debug_level, int, 0);
|
||||
static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
|
||||
module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
|
||||
&mpt_debug_level, 0600);
|
||||
MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h - (default=0)");
|
||||
|
||||
#ifdef MFCNT
|
||||
@@ -220,6 +222,19 @@ pci_enable_io_access(struct pci_dev *pdev)
|
||||
pci_write_config_word(pdev, PCI_COMMAND, command_reg);
|
||||
}
|
||||
|
||||
static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
|
||||
{
|
||||
int ret = param_set_int(val, kp);
|
||||
MPT_ADAPTER *ioc;
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry(ioc, &ioc_list, list)
|
||||
ioc->debug_level = mpt_debug_level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process turbo (context) reply...
|
||||
*/
|
||||
|
@@ -1312,11 +1312,137 @@ mptsas_get_bay_identifier(struct sas_rphy *rphy)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
|
||||
struct request *req)
|
||||
{
|
||||
MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
|
||||
MPT_FRAME_HDR *mf;
|
||||
SmpPassthroughRequest_t *smpreq;
|
||||
struct request *rsp = req->next_rq;
|
||||
int ret;
|
||||
int flagsLength;
|
||||
unsigned long timeleft;
|
||||
char *psge;
|
||||
dma_addr_t dma_addr_in = 0;
|
||||
dma_addr_t dma_addr_out = 0;
|
||||
u64 sas_address = 0;
|
||||
|
||||
if (!rsp) {
|
||||
printk(KERN_ERR "%s: the smp response space is missing\n",
|
||||
__FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* do we need to support multiple segments? */
|
||||
if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
|
||||
printk(KERN_ERR "%s: multiple segments req %u %u, rsp %u %u\n",
|
||||
__FUNCTION__, req->bio->bi_vcnt, req->data_len,
|
||||
rsp->bio->bi_vcnt, rsp->data_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);
|
||||
smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
|
||||
|
||||
if (rphy)
|
||||
sas_address = rphy->identify.sas_address;
|
||||
else {
|
||||
struct mptsas_portinfo *port_info;
|
||||
|
||||
mutex_lock(&ioc->sas_topology_mutex);
|
||||
port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
|
||||
if (port_info && port_info->phy_info)
|
||||
sas_address =
|
||||
port_info->phy_info[0].phy->identify.sas_address;
|
||||
mutex_unlock(&ioc->sas_topology_mutex);
|
||||
}
|
||||
|
||||
*((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
|
||||
|
||||
psge = (char *)
|
||||
(((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
|
||||
|
||||
/* request */
|
||||
flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
||||
MPI_SGE_FLAGS_END_OF_BUFFER |
|
||||
MPI_SGE_FLAGS_DIRECTION |
|
||||
mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT;
|
||||
flagsLength |= (req->data_len - 4);
|
||||
|
||||
dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
|
||||
req->data_len, PCI_DMA_BIDIRECTIONAL);
|
||||
if (!dma_addr_out)
|
||||
goto put_mf;
|
||||
mpt_add_sge(psge, flagsLength, dma_addr_out);
|
||||
psge += (sizeof(u32) + sizeof(dma_addr_t));
|
||||
|
||||
/* response */
|
||||
flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
|
||||
flagsLength |= rsp->data_len + 4;
|
||||
dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
|
||||
rsp->data_len, PCI_DMA_BIDIRECTIONAL);
|
||||
if (!dma_addr_in)
|
||||
goto unmap;
|
||||
mpt_add_sge(psge, flagsLength, dma_addr_in);
|
||||
|
||||
mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
|
||||
|
||||
timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
|
||||
if (!timeleft) {
|
||||
printk(KERN_ERR "%s: smp timeout!\n", __FUNCTION__);
|
||||
/* On timeout reset the board */
|
||||
mpt_HardResetHandler(ioc, CAN_SLEEP);
|
||||
ret = -ETIMEDOUT;
|
||||
goto unmap;
|
||||
}
|
||||
mf = NULL;
|
||||
|
||||
if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {
|
||||
SmpPassthroughReply_t *smprep;
|
||||
|
||||
smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
|
||||
memcpy(req->sense, smprep, sizeof(*smprep));
|
||||
req->sense_len = sizeof(*smprep);
|
||||
} else {
|
||||
printk(KERN_ERR "%s: smp passthru reply failed to be returned\n",
|
||||
__FUNCTION__);
|
||||
ret = -ENXIO;
|
||||
}
|
||||
unmap:
|
||||
if (dma_addr_out)
|
||||
pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
if (dma_addr_in)
|
||||
pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
put_mf:
|
||||
if (mf)
|
||||
mpt_free_msg_frame(ioc, mf);
|
||||
out_unlock:
|
||||
mutex_unlock(&ioc->sas_mgmt.mutex);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sas_function_template mptsas_transport_functions = {
|
||||
.get_linkerrors = mptsas_get_linkerrors,
|
||||
.get_enclosure_identifier = mptsas_get_enclosure_identifier,
|
||||
.get_bay_identifier = mptsas_get_bay_identifier,
|
||||
.phy_reset = mptsas_phy_reset,
|
||||
.smp_handler = mptsas_smp_handler,
|
||||
};
|
||||
|
||||
static struct scsi_transport_template *mptsas_transport_template;
|
||||
|
Reference in New Issue
Block a user