diff options
author | Yang, Bo <Bo.Yang@lsi.com> | 2009-10-06 16:18:02 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-10-29 13:03:18 -0400 |
commit | c35188377f12e5e0a74f18c3dfdd67baf88db514 (patch) | |
tree | 77d4e0d84a623f0981b37f8936d1a4f2ae32de29 /drivers/scsi/megaraid | |
parent | 8d56825321339f0ef7ad08eb58332e1836881e3b (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/scsi/megaraid')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 45 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 1 |
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; | |||
89 | static struct fasync_struct *megasas_async_queue; | 90 | static struct fasync_struct *megasas_async_queue; |
90 | static DEFINE_MUTEX(megasas_async_queue_mutex); | 91 | static DEFINE_MUTEX(megasas_async_queue_mutex); |
91 | 92 | ||
93 | static int megasas_poll_wait_aen; | ||
94 | static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait); | ||
95 | |||
92 | static u32 megasas_dbg_lvl; | 96 | static u32 megasas_dbg_lvl; |
93 | 97 | ||
98 | /* define lock for aen poll */ | ||
99 | spinlock_t poll_aen_lock; | ||
100 | |||
94 | static void | 101 | static void |
95 | megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | 102 | megasas_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, | |||
1292 | static void | 1299 | static void |
1293 | megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) | 1300 | megasas_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 | * */ | ||
3056 | static 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; |