Commit 913809f6 authored by nagalakshmi.nandigama@lsi.com's avatar nagalakshmi.nandigama@lsi.com Committed by James Bottomley

[SCSI] mpt2sas: Removed redundant global mutex for IOCTLs

When the lock_kernel and unlock_kernel routines were removed in the
2.6.39 kernel, a global mutex was added on top of the existing mutex
which already existed. With this implementation, only one IOCTL
will be active at any time no matter how many ever controllers
are present. This causes poor performance.

Removed the global mutex so that the driver can work with the existing
semaphore that was already part of the existing code.
Signed-off-by: default avatarNagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 609dc44b
...@@ -620,11 +620,10 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, ...@@ -620,11 +620,10 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
* @ioc: per adapter object * @ioc: per adapter object
* @karg - (struct mpt2_ioctl_command) * @karg - (struct mpt2_ioctl_command)
* @mf - pointer to mf in user space * @mf - pointer to mf in user space
* @state - NON_BLOCKING or BLOCKING
*/ */
static long static long
_ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command karg,
struct mpt2_ioctl_command karg, void __user *mf, enum block_state state) void __user *mf)
{ {
MPI2RequestHeader_t *mpi_request = NULL, *request; MPI2RequestHeader_t *mpi_request = NULL, *request;
MPI2DefaultReply_t *mpi_reply; MPI2DefaultReply_t *mpi_reply;
...@@ -647,11 +646,6 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, ...@@ -647,11 +646,6 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
issue_reset = 0; issue_reset = 0;
if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
return -EAGAIN;
else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
return -ERESTARTSYS;
if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
ioc->name, __func__); ioc->name, __func__);
...@@ -1013,27 +1007,24 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, ...@@ -1013,27 +1007,24 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
kfree(mpi_request); kfree(mpi_request);
ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
mutex_unlock(&ioc->ctl_cmds.mutex);
return ret; return ret;
} }
/** /**
* _ctl_getiocinfo - main handler for MPT2IOCINFO opcode * _ctl_getiocinfo - main handler for MPT2IOCINFO opcode
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
*/ */
static long static long
_ctl_getiocinfo(void __user *arg) _ctl_getiocinfo(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_ioctl_iocinfo karg; struct mpt2_ioctl_iocinfo karg;
struct MPT2SAS_ADAPTER *ioc;
if (copy_from_user(&karg, arg, sizeof(karg))) { if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n", printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__)); __func__));
...@@ -1069,21 +1060,19 @@ _ctl_getiocinfo(void __user *arg) ...@@ -1069,21 +1060,19 @@ _ctl_getiocinfo(void __user *arg)
/** /**
* _ctl_eventquery - main handler for MPT2EVENTQUERY opcode * _ctl_eventquery - main handler for MPT2EVENTQUERY opcode
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
*/ */
static long static long
_ctl_eventquery(void __user *arg) _ctl_eventquery(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_ioctl_eventquery karg; struct mpt2_ioctl_eventquery karg;
struct MPT2SAS_ADAPTER *ioc;
if (copy_from_user(&karg, arg, sizeof(karg))) { if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n", printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__)); __func__));
...@@ -1102,21 +1091,19 @@ _ctl_eventquery(void __user *arg) ...@@ -1102,21 +1091,19 @@ _ctl_eventquery(void __user *arg)
/** /**
* _ctl_eventenable - main handler for MPT2EVENTENABLE opcode * _ctl_eventenable - main handler for MPT2EVENTENABLE opcode
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
*/ */
static long static long
_ctl_eventenable(void __user *arg) _ctl_eventenable(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_ioctl_eventenable karg; struct mpt2_ioctl_eventenable karg;
struct MPT2SAS_ADAPTER *ioc;
if (copy_from_user(&karg, arg, sizeof(karg))) { if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n", printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__)); __func__));
...@@ -1142,13 +1129,13 @@ _ctl_eventenable(void __user *arg) ...@@ -1142,13 +1129,13 @@ _ctl_eventenable(void __user *arg)
/** /**
* _ctl_eventreport - main handler for MPT2EVENTREPORT opcode * _ctl_eventreport - main handler for MPT2EVENTREPORT opcode
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
*/ */
static long static long
_ctl_eventreport(void __user *arg) _ctl_eventreport(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_ioctl_eventreport karg; struct mpt2_ioctl_eventreport karg;
struct MPT2SAS_ADAPTER *ioc;
u32 number_bytes, max_events, max; u32 number_bytes, max_events, max;
struct mpt2_ioctl_eventreport __user *uarg = arg; struct mpt2_ioctl_eventreport __user *uarg = arg;
...@@ -1157,8 +1144,6 @@ _ctl_eventreport(void __user *arg) ...@@ -1157,8 +1144,6 @@ _ctl_eventreport(void __user *arg)
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__)); __func__));
...@@ -1188,13 +1173,13 @@ _ctl_eventreport(void __user *arg) ...@@ -1188,13 +1173,13 @@ _ctl_eventreport(void __user *arg)
/** /**
* _ctl_do_reset - main handler for MPT2HARDRESET opcode * _ctl_do_reset - main handler for MPT2HARDRESET opcode
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
*/ */
static long static long
_ctl_do_reset(void __user *arg) _ctl_do_reset(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_ioctl_diag_reset karg; struct mpt2_ioctl_diag_reset karg;
struct MPT2SAS_ADAPTER *ioc;
int retval; int retval;
if (copy_from_user(&karg, arg, sizeof(karg))) { if (copy_from_user(&karg, arg, sizeof(karg))) {
...@@ -1202,8 +1187,6 @@ _ctl_do_reset(void __user *arg) ...@@ -1202,8 +1187,6 @@ _ctl_do_reset(void __user *arg)
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
if (ioc->shost_recovery || ioc->pci_error_recovery || if (ioc->shost_recovery || ioc->pci_error_recovery ||
ioc->is_driver_loading) ioc->is_driver_loading)
...@@ -1292,13 +1275,13 @@ _ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc, ...@@ -1292,13 +1275,13 @@ _ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc,
/** /**
* _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode * _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
*/ */
static long static long
_ctl_btdh_mapping(void __user *arg) _ctl_btdh_mapping(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_ioctl_btdh_mapping karg; struct mpt2_ioctl_btdh_mapping karg;
struct MPT2SAS_ADAPTER *ioc;
int rc; int rc;
if (copy_from_user(&karg, arg, sizeof(karg))) { if (copy_from_user(&karg, arg, sizeof(karg))) {
...@@ -1306,8 +1289,6 @@ _ctl_btdh_mapping(void __user *arg) ...@@ -1306,8 +1289,6 @@ _ctl_btdh_mapping(void __user *arg)
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__)); __func__));
...@@ -1576,17 +1557,16 @@ mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register) ...@@ -1576,17 +1557,16 @@ mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register)
/** /**
* _ctl_diag_register - application register with driver * _ctl_diag_register - application register with driver
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
* @state - NON_BLOCKING or BLOCKING
* *
* This will allow the driver to setup any required buffers that will be * This will allow the driver to setup any required buffers that will be
* needed by firmware to communicate with the driver. * needed by firmware to communicate with the driver.
*/ */
static long static long
_ctl_diag_register(void __user *arg, enum block_state state) _ctl_diag_register(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_diag_register karg; struct mpt2_diag_register karg;
struct MPT2SAS_ADAPTER *ioc;
long rc; long rc;
if (copy_from_user(&karg, arg, sizeof(karg))) { if (copy_from_user(&karg, arg, sizeof(karg))) {
...@@ -1594,30 +1574,23 @@ _ctl_diag_register(void __user *arg, enum block_state state) ...@@ -1594,30 +1574,23 @@ _ctl_diag_register(void __user *arg, enum block_state state)
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
return -EAGAIN;
else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
return -ERESTARTSYS;
rc = _ctl_diag_register_2(ioc, &karg); rc = _ctl_diag_register_2(ioc, &karg);
mutex_unlock(&ioc->ctl_cmds.mutex);
return rc; return rc;
} }
/** /**
* _ctl_diag_unregister - application unregister with driver * _ctl_diag_unregister - application unregister with driver
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
* *
* This will allow the driver to cleanup any memory allocated for diag * This will allow the driver to cleanup any memory allocated for diag
* messages and to free up any resources. * messages and to free up any resources.
*/ */
static long static long
_ctl_diag_unregister(void __user *arg) _ctl_diag_unregister(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_diag_unregister karg; struct mpt2_diag_unregister karg;
struct MPT2SAS_ADAPTER *ioc;
void *request_data; void *request_data;
dma_addr_t request_data_dma; dma_addr_t request_data_dma;
u32 request_data_sz; u32 request_data_sz;
...@@ -1628,8 +1601,6 @@ _ctl_diag_unregister(void __user *arg) ...@@ -1628,8 +1601,6 @@ _ctl_diag_unregister(void __user *arg)
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__)); __func__));
...@@ -1678,6 +1649,7 @@ _ctl_diag_unregister(void __user *arg) ...@@ -1678,6 +1649,7 @@ _ctl_diag_unregister(void __user *arg)
/** /**
* _ctl_diag_query - query relevant info associated with diag buffers * _ctl_diag_query - query relevant info associated with diag buffers
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
* *
* The application will send only buffer_type and unique_id. Driver will * The application will send only buffer_type and unique_id. Driver will
...@@ -1685,10 +1657,9 @@ _ctl_diag_unregister(void __user *arg) ...@@ -1685,10 +1657,9 @@ _ctl_diag_unregister(void __user *arg)
* 0x00, the driver will return info specified by Buffer Type. * 0x00, the driver will return info specified by Buffer Type.
*/ */
static long static long
_ctl_diag_query(void __user *arg) _ctl_diag_query(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_diag_query karg; struct mpt2_diag_query karg;
struct MPT2SAS_ADAPTER *ioc;
void *request_data; void *request_data;
int i; int i;
u8 buffer_type; u8 buffer_type;
...@@ -1698,8 +1669,6 @@ _ctl_diag_query(void __user *arg) ...@@ -1698,8 +1669,6 @@ _ctl_diag_query(void __user *arg)
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__)); __func__));
...@@ -1866,17 +1835,15 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) ...@@ -1866,17 +1835,15 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
/** /**
* _ctl_diag_release - request to send Diag Release Message to firmware * _ctl_diag_release - request to send Diag Release Message to firmware
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
* @state - NON_BLOCKING or BLOCKING
* *
* This allows ownership of the specified buffer to returned to the driver, * This allows ownership of the specified buffer to returned to the driver,
* allowing an application to read the buffer without fear that firmware is * allowing an application to read the buffer without fear that firmware is
* overwritting information in the buffer. * overwritting information in the buffer.
*/ */
static long static long
_ctl_diag_release(void __user *arg, enum block_state state) _ctl_diag_release(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_diag_release karg; struct mpt2_diag_release karg;
struct MPT2SAS_ADAPTER *ioc;
void *request_data; void *request_data;
int rc; int rc;
u8 buffer_type; u8 buffer_type;
...@@ -1887,8 +1854,6 @@ _ctl_diag_release(void __user *arg, enum block_state state) ...@@ -1887,8 +1854,6 @@ _ctl_diag_release(void __user *arg, enum block_state state)
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__)); __func__));
...@@ -1942,32 +1907,25 @@ _ctl_diag_release(void __user *arg, enum block_state state) ...@@ -1942,32 +1907,25 @@ _ctl_diag_release(void __user *arg, enum block_state state)
return 0; return 0;
} }
if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
return -EAGAIN;
else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
return -ERESTARTSYS;
rc = _ctl_send_release(ioc, buffer_type, &issue_reset); rc = _ctl_send_release(ioc, buffer_type, &issue_reset);
if (issue_reset) if (issue_reset)
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER); FORCE_BIG_HAMMER);
mutex_unlock(&ioc->ctl_cmds.mutex);
return rc; return rc;
} }
/** /**
* _ctl_diag_read_buffer - request for copy of the diag buffer * _ctl_diag_read_buffer - request for copy of the diag buffer
* @ioc: per adapter object
* @arg - user space buffer containing ioctl content * @arg - user space buffer containing ioctl content
* @state - NON_BLOCKING or BLOCKING
*/ */
static long static long
_ctl_diag_read_buffer(void __user *arg, enum block_state state) _ctl_diag_read_buffer(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
{ {
struct mpt2_diag_read_buffer karg; struct mpt2_diag_read_buffer karg;
struct mpt2_diag_read_buffer __user *uarg = arg; struct mpt2_diag_read_buffer __user *uarg = arg;
struct MPT2SAS_ADAPTER *ioc;
void *request_data, *diag_data; void *request_data, *diag_data;
Mpi2DiagBufferPostRequest_t *mpi_request; Mpi2DiagBufferPostRequest_t *mpi_request;
Mpi2DiagBufferPostReply_t *mpi_reply; Mpi2DiagBufferPostReply_t *mpi_reply;
...@@ -1983,8 +1941,6 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) ...@@ -1983,8 +1941,6 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; return -EFAULT;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__)); __func__));
...@@ -2055,10 +2011,6 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) ...@@ -2055,10 +2011,6 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
} }
/* Get a free request frame and save the message context. /* Get a free request frame and save the message context.
*/ */
if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
return -EAGAIN;
else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
return -ERESTARTSYS;
if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
...@@ -2139,115 +2091,170 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) ...@@ -2139,115 +2091,170 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
out: out:
ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
mutex_unlock(&ioc->ctl_cmds.mutex);
return rc; return rc;
} }
#ifdef CONFIG_COMPAT
/**
* _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
* @ioc: per adapter object
* @cmd - ioctl opcode
* @arg - (struct mpt2_ioctl_command32)
*
* MPT2COMMAND32 - Handle 32bit applications running on 64bit os.
*/
static long
_ctl_compat_mpt_command(struct MPT2SAS_ADAPTER *ioc, unsigned cmd,
void __user *arg)
{
struct mpt2_ioctl_command32 karg32;
struct mpt2_ioctl_command32 __user *uarg;
struct mpt2_ioctl_command karg;
if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
return -EINVAL;
uarg = (struct mpt2_ioctl_command32 __user *) arg;
if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
karg.hdr.ioc_number = karg32.hdr.ioc_number;
karg.hdr.port_number = karg32.hdr.port_number;
karg.hdr.max_data_size = karg32.hdr.max_data_size;
karg.timeout = karg32.timeout;
karg.max_reply_bytes = karg32.max_reply_bytes;
karg.data_in_size = karg32.data_in_size;
karg.data_out_size = karg32.data_out_size;
karg.max_sense_bytes = karg32.max_sense_bytes;
karg.data_sge_offset = karg32.data_sge_offset;
karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
return _ctl_do_mpt_command(ioc, karg, &uarg->mf);
}
#endif
/** /**
* _ctl_ioctl_main - main ioctl entry point * _ctl_ioctl_main - main ioctl entry point
* @file - (struct file) * @file - (struct file)
* @cmd - ioctl opcode * @cmd - ioctl opcode
* @arg - * @arg -
* compat - handles 32 bit applications in 64bit os
*/ */
static long static long
_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg) _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
u8 compat)
{ {
struct MPT2SAS_ADAPTER *ioc;
struct mpt2_ioctl_header ioctl_header;
enum block_state state; enum block_state state;
long ret = -EINVAL; long ret = -EINVAL;
state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : /* get IOCTL header */
BLOCKING; if (copy_from_user(&ioctl_header, (char __user *)arg,
sizeof(struct mpt2_ioctl_header))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
if (ioc->shost_recovery || ioc->pci_error_recovery ||
ioc->is_driver_loading)
return -EAGAIN;
state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
return -EAGAIN;
else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
return -ERESTARTSYS;
switch (cmd) { switch (cmd) {
case MPT2IOCINFO: case MPT2IOCINFO:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo))
ret = _ctl_getiocinfo(arg); ret = _ctl_getiocinfo(ioc, arg);
break; break;
#ifdef CONFIG_COMPAT
case MPT2COMMAND32:
#endif
case MPT2COMMAND: case MPT2COMMAND:
{ {
struct mpt2_ioctl_command karg;
struct mpt2_ioctl_command __user *uarg; struct mpt2_ioctl_command __user *uarg;
struct MPT2SAS_ADAPTER *ioc; struct mpt2_ioctl_command karg;
#ifdef CONFIG_COMPAT
if (compat) {
ret = _ctl_compat_mpt_command(ioc, cmd, arg);
break;
}
#endif
if (copy_from_user(&karg, arg, sizeof(karg))) { if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n", printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
return -EFAULT; ret = -EFAULT;
break;
} }
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
!ioc)
return -ENODEV;
if (ioc->shost_recovery || ioc->pci_error_recovery ||
ioc->is_driver_loading)
return -EAGAIN;
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) { if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
uarg = arg; uarg = arg;
ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf, state); ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf);
} }
break; break;
} }
case MPT2EVENTQUERY: case MPT2EVENTQUERY:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery))
ret = _ctl_eventquery(arg); ret = _ctl_eventquery(ioc, arg);
break; break;
case MPT2EVENTENABLE: case MPT2EVENTENABLE:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable))
ret = _ctl_eventenable(arg); ret = _ctl_eventenable(ioc, arg);
break; break;
case MPT2EVENTREPORT: case MPT2EVENTREPORT:
ret = _ctl_eventreport(arg); ret = _ctl_eventreport(ioc, arg);
break; break;
case MPT2HARDRESET: case MPT2HARDRESET:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset))
ret = _ctl_do_reset(arg); ret = _ctl_do_reset(ioc, arg);
break; break;
case MPT2BTDHMAPPING: case MPT2BTDHMAPPING:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping))
ret = _ctl_btdh_mapping(arg); ret = _ctl_btdh_mapping(ioc, arg);
break; break;
case MPT2DIAGREGISTER: case MPT2DIAGREGISTER:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register))
ret = _ctl_diag_register(arg, state); ret = _ctl_diag_register(ioc, arg);
break; break;
case MPT2DIAGUNREGISTER: case MPT2DIAGUNREGISTER:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister))
ret = _ctl_diag_unregister(arg); ret = _ctl_diag_unregister(ioc, arg);
break; break;
case MPT2DIAGQUERY: case MPT2DIAGQUERY:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query))
ret = _ctl_diag_query(arg); ret = _ctl_diag_query(ioc, arg);
break; break;
case MPT2DIAGRELEASE: case MPT2DIAGRELEASE:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release))
ret = _ctl_diag_release(arg, state); ret = _ctl_diag_release(ioc, arg);
break; break;
case MPT2DIAGREADBUFFER: case MPT2DIAGREADBUFFER:
if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer)) if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer))
ret = _ctl_diag_read_buffer(arg, state); ret = _ctl_diag_read_buffer(ioc, arg);
break; break;
default: default:
{
struct mpt2_ioctl_command karg;
struct MPT2SAS_ADAPTER *ioc;
if (copy_from_user(&karg, arg, sizeof(karg))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
!ioc)
return -ENODEV;
dctlprintk(ioc, printk(MPT2SAS_INFO_FMT dctlprintk(ioc, printk(MPT2SAS_INFO_FMT
"unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd)); "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
break; break;
} }
}
mutex_unlock(&ioc->ctl_cmds.mutex);
return ret; return ret;
} }
...@@ -2262,65 +2269,10 @@ _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -2262,65 +2269,10 @@ _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{ {
long ret; long ret;
mutex_lock(&_ctl_mutex); ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0);
ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
mutex_unlock(&_ctl_mutex);
return ret; return ret;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
/**
* _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
* @file - (struct file)
* @cmd - ioctl opcode
* @arg - (struct mpt2_ioctl_command32)
*
* MPT2COMMAND32 - Handle 32bit applications running on 64bit os.
*/
static long
_ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
{
struct mpt2_ioctl_command32 karg32;
struct mpt2_ioctl_command32 __user *uarg;
struct mpt2_ioctl_command karg;
struct MPT2SAS_ADAPTER *ioc;
enum block_state state;
if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
return -EINVAL;
uarg = (struct mpt2_ioctl_command32 __user *) arg;
if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
printk(KERN_ERR "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -EFAULT;
}
if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
return -ENODEV;
if (ioc->shost_recovery || ioc->pci_error_recovery ||
ioc->is_driver_loading)
return -EAGAIN;
memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
karg.hdr.ioc_number = karg32.hdr.ioc_number;
karg.hdr.port_number = karg32.hdr.port_number;
karg.hdr.max_data_size = karg32.hdr.max_data_size;
karg.timeout = karg32.timeout;
karg.max_reply_bytes = karg32.max_reply_bytes;
karg.data_in_size = karg32.data_in_size;
karg.data_out_size = karg32.data_out_size;
karg.max_sense_bytes = karg32.max_sense_bytes;
karg.data_sge_offset = karg32.data_sge_offset;
karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
return _ctl_do_mpt_command(ioc, karg, &uarg->mf, state);
}
/** /**
* _ctl_ioctl_compat - main ioctl entry point (compat) * _ctl_ioctl_compat - main ioctl entry point (compat)
* @file - * @file -
...@@ -2334,12 +2286,7 @@ _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) ...@@ -2334,12 +2286,7 @@ _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
{ {
long ret; long ret;
mutex_lock(&_ctl_mutex); ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1);
if (cmd == MPT2COMMAND32)
ret = _ctl_compat_mpt_command(file, cmd, arg);
else
ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
mutex_unlock(&_ctl_mutex);
return ret; return ret;
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment