diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_si_intf.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 261 |
1 files changed, 147 insertions, 114 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 7bd7c45b53ef..9397ab49b72e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/moduleparam.h> | 43 | #include <linux/moduleparam.h> |
44 | #include <asm/system.h> | 44 | #include <asm/system.h> |
45 | #include <linux/sched.h> | 45 | #include <linux/sched.h> |
46 | #include <linux/seq_file.h> | ||
46 | #include <linux/timer.h> | 47 | #include <linux/timer.h> |
47 | #include <linux/errno.h> | 48 | #include <linux/errno.h> |
48 | #include <linux/spinlock.h> | 49 | #include <linux/spinlock.h> |
@@ -57,6 +58,7 @@ | |||
57 | #include <asm/irq.h> | 58 | #include <asm/irq.h> |
58 | #include <linux/interrupt.h> | 59 | #include <linux/interrupt.h> |
59 | #include <linux/rcupdate.h> | 60 | #include <linux/rcupdate.h> |
61 | #include <linux/ipmi.h> | ||
60 | #include <linux/ipmi_smi.h> | 62 | #include <linux/ipmi_smi.h> |
61 | #include <asm/io.h> | 63 | #include <asm/io.h> |
62 | #include "ipmi_si_sm.h" | 64 | #include "ipmi_si_sm.h" |
@@ -65,11 +67,10 @@ | |||
65 | #include <linux/string.h> | 67 | #include <linux/string.h> |
66 | #include <linux/ctype.h> | 68 | #include <linux/ctype.h> |
67 | #include <linux/pnp.h> | 69 | #include <linux/pnp.h> |
68 | |||
69 | #ifdef CONFIG_PPC_OF | ||
70 | #include <linux/of_device.h> | 70 | #include <linux/of_device.h> |
71 | #include <linux/of_platform.h> | 71 | #include <linux/of_platform.h> |
72 | #endif | 72 | #include <linux/of_address.h> |
73 | #include <linux/of_irq.h> | ||
73 | 74 | ||
74 | #define PFX "ipmi_si: " | 75 | #define PFX "ipmi_si: " |
75 | 76 | ||
@@ -107,23 +108,13 @@ enum si_type { | |||
107 | }; | 108 | }; |
108 | static char *si_to_str[] = { "kcs", "smic", "bt" }; | 109 | static char *si_to_str[] = { "kcs", "smic", "bt" }; |
109 | 110 | ||
110 | enum ipmi_addr_src { | ||
111 | SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS, | ||
112 | SI_PCI, SI_DEVICETREE, SI_DEFAULT | ||
113 | }; | ||
114 | static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI", | 111 | static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI", |
115 | "ACPI", "SMBIOS", "PCI", | 112 | "ACPI", "SMBIOS", "PCI", |
116 | "device-tree", "default" }; | 113 | "device-tree", "default" }; |
117 | 114 | ||
118 | #define DEVICE_NAME "ipmi_si" | 115 | #define DEVICE_NAME "ipmi_si" |
119 | 116 | ||
120 | static struct platform_driver ipmi_driver = { | 117 | static struct platform_driver ipmi_driver; |
121 | .driver = { | ||
122 | .name = DEVICE_NAME, | ||
123 | .bus = &platform_bus_type | ||
124 | } | ||
125 | }; | ||
126 | |||
127 | 118 | ||
128 | /* | 119 | /* |
129 | * Indexes into stats[] in smi_info below. | 120 | * Indexes into stats[] in smi_info below. |
@@ -291,6 +282,7 @@ struct smi_info { | |||
291 | struct task_struct *thread; | 282 | struct task_struct *thread; |
292 | 283 | ||
293 | struct list_head link; | 284 | struct list_head link; |
285 | union ipmi_smi_info_union addr_info; | ||
294 | }; | 286 | }; |
295 | 287 | ||
296 | #define smi_inc_stat(smi, stat) \ | 288 | #define smi_inc_stat(smi, stat) \ |
@@ -308,9 +300,6 @@ static int pci_registered; | |||
308 | #ifdef CONFIG_ACPI | 300 | #ifdef CONFIG_ACPI |
309 | static int pnp_registered; | 301 | static int pnp_registered; |
310 | #endif | 302 | #endif |
311 | #ifdef CONFIG_PPC_OF | ||
312 | static int of_registered; | ||
313 | #endif | ||
314 | 303 | ||
315 | static unsigned int kipmid_max_busy_us[SI_MAX_PARMS]; | 304 | static unsigned int kipmid_max_busy_us[SI_MAX_PARMS]; |
316 | static int num_max_busy_us; | 305 | static int num_max_busy_us; |
@@ -320,6 +309,7 @@ static int unload_when_empty = 1; | |||
320 | static int add_smi(struct smi_info *smi); | 309 | static int add_smi(struct smi_info *smi); |
321 | static int try_smi_init(struct smi_info *smi); | 310 | static int try_smi_init(struct smi_info *smi); |
322 | static void cleanup_one_si(struct smi_info *to_clean); | 311 | static void cleanup_one_si(struct smi_info *to_clean); |
312 | static void cleanup_ipmi_si(void); | ||
323 | 313 | ||
324 | static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); | 314 | static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); |
325 | static int register_xaction_notifier(struct notifier_block *nb) | 315 | static int register_xaction_notifier(struct notifier_block *nb) |
@@ -350,7 +340,7 @@ static void return_hosed_msg(struct smi_info *smi_info, int cCode) | |||
350 | cCode = IPMI_ERR_UNSPECIFIED; | 340 | cCode = IPMI_ERR_UNSPECIFIED; |
351 | /* else use it as is */ | 341 | /* else use it as is */ |
352 | 342 | ||
353 | /* Make it a reponse */ | 343 | /* Make it a response */ |
354 | msg->rsp[0] = msg->data[0] | 4; | 344 | msg->rsp[0] = msg->data[0] | 4; |
355 | msg->rsp[1] = msg->data[1]; | 345 | msg->rsp[1] = msg->data[1]; |
356 | msg->rsp[2] = cCode; | 346 | msg->rsp[2] = cCode; |
@@ -899,6 +889,14 @@ static void sender(void *send_info, | |||
899 | printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); | 889 | printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); |
900 | #endif | 890 | #endif |
901 | 891 | ||
892 | /* | ||
893 | * last_timeout_jiffies is updated here to avoid | ||
894 | * smi_timeout() handler passing very large time_diff | ||
895 | * value to smi_event_handler() that causes | ||
896 | * the send command to abort. | ||
897 | */ | ||
898 | smi_info->last_timeout_jiffies = jiffies; | ||
899 | |||
902 | mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); | 900 | mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); |
903 | 901 | ||
904 | if (smi_info->thread) | 902 | if (smi_info->thread) |
@@ -1186,6 +1184,18 @@ static int smi_start_processing(void *send_info, | |||
1186 | return 0; | 1184 | return 0; |
1187 | } | 1185 | } |
1188 | 1186 | ||
1187 | static int get_smi_info(void *send_info, struct ipmi_smi_info *data) | ||
1188 | { | ||
1189 | struct smi_info *smi = send_info; | ||
1190 | |||
1191 | data->addr_src = smi->addr_source; | ||
1192 | data->dev = smi->dev; | ||
1193 | data->addr_info = smi->addr_info; | ||
1194 | get_device(smi->dev); | ||
1195 | |||
1196 | return 0; | ||
1197 | } | ||
1198 | |||
1189 | static void set_maintenance_mode(void *send_info, int enable) | 1199 | static void set_maintenance_mode(void *send_info, int enable) |
1190 | { | 1200 | { |
1191 | struct smi_info *smi_info = send_info; | 1201 | struct smi_info *smi_info = send_info; |
@@ -1197,6 +1207,7 @@ static void set_maintenance_mode(void *send_info, int enable) | |||
1197 | static struct ipmi_smi_handlers handlers = { | 1207 | static struct ipmi_smi_handlers handlers = { |
1198 | .owner = THIS_MODULE, | 1208 | .owner = THIS_MODULE, |
1199 | .start_processing = smi_start_processing, | 1209 | .start_processing = smi_start_processing, |
1210 | .get_smi_info = get_smi_info, | ||
1200 | .sender = sender, | 1211 | .sender = sender, |
1201 | .request_events = request_events, | 1212 | .request_events = request_events, |
1202 | .set_maintenance_mode = set_maintenance_mode, | 1213 | .set_maintenance_mode = set_maintenance_mode, |
@@ -1665,6 +1676,17 @@ static int check_hotmod_int_op(const char *curr, const char *option, | |||
1665 | return 0; | 1676 | return 0; |
1666 | } | 1677 | } |
1667 | 1678 | ||
1679 | static struct smi_info *smi_info_alloc(void) | ||
1680 | { | ||
1681 | struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
1682 | |||
1683 | if (info) { | ||
1684 | spin_lock_init(&info->si_lock); | ||
1685 | spin_lock_init(&info->msg_lock); | ||
1686 | } | ||
1687 | return info; | ||
1688 | } | ||
1689 | |||
1668 | static int hotmod_handler(const char *val, struct kernel_param *kp) | 1690 | static int hotmod_handler(const char *val, struct kernel_param *kp) |
1669 | { | 1691 | { |
1670 | char *str = kstrdup(val, GFP_KERNEL); | 1692 | char *str = kstrdup(val, GFP_KERNEL); |
@@ -1779,7 +1801,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1779 | } | 1801 | } |
1780 | 1802 | ||
1781 | if (op == HM_ADD) { | 1803 | if (op == HM_ADD) { |
1782 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1804 | info = smi_info_alloc(); |
1783 | if (!info) { | 1805 | if (!info) { |
1784 | rv = -ENOMEM; | 1806 | rv = -ENOMEM; |
1785 | goto out; | 1807 | goto out; |
@@ -1835,8 +1857,9 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1835 | return rv; | 1857 | return rv; |
1836 | } | 1858 | } |
1837 | 1859 | ||
1838 | static __devinit void hardcode_find_bmc(void) | 1860 | static int __devinit hardcode_find_bmc(void) |
1839 | { | 1861 | { |
1862 | int ret = -ENODEV; | ||
1840 | int i; | 1863 | int i; |
1841 | struct smi_info *info; | 1864 | struct smi_info *info; |
1842 | 1865 | ||
@@ -1844,9 +1867,9 @@ static __devinit void hardcode_find_bmc(void) | |||
1844 | if (!ports[i] && !addrs[i]) | 1867 | if (!ports[i] && !addrs[i]) |
1845 | continue; | 1868 | continue; |
1846 | 1869 | ||
1847 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1870 | info = smi_info_alloc(); |
1848 | if (!info) | 1871 | if (!info) |
1849 | return; | 1872 | return -ENOMEM; |
1850 | 1873 | ||
1851 | info->addr_source = SI_HARDCODED; | 1874 | info->addr_source = SI_HARDCODED; |
1852 | printk(KERN_INFO PFX "probing via hardcoded address\n"); | 1875 | printk(KERN_INFO PFX "probing via hardcoded address\n"); |
@@ -1899,10 +1922,12 @@ static __devinit void hardcode_find_bmc(void) | |||
1899 | if (!add_smi(info)) { | 1922 | if (!add_smi(info)) { |
1900 | if (try_smi_init(info)) | 1923 | if (try_smi_init(info)) |
1901 | cleanup_one_si(info); | 1924 | cleanup_one_si(info); |
1925 | ret = 0; | ||
1902 | } else { | 1926 | } else { |
1903 | kfree(info); | 1927 | kfree(info); |
1904 | } | 1928 | } |
1905 | } | 1929 | } |
1930 | return ret; | ||
1906 | } | 1931 | } |
1907 | 1932 | ||
1908 | #ifdef CONFIG_ACPI | 1933 | #ifdef CONFIG_ACPI |
@@ -1917,7 +1942,8 @@ static __devinit void hardcode_find_bmc(void) | |||
1917 | static int acpi_failure; | 1942 | static int acpi_failure; |
1918 | 1943 | ||
1919 | /* For GPE-type interrupts. */ | 1944 | /* For GPE-type interrupts. */ |
1920 | static u32 ipmi_acpi_gpe(void *context) | 1945 | static u32 ipmi_acpi_gpe(acpi_handle gpe_device, |
1946 | u32 gpe_number, void *context) | ||
1921 | { | 1947 | { |
1922 | struct smi_info *smi_info = context; | 1948 | struct smi_info *smi_info = context; |
1923 | unsigned long flags; | 1949 | unsigned long flags; |
@@ -1974,8 +2000,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1974 | 2000 | ||
1975 | /* | 2001 | /* |
1976 | * Defined at | 2002 | * Defined at |
1977 | * http://h21007.www2.hp.com/portal/download/files | 2003 | * http://h21007.www2.hp.com/portal/download/files/unprot/hpspmi.pdf |
1978 | * /unprot/hpspmi.pdf | ||
1979 | */ | 2004 | */ |
1980 | struct SPMITable { | 2005 | struct SPMITable { |
1981 | s8 Signature[4]; | 2006 | s8 Signature[4]; |
@@ -2019,7 +2044,7 @@ struct SPMITable { | |||
2019 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ | 2044 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ |
2020 | }; | 2045 | }; |
2021 | 2046 | ||
2022 | static __devinit int try_init_spmi(struct SPMITable *spmi) | 2047 | static int __devinit try_init_spmi(struct SPMITable *spmi) |
2023 | { | 2048 | { |
2024 | struct smi_info *info; | 2049 | struct smi_info *info; |
2025 | 2050 | ||
@@ -2028,7 +2053,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
2028 | return -ENODEV; | 2053 | return -ENODEV; |
2029 | } | 2054 | } |
2030 | 2055 | ||
2031 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2056 | info = smi_info_alloc(); |
2032 | if (!info) { | 2057 | if (!info) { |
2033 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); | 2058 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); |
2034 | return -ENOMEM; | 2059 | return -ENOMEM; |
@@ -2102,7 +2127,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
2102 | return 0; | 2127 | return 0; |
2103 | } | 2128 | } |
2104 | 2129 | ||
2105 | static __devinit void spmi_find_bmc(void) | 2130 | static void __devinit spmi_find_bmc(void) |
2106 | { | 2131 | { |
2107 | acpi_status status; | 2132 | acpi_status status; |
2108 | struct SPMITable *spmi; | 2133 | struct SPMITable *spmi; |
@@ -2138,7 +2163,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2138 | if (!acpi_dev) | 2163 | if (!acpi_dev) |
2139 | return -ENODEV; | 2164 | return -ENODEV; |
2140 | 2165 | ||
2141 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2166 | info = smi_info_alloc(); |
2142 | if (!info) | 2167 | if (!info) |
2143 | return -ENOMEM; | 2168 | return -ENOMEM; |
2144 | 2169 | ||
@@ -2146,6 +2171,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2146 | printk(KERN_INFO PFX "probing via ACPI\n"); | 2171 | printk(KERN_INFO PFX "probing via ACPI\n"); |
2147 | 2172 | ||
2148 | handle = acpi_dev->handle; | 2173 | handle = acpi_dev->handle; |
2174 | info->addr_info.acpi_info.acpi_handle = handle; | ||
2149 | 2175 | ||
2150 | /* _IFT tells us the interface type: KCS, BT, etc */ | 2176 | /* _IFT tells us the interface type: KCS, BT, etc */ |
2151 | status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp); | 2177 | status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp); |
@@ -2315,11 +2341,11 @@ static int __devinit decode_dmi(const struct dmi_header *dm, | |||
2315 | return 0; | 2341 | return 0; |
2316 | } | 2342 | } |
2317 | 2343 | ||
2318 | static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | 2344 | static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data) |
2319 | { | 2345 | { |
2320 | struct smi_info *info; | 2346 | struct smi_info *info; |
2321 | 2347 | ||
2322 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2348 | info = smi_info_alloc(); |
2323 | if (!info) { | 2349 | if (!info) { |
2324 | printk(KERN_ERR PFX "Could not allocate SI data\n"); | 2350 | printk(KERN_ERR PFX "Could not allocate SI data\n"); |
2325 | return; | 2351 | return; |
@@ -2426,7 +2452,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2426 | int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; | 2452 | int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; |
2427 | struct smi_info *info; | 2453 | struct smi_info *info; |
2428 | 2454 | ||
2429 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2455 | info = smi_info_alloc(); |
2430 | if (!info) | 2456 | if (!info) |
2431 | return -ENOMEM; | 2457 | return -ENOMEM; |
2432 | 2458 | ||
@@ -2529,20 +2555,24 @@ static struct pci_driver ipmi_pci_driver = { | |||
2529 | }; | 2555 | }; |
2530 | #endif /* CONFIG_PCI */ | 2556 | #endif /* CONFIG_PCI */ |
2531 | 2557 | ||
2532 | 2558 | static struct of_device_id ipmi_match[]; | |
2533 | #ifdef CONFIG_PPC_OF | 2559 | static int __devinit ipmi_probe(struct platform_device *dev) |
2534 | static int __devinit ipmi_of_probe(struct platform_device *dev, | ||
2535 | const struct of_device_id *match) | ||
2536 | { | 2560 | { |
2561 | #ifdef CONFIG_OF | ||
2562 | const struct of_device_id *match; | ||
2537 | struct smi_info *info; | 2563 | struct smi_info *info; |
2538 | struct resource resource; | 2564 | struct resource resource; |
2539 | const int *regsize, *regspacing, *regshift; | 2565 | const __be32 *regsize, *regspacing, *regshift; |
2540 | struct device_node *np = dev->dev.of_node; | 2566 | struct device_node *np = dev->dev.of_node; |
2541 | int ret; | 2567 | int ret; |
2542 | int proplen; | 2568 | int proplen; |
2543 | 2569 | ||
2544 | dev_info(&dev->dev, "probing via device tree\n"); | 2570 | dev_info(&dev->dev, "probing via device tree\n"); |
2545 | 2571 | ||
2572 | match = of_match_device(ipmi_match, &dev->dev); | ||
2573 | if (!match) | ||
2574 | return -EINVAL; | ||
2575 | |||
2546 | ret = of_address_to_resource(np, 0, &resource); | 2576 | ret = of_address_to_resource(np, 0, &resource); |
2547 | if (ret) { | 2577 | if (ret) { |
2548 | dev_warn(&dev->dev, PFX "invalid address from OF\n"); | 2578 | dev_warn(&dev->dev, PFX "invalid address from OF\n"); |
@@ -2567,7 +2597,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev, | |||
2567 | return -EINVAL; | 2597 | return -EINVAL; |
2568 | } | 2598 | } |
2569 | 2599 | ||
2570 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2600 | info = smi_info_alloc(); |
2571 | 2601 | ||
2572 | if (!info) { | 2602 | if (!info) { |
2573 | dev_err(&dev->dev, | 2603 | dev_err(&dev->dev, |
@@ -2589,9 +2619,9 @@ static int __devinit ipmi_of_probe(struct platform_device *dev, | |||
2589 | 2619 | ||
2590 | info->io.addr_data = resource.start; | 2620 | info->io.addr_data = resource.start; |
2591 | 2621 | ||
2592 | info->io.regsize = regsize ? *regsize : DEFAULT_REGSIZE; | 2622 | info->io.regsize = regsize ? be32_to_cpup(regsize) : DEFAULT_REGSIZE; |
2593 | info->io.regspacing = regspacing ? *regspacing : DEFAULT_REGSPACING; | 2623 | info->io.regspacing = regspacing ? be32_to_cpup(regspacing) : DEFAULT_REGSPACING; |
2594 | info->io.regshift = regshift ? *regshift : 0; | 2624 | info->io.regshift = regshift ? be32_to_cpup(regshift) : 0; |
2595 | 2625 | ||
2596 | info->irq = irq_of_parse_and_map(dev->dev.of_node, 0); | 2626 | info->irq = irq_of_parse_and_map(dev->dev.of_node, 0); |
2597 | info->dev = &dev->dev; | 2627 | info->dev = &dev->dev; |
@@ -2606,13 +2636,15 @@ static int __devinit ipmi_of_probe(struct platform_device *dev, | |||
2606 | kfree(info); | 2636 | kfree(info); |
2607 | return -EBUSY; | 2637 | return -EBUSY; |
2608 | } | 2638 | } |
2609 | 2639 | #endif | |
2610 | return 0; | 2640 | return 0; |
2611 | } | 2641 | } |
2612 | 2642 | ||
2613 | static int __devexit ipmi_of_remove(struct platform_device *dev) | 2643 | static int __devexit ipmi_remove(struct platform_device *dev) |
2614 | { | 2644 | { |
2645 | #ifdef CONFIG_OF | ||
2615 | cleanup_one_si(dev_get_drvdata(&dev->dev)); | 2646 | cleanup_one_si(dev_get_drvdata(&dev->dev)); |
2647 | #endif | ||
2616 | return 0; | 2648 | return 0; |
2617 | } | 2649 | } |
2618 | 2650 | ||
@@ -2627,16 +2659,15 @@ static struct of_device_id ipmi_match[] = | |||
2627 | {}, | 2659 | {}, |
2628 | }; | 2660 | }; |
2629 | 2661 | ||
2630 | static struct of_platform_driver ipmi_of_platform_driver = { | 2662 | static struct platform_driver ipmi_driver = { |
2631 | .driver = { | 2663 | .driver = { |
2632 | .name = "ipmi", | 2664 | .name = DEVICE_NAME, |
2633 | .owner = THIS_MODULE, | 2665 | .owner = THIS_MODULE, |
2634 | .of_match_table = ipmi_match, | 2666 | .of_match_table = ipmi_match, |
2635 | }, | 2667 | }, |
2636 | .probe = ipmi_of_probe, | 2668 | .probe = ipmi_probe, |
2637 | .remove = __devexit_p(ipmi_of_remove), | 2669 | .remove = __devexit_p(ipmi_remove), |
2638 | }; | 2670 | }; |
2639 | #endif /* CONFIG_PPC_OF */ | ||
2640 | 2671 | ||
2641 | static int wait_for_msg_done(struct smi_info *smi_info) | 2672 | static int wait_for_msg_done(struct smi_info *smi_info) |
2642 | { | 2673 | { |
@@ -2775,54 +2806,73 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2775 | return rv; | 2806 | return rv; |
2776 | } | 2807 | } |
2777 | 2808 | ||
2778 | static int type_file_read_proc(char *page, char **start, off_t off, | 2809 | static int smi_type_proc_show(struct seq_file *m, void *v) |
2779 | int count, int *eof, void *data) | ||
2780 | { | 2810 | { |
2781 | struct smi_info *smi = data; | 2811 | struct smi_info *smi = m->private; |
2812 | |||
2813 | return seq_printf(m, "%s\n", si_to_str[smi->si_type]); | ||
2814 | } | ||
2782 | 2815 | ||
2783 | return sprintf(page, "%s\n", si_to_str[smi->si_type]); | 2816 | static int smi_type_proc_open(struct inode *inode, struct file *file) |
2817 | { | ||
2818 | return single_open(file, smi_type_proc_show, PDE(inode)->data); | ||
2784 | } | 2819 | } |
2785 | 2820 | ||
2786 | static int stat_file_read_proc(char *page, char **start, off_t off, | 2821 | static const struct file_operations smi_type_proc_ops = { |
2787 | int count, int *eof, void *data) | 2822 | .open = smi_type_proc_open, |
2823 | .read = seq_read, | ||
2824 | .llseek = seq_lseek, | ||
2825 | .release = single_release, | ||
2826 | }; | ||
2827 | |||
2828 | static int smi_si_stats_proc_show(struct seq_file *m, void *v) | ||
2788 | { | 2829 | { |
2789 | char *out = (char *) page; | 2830 | struct smi_info *smi = m->private; |
2790 | struct smi_info *smi = data; | ||
2791 | 2831 | ||
2792 | out += sprintf(out, "interrupts_enabled: %d\n", | 2832 | seq_printf(m, "interrupts_enabled: %d\n", |
2793 | smi->irq && !smi->interrupt_disabled); | 2833 | smi->irq && !smi->interrupt_disabled); |
2794 | out += sprintf(out, "short_timeouts: %u\n", | 2834 | seq_printf(m, "short_timeouts: %u\n", |
2795 | smi_get_stat(smi, short_timeouts)); | 2835 | smi_get_stat(smi, short_timeouts)); |
2796 | out += sprintf(out, "long_timeouts: %u\n", | 2836 | seq_printf(m, "long_timeouts: %u\n", |
2797 | smi_get_stat(smi, long_timeouts)); | 2837 | smi_get_stat(smi, long_timeouts)); |
2798 | out += sprintf(out, "idles: %u\n", | 2838 | seq_printf(m, "idles: %u\n", |
2799 | smi_get_stat(smi, idles)); | 2839 | smi_get_stat(smi, idles)); |
2800 | out += sprintf(out, "interrupts: %u\n", | 2840 | seq_printf(m, "interrupts: %u\n", |
2801 | smi_get_stat(smi, interrupts)); | 2841 | smi_get_stat(smi, interrupts)); |
2802 | out += sprintf(out, "attentions: %u\n", | 2842 | seq_printf(m, "attentions: %u\n", |
2803 | smi_get_stat(smi, attentions)); | 2843 | smi_get_stat(smi, attentions)); |
2804 | out += sprintf(out, "flag_fetches: %u\n", | 2844 | seq_printf(m, "flag_fetches: %u\n", |
2805 | smi_get_stat(smi, flag_fetches)); | 2845 | smi_get_stat(smi, flag_fetches)); |
2806 | out += sprintf(out, "hosed_count: %u\n", | 2846 | seq_printf(m, "hosed_count: %u\n", |
2807 | smi_get_stat(smi, hosed_count)); | 2847 | smi_get_stat(smi, hosed_count)); |
2808 | out += sprintf(out, "complete_transactions: %u\n", | 2848 | seq_printf(m, "complete_transactions: %u\n", |
2809 | smi_get_stat(smi, complete_transactions)); | 2849 | smi_get_stat(smi, complete_transactions)); |
2810 | out += sprintf(out, "events: %u\n", | 2850 | seq_printf(m, "events: %u\n", |
2811 | smi_get_stat(smi, events)); | 2851 | smi_get_stat(smi, events)); |
2812 | out += sprintf(out, "watchdog_pretimeouts: %u\n", | 2852 | seq_printf(m, "watchdog_pretimeouts: %u\n", |
2813 | smi_get_stat(smi, watchdog_pretimeouts)); | 2853 | smi_get_stat(smi, watchdog_pretimeouts)); |
2814 | out += sprintf(out, "incoming_messages: %u\n", | 2854 | seq_printf(m, "incoming_messages: %u\n", |
2815 | smi_get_stat(smi, incoming_messages)); | 2855 | smi_get_stat(smi, incoming_messages)); |
2856 | return 0; | ||
2857 | } | ||
2816 | 2858 | ||
2817 | return out - page; | 2859 | static int smi_si_stats_proc_open(struct inode *inode, struct file *file) |
2860 | { | ||
2861 | return single_open(file, smi_si_stats_proc_show, PDE(inode)->data); | ||
2818 | } | 2862 | } |
2819 | 2863 | ||
2820 | static int param_read_proc(char *page, char **start, off_t off, | 2864 | static const struct file_operations smi_si_stats_proc_ops = { |
2821 | int count, int *eof, void *data) | 2865 | .open = smi_si_stats_proc_open, |
2866 | .read = seq_read, | ||
2867 | .llseek = seq_lseek, | ||
2868 | .release = single_release, | ||
2869 | }; | ||
2870 | |||
2871 | static int smi_params_proc_show(struct seq_file *m, void *v) | ||
2822 | { | 2872 | { |
2823 | struct smi_info *smi = data; | 2873 | struct smi_info *smi = m->private; |
2824 | 2874 | ||
2825 | return sprintf(page, | 2875 | return seq_printf(m, |
2826 | "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n", | 2876 | "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n", |
2827 | si_to_str[smi->si_type], | 2877 | si_to_str[smi->si_type], |
2828 | addr_space_to_str[smi->io.addr_type], | 2878 | addr_space_to_str[smi->io.addr_type], |
@@ -2834,6 +2884,18 @@ static int param_read_proc(char *page, char **start, off_t off, | |||
2834 | smi->slave_addr); | 2884 | smi->slave_addr); |
2835 | } | 2885 | } |
2836 | 2886 | ||
2887 | static int smi_params_proc_open(struct inode *inode, struct file *file) | ||
2888 | { | ||
2889 | return single_open(file, smi_params_proc_show, PDE(inode)->data); | ||
2890 | } | ||
2891 | |||
2892 | static const struct file_operations smi_params_proc_ops = { | ||
2893 | .open = smi_params_proc_open, | ||
2894 | .read = seq_read, | ||
2895 | .llseek = seq_lseek, | ||
2896 | .release = single_release, | ||
2897 | }; | ||
2898 | |||
2837 | /* | 2899 | /* |
2838 | * oem_data_avail_to_receive_msg_avail | 2900 | * oem_data_avail_to_receive_msg_avail |
2839 | * @info - smi_info structure with msg_flags set | 2901 | * @info - smi_info structure with msg_flags set |
@@ -2900,7 +2962,7 @@ static void return_hosed_msg_badsize(struct smi_info *smi_info) | |||
2900 | { | 2962 | { |
2901 | struct ipmi_smi_msg *msg = smi_info->curr_msg; | 2963 | struct ipmi_smi_msg *msg = smi_info->curr_msg; |
2902 | 2964 | ||
2903 | /* Make it a reponse */ | 2965 | /* Make it a response */ |
2904 | msg->rsp[0] = msg->data[0] | 4; | 2966 | msg->rsp[0] = msg->data[0] | 4; |
2905 | msg->rsp[1] = msg->data[1]; | 2967 | msg->rsp[1] = msg->data[1]; |
2906 | msg->rsp[2] = CANNOT_RETURN_REQUESTED_LENGTH; | 2968 | msg->rsp[2] = CANNOT_RETURN_REQUESTED_LENGTH; |
@@ -3002,7 +3064,7 @@ static __devinitdata struct ipmi_default_vals | |||
3002 | { .port = 0 } | 3064 | { .port = 0 } |
3003 | }; | 3065 | }; |
3004 | 3066 | ||
3005 | static __devinit void default_find_bmc(void) | 3067 | static void __devinit default_find_bmc(void) |
3006 | { | 3068 | { |
3007 | struct smi_info *info; | 3069 | struct smi_info *info; |
3008 | int i; | 3070 | int i; |
@@ -3014,7 +3076,7 @@ static __devinit void default_find_bmc(void) | |||
3014 | if (check_legacy_ioport(ipmi_defaults[i].port)) | 3076 | if (check_legacy_ioport(ipmi_defaults[i].port)) |
3015 | continue; | 3077 | continue; |
3016 | #endif | 3078 | #endif |
3017 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 3079 | info = smi_info_alloc(); |
3018 | if (!info) | 3080 | if (!info) |
3019 | return; | 3081 | return; |
3020 | 3082 | ||
@@ -3139,9 +3201,6 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3139 | goto out_err; | 3201 | goto out_err; |
3140 | } | 3202 | } |
3141 | 3203 | ||
3142 | spin_lock_init(&(new_smi->si_lock)); | ||
3143 | spin_lock_init(&(new_smi->msg_lock)); | ||
3144 | |||
3145 | /* Do low-level detection first. */ | 3204 | /* Do low-level detection first. */ |
3146 | if (new_smi->handlers->detect(new_smi->si_sm)) { | 3205 | if (new_smi->handlers->detect(new_smi->si_sm)) { |
3147 | if (new_smi->addr_source) | 3206 | if (new_smi->addr_source) |
@@ -3230,7 +3289,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3230 | } | 3289 | } |
3231 | 3290 | ||
3232 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", | 3291 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", |
3233 | type_file_read_proc, | 3292 | &smi_type_proc_ops, |
3234 | new_smi); | 3293 | new_smi); |
3235 | if (rv) { | 3294 | if (rv) { |
3236 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); | 3295 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
@@ -3238,7 +3297,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3238 | } | 3297 | } |
3239 | 3298 | ||
3240 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", | 3299 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", |
3241 | stat_file_read_proc, | 3300 | &smi_si_stats_proc_ops, |
3242 | new_smi); | 3301 | new_smi); |
3243 | if (rv) { | 3302 | if (rv) { |
3244 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); | 3303 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
@@ -3246,7 +3305,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3246 | } | 3305 | } |
3247 | 3306 | ||
3248 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", | 3307 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", |
3249 | param_read_proc, | 3308 | &smi_params_proc_ops, |
3250 | new_smi); | 3309 | new_smi); |
3251 | if (rv) { | 3310 | if (rv) { |
3252 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); | 3311 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
@@ -3305,7 +3364,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3305 | return rv; | 3364 | return rv; |
3306 | } | 3365 | } |
3307 | 3366 | ||
3308 | static __devinit int init_ipmi_si(void) | 3367 | static int __devinit init_ipmi_si(void) |
3309 | { | 3368 | { |
3310 | int i; | 3369 | int i; |
3311 | char *str; | 3370 | char *str; |
@@ -3317,8 +3376,7 @@ static __devinit int init_ipmi_si(void) | |||
3317 | return 0; | 3376 | return 0; |
3318 | initialized = 1; | 3377 | initialized = 1; |
3319 | 3378 | ||
3320 | /* Register the device drivers. */ | 3379 | rv = platform_driver_register(&ipmi_driver); |
3321 | rv = driver_register(&ipmi_driver.driver); | ||
3322 | if (rv) { | 3380 | if (rv) { |
3323 | printk(KERN_ERR PFX "Unable to register driver: %d\n", rv); | 3381 | printk(KERN_ERR PFX "Unable to register driver: %d\n", rv); |
3324 | return rv; | 3382 | return rv; |
@@ -3342,15 +3400,9 @@ static __devinit int init_ipmi_si(void) | |||
3342 | 3400 | ||
3343 | printk(KERN_INFO "IPMI System Interface driver.\n"); | 3401 | printk(KERN_INFO "IPMI System Interface driver.\n"); |
3344 | 3402 | ||
3345 | hardcode_find_bmc(); | ||
3346 | |||
3347 | /* If the user gave us a device, they presumably want us to use it */ | 3403 | /* If the user gave us a device, they presumably want us to use it */ |
3348 | mutex_lock(&smi_infos_lock); | 3404 | if (!hardcode_find_bmc()) |
3349 | if (!list_empty(&smi_infos)) { | ||
3350 | mutex_unlock(&smi_infos_lock); | ||
3351 | return 0; | 3405 | return 0; |
3352 | } | ||
3353 | mutex_unlock(&smi_infos_lock); | ||
3354 | 3406 | ||
3355 | #ifdef CONFIG_PCI | 3407 | #ifdef CONFIG_PCI |
3356 | rv = pci_register_driver(&ipmi_pci_driver); | 3408 | rv = pci_register_driver(&ipmi_pci_driver); |
@@ -3373,11 +3425,6 @@ static __devinit int init_ipmi_si(void) | |||
3373 | spmi_find_bmc(); | 3425 | spmi_find_bmc(); |
3374 | #endif | 3426 | #endif |
3375 | 3427 | ||
3376 | #ifdef CONFIG_PPC_OF | ||
3377 | of_register_platform_driver(&ipmi_of_platform_driver); | ||
3378 | of_registered = 1; | ||
3379 | #endif | ||
3380 | |||
3381 | /* We prefer devices with interrupts, but in the case of a machine | 3428 | /* We prefer devices with interrupts, but in the case of a machine |
3382 | with multiple BMCs we assume that there will be several instances | 3429 | with multiple BMCs we assume that there will be several instances |
3383 | of a given type so if we succeed in registering a type then also | 3430 | of a given type so if we succeed in registering a type then also |
@@ -3428,16 +3475,7 @@ static __devinit int init_ipmi_si(void) | |||
3428 | mutex_lock(&smi_infos_lock); | 3475 | mutex_lock(&smi_infos_lock); |
3429 | if (unload_when_empty && list_empty(&smi_infos)) { | 3476 | if (unload_when_empty && list_empty(&smi_infos)) { |
3430 | mutex_unlock(&smi_infos_lock); | 3477 | mutex_unlock(&smi_infos_lock); |
3431 | #ifdef CONFIG_PCI | 3478 | cleanup_ipmi_si(); |
3432 | if (pci_registered) | ||
3433 | pci_unregister_driver(&ipmi_pci_driver); | ||
3434 | #endif | ||
3435 | |||
3436 | #ifdef CONFIG_PPC_OF | ||
3437 | if (of_registered) | ||
3438 | of_unregister_platform_driver(&ipmi_of_platform_driver); | ||
3439 | #endif | ||
3440 | driver_unregister(&ipmi_driver.driver); | ||
3441 | printk(KERN_WARNING PFX | 3479 | printk(KERN_WARNING PFX |
3442 | "Unable to find any System Interface(s)\n"); | 3480 | "Unable to find any System Interface(s)\n"); |
3443 | return -ENODEV; | 3481 | return -ENODEV; |
@@ -3518,7 +3556,7 @@ static void cleanup_one_si(struct smi_info *to_clean) | |||
3518 | kfree(to_clean); | 3556 | kfree(to_clean); |
3519 | } | 3557 | } |
3520 | 3558 | ||
3521 | static __exit void cleanup_ipmi_si(void) | 3559 | static void cleanup_ipmi_si(void) |
3522 | { | 3560 | { |
3523 | struct smi_info *e, *tmp_e; | 3561 | struct smi_info *e, *tmp_e; |
3524 | 3562 | ||
@@ -3534,17 +3572,12 @@ static __exit void cleanup_ipmi_si(void) | |||
3534 | pnp_unregister_driver(&ipmi_pnp_driver); | 3572 | pnp_unregister_driver(&ipmi_pnp_driver); |
3535 | #endif | 3573 | #endif |
3536 | 3574 | ||
3537 | #ifdef CONFIG_PPC_OF | 3575 | platform_driver_unregister(&ipmi_driver); |
3538 | if (of_registered) | ||
3539 | of_unregister_platform_driver(&ipmi_of_platform_driver); | ||
3540 | #endif | ||
3541 | 3576 | ||
3542 | mutex_lock(&smi_infos_lock); | 3577 | mutex_lock(&smi_infos_lock); |
3543 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) | 3578 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) |
3544 | cleanup_one_si(e); | 3579 | cleanup_one_si(e); |
3545 | mutex_unlock(&smi_infos_lock); | 3580 | mutex_unlock(&smi_infos_lock); |
3546 | |||
3547 | driver_unregister(&ipmi_driver.driver); | ||
3548 | } | 3581 | } |
3549 | module_exit(cleanup_ipmi_si); | 3582 | module_exit(cleanup_ipmi_si); |
3550 | 3583 | ||