Commit c3518837 authored by Yang, Bo's avatar Yang, Bo Committed by James Bottomley

[SCSI] megaraid_sas: Add poll mechanism to megaraid sas driver

Add Poll_wait mechanism to SAS-2 MegaRAID SAS Linux driver. Driver
will wakeup poll after the driver get event from MegaRAID SAS FW.

Signed-off-by Bo Yang<bo.yang@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 8d568253
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/poll.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
...@@ -89,8 +90,14 @@ static struct megasas_mgmt_info megasas_mgmt_info; ...@@ -89,8 +90,14 @@ static struct megasas_mgmt_info megasas_mgmt_info;
static struct fasync_struct *megasas_async_queue; static struct fasync_struct *megasas_async_queue;
static DEFINE_MUTEX(megasas_async_queue_mutex); static DEFINE_MUTEX(megasas_async_queue_mutex);
static int megasas_poll_wait_aen;
static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
static u32 megasas_dbg_lvl; static u32 megasas_dbg_lvl;
/* define lock for aen poll */
spinlock_t poll_aen_lock;
static void static void
megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
u8 alt_status); u8 alt_status);
...@@ -1292,11 +1299,17 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, ...@@ -1292,11 +1299,17 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
static void static void
megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
{ {
unsigned long flags;
/* /*
* Don't signal app if it is just an aborted previously registered aen * Don't signal app if it is just an aborted previously registered aen
*/ */
if (!cmd->abort_aen) if ((!cmd->abort_aen) && (instance->unload == 0)) {
spin_lock_irqsave(&poll_aen_lock, flags);
megasas_poll_wait_aen = 1;
spin_unlock_irqrestore(&poll_aen_lock, flags);
wake_up(&megasas_poll_wait);
kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
}
else else
cmd->abort_aen = 0; cmd->abort_aen = 0;
...@@ -1381,6 +1394,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, ...@@ -1381,6 +1394,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
{ {
int exception = 0; int exception = 0;
struct megasas_header *hdr = &cmd->frame->hdr; struct megasas_header *hdr = &cmd->frame->hdr;
unsigned long flags;
if (cmd->scmd) if (cmd->scmd)
cmd->scmd->SCp.ptr = NULL; cmd->scmd->SCp.ptr = NULL;
...@@ -1470,6 +1484,12 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, ...@@ -1470,6 +1484,12 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
case MFI_CMD_SMP: case MFI_CMD_SMP:
case MFI_CMD_STP: case MFI_CMD_STP:
case MFI_CMD_DCMD: case MFI_CMD_DCMD:
if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
spin_lock_irqsave(&poll_aen_lock, flags);
megasas_poll_wait_aen = 0;
spin_unlock_irqrestore(&poll_aen_lock, flags);
}
/* /*
* See if got an event notification * See if got an event notification
...@@ -2583,6 +2603,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2583,6 +2603,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
*instance->producer = 0; *instance->producer = 0;
*instance->consumer = 0; *instance->consumer = 0;
megasas_poll_wait_aen = 0;
instance->evt_detail = pci_alloc_consistent(pdev, instance->evt_detail = pci_alloc_consistent(pdev,
sizeof(struct sizeof(struct
...@@ -2607,6 +2628,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2607,6 +2628,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
spin_lock_init(&instance->cmd_pool_lock); spin_lock_init(&instance->cmd_pool_lock);
spin_lock_init(&instance->completion_lock); spin_lock_init(&instance->completion_lock);
spin_lock_init(&poll_aen_lock);
mutex_init(&instance->aen_mutex); mutex_init(&instance->aen_mutex);
sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
...@@ -2621,6 +2643,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2621,6 +2643,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
megasas_dbg_lvl = 0; megasas_dbg_lvl = 0;
instance->flag = 0; instance->flag = 0;
instance->unload = 0;
instance->last_time = 0; instance->last_time = 0;
/* /*
...@@ -2924,6 +2947,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) ...@@ -2924,6 +2947,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
struct megasas_instance *instance; struct megasas_instance *instance;
instance = pci_get_drvdata(pdev); instance = pci_get_drvdata(pdev);
instance->unload = 1;
host = instance->host; host = instance->host;
if (poll_mode_io) if (poll_mode_io)
...@@ -3026,6 +3050,23 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) ...@@ -3026,6 +3050,23 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
return rc; return rc;
} }
/**
* megasas_mgmt_poll - char node "poll" entry point
* */
static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
{
unsigned int mask;
unsigned long flags;
poll_wait(file, &megasas_poll_wait, wait);
spin_lock_irqsave(&poll_aen_lock, flags);
if (megasas_poll_wait_aen)
mask = (POLLIN | POLLRDNORM);
else
mask = 0;
spin_unlock_irqrestore(&poll_aen_lock, flags);
return mask;
}
/** /**
* megasas_mgmt_fw_ioctl - Issues management ioctls to FW * megasas_mgmt_fw_ioctl - Issues management ioctls to FW
* @instance: Adapter soft state * @instance: Adapter soft state
...@@ -3067,6 +3108,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, ...@@ -3067,6 +3108,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
*/ */
memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
cmd->frame->hdr.context = cmd->index; cmd->frame->hdr.context = cmd->index;
cmd->frame->hdr.pad_0 = 0;
/* /*
* The management interface between applications and the fw uses * The management interface between applications and the fw uses
...@@ -3348,6 +3390,7 @@ static const struct file_operations megasas_mgmt_fops = { ...@@ -3348,6 +3390,7 @@ static const struct file_operations megasas_mgmt_fops = {
.open = megasas_mgmt_open, .open = megasas_mgmt_open,
.fasync = megasas_mgmt_fasync, .fasync = megasas_mgmt_fasync,
.unlocked_ioctl = megasas_mgmt_ioctl, .unlocked_ioctl = megasas_mgmt_ioctl,
.poll = megasas_mgmt_poll,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = megasas_mgmt_compat_ioctl, .compat_ioctl = megasas_mgmt_compat_ioctl,
#endif #endif
......
...@@ -1120,6 +1120,7 @@ struct megasas_instance { ...@@ -1120,6 +1120,7 @@ struct megasas_instance {
struct tasklet_struct isr_tasklet; struct tasklet_struct isr_tasklet;
u8 flag; u8 flag;
u8 unload;
unsigned long last_time; unsigned long last_time;
struct timer_list io_completion_timer; struct timer_list io_completion_timer;
......
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