mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-08 19:56:24 -04:00
Merge patch series "mpt3sas driver udpates"
Shivasharan S <shivasharan.srikanteshwara@broadcom.com> says: This patch series adds support for the MCTP passthrough function over the MPI interface for management commands. Also fix issue related to task management handling during IOCTL timeout. Link: https://lore.kernel.org/r/1739410016-27503-1-git-send-email-shivasharan.srikanteshwara@broadcom.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
@@ -125,6 +125,12 @@
|
||||
* 06-24-19 02.00.55 Bumped MPI2_HEADER_VERSION_UNIT
|
||||
* 08-01-19 02.00.56 Bumped MPI2_HEADER_VERSION_UNIT
|
||||
* 10-02-19 02.00.57 Bumped MPI2_HEADER_VERSION_UNIT
|
||||
* 07-20-20 02.00.58 Bumped MPI2_HEADER_VERSION_UNIT
|
||||
* 03-30-21 02.00.59 Bumped MPI2_HEADER_VERSION_UNIT
|
||||
* 06-03-22 02.00.60 Bumped MPI2_HEADER_VERSION_UNIT
|
||||
* 09-20-23 02.00.61 Bumped MPI2_HEADER_VERSION_UNIT
|
||||
* 09-13-24 02.00.62 Bumped MPI2_HEADER_VERSION_UNIT
|
||||
* Added MPI2_FUNCTION_MCTP_PASSTHROUGH
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -165,7 +171,7 @@
|
||||
|
||||
|
||||
/* Unit and Dev versioning for this MPI header set */
|
||||
#define MPI2_HEADER_VERSION_UNIT (0x39)
|
||||
#define MPI2_HEADER_VERSION_UNIT (0x3E)
|
||||
#define MPI2_HEADER_VERSION_DEV (0x00)
|
||||
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
|
||||
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
|
||||
@@ -669,6 +675,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION {
|
||||
#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30)
|
||||
#define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31)
|
||||
#define MPI2_FUNCTION_NVME_ENCAPSULATED (0x33)
|
||||
#define MPI2_FUNCTION_MCTP_PASSTHROUGH (0x34)
|
||||
#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0)
|
||||
#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF)
|
||||
|
||||
|
||||
@@ -251,6 +251,7 @@
|
||||
* 12-17-18 02.00.47 Swap locations of Slotx2 and Slotx4 in ManPage 7.
|
||||
* 08-01-19 02.00.49 Add MPI26_MANPAGE7_FLAG_X2_X4_SLOT_INFO_VALID
|
||||
* Add MPI26_IOUNITPAGE1_NVME_WRCACHE_SHIFT
|
||||
* 09-13-24 02.00.50 Added PCIe 32 GT/s link rate
|
||||
*/
|
||||
|
||||
#ifndef MPI2_CNFG_H
|
||||
@@ -1121,6 +1122,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
|
||||
#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS (0x01)
|
||||
#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS (0x02)
|
||||
#define MPI2_IOUNITPAGE7_PCIE_SPEED_16_0_GBPS (0x03)
|
||||
#define MPI2_IOUNITPAGE7_PCIE_SPEED_32_0_GBPS (0x04)
|
||||
|
||||
/*defines for IO Unit Page 7 ProcessorState field */
|
||||
#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND (0x0000000F)
|
||||
@@ -2301,6 +2303,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
|
||||
#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
|
||||
|
||||
/*values for SAS IO Unit Page 1 AdditionalControlFlags */
|
||||
#define MPI2_SASIOUNIT1_ACONTROL_PROD_SPECIFIC_1 (0x8000)
|
||||
#define MPI2_SASIOUNIT1_ACONTROL_DA_PERSIST_CONNECT (0x0100)
|
||||
#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080)
|
||||
#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040)
|
||||
@@ -3591,6 +3594,7 @@ typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_5_0 (0x03)
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_8_0 (0x04)
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_16_0 (0x05)
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_32_0 (0x06)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
@@ -3700,6 +3704,7 @@ typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_1 {
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_5_0 (0x30)
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_8_0 (0x40)
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_16_0 (0x50)
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_32_0 (0x60)
|
||||
|
||||
/*values for PCIe IO Unit Page 1 DMDReportPCIe */
|
||||
#define MPI26_PCIEIOUNIT1_DMDRPT_UNIT_MASK (0x80)
|
||||
|
||||
@@ -179,6 +179,7 @@
|
||||
* Added MPI26_IOCFACTS_CAPABILITY_COREDUMP_ENABLED
|
||||
* Added MPI2_FW_DOWNLOAD_ITYPE_COREDUMP
|
||||
* Added MPI2_FW_UPLOAD_ITYPE_COREDUMP
|
||||
* 9-13-24 02.00.39 Added MPI26_MCTP_PASSTHROUGH messages
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -382,6 +383,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY {
|
||||
/*ProductID field uses MPI2_FW_HEADER_PID_ */
|
||||
|
||||
/*IOCCapabilities */
|
||||
#define MPI26_IOCFACTS_CAPABILITY_MCTP_PASSTHRU (0x00800000)
|
||||
#define MPI26_IOCFACTS_CAPABILITY_COREDUMP_ENABLED (0x00200000)
|
||||
#define MPI26_IOCFACTS_CAPABILITY_PCIE_SRIOV (0x00100000)
|
||||
#define MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ (0x00080000)
|
||||
@@ -1798,5 +1800,57 @@ typedef struct _MPI26_IOUNIT_CONTROL_REPLY {
|
||||
Mpi26IoUnitControlReply_t,
|
||||
*pMpi26IoUnitControlReply_t;
|
||||
|
||||
/****************************************************************************
|
||||
* MCTP Passthrough messages (MPI v2.6 and later only.)
|
||||
****************************************************************************/
|
||||
|
||||
/* MCTP Passthrough Request Message */
|
||||
typedef struct _MPI26_MCTP_PASSTHROUGH_REQUEST {
|
||||
U8 MsgContext; /* 0x00 */
|
||||
U8 Reserved1[2]; /* 0x01 */
|
||||
U8 Function; /* 0x03 */
|
||||
U8 Reserved2[3]; /* 0x04 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U32 Reserved4; /* 0x0C */
|
||||
U8 Flags; /* 0x10 */
|
||||
U8 Reserved5[3]; /* 0x11 */
|
||||
U32 Reserved6; /* 0x14 */
|
||||
U32 H2DLength; /* 0x18 */
|
||||
U32 D2HLength; /* 0x1C */
|
||||
MPI25_SGE_IO_UNION H2DSGL; /* 0x20 */
|
||||
MPI25_SGE_IO_UNION D2HSGL; /* 0x30 */
|
||||
} MPI26_MCTP_PASSTHROUGH_REQUEST,
|
||||
*PTR_MPI26_MCTP_PASSTHROUGH_REQUEST,
|
||||
Mpi26MctpPassthroughRequest_t,
|
||||
*pMpi26MctpPassthroughRequest_t;
|
||||
|
||||
/* values for the MsgContext field */
|
||||
#define MPI26_MCTP_MSG_CONEXT_UNUSED (0x00)
|
||||
|
||||
/* values for the Flags field */
|
||||
#define MPI26_MCTP_FLAGS_MSG_FORMAT_MPT (0x01)
|
||||
|
||||
/* MCTP Passthrough Reply Message */
|
||||
typedef struct _MPI26_MCTP_PASSTHROUGH_REPLY {
|
||||
U8 MsgContext; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U8 Reserved2[3]; /* 0x04 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved3; /* 0x0A */
|
||||
U16 Reserved4; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U32 ResponseDataLength; /* 0x14 */
|
||||
} MPI26_MCTP_PASSTHROUGH_REPLY,
|
||||
*PTR_MPI26_MCTP_PASSTHROUGH_REPLY,
|
||||
Mpi26MctpPassthroughReply_t,
|
||||
*pMpi26MctpPassthroughReply_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1202,6 +1202,11 @@ _base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
|
||||
ioc->sge_size;
|
||||
func_str = "nvme_encapsulated";
|
||||
break;
|
||||
case MPI2_FUNCTION_MCTP_PASSTHROUGH:
|
||||
frame_sz = sizeof(Mpi26MctpPassthroughRequest_t) +
|
||||
ioc->sge_size;
|
||||
func_str = "mctp_passthru";
|
||||
break;
|
||||
default:
|
||||
frame_sz = 32;
|
||||
func_str = "unknown";
|
||||
@@ -4874,6 +4879,12 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc)
|
||||
i++;
|
||||
}
|
||||
|
||||
if (ioc->facts.IOCCapabilities &
|
||||
MPI26_IOCFACTS_CAPABILITY_MCTP_PASSTHRU) {
|
||||
pr_cont("%sMCTP Passthru", i ? "," : "");
|
||||
i++;
|
||||
}
|
||||
|
||||
iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
|
||||
if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
|
||||
pr_cont("%sNCQ", i ? "," : "");
|
||||
|
||||
@@ -77,8 +77,8 @@
|
||||
#define MPT3SAS_DRIVER_NAME "mpt3sas"
|
||||
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
|
||||
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
|
||||
#define MPT3SAS_DRIVER_VERSION "51.100.00.00"
|
||||
#define MPT3SAS_MAJOR_VERSION 51
|
||||
#define MPT3SAS_DRIVER_VERSION "52.100.00.00"
|
||||
#define MPT3SAS_MAJOR_VERSION 52
|
||||
#define MPT3SAS_MINOR_VERSION 100
|
||||
#define MPT3SAS_BUILD_VERSION 00
|
||||
#define MPT3SAS_RELEASE_VERSION 00
|
||||
|
||||
@@ -186,6 +186,9 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
|
||||
case MPI2_FUNCTION_NVME_ENCAPSULATED:
|
||||
desc = "nvme_encapsulated";
|
||||
break;
|
||||
case MPI2_FUNCTION_MCTP_PASSTHROUGH:
|
||||
desc = "mctp_passthrough";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!desc)
|
||||
@@ -652,6 +655,40 @@ _ctl_set_task_mid(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command *karg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _ctl_send_mctp_passthru_req - Send an MCTP passthru request
|
||||
* @ioc: per adapter object
|
||||
* @mctp_passthru_req: MPI mctp passhthru request from caller
|
||||
* @psge: pointer to the H2DSGL
|
||||
* @data_out_dma: DMA buffer for H2D SGL
|
||||
* @data_out_sz: H2D length
|
||||
* @data_in_dma: DMA buffer for D2H SGL
|
||||
* @data_in_sz: D2H length
|
||||
* @smid: SMID to submit the request
|
||||
*
|
||||
*/
|
||||
static void
|
||||
_ctl_send_mctp_passthru_req(
|
||||
struct MPT3SAS_ADAPTER *ioc,
|
||||
Mpi26MctpPassthroughRequest_t *mctp_passthru_req, void *psge,
|
||||
dma_addr_t data_out_dma, int data_out_sz,
|
||||
dma_addr_t data_in_dma, int data_in_sz,
|
||||
u16 smid)
|
||||
{
|
||||
mctp_passthru_req->H2DLength = data_out_sz;
|
||||
mctp_passthru_req->D2HLength = data_in_sz;
|
||||
|
||||
/* Build the H2D SGL from the data out buffer */
|
||||
ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, 0, 0);
|
||||
|
||||
psge += ioc->sge_size_ieee;
|
||||
|
||||
/* Build the D2H SGL for the data in buffer */
|
||||
ioc->build_sg(ioc, psge, 0, 0, data_in_dma, data_in_sz);
|
||||
|
||||
ioc->put_smid_default(ioc, smid);
|
||||
}
|
||||
|
||||
/**
|
||||
* _ctl_do_mpt_command - main handler for MPT3COMMAND opcode
|
||||
* @ioc: per adapter object
|
||||
@@ -679,6 +716,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
||||
size_t data_in_sz = 0;
|
||||
long ret;
|
||||
u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE;
|
||||
int tm_ret;
|
||||
|
||||
issue_reset = 0;
|
||||
|
||||
@@ -792,6 +830,23 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
||||
|
||||
init_completion(&ioc->ctl_cmds.done);
|
||||
switch (mpi_request->Function) {
|
||||
case MPI2_FUNCTION_MCTP_PASSTHROUGH:
|
||||
{
|
||||
Mpi26MctpPassthroughRequest_t *mctp_passthru_req =
|
||||
(Mpi26MctpPassthroughRequest_t *)request;
|
||||
|
||||
if (!(ioc->facts.IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_MCTP_PASSTHRU)) {
|
||||
ioc_err(ioc, "%s: MCTP Passthrough request not supported\n",
|
||||
__func__);
|
||||
mpt3sas_base_free_smid(ioc, smid);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
_ctl_send_mctp_passthru_req(ioc, mctp_passthru_req, psge, data_out_dma,
|
||||
data_out_sz, data_in_dma, data_in_sz, smid);
|
||||
break;
|
||||
}
|
||||
case MPI2_FUNCTION_NVME_ENCAPSULATED:
|
||||
{
|
||||
nvme_encap_request = (Mpi26NVMeEncapsulatedRequest_t *)request;
|
||||
@@ -1120,18 +1175,25 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
|
||||
if (pcie_device && (!ioc->tm_custom_handling) &&
|
||||
(!(mpt3sas_scsih_is_pcie_scsi_device(
|
||||
pcie_device->device_info))))
|
||||
mpt3sas_scsih_issue_locked_tm(ioc,
|
||||
tm_ret = mpt3sas_scsih_issue_locked_tm(ioc,
|
||||
le16_to_cpu(mpi_request->FunctionDependent1),
|
||||
0, 0, 0,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
|
||||
0, pcie_device->reset_timeout,
|
||||
MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE);
|
||||
else
|
||||
mpt3sas_scsih_issue_locked_tm(ioc,
|
||||
tm_ret = mpt3sas_scsih_issue_locked_tm(ioc,
|
||||
le16_to_cpu(mpi_request->FunctionDependent1),
|
||||
0, 0, 0,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
|
||||
0, 30, MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET);
|
||||
|
||||
if (tm_ret != SUCCESS) {
|
||||
ioc_info(ioc,
|
||||
"target reset failed, issue hard reset: handle (0x%04x)\n",
|
||||
le16_to_cpu(mpi_request->FunctionDependent1));
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
}
|
||||
} else
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
}
|
||||
@@ -1200,6 +1262,8 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
|
||||
}
|
||||
karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
|
||||
|
||||
karg.driver_capability |= MPT3_IOCTL_IOCINFO_DRIVER_CAP_MCTP_PASSTHRU;
|
||||
|
||||
if (copy_to_user(arg, &karg, sizeof(karg))) {
|
||||
pr_err("failure at %s:%d/%s()!\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
@@ -2786,6 +2850,217 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* _ctl_get_mpt_mctp_passthru_adapter - Traverse the IOC list and return the IOC at
|
||||
* dev_index positionthat support MCTP passhtru
|
||||
* @dev_index: position in the mpt3sas_ioc_list to search for
|
||||
* Return pointer to the IOC on success
|
||||
* NULL if device not found error
|
||||
*/
|
||||
static struct MPT3SAS_ADAPTER *
|
||||
_ctl_get_mpt_mctp_passthru_adapter(int dev_index)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc = NULL;
|
||||
int count = 0;
|
||||
|
||||
spin_lock(&gioc_lock);
|
||||
/* Traverse ioc list and return number of IOC that support MCTP passthru */
|
||||
list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
|
||||
if (ioc->facts.IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_MCTP_PASSTHRU) {
|
||||
if (count == dev_index) {
|
||||
spin_unlock(&gioc_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&gioc_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpt3sas_get_device_count - Retrieve the count of MCTP passthrough
|
||||
* capable devices managed by the driver.
|
||||
*
|
||||
* Returns number of devices that support MCTP passthrough.
|
||||
*/
|
||||
int
|
||||
mpt3sas_get_device_count(void)
|
||||
{
|
||||
int count = 0;
|
||||
struct MPT3SAS_ADAPTER *ioc = NULL;
|
||||
|
||||
spin_lock(&gioc_lock);
|
||||
/* Traverse ioc list and return number of IOC that support MCTP passthru */
|
||||
list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
|
||||
if (ioc->facts.IOCCapabilities & MPI26_IOCFACTS_CAPABILITY_MCTP_PASSTHRU)
|
||||
count++;
|
||||
|
||||
spin_unlock(&gioc_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL(mpt3sas_get_device_count);
|
||||
|
||||
/**
|
||||
* mpt3sas_send_passthru_cmd - Send an MPI MCTP passthrough command to
|
||||
* firmware
|
||||
* @command: The MPI MCTP passthrough command to send to firmware
|
||||
*
|
||||
* Returns 0 on success, anything else is error.
|
||||
*/
|
||||
int mpt3sas_send_mctp_passthru_req(struct mpt3_passthru_command *command)
|
||||
{
|
||||
struct MPT3SAS_ADAPTER *ioc;
|
||||
MPI2RequestHeader_t *mpi_request = NULL, *request;
|
||||
MPI2DefaultReply_t *mpi_reply;
|
||||
Mpi26MctpPassthroughRequest_t *mctp_passthru_req;
|
||||
u16 smid;
|
||||
unsigned long timeout;
|
||||
u8 issue_reset = 0;
|
||||
u32 sz;
|
||||
void *psge;
|
||||
void *data_out = NULL;
|
||||
dma_addr_t data_out_dma = 0;
|
||||
size_t data_out_sz = 0;
|
||||
void *data_in = NULL;
|
||||
dma_addr_t data_in_dma = 0;
|
||||
size_t data_in_sz = 0;
|
||||
long ret;
|
||||
|
||||
/* Retrieve ioc from dev_index */
|
||||
ioc = _ctl_get_mpt_mctp_passthru_adapter(command->dev_index);
|
||||
if (!ioc)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&ioc->pci_access_mutex);
|
||||
if (ioc->shost_recovery ||
|
||||
ioc->pci_error_recovery || ioc->is_driver_loading ||
|
||||
ioc->remove_host) {
|
||||
ret = -EAGAIN;
|
||||
goto unlock_pci_access;
|
||||
}
|
||||
|
||||
/* Lock the ctl_cmds mutex to ensure a single ctl cmd is pending */
|
||||
if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) {
|
||||
ret = -ERESTARTSYS;
|
||||
goto unlock_pci_access;
|
||||
}
|
||||
|
||||
if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
|
||||
ioc_err(ioc, "%s: ctl_cmd in use\n", __func__);
|
||||
ret = -EAGAIN;
|
||||
goto unlock_ctl_cmds;
|
||||
}
|
||||
|
||||
ret = mpt3sas_wait_for_ioc(ioc, IOC_OPERATIONAL_WAIT_COUNT);
|
||||
if (ret)
|
||||
goto unlock_ctl_cmds;
|
||||
|
||||
mpi_request = (MPI2RequestHeader_t *)command->mpi_request;
|
||||
if (mpi_request->Function != MPI2_FUNCTION_MCTP_PASSTHROUGH) {
|
||||
ioc_err(ioc, "%s: Invalid request receveid, Function 0x%x\n",
|
||||
__func__, mpi_request->Function);
|
||||
ret = -EINVAL;
|
||||
goto unlock_ctl_cmds;
|
||||
}
|
||||
|
||||
/* Use first reserved smid for passthrough commands */
|
||||
smid = ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT + 1;
|
||||
ret = 0;
|
||||
ioc->ctl_cmds.status = MPT3_CMD_PENDING;
|
||||
memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
|
||||
request = mpt3sas_base_get_msg_frame(ioc, smid);
|
||||
memset(request, 0, ioc->request_sz);
|
||||
memcpy(request, command->mpi_request, sizeof(Mpi26MctpPassthroughRequest_t));
|
||||
ioc->ctl_cmds.smid = smid;
|
||||
data_out_sz = command->data_out_size;
|
||||
data_in_sz = command->data_in_size;
|
||||
|
||||
/* obtain dma-able memory for data transfer */
|
||||
if (data_out_sz) /* WRITE */ {
|
||||
data_out = dma_alloc_coherent(&ioc->pdev->dev, data_out_sz,
|
||||
&data_out_dma, GFP_ATOMIC);
|
||||
if (!data_out) {
|
||||
ret = -ENOMEM;
|
||||
mpt3sas_base_free_smid(ioc, smid);
|
||||
goto out;
|
||||
}
|
||||
memcpy(data_out, command->data_out_buf_ptr, data_out_sz);
|
||||
|
||||
}
|
||||
|
||||
if (data_in_sz) /* READ */ {
|
||||
data_in = dma_alloc_coherent(&ioc->pdev->dev, data_in_sz,
|
||||
&data_in_dma, GFP_ATOMIC);
|
||||
if (!data_in) {
|
||||
ret = -ENOMEM;
|
||||
mpt3sas_base_free_smid(ioc, smid);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
psge = &((Mpi26MctpPassthroughRequest_t *)request)->H2DSGL;
|
||||
|
||||
init_completion(&ioc->ctl_cmds.done);
|
||||
|
||||
mctp_passthru_req = (Mpi26MctpPassthroughRequest_t *)request;
|
||||
|
||||
_ctl_send_mctp_passthru_req(ioc, mctp_passthru_req, psge, data_out_dma,
|
||||
data_out_sz, data_in_dma, data_in_sz, smid);
|
||||
|
||||
timeout = command->timeout;
|
||||
if (timeout < MPT3_IOCTL_DEFAULT_TIMEOUT)
|
||||
timeout = MPT3_IOCTL_DEFAULT_TIMEOUT;
|
||||
|
||||
wait_for_completion_timeout(&ioc->ctl_cmds.done, timeout*HZ);
|
||||
if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
|
||||
mpt3sas_check_cmd_timeout(ioc,
|
||||
ioc->ctl_cmds.status, mpi_request,
|
||||
sizeof(Mpi26MctpPassthroughRequest_t), issue_reset);
|
||||
goto issue_host_reset;
|
||||
}
|
||||
|
||||
mpi_reply = ioc->ctl_cmds.reply;
|
||||
|
||||
/* copy out xdata to user */
|
||||
if (data_in_sz)
|
||||
memcpy(command->data_in_buf_ptr, data_in, data_in_sz);
|
||||
|
||||
/* copy out reply message frame to user */
|
||||
if (command->max_reply_bytes) {
|
||||
sz = min_t(u32, command->max_reply_bytes, ioc->reply_sz);
|
||||
memcpy(command->reply_frame_buf_ptr, ioc->ctl_cmds.reply, sz);
|
||||
}
|
||||
|
||||
issue_host_reset:
|
||||
if (issue_reset) {
|
||||
ret = -ENODATA;
|
||||
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
|
||||
}
|
||||
|
||||
out:
|
||||
/* free memory associated with sg buffers */
|
||||
if (data_in)
|
||||
dma_free_coherent(&ioc->pdev->dev, data_in_sz, data_in,
|
||||
data_in_dma);
|
||||
|
||||
if (data_out)
|
||||
dma_free_coherent(&ioc->pdev->dev, data_out_sz, data_out,
|
||||
data_out_dma);
|
||||
|
||||
ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
|
||||
|
||||
unlock_ctl_cmds:
|
||||
mutex_unlock(&ioc->ctl_cmds.mutex);
|
||||
|
||||
unlock_pci_access:
|
||||
mutex_unlock(&ioc->pci_access_mutex);
|
||||
return ret;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(mpt3sas_send_mctp_passthru_req);
|
||||
|
||||
/**
|
||||
* _ctl_ioctl - mpt3ctl main ioctl entry point (unlocked)
|
||||
* @file: (struct file)
|
||||
|
||||
@@ -160,6 +160,9 @@ struct mpt3_ioctl_pci_info {
|
||||
#define MPT3_IOCTL_INTERFACE_SAS35 (0x07)
|
||||
#define MPT2_IOCTL_VERSION_LENGTH (32)
|
||||
|
||||
/* Bits set for mpt3_ioctl_iocinfo.driver_cap */
|
||||
#define MPT3_IOCTL_IOCINFO_DRIVER_CAP_MCTP_PASSTHRU 0x1
|
||||
|
||||
/**
|
||||
* struct mpt3_ioctl_iocinfo - generic controller info
|
||||
* @hdr - generic header
|
||||
@@ -175,6 +178,7 @@ struct mpt3_ioctl_pci_info {
|
||||
* @driver_version - driver version - 32 ASCII characters
|
||||
* @rsvd1 - reserved
|
||||
* @scsi_id - scsi id of adapter 0
|
||||
* @driver_capability - driver capabilities
|
||||
* @rsvd2 - reserved
|
||||
* @pci_information - pci info (2nd revision)
|
||||
*/
|
||||
@@ -192,7 +196,8 @@ struct mpt3_ioctl_iocinfo {
|
||||
uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH];
|
||||
uint8_t rsvd1;
|
||||
uint8_t scsi_id;
|
||||
uint16_t rsvd2;
|
||||
uint8_t driver_capability;
|
||||
uint8_t rsvd2;
|
||||
struct mpt3_ioctl_pci_info pci_information;
|
||||
};
|
||||
|
||||
@@ -458,4 +463,46 @@ struct mpt3_enable_diag_sbr_reload {
|
||||
struct mpt3_ioctl_header hdr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mpt3_passthru_command - generic mpt firmware passthru command
|
||||
* @dev_index - device index
|
||||
* @timeout - command timeout in seconds. (if zero then use driver default
|
||||
* value).
|
||||
* @reply_frame_buf_ptr - MPI reply location
|
||||
* @data_in_buf_ptr - destination for read
|
||||
* @data_out_buf_ptr - data source for write
|
||||
* @max_reply_bytes - maximum number of reply bytes to be sent to app.
|
||||
* @data_in_size - number bytes for data transfer in (read)
|
||||
* @data_out_size - number bytes for data transfer out (write)
|
||||
* @mpi_request - request frame
|
||||
*/
|
||||
struct mpt3_passthru_command {
|
||||
u8 dev_index;
|
||||
uint32_t timeout;
|
||||
void *reply_frame_buf_ptr;
|
||||
void *data_in_buf_ptr;
|
||||
void *data_out_buf_ptr;
|
||||
uint32_t max_reply_bytes;
|
||||
uint32_t data_in_size;
|
||||
uint32_t data_out_size;
|
||||
Mpi26MctpPassthroughRequest_t *mpi_request;
|
||||
};
|
||||
|
||||
/*
|
||||
* mpt3sas_get_device_count - Retrieve the count of MCTP passthrough
|
||||
* capable devices managed by the driver.
|
||||
*
|
||||
* Returns number of devices that support MCTP passthrough.
|
||||
*/
|
||||
int mpt3sas_get_device_count(void);
|
||||
|
||||
/*
|
||||
* mpt3sas_send_passthru_cmd - Send an MPI MCTP passthrough command to
|
||||
* firmware
|
||||
* @command: The MPI MCTP passthrough command to send to firmware
|
||||
*
|
||||
* Returns 0 on success, anything else is error .
|
||||
*/
|
||||
int mpt3sas_send_mctp_passthru_req(struct mpt3_passthru_command *command);
|
||||
|
||||
#endif /* MPT3SAS_CTL_H_INCLUDED */
|
||||
|
||||
Reference in New Issue
Block a user