aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/megaraid/megaraid_sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas.c')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c152
1 files changed, 146 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);