diff options
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 572 |
1 files changed, 448 insertions, 124 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index e3c5c5282203..d7ec921865c4 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Linux MegaRAID driver for SAS based RAID controllers | 3 | * Linux MegaRAID driver for SAS based RAID controllers |
4 | * | 4 | * |
5 | * Copyright (c) 2003-2005 LSI Logic Corporation. | 5 | * Copyright (c) 2003-2005 LSI Corporation. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
@@ -10,7 +10,7 @@ | |||
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * FILE : megaraid_sas.c | 12 | * FILE : megaraid_sas.c |
13 | * Version : v00.00.03.10-rc5 | 13 | * Version : v00.00.03.16-rc1 |
14 | * | 14 | * |
15 | * Authors: | 15 | * Authors: |
16 | * (email-id : megaraidlinux@lsi.com) | 16 | * (email-id : megaraidlinux@lsi.com) |
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/spinlock.h> | 33 | #include <linux/spinlock.h> |
34 | #include <linux/mutex.h> | ||
34 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
35 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
36 | #include <linux/uio.h> | 37 | #include <linux/uio.h> |
@@ -46,10 +47,18 @@ | |||
46 | #include <scsi/scsi_host.h> | 47 | #include <scsi/scsi_host.h> |
47 | #include "megaraid_sas.h" | 48 | #include "megaraid_sas.h" |
48 | 49 | ||
50 | /* | ||
51 | * poll_mode_io:1- schedule complete completion from q cmd | ||
52 | */ | ||
53 | static unsigned int poll_mode_io; | ||
54 | module_param_named(poll_mode_io, poll_mode_io, int, 0); | ||
55 | MODULE_PARM_DESC(poll_mode_io, | ||
56 | "Complete cmds from IO path, (default=0)"); | ||
57 | |||
49 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
50 | MODULE_VERSION(MEGASAS_VERSION); | 59 | MODULE_VERSION(MEGASAS_VERSION); |
51 | MODULE_AUTHOR("megaraidlinux@lsi.com"); | 60 | MODULE_AUTHOR("megaraidlinux@lsi.com"); |
52 | MODULE_DESCRIPTION("LSI Logic MegaRAID SAS Driver"); | 61 | MODULE_DESCRIPTION("LSI MegaRAID SAS Driver"); |
53 | 62 | ||
54 | /* | 63 | /* |
55 | * PCI ID table for all supported controllers | 64 | * PCI ID table for all supported controllers |
@@ -76,6 +85,10 @@ static DEFINE_MUTEX(megasas_async_queue_mutex); | |||
76 | 85 | ||
77 | static u32 megasas_dbg_lvl; | 86 | static u32 megasas_dbg_lvl; |
78 | 87 | ||
88 | static void | ||
89 | megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | ||
90 | u8 alt_status); | ||
91 | |||
79 | /** | 92 | /** |
80 | * megasas_get_cmd - Get a command from the free pool | 93 | * megasas_get_cmd - Get a command from the free pool |
81 | * @instance: Adapter soft state | 94 | * @instance: Adapter soft state |
@@ -855,6 +868,12 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) | |||
855 | atomic_inc(&instance->fw_outstanding); | 868 | atomic_inc(&instance->fw_outstanding); |
856 | 869 | ||
857 | 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 | |||
858 | 877 | ||
859 | return 0; | 878 | return 0; |
860 | 879 | ||
@@ -886,6 +905,64 @@ static int megasas_slave_configure(struct scsi_device *sdev) | |||
886 | } | 905 | } |
887 | 906 | ||
888 | /** | 907 | /** |
908 | * megasas_complete_cmd_dpc - Returns FW's controller structure | ||
909 | * @instance_addr: Address of adapter soft state | ||
910 | * | ||
911 | * Tasklet to complete cmds | ||
912 | */ | ||
913 | static void megasas_complete_cmd_dpc(unsigned long instance_addr) | ||
914 | { | ||
915 | u32 producer; | ||
916 | u32 consumer; | ||
917 | u32 context; | ||
918 | struct megasas_cmd *cmd; | ||
919 | struct megasas_instance *instance = | ||
920 | (struct megasas_instance *)instance_addr; | ||
921 | unsigned long flags; | ||
922 | |||
923 | /* If we have already declared adapter dead, donot complete cmds */ | ||
924 | if (instance->hw_crit_error) | ||
925 | return; | ||
926 | |||
927 | spin_lock_irqsave(&instance->completion_lock, flags); | ||
928 | |||
929 | producer = *instance->producer; | ||
930 | consumer = *instance->consumer; | ||
931 | |||
932 | while (consumer != producer) { | ||
933 | context = instance->reply_queue[consumer]; | ||
934 | |||
935 | cmd = instance->cmd_list[context]; | ||
936 | |||
937 | megasas_complete_cmd(instance, cmd, DID_OK); | ||
938 | |||
939 | consumer++; | ||
940 | if (consumer == (instance->max_fw_cmds + 1)) { | ||
941 | consumer = 0; | ||
942 | } | ||
943 | } | ||
944 | |||
945 | *instance->consumer = producer; | ||
946 | |||
947 | spin_unlock_irqrestore(&instance->completion_lock, flags); | ||
948 | |||
949 | /* | ||
950 | * Check if we can restore can_queue | ||
951 | */ | ||
952 | if (instance->flag & MEGASAS_FW_BUSY | ||
953 | && time_after(jiffies, instance->last_time + 5 * HZ) | ||
954 | && atomic_read(&instance->fw_outstanding) < 17) { | ||
955 | |||
956 | spin_lock_irqsave(instance->host->host_lock, flags); | ||
957 | instance->flag &= ~MEGASAS_FW_BUSY; | ||
958 | instance->host->can_queue = | ||
959 | instance->max_fw_cmds - MEGASAS_INT_CMDS; | ||
960 | |||
961 | spin_unlock_irqrestore(instance->host->host_lock, flags); | ||
962 | } | ||
963 | } | ||
964 | |||
965 | /** | ||
889 | * megasas_wait_for_outstanding - Wait for all outstanding cmds | 966 | * megasas_wait_for_outstanding - Wait for all outstanding cmds |
890 | * @instance: Adapter soft state | 967 | * @instance: Adapter soft state |
891 | * | 968 | * |
@@ -908,6 +985,11 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) | |||
908 | if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { | 985 | if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { |
909 | printk(KERN_NOTICE "megasas: [%2d]waiting for %d " | 986 | printk(KERN_NOTICE "megasas: [%2d]waiting for %d " |
910 | "commands to complete\n",i,outstanding); | 987 | "commands to complete\n",i,outstanding); |
988 | /* | ||
989 | * Call cmd completion routine. Cmd to be | ||
990 | * be completed directly without depending on isr. | ||
991 | */ | ||
992 | megasas_complete_cmd_dpc((unsigned long)instance); | ||
911 | } | 993 | } |
912 | 994 | ||
913 | msleep(1000); | 995 | msleep(1000); |
@@ -1100,7 +1182,7 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
1100 | static struct scsi_host_template megasas_template = { | 1182 | static struct scsi_host_template megasas_template = { |
1101 | 1183 | ||
1102 | .module = THIS_MODULE, | 1184 | .module = THIS_MODULE, |
1103 | .name = "LSI Logic SAS based MegaRAID driver", | 1185 | .name = "LSI SAS based MegaRAID driver", |
1104 | .proc_name = "megaraid_sas", | 1186 | .proc_name = "megaraid_sas", |
1105 | .slave_configure = megasas_slave_configure, | 1187 | .slave_configure = megasas_slave_configure, |
1106 | .queuecommand = megasas_queue_command, | 1188 | .queuecommand = megasas_queue_command, |
@@ -1749,57 +1831,119 @@ megasas_get_ctrl_info(struct megasas_instance *instance, | |||
1749 | } | 1831 | } |
1750 | 1832 | ||
1751 | /** | 1833 | /** |
1752 | * megasas_complete_cmd_dpc - Returns FW's controller structure | 1834 | * megasas_issue_init_mfi - Initializes the FW |
1753 | * @instance_addr: Address of adapter soft state | 1835 | * @instance: Adapter soft state |
1754 | * | 1836 | * |
1755 | * Tasklet to complete cmds | 1837 | * Issues the INIT MFI cmd |
1756 | */ | 1838 | */ |
1757 | static void megasas_complete_cmd_dpc(unsigned long instance_addr) | 1839 | static int |
1840 | megasas_issue_init_mfi(struct megasas_instance *instance) | ||
1758 | { | 1841 | { |
1759 | u32 producer; | ||
1760 | u32 consumer; | ||
1761 | u32 context; | 1842 | u32 context; |
1843 | |||
1762 | struct megasas_cmd *cmd; | 1844 | struct megasas_cmd *cmd; |
1763 | struct megasas_instance *instance = (struct megasas_instance *)instance_addr; | ||
1764 | unsigned long flags; | ||
1765 | 1845 | ||
1766 | /* If we have already declared adapter dead, donot complete cmds */ | 1846 | struct megasas_init_frame *init_frame; |
1767 | if (instance->hw_crit_error) | 1847 | struct megasas_init_queue_info *initq_info; |
1768 | return; | 1848 | dma_addr_t init_frame_h; |
1849 | dma_addr_t initq_info_h; | ||
1769 | 1850 | ||
1770 | producer = *instance->producer; | 1851 | /* |
1771 | consumer = *instance->consumer; | 1852 | * Prepare a init frame. Note the init frame points to queue info |
1853 | * structure. Each frame has SGL allocated after first 64 bytes. For | ||
1854 | * this frame - since we don't need any SGL - we use SGL's space as | ||
1855 | * queue info structure | ||
1856 | * | ||
1857 | * We will not get a NULL command below. We just created the pool. | ||
1858 | */ | ||
1859 | cmd = megasas_get_cmd(instance); | ||
1772 | 1860 | ||
1773 | while (consumer != producer) { | 1861 | init_frame = (struct megasas_init_frame *)cmd->frame; |
1774 | context = instance->reply_queue[consumer]; | 1862 | initq_info = (struct megasas_init_queue_info *) |
1863 | ((unsigned long)init_frame + 64); | ||
1775 | 1864 | ||
1776 | cmd = instance->cmd_list[context]; | 1865 | init_frame_h = cmd->frame_phys_addr; |
1866 | initq_info_h = init_frame_h + 64; | ||
1777 | 1867 | ||
1778 | megasas_complete_cmd(instance, cmd, DID_OK); | 1868 | context = init_frame->context; |
1869 | memset(init_frame, 0, MEGAMFI_FRAME_SIZE); | ||
1870 | memset(initq_info, 0, sizeof(struct megasas_init_queue_info)); | ||
1871 | init_frame->context = context; | ||
1779 | 1872 | ||
1780 | consumer++; | 1873 | initq_info->reply_queue_entries = instance->max_fw_cmds + 1; |
1781 | if (consumer == (instance->max_fw_cmds + 1)) { | 1874 | initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h; |
1782 | consumer = 0; | ||
1783 | } | ||
1784 | } | ||
1785 | 1875 | ||
1786 | *instance->consumer = producer; | 1876 | initq_info->producer_index_phys_addr_lo = instance->producer_h; |
1877 | initq_info->consumer_index_phys_addr_lo = instance->consumer_h; | ||
1878 | |||
1879 | init_frame->cmd = MFI_CMD_INIT; | ||
1880 | init_frame->cmd_status = 0xFF; | ||
1881 | init_frame->queue_info_new_phys_addr_lo = initq_info_h; | ||
1882 | |||
1883 | init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info); | ||
1787 | 1884 | ||
1788 | /* | 1885 | /* |
1789 | * Check if we can restore can_queue | 1886 | * disable the intr before firing the init frame to FW |
1790 | */ | 1887 | */ |
1791 | if (instance->flag & MEGASAS_FW_BUSY | 1888 | instance->instancet->disable_intr(instance->reg_set); |
1792 | && time_after(jiffies, instance->last_time + 5 * HZ) | ||
1793 | && atomic_read(&instance->fw_outstanding) < 17) { | ||
1794 | 1889 | ||
1795 | spin_lock_irqsave(instance->host->host_lock, flags); | 1890 | /* |
1796 | instance->flag &= ~MEGASAS_FW_BUSY; | 1891 | * Issue the init frame in polled mode |
1797 | instance->host->can_queue = | 1892 | */ |
1798 | instance->max_fw_cmds - MEGASAS_INT_CMDS; | ||
1799 | 1893 | ||
1800 | spin_unlock_irqrestore(instance->host->host_lock, flags); | 1894 | if (megasas_issue_polled(instance, cmd)) { |
1895 | printk(KERN_ERR "megasas: Failed to init firmware\n"); | ||
1896 | megasas_return_cmd(instance, cmd); | ||
1897 | goto fail_fw_init; | ||
1801 | } | 1898 | } |
1802 | 1899 | ||
1900 | megasas_return_cmd(instance, cmd); | ||
1901 | |||
1902 | return 0; | ||
1903 | |||
1904 | fail_fw_init: | ||
1905 | return -EINVAL; | ||
1906 | } | ||
1907 | |||
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 | */ | ||
1915 | static inline void | ||
1916 | megasas_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 | */ | ||
1934 | static void | ||
1935 | megasas_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); | ||
1803 | } | 1947 | } |
1804 | 1948 | ||
1805 | /** | 1949 | /** |
@@ -1814,22 +1958,15 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
1814 | u32 reply_q_sz; | 1958 | u32 reply_q_sz; |
1815 | u32 max_sectors_1; | 1959 | u32 max_sectors_1; |
1816 | u32 max_sectors_2; | 1960 | u32 max_sectors_2; |
1961 | u32 tmp_sectors; | ||
1817 | struct megasas_register_set __iomem *reg_set; | 1962 | struct megasas_register_set __iomem *reg_set; |
1818 | |||
1819 | struct megasas_cmd *cmd; | ||
1820 | struct megasas_ctrl_info *ctrl_info; | 1963 | struct megasas_ctrl_info *ctrl_info; |
1821 | |||
1822 | struct megasas_init_frame *init_frame; | ||
1823 | struct megasas_init_queue_info *initq_info; | ||
1824 | dma_addr_t init_frame_h; | ||
1825 | dma_addr_t initq_info_h; | ||
1826 | |||
1827 | /* | 1964 | /* |
1828 | * Map the message registers | 1965 | * Map the message registers |
1829 | */ | 1966 | */ |
1830 | instance->base_addr = pci_resource_start(instance->pdev, 0); | 1967 | instance->base_addr = pci_resource_start(instance->pdev, 0); |
1831 | 1968 | ||
1832 | if (pci_request_regions(instance->pdev, "megasas: LSI Logic")) { | 1969 | if (pci_request_regions(instance->pdev, "megasas: LSI")) { |
1833 | printk(KERN_DEBUG "megasas: IO memory region busy!\n"); | 1970 | printk(KERN_DEBUG "megasas: IO memory region busy!\n"); |
1834 | return -EBUSY; | 1971 | return -EBUSY; |
1835 | } | 1972 | } |
@@ -1900,52 +2037,8 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
1900 | goto fail_reply_queue; | 2037 | goto fail_reply_queue; |
1901 | } | 2038 | } |
1902 | 2039 | ||
1903 | /* | 2040 | if (megasas_issue_init_mfi(instance)) |
1904 | * Prepare a init frame. Note the init frame points to queue info | ||
1905 | * structure. Each frame has SGL allocated after first 64 bytes. For | ||
1906 | * this frame - since we don't need any SGL - we use SGL's space as | ||
1907 | * queue info structure | ||
1908 | * | ||
1909 | * We will not get a NULL command below. We just created the pool. | ||
1910 | */ | ||
1911 | cmd = megasas_get_cmd(instance); | ||
1912 | |||
1913 | init_frame = (struct megasas_init_frame *)cmd->frame; | ||
1914 | initq_info = (struct megasas_init_queue_info *) | ||
1915 | ((unsigned long)init_frame + 64); | ||
1916 | |||
1917 | init_frame_h = cmd->frame_phys_addr; | ||
1918 | initq_info_h = init_frame_h + 64; | ||
1919 | |||
1920 | memset(init_frame, 0, MEGAMFI_FRAME_SIZE); | ||
1921 | memset(initq_info, 0, sizeof(struct megasas_init_queue_info)); | ||
1922 | |||
1923 | initq_info->reply_queue_entries = instance->max_fw_cmds + 1; | ||
1924 | initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h; | ||
1925 | |||
1926 | initq_info->producer_index_phys_addr_lo = instance->producer_h; | ||
1927 | initq_info->consumer_index_phys_addr_lo = instance->consumer_h; | ||
1928 | |||
1929 | init_frame->cmd = MFI_CMD_INIT; | ||
1930 | init_frame->cmd_status = 0xFF; | ||
1931 | init_frame->queue_info_new_phys_addr_lo = initq_info_h; | ||
1932 | |||
1933 | init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info); | ||
1934 | |||
1935 | /* | ||
1936 | * disable the intr before firing the init frame to FW | ||
1937 | */ | ||
1938 | instance->instancet->disable_intr(instance->reg_set); | ||
1939 | |||
1940 | /* | ||
1941 | * Issue the init frame in polled mode | ||
1942 | */ | ||
1943 | if (megasas_issue_polled(instance, cmd)) { | ||
1944 | printk(KERN_DEBUG "megasas: Failed to init firmware\n"); | ||
1945 | goto fail_fw_init; | 2041 | goto fail_fw_init; |
1946 | } | ||
1947 | |||
1948 | megasas_return_cmd(instance, cmd); | ||
1949 | 2042 | ||
1950 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); | 2043 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); |
1951 | 2044 | ||
@@ -1958,17 +2051,20 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
1958 | * Note that older firmwares ( < FW ver 30) didn't report information | 2051 | * Note that older firmwares ( < FW ver 30) didn't report information |
1959 | * to calculate max_sectors_1. So the number ended up as zero always. | 2052 | * to calculate max_sectors_1. So the number ended up as zero always. |
1960 | */ | 2053 | */ |
2054 | tmp_sectors = 0; | ||
1961 | if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) { | 2055 | if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) { |
1962 | 2056 | ||
1963 | max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * | 2057 | max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * |
1964 | ctrl_info->max_strips_per_io; | 2058 | ctrl_info->max_strips_per_io; |
1965 | max_sectors_2 = ctrl_info->max_request_size; | 2059 | max_sectors_2 = ctrl_info->max_request_size; |
1966 | 2060 | ||
1967 | instance->max_sectors_per_req = (max_sectors_1 < max_sectors_2) | 2061 | tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2); |
1968 | ? max_sectors_1 : max_sectors_2; | 2062 | } |
1969 | } else | 2063 | |
1970 | instance->max_sectors_per_req = instance->max_num_sge * | 2064 | instance->max_sectors_per_req = instance->max_num_sge * |
1971 | PAGE_SIZE / 512; | 2065 | PAGE_SIZE / 512; |
2066 | if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors)) | ||
2067 | instance->max_sectors_per_req = tmp_sectors; | ||
1972 | 2068 | ||
1973 | kfree(ctrl_info); | 2069 | kfree(ctrl_info); |
1974 | 2070 | ||
@@ -1976,12 +2072,17 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
1976 | * Setup tasklet for cmd completion | 2072 | * Setup tasklet for cmd completion |
1977 | */ | 2073 | */ |
1978 | 2074 | ||
1979 | tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, | 2075 | tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, |
1980 | (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); | ||
1981 | return 0; | 2083 | return 0; |
1982 | 2084 | ||
1983 | fail_fw_init: | 2085 | fail_fw_init: |
1984 | megasas_return_cmd(instance, cmd); | ||
1985 | 2086 | ||
1986 | pci_free_consistent(instance->pdev, reply_q_sz, | 2087 | pci_free_consistent(instance->pdev, reply_q_sz, |
1987 | instance->reply_queue, instance->reply_queue_h); | 2088 | instance->reply_queue, instance->reply_queue_h); |
@@ -2263,6 +2364,28 @@ static int megasas_io_attach(struct megasas_instance *instance) | |||
2263 | return 0; | 2364 | return 0; |
2264 | } | 2365 | } |
2265 | 2366 | ||
2367 | static int | ||
2368 | megasas_set_dma_mask(struct pci_dev *pdev) | ||
2369 | { | ||
2370 | /* | ||
2371 | * All our contollers are capable of performing 64-bit DMA | ||
2372 | */ | ||
2373 | if (IS_DMA64) { | ||
2374 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) { | ||
2375 | |||
2376 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) | ||
2377 | goto fail_set_dma_mask; | ||
2378 | } | ||
2379 | } else { | ||
2380 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) | ||
2381 | goto fail_set_dma_mask; | ||
2382 | } | ||
2383 | return 0; | ||
2384 | |||
2385 | fail_set_dma_mask: | ||
2386 | return 1; | ||
2387 | } | ||
2388 | |||
2266 | /** | 2389 | /** |
2267 | * megasas_probe_one - PCI hotplug entry point | 2390 | * megasas_probe_one - PCI hotplug entry point |
2268 | * @pdev: PCI device structure | 2391 | * @pdev: PCI device structure |
@@ -2296,19 +2419,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2296 | 2419 | ||
2297 | pci_set_master(pdev); | 2420 | pci_set_master(pdev); |
2298 | 2421 | ||
2299 | /* | 2422 | if (megasas_set_dma_mask(pdev)) |
2300 | * All our contollers are capable of performing 64-bit DMA | 2423 | goto fail_set_dma_mask; |
2301 | */ | ||
2302 | if (IS_DMA64) { | ||
2303 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) { | ||
2304 | |||
2305 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) | ||
2306 | goto fail_set_dma_mask; | ||
2307 | } | ||
2308 | } else { | ||
2309 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) | ||
2310 | goto fail_set_dma_mask; | ||
2311 | } | ||
2312 | 2424 | ||
2313 | host = scsi_host_alloc(&megasas_template, | 2425 | host = scsi_host_alloc(&megasas_template, |
2314 | sizeof(struct megasas_instance)); | 2426 | sizeof(struct megasas_instance)); |
@@ -2357,8 +2469,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2357 | init_waitqueue_head(&instance->abort_cmd_wait_q); | 2469 | init_waitqueue_head(&instance->abort_cmd_wait_q); |
2358 | 2470 | ||
2359 | spin_lock_init(&instance->cmd_pool_lock); | 2471 | spin_lock_init(&instance->cmd_pool_lock); |
2472 | spin_lock_init(&instance->completion_lock); | ||
2360 | 2473 | ||
2361 | sema_init(&instance->aen_mutex, 1); | 2474 | mutex_init(&instance->aen_mutex); |
2362 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); | 2475 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); |
2363 | 2476 | ||
2364 | /* | 2477 | /* |
@@ -2490,8 +2603,10 @@ static void megasas_flush_cache(struct megasas_instance *instance) | |||
2490 | /** | 2603 | /** |
2491 | * megasas_shutdown_controller - Instructs FW to shutdown the controller | 2604 | * megasas_shutdown_controller - Instructs FW to shutdown the controller |
2492 | * @instance: Adapter soft state | 2605 | * @instance: Adapter soft state |
2606 | * @opcode: Shutdown/Hibernate | ||
2493 | */ | 2607 | */ |
2494 | static void megasas_shutdown_controller(struct megasas_instance *instance) | 2608 | static void megasas_shutdown_controller(struct megasas_instance *instance, |
2609 | u32 opcode) | ||
2495 | { | 2610 | { |
2496 | struct megasas_cmd *cmd; | 2611 | struct megasas_cmd *cmd; |
2497 | struct megasas_dcmd_frame *dcmd; | 2612 | struct megasas_dcmd_frame *dcmd; |
@@ -2514,7 +2629,7 @@ static void megasas_shutdown_controller(struct megasas_instance *instance) | |||
2514 | dcmd->flags = MFI_FRAME_DIR_NONE; | 2629 | dcmd->flags = MFI_FRAME_DIR_NONE; |
2515 | dcmd->timeout = 0; | 2630 | dcmd->timeout = 0; |
2516 | dcmd->data_xfer_len = 0; | 2631 | dcmd->data_xfer_len = 0; |
2517 | dcmd->opcode = MR_DCMD_CTRL_SHUTDOWN; | 2632 | dcmd->opcode = opcode; |
2518 | 2633 | ||
2519 | megasas_issue_blocked_cmd(instance, cmd); | 2634 | megasas_issue_blocked_cmd(instance, cmd); |
2520 | 2635 | ||
@@ -2524,6 +2639,139 @@ static void megasas_shutdown_controller(struct megasas_instance *instance) | |||
2524 | } | 2639 | } |
2525 | 2640 | ||
2526 | /** | 2641 | /** |
2642 | * megasas_suspend - driver suspend entry point | ||
2643 | * @pdev: PCI device structure | ||
2644 | * @state: PCI power state to suspend routine | ||
2645 | */ | ||
2646 | static int __devinit | ||
2647 | megasas_suspend(struct pci_dev *pdev, pm_message_t state) | ||
2648 | { | ||
2649 | struct Scsi_Host *host; | ||
2650 | struct megasas_instance *instance; | ||
2651 | |||
2652 | instance = pci_get_drvdata(pdev); | ||
2653 | host = instance->host; | ||
2654 | |||
2655 | if (poll_mode_io) | ||
2656 | del_timer_sync(&instance->io_completion_timer); | ||
2657 | |||
2658 | megasas_flush_cache(instance); | ||
2659 | megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); | ||
2660 | tasklet_kill(&instance->isr_tasklet); | ||
2661 | |||
2662 | pci_set_drvdata(instance->pdev, instance); | ||
2663 | instance->instancet->disable_intr(instance->reg_set); | ||
2664 | free_irq(instance->pdev->irq, instance); | ||
2665 | |||
2666 | pci_save_state(pdev); | ||
2667 | pci_disable_device(pdev); | ||
2668 | |||
2669 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
2670 | |||
2671 | return 0; | ||
2672 | } | ||
2673 | |||
2674 | /** | ||
2675 | * megasas_resume- driver resume entry point | ||
2676 | * @pdev: PCI device structure | ||
2677 | */ | ||
2678 | static int __devinit | ||
2679 | megasas_resume(struct pci_dev *pdev) | ||
2680 | { | ||
2681 | int rval; | ||
2682 | struct Scsi_Host *host; | ||
2683 | struct megasas_instance *instance; | ||
2684 | |||
2685 | instance = pci_get_drvdata(pdev); | ||
2686 | host = instance->host; | ||
2687 | pci_set_power_state(pdev, PCI_D0); | ||
2688 | pci_enable_wake(pdev, PCI_D0, 0); | ||
2689 | pci_restore_state(pdev); | ||
2690 | |||
2691 | /* | ||
2692 | * PCI prepping: enable device set bus mastering and dma mask | ||
2693 | */ | ||
2694 | rval = pci_enable_device(pdev); | ||
2695 | |||
2696 | if (rval) { | ||
2697 | printk(KERN_ERR "megasas: Enable device failed\n"); | ||
2698 | return rval; | ||
2699 | } | ||
2700 | |||
2701 | pci_set_master(pdev); | ||
2702 | |||
2703 | if (megasas_set_dma_mask(pdev)) | ||
2704 | goto fail_set_dma_mask; | ||
2705 | |||
2706 | /* | ||
2707 | * Initialize MFI Firmware | ||
2708 | */ | ||
2709 | |||
2710 | *instance->producer = 0; | ||
2711 | *instance->consumer = 0; | ||
2712 | |||
2713 | atomic_set(&instance->fw_outstanding, 0); | ||
2714 | |||
2715 | /* | ||
2716 | * We expect the FW state to be READY | ||
2717 | */ | ||
2718 | if (megasas_transition_to_ready(instance)) | ||
2719 | goto fail_ready_state; | ||
2720 | |||
2721 | if (megasas_issue_init_mfi(instance)) | ||
2722 | goto fail_init_mfi; | ||
2723 | |||
2724 | tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, | ||
2725 | (unsigned long)instance); | ||
2726 | |||
2727 | /* | ||
2728 | * Register IRQ | ||
2729 | */ | ||
2730 | if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, | ||
2731 | "megasas", instance)) { | ||
2732 | printk(KERN_ERR "megasas: Failed to register IRQ\n"); | ||
2733 | goto fail_irq; | ||
2734 | } | ||
2735 | |||
2736 | instance->instancet->enable_intr(instance->reg_set); | ||
2737 | |||
2738 | /* | ||
2739 | * Initiate AEN (Asynchronous Event Notification) | ||
2740 | */ | ||
2741 | if (megasas_start_aen(instance)) | ||
2742 | printk(KERN_ERR "megasas: Start AEN failed\n"); | ||
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); | ||
2749 | return 0; | ||
2750 | |||
2751 | fail_irq: | ||
2752 | fail_init_mfi: | ||
2753 | if (instance->evt_detail) | ||
2754 | pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), | ||
2755 | instance->evt_detail, | ||
2756 | instance->evt_detail_h); | ||
2757 | |||
2758 | if (instance->producer) | ||
2759 | pci_free_consistent(pdev, sizeof(u32), instance->producer, | ||
2760 | instance->producer_h); | ||
2761 | if (instance->consumer) | ||
2762 | pci_free_consistent(pdev, sizeof(u32), instance->consumer, | ||
2763 | instance->consumer_h); | ||
2764 | scsi_host_put(host); | ||
2765 | |||
2766 | fail_set_dma_mask: | ||
2767 | fail_ready_state: | ||
2768 | |||
2769 | pci_disable_device(pdev); | ||
2770 | |||
2771 | return -ENODEV; | ||
2772 | } | ||
2773 | |||
2774 | /** | ||
2527 | * megasas_detach_one - PCI hot"un"plug entry point | 2775 | * megasas_detach_one - PCI hot"un"plug entry point |
2528 | * @pdev: PCI device structure | 2776 | * @pdev: PCI device structure |
2529 | */ | 2777 | */ |
@@ -2536,9 +2784,12 @@ static void megasas_detach_one(struct pci_dev *pdev) | |||
2536 | instance = pci_get_drvdata(pdev); | 2784 | instance = pci_get_drvdata(pdev); |
2537 | host = instance->host; | 2785 | host = instance->host; |
2538 | 2786 | ||
2787 | if (poll_mode_io) | ||
2788 | del_timer_sync(&instance->io_completion_timer); | ||
2789 | |||
2539 | scsi_remove_host(instance->host); | 2790 | scsi_remove_host(instance->host); |
2540 | megasas_flush_cache(instance); | 2791 | megasas_flush_cache(instance); |
2541 | megasas_shutdown_controller(instance); | 2792 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
2542 | tasklet_kill(&instance->isr_tasklet); | 2793 | tasklet_kill(&instance->isr_tasklet); |
2543 | 2794 | ||
2544 | /* | 2795 | /* |
@@ -2660,6 +2911,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
2660 | void *sense = NULL; | 2911 | void *sense = NULL; |
2661 | dma_addr_t sense_handle; | 2912 | dma_addr_t sense_handle; |
2662 | u32 *sense_ptr; | 2913 | u32 *sense_ptr; |
2914 | unsigned long *sense_buff; | ||
2663 | 2915 | ||
2664 | memset(kbuff_arr, 0, sizeof(kbuff_arr)); | 2916 | memset(kbuff_arr, 0, sizeof(kbuff_arr)); |
2665 | 2917 | ||
@@ -2764,14 +3016,16 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
2764 | */ | 3016 | */ |
2765 | if (ioc->sense_len) { | 3017 | if (ioc->sense_len) { |
2766 | /* | 3018 | /* |
2767 | * sense_ptr points to the location that has the user | 3019 | * sense_buff points to the location that has the user |
2768 | * sense buffer address | 3020 | * sense buffer address |
2769 | */ | 3021 | */ |
2770 | sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw + | 3022 | sense_buff = (unsigned long *) ((unsigned long)ioc->frame.raw + |
2771 | ioc->sense_off); | 3023 | ioc->sense_off); |
2772 | 3024 | ||
2773 | if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), | 3025 | if (copy_to_user((void __user *)(unsigned long)(*sense_buff), |
2774 | sense, ioc->sense_len)) { | 3026 | sense, ioc->sense_len)) { |
3027 | printk(KERN_ERR "megasas: Failed to copy out to user " | ||
3028 | "sense data\n"); | ||
2775 | error = -EFAULT; | 3029 | error = -EFAULT; |
2776 | goto out; | 3030 | goto out; |
2777 | } | 3031 | } |
@@ -2874,10 +3128,10 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) | |||
2874 | if (!instance) | 3128 | if (!instance) |
2875 | return -ENODEV; | 3129 | return -ENODEV; |
2876 | 3130 | ||
2877 | down(&instance->aen_mutex); | 3131 | mutex_lock(&instance->aen_mutex); |
2878 | error = megasas_register_aen(instance, aen.seq_num, | 3132 | error = megasas_register_aen(instance, aen.seq_num, |
2879 | aen.class_locale_word); | 3133 | aen.class_locale_word); |
2880 | up(&instance->aen_mutex); | 3134 | mutex_unlock(&instance->aen_mutex); |
2881 | return error; | 3135 | return error; |
2882 | } | 3136 | } |
2883 | 3137 | ||
@@ -2977,6 +3231,8 @@ static struct pci_driver megasas_pci_driver = { | |||
2977 | .id_table = megasas_pci_table, | 3231 | .id_table = megasas_pci_table, |
2978 | .probe = megasas_probe_one, | 3232 | .probe = megasas_probe_one, |
2979 | .remove = __devexit_p(megasas_detach_one), | 3233 | .remove = __devexit_p(megasas_detach_one), |
3234 | .suspend = megasas_suspend, | ||
3235 | .resume = megasas_resume, | ||
2980 | .shutdown = megasas_shutdown, | 3236 | .shutdown = megasas_shutdown, |
2981 | }; | 3237 | }; |
2982 | 3238 | ||
@@ -3004,7 +3260,7 @@ static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, | |||
3004 | static ssize_t | 3260 | static ssize_t |
3005 | megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) | 3261 | megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) |
3006 | { | 3262 | { |
3007 | return sprintf(buf,"%u",megasas_dbg_lvl); | 3263 | return sprintf(buf, "%u\n", megasas_dbg_lvl); |
3008 | } | 3264 | } |
3009 | 3265 | ||
3010 | static ssize_t | 3266 | static ssize_t |
@@ -3019,7 +3275,65 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun | |||
3019 | } | 3275 | } |
3020 | 3276 | ||
3021 | static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl, | 3277 | static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl, |
3022 | megasas_sysfs_set_dbg_lvl); | 3278 | megasas_sysfs_set_dbg_lvl); |
3279 | |||
3280 | static ssize_t | ||
3281 | megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf) | ||
3282 | { | ||
3283 | return sprintf(buf, "%u\n", poll_mode_io); | ||
3284 | } | ||
3285 | |||
3286 | static ssize_t | ||
3287 | megasas_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 | |||
3330 | out: | ||
3331 | return retval; | ||
3332 | } | ||
3333 | |||
3334 | static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO, | ||
3335 | megasas_sysfs_show_poll_mode_io, | ||
3336 | megasas_sysfs_set_poll_mode_io); | ||
3023 | 3337 | ||
3024 | /** | 3338 | /** |
3025 | * megasas_init - Driver load entry point | 3339 | * megasas_init - Driver load entry point |
@@ -3070,8 +3384,16 @@ static int __init megasas_init(void) | |||
3070 | &driver_attr_dbg_lvl); | 3384 | &driver_attr_dbg_lvl); |
3071 | if (rval) | 3385 | if (rval) |
3072 | 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; | ||
3073 | 3391 | ||
3074 | return rval; | 3392 | return rval; |
3393 | |||
3394 | err_dcf_poll_mode_io: | ||
3395 | driver_remove_file(&megasas_pci_driver.driver, | ||
3396 | &driver_attr_dbg_lvl); | ||
3075 | err_dcf_dbg_lvl: | 3397 | err_dcf_dbg_lvl: |
3076 | driver_remove_file(&megasas_pci_driver.driver, | 3398 | driver_remove_file(&megasas_pci_driver.driver, |
3077 | &driver_attr_release_date); | 3399 | &driver_attr_release_date); |
@@ -3090,6 +3412,8 @@ err_pcidrv: | |||
3090 | static void __exit megasas_exit(void) | 3412 | static void __exit megasas_exit(void) |
3091 | { | 3413 | { |
3092 | 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, | ||
3093 | &driver_attr_dbg_lvl); | 3417 | &driver_attr_dbg_lvl); |
3094 | driver_remove_file(&megasas_pci_driver.driver, | 3418 | driver_remove_file(&megasas_pci_driver.driver, |
3095 | &driver_attr_release_date); | 3419 | &driver_attr_release_date); |