aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorYang, Bo <Bo.Yang@lsi.com>2009-10-06 16:18:02 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-10-29 13:03:18 -0400
commitc35188377f12e5e0a74f18c3dfdd67baf88db514 (patch)
tree77d4e0d84a623f0981b37f8936d1a4f2ae32de29 /drivers
parent8d56825321339f0ef7ad08eb58332e1836881e3b (diff)
[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: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c45
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h1
2 files changed, 45 insertions, 1 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 6fd1e1796029..0d44fecf367d 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -40,6 +40,7 @@
40#include <linux/compat.h> 40#include <linux/compat.h>
41#include <linux/blkdev.h> 41#include <linux/blkdev.h>
42#include <linux/mutex.h> 42#include <linux/mutex.h>
43#include <linux/poll.h>
43 44
44#include <scsi/scsi.h> 45#include <scsi/scsi.h>
45#include <scsi/scsi_cmnd.h> 46#include <scsi/scsi_cmnd.h>
@@ -89,8 +90,14 @@ static struct megasas_mgmt_info megasas_mgmt_info;
89static struct fasync_struct *megasas_async_queue; 90static struct fasync_struct *megasas_async_queue;
90static DEFINE_MUTEX(megasas_async_queue_mutex); 91static DEFINE_MUTEX(megasas_async_queue_mutex);
91 92
93static int megasas_poll_wait_aen;
94static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait);
95
92static u32 megasas_dbg_lvl; 96static u32 megasas_dbg_lvl;
93 97
98/* define lock for aen poll */
99spinlock_t poll_aen_lock;
100
94static void 101static void
95megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, 102megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
96 u8 alt_status); 103 u8 alt_status);
@@ -1292,11 +1299,17 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
1292static void 1299static void
1293megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) 1300megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
1294{ 1301{
1302 unsigned long flags;
1295 /* 1303 /*
1296 * Don't signal app if it is just an aborted previously registered aen 1304 * Don't signal app if it is just an aborted previously registered aen
1297 */ 1305 */
1298 if (!cmd->abort_aen) 1306 if ((!cmd->abort_aen) && (instance->unload == 0)) {
1307 spin_lock_irqsave(&poll_aen_lock, flags);
1308 megasas_poll_wait_aen = 1;
1309 spin_unlock_irqrestore(&poll_aen_lock, flags);
1310 wake_up(&megasas_poll_wait);
1299 kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); 1311 kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
1312 }
1300 else 1313 else
1301 cmd->abort_aen = 0; 1314 cmd->abort_aen = 0;
1302 1315
@@ -1381,6 +1394,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
1381{ 1394{
1382 int exception = 0; 1395 int exception = 0;
1383 struct megasas_header *hdr = &cmd->frame->hdr; 1396 struct megasas_header *hdr = &cmd->frame->hdr;
1397 unsigned long flags;
1384 1398
1385 if (cmd->scmd) 1399 if (cmd->scmd)
1386 cmd->scmd->SCp.ptr = NULL; 1400 cmd->scmd->SCp.ptr = NULL;
@@ -1470,6 +1484,12 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
1470 case MFI_CMD_SMP: 1484 case MFI_CMD_SMP:
1471 case MFI_CMD_STP: 1485 case MFI_CMD_STP:
1472 case MFI_CMD_DCMD: 1486 case MFI_CMD_DCMD:
1487 if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
1488 cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
1489 spin_lock_irqsave(&poll_aen_lock, flags);
1490 megasas_poll_wait_aen = 0;
1491 spin_unlock_irqrestore(&poll_aen_lock, flags);
1492 }
1473 1493
1474 /* 1494 /*
1475 * See if got an event notification 1495 * See if got an event notification
@@ -2583,6 +2603,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2583 2603
2584 *instance->producer = 0; 2604 *instance->producer = 0;
2585 *instance->consumer = 0; 2605 *instance->consumer = 0;
2606 megasas_poll_wait_aen = 0;
2586 2607
2587 instance->evt_detail = pci_alloc_consistent(pdev, 2608 instance->evt_detail = pci_alloc_consistent(pdev,
2588 sizeof(struct 2609 sizeof(struct
@@ -2607,6 +2628,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2607 2628
2608 spin_lock_init(&instance->cmd_pool_lock); 2629 spin_lock_init(&instance->cmd_pool_lock);
2609 spin_lock_init(&instance->completion_lock); 2630 spin_lock_init(&instance->completion_lock);
2631 spin_lock_init(&poll_aen_lock);
2610 2632
2611 mutex_init(&instance->aen_mutex); 2633 mutex_init(&instance->aen_mutex);
2612 sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); 2634 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 2643
2622 megasas_dbg_lvl = 0; 2644 megasas_dbg_lvl = 0;
2623 instance->flag = 0; 2645 instance->flag = 0;
2646 instance->unload = 0;
2624 instance->last_time = 0; 2647 instance->last_time = 0;
2625 2648
2626 /* 2649 /*
@@ -2924,6 +2947,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
2924 struct megasas_instance *instance; 2947 struct megasas_instance *instance;
2925 2948
2926 instance = pci_get_drvdata(pdev); 2949 instance = pci_get_drvdata(pdev);
2950 instance->unload = 1;
2927 host = instance->host; 2951 host = instance->host;
2928 2952
2929 if (poll_mode_io) 2953 if (poll_mode_io)
@@ -3027,6 +3051,23 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
3027} 3051}
3028 3052
3029/** 3053/**
3054 * megasas_mgmt_poll - char node "poll" entry point
3055 * */
3056static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
3057{
3058 unsigned int mask;
3059 unsigned long flags;
3060 poll_wait(file, &megasas_poll_wait, wait);
3061 spin_lock_irqsave(&poll_aen_lock, flags);
3062 if (megasas_poll_wait_aen)
3063 mask = (POLLIN | POLLRDNORM);
3064 else
3065 mask = 0;
3066 spin_unlock_irqrestore(&poll_aen_lock, flags);
3067 return mask;
3068}
3069
3070/**
3030 * megasas_mgmt_fw_ioctl - Issues management ioctls to FW 3071 * megasas_mgmt_fw_ioctl - Issues management ioctls to FW
3031 * @instance: Adapter soft state 3072 * @instance: Adapter soft state
3032 * @argp: User's ioctl packet 3073 * @argp: User's ioctl packet
@@ -3067,6 +3108,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
3067 */ 3108 */
3068 memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); 3109 memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
3069 cmd->frame->hdr.context = cmd->index; 3110 cmd->frame->hdr.context = cmd->index;
3111 cmd->frame->hdr.pad_0 = 0;
3070 3112
3071 /* 3113 /*
3072 * The management interface between applications and the fw uses 3114 * The management interface between applications and the fw uses
@@ -3348,6 +3390,7 @@ static const struct file_operations megasas_mgmt_fops = {
3348 .open = megasas_mgmt_open, 3390 .open = megasas_mgmt_open,
3349 .fasync = megasas_mgmt_fasync, 3391 .fasync = megasas_mgmt_fasync,
3350 .unlocked_ioctl = megasas_mgmt_ioctl, 3392 .unlocked_ioctl = megasas_mgmt_ioctl,
3393 .poll = megasas_mgmt_poll,
3351#ifdef CONFIG_COMPAT 3394#ifdef CONFIG_COMPAT
3352 .compat_ioctl = megasas_mgmt_compat_ioctl, 3395 .compat_ioctl = megasas_mgmt_compat_ioctl,
3353#endif 3396#endif
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 0d033248fdf1..900359fd3fb9 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1120,6 +1120,7 @@ struct megasas_instance {
1120 struct tasklet_struct isr_tasklet; 1120 struct tasklet_struct isr_tasklet;
1121 1121
1122 u8 flag; 1122 u8 flag;
1123 u8 unload;
1123 unsigned long last_time; 1124 unsigned long last_time;
1124 1125
1125 struct timer_list io_completion_timer; 1126 struct timer_list io_completion_timer;