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; |
