diff options
author | Corey Minyard <cminyard@mvista.com> | 2017-09-12 23:28:49 -0400 |
---|---|---|
committer | Corey Minyard <cminyard@mvista.com> | 2017-09-27 17:03:45 -0400 |
commit | 44814ec982d2905d50fe4d0cdaf693b76afe7f64 (patch) | |
tree | b7ce3392fde9e9ff2efcdaaa2b2fc529d93df132 | |
parent | bb398a4cb09a0ed96cf0fc2e90012cf6bf13a824 (diff) |
ipmi_si: Move the hotmod handling to another file.
Signed-off-by: Corey Minyard <cminyard@mvista.com>
-rw-r--r-- | drivers/char/ipmi/Makefile | 3 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si.h | 2 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_hotmod.c | 242 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 261 |
4 files changed, 264 insertions, 244 deletions
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index eefb0b301e83..61c7d5d32f4a 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile | |||
@@ -2,7 +2,8 @@ | |||
2 | # Makefile for the ipmi drivers. | 2 | # Makefile for the ipmi drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o | 5 | ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o \ |
6 | ipmi_si_hotmod.o | ||
6 | 7 | ||
7 | obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o | 8 | obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o |
8 | obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o | 9 | obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o |
diff --git a/drivers/char/ipmi/ipmi_si.h b/drivers/char/ipmi/ipmi_si.h index 9573b35d73af..4ceb5ac3ad98 100644 --- a/drivers/char/ipmi/ipmi_si.h +++ b/drivers/char/ipmi/ipmi_si.h | |||
@@ -20,3 +20,5 @@ void ipmi_irq_start_cleanup(struct si_sm_io *io); | |||
20 | int ipmi_std_irq_setup(struct si_sm_io *io); | 20 | int ipmi_std_irq_setup(struct si_sm_io *io); |
21 | void ipmi_irq_finish_setup(struct si_sm_io *io); | 21 | void ipmi_irq_finish_setup(struct si_sm_io *io); |
22 | int ipmi_si_remove_by_dev(struct device *dev); | 22 | int ipmi_si_remove_by_dev(struct device *dev); |
23 | void ipmi_si_remove_by_data(int addr_space, enum si_type si_type, | ||
24 | unsigned long addr); | ||
diff --git a/drivers/char/ipmi/ipmi_si_hotmod.c b/drivers/char/ipmi/ipmi_si_hotmod.c new file mode 100644 index 000000000000..da5716159974 --- /dev/null +++ b/drivers/char/ipmi/ipmi_si_hotmod.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * ipmi_si_hotmod.c | ||
3 | * | ||
4 | * Handling for dynamically adding/removing IPMI devices through | ||
5 | * a module parameter (and thus sysfs). | ||
6 | */ | ||
7 | #include <linux/moduleparam.h> | ||
8 | #include <linux/ipmi.h> | ||
9 | #include "ipmi_si.h" | ||
10 | |||
11 | #define PFX "ipmi_hotmod: " | ||
12 | |||
13 | static int hotmod_handler(const char *val, struct kernel_param *kp); | ||
14 | |||
15 | module_param_call(hotmod, hotmod_handler, NULL, NULL, 0200); | ||
16 | MODULE_PARM_DESC(hotmod, "Add and remove interfaces. See" | ||
17 | " Documentation/IPMI.txt in the kernel sources for the" | ||
18 | " gory details."); | ||
19 | |||
20 | /* | ||
21 | * Parms come in as <op1>[:op2[:op3...]]. ops are: | ||
22 | * add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]] | ||
23 | * Options are: | ||
24 | * rsp=<regspacing> | ||
25 | * rsi=<regsize> | ||
26 | * rsh=<regshift> | ||
27 | * irq=<irq> | ||
28 | * ipmb=<ipmb addr> | ||
29 | */ | ||
30 | enum hotmod_op { HM_ADD, HM_REMOVE }; | ||
31 | struct hotmod_vals { | ||
32 | const char *name; | ||
33 | const int val; | ||
34 | }; | ||
35 | |||
36 | static const struct hotmod_vals hotmod_ops[] = { | ||
37 | { "add", HM_ADD }, | ||
38 | { "remove", HM_REMOVE }, | ||
39 | { NULL } | ||
40 | }; | ||
41 | |||
42 | static const struct hotmod_vals hotmod_si[] = { | ||
43 | { "kcs", SI_KCS }, | ||
44 | { "smic", SI_SMIC }, | ||
45 | { "bt", SI_BT }, | ||
46 | { NULL } | ||
47 | }; | ||
48 | |||
49 | static const struct hotmod_vals hotmod_as[] = { | ||
50 | { "mem", IPMI_MEM_ADDR_SPACE }, | ||
51 | { "i/o", IPMI_IO_ADDR_SPACE }, | ||
52 | { NULL } | ||
53 | }; | ||
54 | |||
55 | static int parse_str(const struct hotmod_vals *v, int *val, char *name, | ||
56 | char **curr) | ||
57 | { | ||
58 | char *s; | ||
59 | int i; | ||
60 | |||
61 | s = strchr(*curr, ','); | ||
62 | if (!s) { | ||
63 | pr_warn(PFX "No hotmod %s given.\n", name); | ||
64 | return -EINVAL; | ||
65 | } | ||
66 | *s = '\0'; | ||
67 | s++; | ||
68 | for (i = 0; v[i].name; i++) { | ||
69 | if (strcmp(*curr, v[i].name) == 0) { | ||
70 | *val = v[i].val; | ||
71 | *curr = s; | ||
72 | return 0; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | pr_warn(PFX "Invalid hotmod %s '%s'\n", name, *curr); | ||
77 | return -EINVAL; | ||
78 | } | ||
79 | |||
80 | static int check_hotmod_int_op(const char *curr, const char *option, | ||
81 | const char *name, int *val) | ||
82 | { | ||
83 | char *n; | ||
84 | |||
85 | if (strcmp(curr, name) == 0) { | ||
86 | if (!option) { | ||
87 | pr_warn(PFX "No option given for '%s'\n", curr); | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | *val = simple_strtoul(option, &n, 0); | ||
91 | if ((*n != '\0') || (*option == '\0')) { | ||
92 | pr_warn(PFX "Bad option given for '%s'\n", curr); | ||
93 | return -EINVAL; | ||
94 | } | ||
95 | return 1; | ||
96 | } | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int hotmod_handler(const char *val, struct kernel_param *kp) | ||
101 | { | ||
102 | char *str = kstrdup(val, GFP_KERNEL); | ||
103 | int rv; | ||
104 | char *next, *curr, *s, *n, *o; | ||
105 | enum hotmod_op op; | ||
106 | enum si_type si_type; | ||
107 | int addr_space; | ||
108 | unsigned long addr; | ||
109 | int regspacing; | ||
110 | int regsize; | ||
111 | int regshift; | ||
112 | int irq; | ||
113 | int ipmb; | ||
114 | int ival; | ||
115 | int len; | ||
116 | |||
117 | if (!str) | ||
118 | return -ENOMEM; | ||
119 | |||
120 | /* Kill any trailing spaces, as we can get a "\n" from echo. */ | ||
121 | len = strlen(str); | ||
122 | ival = len - 1; | ||
123 | while ((ival >= 0) && isspace(str[ival])) { | ||
124 | str[ival] = '\0'; | ||
125 | ival--; | ||
126 | } | ||
127 | |||
128 | for (curr = str; curr; curr = next) { | ||
129 | regspacing = 1; | ||
130 | regsize = 1; | ||
131 | regshift = 0; | ||
132 | irq = 0; | ||
133 | ipmb = 0; /* Choose the default if not specified */ | ||
134 | |||
135 | next = strchr(curr, ':'); | ||
136 | if (next) { | ||
137 | *next = '\0'; | ||
138 | next++; | ||
139 | } | ||
140 | |||
141 | rv = parse_str(hotmod_ops, &ival, "operation", &curr); | ||
142 | if (rv) | ||
143 | break; | ||
144 | op = ival; | ||
145 | |||
146 | rv = parse_str(hotmod_si, &ival, "interface type", &curr); | ||
147 | if (rv) | ||
148 | break; | ||
149 | si_type = ival; | ||
150 | |||
151 | rv = parse_str(hotmod_as, &addr_space, "address space", &curr); | ||
152 | if (rv) | ||
153 | break; | ||
154 | |||
155 | s = strchr(curr, ','); | ||
156 | if (s) { | ||
157 | *s = '\0'; | ||
158 | s++; | ||
159 | } | ||
160 | addr = simple_strtoul(curr, &n, 0); | ||
161 | if ((*n != '\0') || (*curr == '\0')) { | ||
162 | pr_warn(PFX "Invalid hotmod address '%s'\n", curr); | ||
163 | break; | ||
164 | } | ||
165 | |||
166 | while (s) { | ||
167 | curr = s; | ||
168 | s = strchr(curr, ','); | ||
169 | if (s) { | ||
170 | *s = '\0'; | ||
171 | s++; | ||
172 | } | ||
173 | o = strchr(curr, '='); | ||
174 | if (o) { | ||
175 | *o = '\0'; | ||
176 | o++; | ||
177 | } | ||
178 | rv = check_hotmod_int_op(curr, o, "rsp", ®spacing); | ||
179 | if (rv < 0) | ||
180 | goto out; | ||
181 | else if (rv) | ||
182 | continue; | ||
183 | rv = check_hotmod_int_op(curr, o, "rsi", ®size); | ||
184 | if (rv < 0) | ||
185 | goto out; | ||
186 | else if (rv) | ||
187 | continue; | ||
188 | rv = check_hotmod_int_op(curr, o, "rsh", ®shift); | ||
189 | if (rv < 0) | ||
190 | goto out; | ||
191 | else if (rv) | ||
192 | continue; | ||
193 | rv = check_hotmod_int_op(curr, o, "irq", &irq); | ||
194 | if (rv < 0) | ||
195 | goto out; | ||
196 | else if (rv) | ||
197 | continue; | ||
198 | rv = check_hotmod_int_op(curr, o, "ipmb", &ipmb); | ||
199 | if (rv < 0) | ||
200 | goto out; | ||
201 | else if (rv) | ||
202 | continue; | ||
203 | |||
204 | rv = -EINVAL; | ||
205 | pr_warn(PFX "Invalid hotmod option '%s'\n", curr); | ||
206 | goto out; | ||
207 | } | ||
208 | |||
209 | if (op == HM_ADD) { | ||
210 | struct si_sm_io io; | ||
211 | |||
212 | memset(&io, 0, sizeof(io)); | ||
213 | io.addr_source = SI_HOTMOD; | ||
214 | io.si_type = si_type; | ||
215 | io.addr_data = addr; | ||
216 | io.addr_type = addr_space; | ||
217 | |||
218 | io.addr = NULL; | ||
219 | io.regspacing = regspacing; | ||
220 | if (!io.regspacing) | ||
221 | io.regspacing = DEFAULT_REGSPACING; | ||
222 | io.regsize = regsize; | ||
223 | if (!io.regsize) | ||
224 | io.regsize = DEFAULT_REGSIZE; | ||
225 | io.regshift = regshift; | ||
226 | io.irq = irq; | ||
227 | if (io.irq) | ||
228 | io.irq_setup = ipmi_std_irq_setup; | ||
229 | io.slave_addr = ipmb; | ||
230 | |||
231 | rv = ipmi_si_add_smi(&io); | ||
232 | if (rv) | ||
233 | goto out; | ||
234 | } else { | ||
235 | ipmi_si_remove_by_data(addr_space, si_type, addr); | ||
236 | } | ||
237 | } | ||
238 | rv = len; | ||
239 | out: | ||
240 | kfree(str); | ||
241 | return rv; | ||
242 | } | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 6c2e14af8321..02e263b2152a 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1310,13 +1310,6 @@ static unsigned int num_slave_addrs; | |||
1310 | 1310 | ||
1311 | static const char * const addr_space_to_str[] = { "i/o", "mem" }; | 1311 | static const char * const addr_space_to_str[] = { "i/o", "mem" }; |
1312 | 1312 | ||
1313 | static int hotmod_handler(const char *val, struct kernel_param *kp); | ||
1314 | |||
1315 | module_param_call(hotmod, hotmod_handler, NULL, NULL, 0200); | ||
1316 | MODULE_PARM_DESC(hotmod, "Add and remove interfaces. See" | ||
1317 | " Documentation/IPMI.txt in the kernel sources for the" | ||
1318 | " gory details."); | ||
1319 | |||
1320 | #ifdef CONFIG_ACPI | 1313 | #ifdef CONFIG_ACPI |
1321 | module_param_named(tryacpi, si_tryacpi, bool, 0); | 1314 | module_param_named(tryacpi, si_tryacpi, bool, 0); |
1322 | MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" | 1315 | MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" |
@@ -1689,86 +1682,6 @@ static int mem_setup(struct si_sm_io *io) | |||
1689 | return 0; | 1682 | return 0; |
1690 | } | 1683 | } |
1691 | 1684 | ||
1692 | /* | ||
1693 | * Parms come in as <op1>[:op2[:op3...]]. ops are: | ||
1694 | * add|remove,kcs|bt|smic,mem|i/o,<address>[,<opt1>[,<opt2>[,...]]] | ||
1695 | * Options are: | ||
1696 | * rsp=<regspacing> | ||
1697 | * rsi=<regsize> | ||
1698 | * rsh=<regshift> | ||
1699 | * irq=<irq> | ||
1700 | * ipmb=<ipmb addr> | ||
1701 | */ | ||
1702 | enum hotmod_op { HM_ADD, HM_REMOVE }; | ||
1703 | struct hotmod_vals { | ||
1704 | const char *name; | ||
1705 | const int val; | ||
1706 | }; | ||
1707 | |||
1708 | static const struct hotmod_vals hotmod_ops[] = { | ||
1709 | { "add", HM_ADD }, | ||
1710 | { "remove", HM_REMOVE }, | ||
1711 | { NULL } | ||
1712 | }; | ||
1713 | |||
1714 | static const struct hotmod_vals hotmod_si[] = { | ||
1715 | { "kcs", SI_KCS }, | ||
1716 | { "smic", SI_SMIC }, | ||
1717 | { "bt", SI_BT }, | ||
1718 | { NULL } | ||
1719 | }; | ||
1720 | |||
1721 | static const struct hotmod_vals hotmod_as[] = { | ||
1722 | { "mem", IPMI_MEM_ADDR_SPACE }, | ||
1723 | { "i/o", IPMI_IO_ADDR_SPACE }, | ||
1724 | { NULL } | ||
1725 | }; | ||
1726 | |||
1727 | static int parse_str(const struct hotmod_vals *v, int *val, char *name, | ||
1728 | char **curr) | ||
1729 | { | ||
1730 | char *s; | ||
1731 | int i; | ||
1732 | |||
1733 | s = strchr(*curr, ','); | ||
1734 | if (!s) { | ||
1735 | pr_warn(PFX "No hotmod %s given.\n", name); | ||
1736 | return -EINVAL; | ||
1737 | } | ||
1738 | *s = '\0'; | ||
1739 | s++; | ||
1740 | for (i = 0; v[i].name; i++) { | ||
1741 | if (strcmp(*curr, v[i].name) == 0) { | ||
1742 | *val = v[i].val; | ||
1743 | *curr = s; | ||
1744 | return 0; | ||
1745 | } | ||
1746 | } | ||
1747 | |||
1748 | pr_warn(PFX "Invalid hotmod %s '%s'\n", name, *curr); | ||
1749 | return -EINVAL; | ||
1750 | } | ||
1751 | |||
1752 | static int check_hotmod_int_op(const char *curr, const char *option, | ||
1753 | const char *name, int *val) | ||
1754 | { | ||
1755 | char *n; | ||
1756 | |||
1757 | if (strcmp(curr, name) == 0) { | ||
1758 | if (!option) { | ||
1759 | pr_warn(PFX "No option given for '%s'\n", curr); | ||
1760 | return -EINVAL; | ||
1761 | } | ||
1762 | *val = simple_strtoul(option, &n, 0); | ||
1763 | if ((*n != '\0') || (*option == '\0')) { | ||
1764 | pr_warn(PFX "Bad option given for '%s'\n", curr); | ||
1765 | return -EINVAL; | ||
1766 | } | ||
1767 | return 1; | ||
1768 | } | ||
1769 | return 0; | ||
1770 | } | ||
1771 | |||
1772 | static struct smi_info *smi_info_alloc(void) | 1685 | static struct smi_info *smi_info_alloc(void) |
1773 | { | 1686 | { |
1774 | struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); | 1687 | struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); |
@@ -1778,162 +1691,6 @@ static struct smi_info *smi_info_alloc(void) | |||
1778 | return info; | 1691 | return info; |
1779 | } | 1692 | } |
1780 | 1693 | ||
1781 | static int hotmod_handler(const char *val, struct kernel_param *kp) | ||
1782 | { | ||
1783 | char *str = kstrdup(val, GFP_KERNEL); | ||
1784 | int rv; | ||
1785 | char *next, *curr, *s, *n, *o; | ||
1786 | enum hotmod_op op; | ||
1787 | enum si_type si_type; | ||
1788 | int addr_space; | ||
1789 | unsigned long addr; | ||
1790 | int regspacing; | ||
1791 | int regsize; | ||
1792 | int regshift; | ||
1793 | int irq; | ||
1794 | int ipmb; | ||
1795 | int ival; | ||
1796 | int len; | ||
1797 | |||
1798 | if (!str) | ||
1799 | return -ENOMEM; | ||
1800 | |||
1801 | /* Kill any trailing spaces, as we can get a "\n" from echo. */ | ||
1802 | len = strlen(str); | ||
1803 | ival = len - 1; | ||
1804 | while ((ival >= 0) && isspace(str[ival])) { | ||
1805 | str[ival] = '\0'; | ||
1806 | ival--; | ||
1807 | } | ||
1808 | |||
1809 | for (curr = str; curr; curr = next) { | ||
1810 | regspacing = 1; | ||
1811 | regsize = 1; | ||
1812 | regshift = 0; | ||
1813 | irq = 0; | ||
1814 | ipmb = 0; /* Choose the default if not specified */ | ||
1815 | |||
1816 | next = strchr(curr, ':'); | ||
1817 | if (next) { | ||
1818 | *next = '\0'; | ||
1819 | next++; | ||
1820 | } | ||
1821 | |||
1822 | rv = parse_str(hotmod_ops, &ival, "operation", &curr); | ||
1823 | if (rv) | ||
1824 | break; | ||
1825 | op = ival; | ||
1826 | |||
1827 | rv = parse_str(hotmod_si, &ival, "interface type", &curr); | ||
1828 | if (rv) | ||
1829 | break; | ||
1830 | si_type = ival; | ||
1831 | |||
1832 | rv = parse_str(hotmod_as, &addr_space, "address space", &curr); | ||
1833 | if (rv) | ||
1834 | break; | ||
1835 | |||
1836 | s = strchr(curr, ','); | ||
1837 | if (s) { | ||
1838 | *s = '\0'; | ||
1839 | s++; | ||
1840 | } | ||
1841 | addr = simple_strtoul(curr, &n, 0); | ||
1842 | if ((*n != '\0') || (*curr == '\0')) { | ||
1843 | pr_warn(PFX "Invalid hotmod address '%s'\n", curr); | ||
1844 | break; | ||
1845 | } | ||
1846 | |||
1847 | while (s) { | ||
1848 | curr = s; | ||
1849 | s = strchr(curr, ','); | ||
1850 | if (s) { | ||
1851 | *s = '\0'; | ||
1852 | s++; | ||
1853 | } | ||
1854 | o = strchr(curr, '='); | ||
1855 | if (o) { | ||
1856 | *o = '\0'; | ||
1857 | o++; | ||
1858 | } | ||
1859 | rv = check_hotmod_int_op(curr, o, "rsp", ®spacing); | ||
1860 | if (rv < 0) | ||
1861 | goto out; | ||
1862 | else if (rv) | ||
1863 | continue; | ||
1864 | rv = check_hotmod_int_op(curr, o, "rsi", ®size); | ||
1865 | if (rv < 0) | ||
1866 | goto out; | ||
1867 | else if (rv) | ||
1868 | continue; | ||
1869 | rv = check_hotmod_int_op(curr, o, "rsh", ®shift); | ||
1870 | if (rv < 0) | ||
1871 | goto out; | ||
1872 | else if (rv) | ||
1873 | continue; | ||
1874 | rv = check_hotmod_int_op(curr, o, "irq", &irq); | ||
1875 | if (rv < 0) | ||
1876 | goto out; | ||
1877 | else if (rv) | ||
1878 | continue; | ||
1879 | rv = check_hotmod_int_op(curr, o, "ipmb", &ipmb); | ||
1880 | if (rv < 0) | ||
1881 | goto out; | ||
1882 | else if (rv) | ||
1883 | continue; | ||
1884 | |||
1885 | rv = -EINVAL; | ||
1886 | pr_warn(PFX "Invalid hotmod option '%s'\n", curr); | ||
1887 | goto out; | ||
1888 | } | ||
1889 | |||
1890 | if (op == HM_ADD) { | ||
1891 | struct si_sm_io io; | ||
1892 | |||
1893 | memset(&io, 0, sizeof(io)); | ||
1894 | io.addr_source = SI_HOTMOD; | ||
1895 | io.si_type = si_type; | ||
1896 | io.addr_data = addr; | ||
1897 | io.addr_type = addr_space; | ||
1898 | |||
1899 | io.addr = NULL; | ||
1900 | io.regspacing = regspacing; | ||
1901 | if (!io.regspacing) | ||
1902 | io.regspacing = DEFAULT_REGSPACING; | ||
1903 | io.regsize = regsize; | ||
1904 | if (!io.regsize) | ||
1905 | io.regsize = DEFAULT_REGSIZE; | ||
1906 | io.regshift = regshift; | ||
1907 | io.irq = irq; | ||
1908 | if (io.irq) | ||
1909 | io.irq_setup = ipmi_std_irq_setup; | ||
1910 | io.slave_addr = ipmb; | ||
1911 | |||
1912 | rv = ipmi_si_add_smi(&io); | ||
1913 | if (rv) | ||
1914 | goto out; | ||
1915 | } else { | ||
1916 | /* remove */ | ||
1917 | struct smi_info *e, *tmp_e; | ||
1918 | |||
1919 | mutex_lock(&smi_infos_lock); | ||
1920 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) { | ||
1921 | if (e->io.addr_type != addr_space) | ||
1922 | continue; | ||
1923 | if (e->io.si_type != si_type) | ||
1924 | continue; | ||
1925 | if (e->io.addr_data == addr) | ||
1926 | cleanup_one_si(e); | ||
1927 | } | ||
1928 | mutex_unlock(&smi_infos_lock); | ||
1929 | } | ||
1930 | } | ||
1931 | rv = len; | ||
1932 | out: | ||
1933 | kfree(str); | ||
1934 | return rv; | ||
1935 | } | ||
1936 | |||
1937 | static int hardcode_find_bmc(void) | 1694 | static int hardcode_find_bmc(void) |
1938 | { | 1695 | { |
1939 | int ret = -ENODEV; | 1696 | int ret = -ENODEV; |
@@ -3779,6 +3536,24 @@ int ipmi_si_remove_by_dev(struct device *dev) | |||
3779 | return rv; | 3536 | return rv; |
3780 | } | 3537 | } |
3781 | 3538 | ||
3539 | void ipmi_si_remove_by_data(int addr_space, enum si_type si_type, | ||
3540 | unsigned long addr) | ||
3541 | { | ||
3542 | /* remove */ | ||
3543 | struct smi_info *e, *tmp_e; | ||
3544 | |||
3545 | mutex_lock(&smi_infos_lock); | ||
3546 | list_for_each_entry_safe(e, tmp_e, &smi_infos, link) { | ||
3547 | if (e->io.addr_type != addr_space) | ||
3548 | continue; | ||
3549 | if (e->io.si_type != si_type) | ||
3550 | continue; | ||
3551 | if (e->io.addr_data == addr) | ||
3552 | cleanup_one_si(e); | ||
3553 | } | ||
3554 | mutex_unlock(&smi_infos_lock); | ||
3555 | } | ||
3556 | |||
3782 | static void cleanup_ipmi_si(void) | 3557 | static void cleanup_ipmi_si(void) |
3783 | { | 3558 | { |
3784 | struct smi_info *e, *tmp_e; | 3559 | struct smi_info *e, *tmp_e; |