aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/megaraid
diff options
context:
space:
mode:
authorbo yang <bo.yang@lsi.com>2007-11-09 04:40:16 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-11 19:22:44 -0500
commitad84db2e2e1817bb8a29e7c9108eb66bf023d99f (patch)
tree3dad9cd19c3bc2c9c6e98612c050a9e8343c3f65 /drivers/scsi/megaraid
parent7343eb6570ae3b299e7b5185b139d8335ef60e9b (diff)
[SCSI] megaraid_sas: support for poll_mode_io (reduced interrupt)
Added module parameter "poll_mode_io" to support for "polling" (reduced interrupt operation). In this mode, IO completion interrupts are delayed. At the end of initiating IOs, the driver schedules for cmd completion if there are pending cmds. A timer-based interrupt has also been added to prevent IO completion from being delayed indefinitely in the case that no new IOs are initiated. Some formatting issues in resume, suspend comment block also corrected Signed-off-by: Bo Yang <bo.yang@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c152
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h3
2 files changed, 149 insertions, 6 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 08c3d4315eb8..499f994f503d 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -47,6 +47,14 @@
47#include <scsi/scsi_host.h> 47#include <scsi/scsi_host.h>
48#include "megaraid_sas.h" 48#include "megaraid_sas.h"
49 49
50/*
51 * poll_mode_io:1- schedule complete completion from q cmd
52 */
53static unsigned int poll_mode_io;
54module_param_named(poll_mode_io, poll_mode_io, int, 0);
55MODULE_PARM_DESC(poll_mode_io,
56 "Complete cmds from IO path, (default=0)");
57
50MODULE_LICENSE("GPL"); 58MODULE_LICENSE("GPL");
51MODULE_VERSION(MEGASAS_VERSION); 59MODULE_VERSION(MEGASAS_VERSION);
52MODULE_AUTHOR("megaraidlinux@lsi.com"); 60MODULE_AUTHOR("megaraidlinux@lsi.com");
@@ -860,6 +868,12 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
860 atomic_inc(&instance->fw_outstanding); 868 atomic_inc(&instance->fw_outstanding);
861 869
862 instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set); 870 instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
871 /*
872 * Check if we have pend cmds to be completed
873 */
874 if (poll_mode_io && atomic_read(&instance->fw_outstanding))
875 tasklet_schedule(&instance->isr_tasklet);
876
863 877
864 return 0; 878 return 0;
865 879
@@ -1892,6 +1906,47 @@ fail_fw_init:
1892} 1906}
1893 1907
1894/** 1908/**
1909 * megasas_start_timer - Initializes a timer object
1910 * @instance: Adapter soft state
1911 * @timer: timer object to be initialized
1912 * @fn: timer function
1913 * @interval: time interval between timer function call
1914 */
1915static inline void
1916megasas_start_timer(struct megasas_instance *instance,
1917 struct timer_list *timer,
1918 void *fn, unsigned long interval)
1919{
1920 init_timer(timer);
1921 timer->expires = jiffies + interval;
1922 timer->data = (unsigned long)instance;
1923 timer->function = fn;
1924 add_timer(timer);
1925}
1926
1927/**
1928 * megasas_io_completion_timer - Timer fn
1929 * @instance_addr: Address of adapter soft state
1930 *
1931 * Schedules tasklet for cmd completion
1932 * if poll_mode_io is set
1933 */
1934static void
1935megasas_io_completion_timer(unsigned long instance_addr)
1936{
1937 struct megasas_instance *instance =
1938 (struct megasas_instance *)instance_addr;
1939
1940 if (atomic_read(&instance->fw_outstanding))
1941 tasklet_schedule(&instance->isr_tasklet);
1942
1943 /* Restart timer */
1944 if (poll_mode_io)
1945 mod_timer(&instance->io_completion_timer,
1946 jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
1947}
1948
1949/**
1895 * megasas_init_mfi - Initializes the FW 1950 * megasas_init_mfi - Initializes the FW
1896 * @instance: Adapter soft state 1951 * @instance: Adapter soft state
1897 * 1952 *
@@ -2017,8 +2072,14 @@ static int megasas_init_mfi(struct megasas_instance *instance)
2017 * Setup tasklet for cmd completion 2072 * Setup tasklet for cmd completion
2018 */ 2073 */
2019 2074
2020 tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, 2075 tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
2021 (unsigned long)instance); 2076 (unsigned long)instance);
2077
2078 /* Initialize the cmd completion timer */
2079 if (poll_mode_io)
2080 megasas_start_timer(instance, &instance->io_completion_timer,
2081 megasas_io_completion_timer,
2082 MEGASAS_COMPLETION_TIMER_INTERVAL);
2022 return 0; 2083 return 0;
2023 2084
2024 fail_fw_init: 2085 fail_fw_init:
@@ -2578,8 +2639,8 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
2578} 2639}
2579 2640
2580/** 2641/**
2581 * megasas_suspend - driver suspend entry point 2642 * megasas_suspend - driver suspend entry point
2582 * @pdev: PCI device structure 2643 * @pdev: PCI device structure
2583 * @state: PCI power state to suspend routine 2644 * @state: PCI power state to suspend routine
2584 */ 2645 */
2585static int __devinit 2646static int __devinit
@@ -2591,6 +2652,9 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
2591 instance = pci_get_drvdata(pdev); 2652 instance = pci_get_drvdata(pdev);
2592 host = instance->host; 2653 host = instance->host;
2593 2654
2655 if (poll_mode_io)
2656 del_timer_sync(&instance->io_completion_timer);
2657
2594 megasas_flush_cache(instance); 2658 megasas_flush_cache(instance);
2595 megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); 2659 megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
2596 tasklet_kill(&instance->isr_tasklet); 2660 tasklet_kill(&instance->isr_tasklet);
@@ -2677,6 +2741,11 @@ megasas_resume(struct pci_dev *pdev)
2677 if (megasas_start_aen(instance)) 2741 if (megasas_start_aen(instance))
2678 printk(KERN_ERR "megasas: Start AEN failed\n"); 2742 printk(KERN_ERR "megasas: Start AEN failed\n");
2679 2743
2744 /* Initialize the cmd completion timer */
2745 if (poll_mode_io)
2746 megasas_start_timer(instance, &instance->io_completion_timer,
2747 megasas_io_completion_timer,
2748 MEGASAS_COMPLETION_TIMER_INTERVAL);
2680 return 0; 2749 return 0;
2681 2750
2682fail_irq: 2751fail_irq:
@@ -2715,6 +2784,9 @@ static void megasas_detach_one(struct pci_dev *pdev)
2715 instance = pci_get_drvdata(pdev); 2784 instance = pci_get_drvdata(pdev);
2716 host = instance->host; 2785 host = instance->host;
2717 2786
2787 if (poll_mode_io)
2788 del_timer_sync(&instance->io_completion_timer);
2789
2718 scsi_remove_host(instance->host); 2790 scsi_remove_host(instance->host);
2719 megasas_flush_cache(instance); 2791 megasas_flush_cache(instance);
2720 megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); 2792 megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
@@ -3188,7 +3260,7 @@ static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
3188static ssize_t 3260static ssize_t
3189megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) 3261megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
3190{ 3262{
3191 return sprintf(buf,"%u",megasas_dbg_lvl); 3263 return sprintf(buf, "%u\n", megasas_dbg_lvl);
3192} 3264}
3193 3265
3194static ssize_t 3266static ssize_t
@@ -3203,7 +3275,65 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun
3203} 3275}
3204 3276
3205static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl, 3277static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl,
3206 megasas_sysfs_set_dbg_lvl); 3278 megasas_sysfs_set_dbg_lvl);
3279
3280static ssize_t
3281megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
3282{
3283 return sprintf(buf, "%u\n", poll_mode_io);
3284}
3285
3286static ssize_t
3287megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
3288 const char *buf, size_t count)
3289{
3290 int retval = count;
3291 int tmp = poll_mode_io;
3292 int i;
3293 struct megasas_instance *instance;
3294
3295 if (sscanf(buf, "%u", &poll_mode_io) < 1) {
3296 printk(KERN_ERR "megasas: could not set poll_mode_io\n");
3297 retval = -EINVAL;
3298 }
3299
3300 /*
3301 * Check if poll_mode_io is already set or is same as previous value
3302 */
3303 if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
3304 goto out;
3305
3306 if (poll_mode_io) {
3307 /*
3308 * Start timers for all adapters
3309 */
3310 for (i = 0; i < megasas_mgmt_info.max_index; i++) {
3311 instance = megasas_mgmt_info.instance[i];
3312 if (instance) {
3313 megasas_start_timer(instance,
3314 &instance->io_completion_timer,
3315 megasas_io_completion_timer,
3316 MEGASAS_COMPLETION_TIMER_INTERVAL);
3317 }
3318 }
3319 } else {
3320 /*
3321 * Delete timers for all adapters
3322 */
3323 for (i = 0; i < megasas_mgmt_info.max_index; i++) {
3324 instance = megasas_mgmt_info.instance[i];
3325 if (instance)
3326 del_timer_sync(&instance->io_completion_timer);
3327 }
3328 }
3329
3330out:
3331 return retval;
3332}
3333
3334static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO,
3335 megasas_sysfs_show_poll_mode_io,
3336 megasas_sysfs_set_poll_mode_io);
3207 3337
3208/** 3338/**
3209 * megasas_init - Driver load entry point 3339 * megasas_init - Driver load entry point
@@ -3254,8 +3384,16 @@ static int __init megasas_init(void)
3254 &driver_attr_dbg_lvl); 3384 &driver_attr_dbg_lvl);
3255 if (rval) 3385 if (rval)
3256 goto err_dcf_dbg_lvl; 3386 goto err_dcf_dbg_lvl;
3387 rval = driver_create_file(&megasas_pci_driver.driver,
3388 &driver_attr_poll_mode_io);
3389 if (rval)
3390 goto err_dcf_poll_mode_io;
3257 3391
3258 return rval; 3392 return rval;
3393
3394err_dcf_poll_mode_io:
3395 driver_remove_file(&megasas_pci_driver.driver,
3396 &driver_attr_dbg_lvl);
3259err_dcf_dbg_lvl: 3397err_dcf_dbg_lvl:
3260 driver_remove_file(&megasas_pci_driver.driver, 3398 driver_remove_file(&megasas_pci_driver.driver,
3261 &driver_attr_release_date); 3399 &driver_attr_release_date);
@@ -3274,6 +3412,8 @@ err_pcidrv:
3274static void __exit megasas_exit(void) 3412static void __exit megasas_exit(void)
3275{ 3413{
3276 driver_remove_file(&megasas_pci_driver.driver, 3414 driver_remove_file(&megasas_pci_driver.driver,
3415 &driver_attr_poll_mode_io);
3416 driver_remove_file(&megasas_pci_driver.driver,
3277 &driver_attr_dbg_lvl); 3417 &driver_attr_dbg_lvl);
3278 driver_remove_file(&megasas_pci_driver.driver, 3418 driver_remove_file(&megasas_pci_driver.driver,
3279 &driver_attr_release_date); 3419 &driver_attr_release_date);
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index c3575a304c6a..dcc66fc9c2cb 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -572,6 +572,7 @@ struct megasas_ctrl_info {
572 572
573#define MFI_OB_INTR_STATUS_MASK 0x00000002 573#define MFI_OB_INTR_STATUS_MASK 0x00000002
574#define MFI_POLL_TIMEOUT_SECS 60 574#define MFI_POLL_TIMEOUT_SECS 60
575#define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10)
575 576
576#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 577#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
577 578
@@ -1111,6 +1112,8 @@ struct megasas_instance {
1111 1112
1112 u8 flag; 1113 u8 flag;
1113 unsigned long last_time; 1114 unsigned long last_time;
1115
1116 struct timer_list io_completion_timer;
1114}; 1117};
1115 1118
1116#define MEGASAS_IS_LOGICAL(scp) \ 1119#define MEGASAS_IS_LOGICAL(scp) \