Commit 14bca6c39d8245a0313f55309bfeb6bf60cc17c8
Committed by
Linus Torvalds
1 parent
f24659d96f
Exists in
master
and in
7 other branches
i2o: remove extraneous kernel-doc
Remove excess kernel-doc function parameter notation from i2o/. Warning(drivers/message/i2o/iop.c:64): Excess function parameter 'msg' description in 'i2o_msg_get_wait' Warning(drivers/message/i2o/device.c:62): Excess function parameter 'drv' description in 'i2o_device_claim' Warning(drivers/message/i2o/device.c:95): Excess function parameter 'drv' description in 'i2o_device_claim_release' Warning(drivers/message/i2o/driver.c:186): Excess function parameter 'msg' description in 'i2o_driver_dispatch' Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 0 additions and 3 deletions Inline Diff
drivers/message/i2o/device.c
1 | /* | 1 | /* |
2 | * Functions to handle I2O devices | 2 | * Functions to handle I2O devices |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.com> | 4 | * Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.com> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
8 | * Free Software Foundation; either version 2 of the License, or (at your | 8 | * Free Software Foundation; either version 2 of the License, or (at your |
9 | * option) any later version. | 9 | * option) any later version. |
10 | * | 10 | * |
11 | * Fixes/additions: | 11 | * Fixes/additions: |
12 | * Markus Lidel <Markus.Lidel@shadowconnect.com> | 12 | * Markus Lidel <Markus.Lidel@shadowconnect.com> |
13 | * initial version. | 13 | * initial version. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/i2o.h> | 17 | #include <linux/i2o.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include "core.h" | 21 | #include "core.h" |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * i2o_device_issue_claim - claim or release a device | 24 | * i2o_device_issue_claim - claim or release a device |
25 | * @dev: I2O device to claim or release | 25 | * @dev: I2O device to claim or release |
26 | * @cmd: claim or release command | 26 | * @cmd: claim or release command |
27 | * @type: type of claim | 27 | * @type: type of claim |
28 | * | 28 | * |
29 | * Issue I2O UTIL_CLAIM or UTIL_RELEASE messages. The message to be sent | 29 | * Issue I2O UTIL_CLAIM or UTIL_RELEASE messages. The message to be sent |
30 | * is set by cmd. dev is the I2O device which should be claim or | 30 | * is set by cmd. dev is the I2O device which should be claim or |
31 | * released and the type is the claim type (see the I2O spec). | 31 | * released and the type is the claim type (see the I2O spec). |
32 | * | 32 | * |
33 | * Returs 0 on success or negative error code on failure. | 33 | * Returs 0 on success or negative error code on failure. |
34 | */ | 34 | */ |
35 | static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, | 35 | static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, |
36 | u32 type) | 36 | u32 type) |
37 | { | 37 | { |
38 | struct i2o_message *msg; | 38 | struct i2o_message *msg; |
39 | 39 | ||
40 | msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); | 40 | msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); |
41 | if (IS_ERR(msg)) | 41 | if (IS_ERR(msg)) |
42 | return PTR_ERR(msg); | 42 | return PTR_ERR(msg); |
43 | 43 | ||
44 | msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); | 44 | msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); |
45 | msg->u.head[1] = | 45 | msg->u.head[1] = |
46 | cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid); | 46 | cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid); |
47 | msg->body[0] = cpu_to_le32(type); | 47 | msg->body[0] = cpu_to_le32(type); |
48 | 48 | ||
49 | return i2o_msg_post_wait(dev->iop, msg, 60); | 49 | return i2o_msg_post_wait(dev->iop, msg, 60); |
50 | } | 50 | } |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * i2o_device_claim - claim a device for use by an OSM | 53 | * i2o_device_claim - claim a device for use by an OSM |
54 | * @dev: I2O device to claim | 54 | * @dev: I2O device to claim |
55 | * @drv: I2O driver which wants to claim the device | ||
56 | * | 55 | * |
57 | * Do the leg work to assign a device to a given OSM. If the claim succeeds, | 56 | * Do the leg work to assign a device to a given OSM. If the claim succeeds, |
58 | * the owner is the primary. If the attempt fails a negative errno code | 57 | * the owner is the primary. If the attempt fails a negative errno code |
59 | * is returned. On success zero is returned. | 58 | * is returned. On success zero is returned. |
60 | */ | 59 | */ |
61 | int i2o_device_claim(struct i2o_device *dev) | 60 | int i2o_device_claim(struct i2o_device *dev) |
62 | { | 61 | { |
63 | int rc = 0; | 62 | int rc = 0; |
64 | 63 | ||
65 | mutex_lock(&dev->lock); | 64 | mutex_lock(&dev->lock); |
66 | 65 | ||
67 | rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY); | 66 | rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY); |
68 | if (!rc) | 67 | if (!rc) |
69 | pr_debug("i2o: claim of device %d succeded\n", | 68 | pr_debug("i2o: claim of device %d succeded\n", |
70 | dev->lct_data.tid); | 69 | dev->lct_data.tid); |
71 | else | 70 | else |
72 | pr_debug("i2o: claim of device %d failed %d\n", | 71 | pr_debug("i2o: claim of device %d failed %d\n", |
73 | dev->lct_data.tid, rc); | 72 | dev->lct_data.tid, rc); |
74 | 73 | ||
75 | mutex_unlock(&dev->lock); | 74 | mutex_unlock(&dev->lock); |
76 | 75 | ||
77 | return rc; | 76 | return rc; |
78 | } | 77 | } |
79 | 78 | ||
80 | /** | 79 | /** |
81 | * i2o_device_claim_release - release a device that the OSM is using | 80 | * i2o_device_claim_release - release a device that the OSM is using |
82 | * @dev: device to release | 81 | * @dev: device to release |
83 | * @drv: driver which claimed the device | ||
84 | * | 82 | * |
85 | * Drop a claim by an OSM on a given I2O device. | 83 | * Drop a claim by an OSM on a given I2O device. |
86 | * | 84 | * |
87 | * AC - some devices seem to want to refuse an unclaim until they have | 85 | * AC - some devices seem to want to refuse an unclaim until they have |
88 | * finished internal processing. It makes sense since you don't want a | 86 | * finished internal processing. It makes sense since you don't want a |
89 | * new device to go reconfiguring the entire system until you are done. | 87 | * new device to go reconfiguring the entire system until you are done. |
90 | * Thus we are prepared to wait briefly. | 88 | * Thus we are prepared to wait briefly. |
91 | * | 89 | * |
92 | * Returns 0 on success or negative error code on failure. | 90 | * Returns 0 on success or negative error code on failure. |
93 | */ | 91 | */ |
94 | int i2o_device_claim_release(struct i2o_device *dev) | 92 | int i2o_device_claim_release(struct i2o_device *dev) |
95 | { | 93 | { |
96 | int tries; | 94 | int tries; |
97 | int rc = 0; | 95 | int rc = 0; |
98 | 96 | ||
99 | mutex_lock(&dev->lock); | 97 | mutex_lock(&dev->lock); |
100 | 98 | ||
101 | /* | 99 | /* |
102 | * If the controller takes a nonblocking approach to | 100 | * If the controller takes a nonblocking approach to |
103 | * releases we have to sleep/poll for a few times. | 101 | * releases we have to sleep/poll for a few times. |
104 | */ | 102 | */ |
105 | for (tries = 0; tries < 10; tries++) { | 103 | for (tries = 0; tries < 10; tries++) { |
106 | rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_RELEASE, | 104 | rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_RELEASE, |
107 | I2O_CLAIM_PRIMARY); | 105 | I2O_CLAIM_PRIMARY); |
108 | if (!rc) | 106 | if (!rc) |
109 | break; | 107 | break; |
110 | 108 | ||
111 | ssleep(1); | 109 | ssleep(1); |
112 | } | 110 | } |
113 | 111 | ||
114 | if (!rc) | 112 | if (!rc) |
115 | pr_debug("i2o: claim release of device %d succeded\n", | 113 | pr_debug("i2o: claim release of device %d succeded\n", |
116 | dev->lct_data.tid); | 114 | dev->lct_data.tid); |
117 | else | 115 | else |
118 | pr_debug("i2o: claim release of device %d failed %d\n", | 116 | pr_debug("i2o: claim release of device %d failed %d\n", |
119 | dev->lct_data.tid, rc); | 117 | dev->lct_data.tid, rc); |
120 | 118 | ||
121 | mutex_unlock(&dev->lock); | 119 | mutex_unlock(&dev->lock); |
122 | 120 | ||
123 | return rc; | 121 | return rc; |
124 | } | 122 | } |
125 | 123 | ||
126 | /** | 124 | /** |
127 | * i2o_device_release - release the memory for a I2O device | 125 | * i2o_device_release - release the memory for a I2O device |
128 | * @dev: I2O device which should be released | 126 | * @dev: I2O device which should be released |
129 | * | 127 | * |
130 | * Release the allocated memory. This function is called if refcount of | 128 | * Release the allocated memory. This function is called if refcount of |
131 | * device reaches 0 automatically. | 129 | * device reaches 0 automatically. |
132 | */ | 130 | */ |
133 | static void i2o_device_release(struct device *dev) | 131 | static void i2o_device_release(struct device *dev) |
134 | { | 132 | { |
135 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 133 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
136 | 134 | ||
137 | pr_debug("i2o: device %s released\n", dev->bus_id); | 135 | pr_debug("i2o: device %s released\n", dev->bus_id); |
138 | 136 | ||
139 | kfree(i2o_dev); | 137 | kfree(i2o_dev); |
140 | } | 138 | } |
141 | 139 | ||
142 | /** | 140 | /** |
143 | * i2o_device_show_class_id - Displays class id of I2O device | 141 | * i2o_device_show_class_id - Displays class id of I2O device |
144 | * @dev: device of which the class id should be displayed | 142 | * @dev: device of which the class id should be displayed |
145 | * @attr: pointer to device attribute | 143 | * @attr: pointer to device attribute |
146 | * @buf: buffer into which the class id should be printed | 144 | * @buf: buffer into which the class id should be printed |
147 | * | 145 | * |
148 | * Returns the number of bytes which are printed into the buffer. | 146 | * Returns the number of bytes which are printed into the buffer. |
149 | */ | 147 | */ |
150 | static ssize_t i2o_device_show_class_id(struct device *dev, | 148 | static ssize_t i2o_device_show_class_id(struct device *dev, |
151 | struct device_attribute *attr, | 149 | struct device_attribute *attr, |
152 | char *buf) | 150 | char *buf) |
153 | { | 151 | { |
154 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 152 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
155 | 153 | ||
156 | sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id); | 154 | sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id); |
157 | return strlen(buf) + 1; | 155 | return strlen(buf) + 1; |
158 | } | 156 | } |
159 | 157 | ||
160 | /** | 158 | /** |
161 | * i2o_device_show_tid - Displays TID of I2O device | 159 | * i2o_device_show_tid - Displays TID of I2O device |
162 | * @dev: device of which the TID should be displayed | 160 | * @dev: device of which the TID should be displayed |
163 | * @attr: pointer to device attribute | 161 | * @attr: pointer to device attribute |
164 | * @buf: buffer into which the TID should be printed | 162 | * @buf: buffer into which the TID should be printed |
165 | * | 163 | * |
166 | * Returns the number of bytes which are printed into the buffer. | 164 | * Returns the number of bytes which are printed into the buffer. |
167 | */ | 165 | */ |
168 | static ssize_t i2o_device_show_tid(struct device *dev, | 166 | static ssize_t i2o_device_show_tid(struct device *dev, |
169 | struct device_attribute *attr, char *buf) | 167 | struct device_attribute *attr, char *buf) |
170 | { | 168 | { |
171 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 169 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
172 | 170 | ||
173 | sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid); | 171 | sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid); |
174 | return strlen(buf) + 1; | 172 | return strlen(buf) + 1; |
175 | } | 173 | } |
176 | 174 | ||
177 | /* I2O device attributes */ | 175 | /* I2O device attributes */ |
178 | struct device_attribute i2o_device_attrs[] = { | 176 | struct device_attribute i2o_device_attrs[] = { |
179 | __ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL), | 177 | __ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL), |
180 | __ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL), | 178 | __ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL), |
181 | __ATTR_NULL | 179 | __ATTR_NULL |
182 | }; | 180 | }; |
183 | 181 | ||
184 | /** | 182 | /** |
185 | * i2o_device_alloc - Allocate a I2O device and initialize it | 183 | * i2o_device_alloc - Allocate a I2O device and initialize it |
186 | * | 184 | * |
187 | * Allocate the memory for a I2O device and initialize locks and lists | 185 | * Allocate the memory for a I2O device and initialize locks and lists |
188 | * | 186 | * |
189 | * Returns the allocated I2O device or a negative error code if the device | 187 | * Returns the allocated I2O device or a negative error code if the device |
190 | * could not be allocated. | 188 | * could not be allocated. |
191 | */ | 189 | */ |
192 | static struct i2o_device *i2o_device_alloc(void) | 190 | static struct i2o_device *i2o_device_alloc(void) |
193 | { | 191 | { |
194 | struct i2o_device *dev; | 192 | struct i2o_device *dev; |
195 | 193 | ||
196 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 194 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
197 | if (!dev) | 195 | if (!dev) |
198 | return ERR_PTR(-ENOMEM); | 196 | return ERR_PTR(-ENOMEM); |
199 | 197 | ||
200 | INIT_LIST_HEAD(&dev->list); | 198 | INIT_LIST_HEAD(&dev->list); |
201 | mutex_init(&dev->lock); | 199 | mutex_init(&dev->lock); |
202 | 200 | ||
203 | dev->device.bus = &i2o_bus_type; | 201 | dev->device.bus = &i2o_bus_type; |
204 | dev->device.release = &i2o_device_release; | 202 | dev->device.release = &i2o_device_release; |
205 | 203 | ||
206 | return dev; | 204 | return dev; |
207 | } | 205 | } |
208 | 206 | ||
209 | /** | 207 | /** |
210 | * i2o_device_add - allocate a new I2O device and add it to the IOP | 208 | * i2o_device_add - allocate a new I2O device and add it to the IOP |
211 | * @c: I2O controller that the device is on | 209 | * @c: I2O controller that the device is on |
212 | * @entry: LCT entry of the I2O device | 210 | * @entry: LCT entry of the I2O device |
213 | * | 211 | * |
214 | * Allocate a new I2O device and initialize it with the LCT entry. The | 212 | * Allocate a new I2O device and initialize it with the LCT entry. The |
215 | * device is appended to the device list of the controller. | 213 | * device is appended to the device list of the controller. |
216 | * | 214 | * |
217 | * Returns zero on success, or a -ve errno. | 215 | * Returns zero on success, or a -ve errno. |
218 | */ | 216 | */ |
219 | static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry) | 217 | static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry) |
220 | { | 218 | { |
221 | struct i2o_device *i2o_dev, *tmp; | 219 | struct i2o_device *i2o_dev, *tmp; |
222 | int rc; | 220 | int rc; |
223 | 221 | ||
224 | i2o_dev = i2o_device_alloc(); | 222 | i2o_dev = i2o_device_alloc(); |
225 | if (IS_ERR(i2o_dev)) { | 223 | if (IS_ERR(i2o_dev)) { |
226 | printk(KERN_ERR "i2o: unable to allocate i2o device\n"); | 224 | printk(KERN_ERR "i2o: unable to allocate i2o device\n"); |
227 | return PTR_ERR(i2o_dev); | 225 | return PTR_ERR(i2o_dev); |
228 | } | 226 | } |
229 | 227 | ||
230 | i2o_dev->lct_data = *entry; | 228 | i2o_dev->lct_data = *entry; |
231 | 229 | ||
232 | snprintf(i2o_dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, | 230 | snprintf(i2o_dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, |
233 | i2o_dev->lct_data.tid); | 231 | i2o_dev->lct_data.tid); |
234 | 232 | ||
235 | i2o_dev->iop = c; | 233 | i2o_dev->iop = c; |
236 | i2o_dev->device.parent = &c->device; | 234 | i2o_dev->device.parent = &c->device; |
237 | 235 | ||
238 | rc = device_register(&i2o_dev->device); | 236 | rc = device_register(&i2o_dev->device); |
239 | if (rc) | 237 | if (rc) |
240 | goto err; | 238 | goto err; |
241 | 239 | ||
242 | list_add_tail(&i2o_dev->list, &c->devices); | 240 | list_add_tail(&i2o_dev->list, &c->devices); |
243 | 241 | ||
244 | /* create user entries for this device */ | 242 | /* create user entries for this device */ |
245 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); | 243 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); |
246 | if (tmp && (tmp != i2o_dev)) { | 244 | if (tmp && (tmp != i2o_dev)) { |
247 | rc = sysfs_create_link(&i2o_dev->device.kobj, | 245 | rc = sysfs_create_link(&i2o_dev->device.kobj, |
248 | &tmp->device.kobj, "user"); | 246 | &tmp->device.kobj, "user"); |
249 | if (rc) | 247 | if (rc) |
250 | goto unreg_dev; | 248 | goto unreg_dev; |
251 | } | 249 | } |
252 | 250 | ||
253 | /* create user entries refering to this device */ | 251 | /* create user entries refering to this device */ |
254 | list_for_each_entry(tmp, &c->devices, list) | 252 | list_for_each_entry(tmp, &c->devices, list) |
255 | if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | 253 | if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) |
256 | && (tmp != i2o_dev)) { | 254 | && (tmp != i2o_dev)) { |
257 | rc = sysfs_create_link(&tmp->device.kobj, | 255 | rc = sysfs_create_link(&tmp->device.kobj, |
258 | &i2o_dev->device.kobj, "user"); | 256 | &i2o_dev->device.kobj, "user"); |
259 | if (rc) | 257 | if (rc) |
260 | goto rmlink1; | 258 | goto rmlink1; |
261 | } | 259 | } |
262 | 260 | ||
263 | /* create parent entries for this device */ | 261 | /* create parent entries for this device */ |
264 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); | 262 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); |
265 | if (tmp && (tmp != i2o_dev)) { | 263 | if (tmp && (tmp != i2o_dev)) { |
266 | rc = sysfs_create_link(&i2o_dev->device.kobj, | 264 | rc = sysfs_create_link(&i2o_dev->device.kobj, |
267 | &tmp->device.kobj, "parent"); | 265 | &tmp->device.kobj, "parent"); |
268 | if (rc) | 266 | if (rc) |
269 | goto rmlink1; | 267 | goto rmlink1; |
270 | } | 268 | } |
271 | 269 | ||
272 | /* create parent entries refering to this device */ | 270 | /* create parent entries refering to this device */ |
273 | list_for_each_entry(tmp, &c->devices, list) | 271 | list_for_each_entry(tmp, &c->devices, list) |
274 | if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | 272 | if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) |
275 | && (tmp != i2o_dev)) { | 273 | && (tmp != i2o_dev)) { |
276 | rc = sysfs_create_link(&tmp->device.kobj, | 274 | rc = sysfs_create_link(&tmp->device.kobj, |
277 | &i2o_dev->device.kobj, "parent"); | 275 | &i2o_dev->device.kobj, "parent"); |
278 | if (rc) | 276 | if (rc) |
279 | goto rmlink2; | 277 | goto rmlink2; |
280 | } | 278 | } |
281 | 279 | ||
282 | i2o_driver_notify_device_add_all(i2o_dev); | 280 | i2o_driver_notify_device_add_all(i2o_dev); |
283 | 281 | ||
284 | pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id); | 282 | pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id); |
285 | 283 | ||
286 | return 0; | 284 | return 0; |
287 | 285 | ||
288 | rmlink2: | 286 | rmlink2: |
289 | /* If link creating failed halfway, we loop whole list to cleanup. | 287 | /* If link creating failed halfway, we loop whole list to cleanup. |
290 | * And we don't care wrong removing of link, because sysfs_remove_link | 288 | * And we don't care wrong removing of link, because sysfs_remove_link |
291 | * will take care of it. | 289 | * will take care of it. |
292 | */ | 290 | */ |
293 | list_for_each_entry(tmp, &c->devices, list) { | 291 | list_for_each_entry(tmp, &c->devices, list) { |
294 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | 292 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) |
295 | sysfs_remove_link(&tmp->device.kobj, "parent"); | 293 | sysfs_remove_link(&tmp->device.kobj, "parent"); |
296 | } | 294 | } |
297 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); | 295 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); |
298 | rmlink1: | 296 | rmlink1: |
299 | list_for_each_entry(tmp, &c->devices, list) | 297 | list_for_each_entry(tmp, &c->devices, list) |
300 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | 298 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) |
301 | sysfs_remove_link(&tmp->device.kobj, "user"); | 299 | sysfs_remove_link(&tmp->device.kobj, "user"); |
302 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); | 300 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); |
303 | unreg_dev: | 301 | unreg_dev: |
304 | list_del(&i2o_dev->list); | 302 | list_del(&i2o_dev->list); |
305 | device_unregister(&i2o_dev->device); | 303 | device_unregister(&i2o_dev->device); |
306 | err: | 304 | err: |
307 | kfree(i2o_dev); | 305 | kfree(i2o_dev); |
308 | return rc; | 306 | return rc; |
309 | } | 307 | } |
310 | 308 | ||
311 | /** | 309 | /** |
312 | * i2o_device_remove - remove an I2O device from the I2O core | 310 | * i2o_device_remove - remove an I2O device from the I2O core |
313 | * @i2o_dev: I2O device which should be released | 311 | * @i2o_dev: I2O device which should be released |
314 | * | 312 | * |
315 | * Is used on I2O controller removal or LCT modification, when the device | 313 | * Is used on I2O controller removal or LCT modification, when the device |
316 | * is removed from the system. Note that the device could still hang | 314 | * is removed from the system. Note that the device could still hang |
317 | * around until the refcount reaches 0. | 315 | * around until the refcount reaches 0. |
318 | */ | 316 | */ |
319 | void i2o_device_remove(struct i2o_device *i2o_dev) | 317 | void i2o_device_remove(struct i2o_device *i2o_dev) |
320 | { | 318 | { |
321 | struct i2o_device *tmp; | 319 | struct i2o_device *tmp; |
322 | struct i2o_controller *c = i2o_dev->iop; | 320 | struct i2o_controller *c = i2o_dev->iop; |
323 | 321 | ||
324 | i2o_driver_notify_device_remove_all(i2o_dev); | 322 | i2o_driver_notify_device_remove_all(i2o_dev); |
325 | 323 | ||
326 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); | 324 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); |
327 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); | 325 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); |
328 | 326 | ||
329 | list_for_each_entry(tmp, &c->devices, list) { | 327 | list_for_each_entry(tmp, &c->devices, list) { |
330 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | 328 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) |
331 | sysfs_remove_link(&tmp->device.kobj, "parent"); | 329 | sysfs_remove_link(&tmp->device.kobj, "parent"); |
332 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | 330 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) |
333 | sysfs_remove_link(&tmp->device.kobj, "user"); | 331 | sysfs_remove_link(&tmp->device.kobj, "user"); |
334 | } | 332 | } |
335 | list_del(&i2o_dev->list); | 333 | list_del(&i2o_dev->list); |
336 | 334 | ||
337 | device_unregister(&i2o_dev->device); | 335 | device_unregister(&i2o_dev->device); |
338 | } | 336 | } |
339 | 337 | ||
340 | /** | 338 | /** |
341 | * i2o_device_parse_lct - Parse a previously fetched LCT and create devices | 339 | * i2o_device_parse_lct - Parse a previously fetched LCT and create devices |
342 | * @c: I2O controller from which the LCT should be parsed. | 340 | * @c: I2O controller from which the LCT should be parsed. |
343 | * | 341 | * |
344 | * The Logical Configuration Table tells us what we can talk to on the | 342 | * The Logical Configuration Table tells us what we can talk to on the |
345 | * board. For every entry we create an I2O device, which is registered in | 343 | * board. For every entry we create an I2O device, which is registered in |
346 | * the I2O core. | 344 | * the I2O core. |
347 | * | 345 | * |
348 | * Returns 0 on success or negative error code on failure. | 346 | * Returns 0 on success or negative error code on failure. |
349 | */ | 347 | */ |
350 | int i2o_device_parse_lct(struct i2o_controller *c) | 348 | int i2o_device_parse_lct(struct i2o_controller *c) |
351 | { | 349 | { |
352 | struct i2o_device *dev, *tmp; | 350 | struct i2o_device *dev, *tmp; |
353 | i2o_lct *lct; | 351 | i2o_lct *lct; |
354 | u32 *dlct = c->dlct.virt; | 352 | u32 *dlct = c->dlct.virt; |
355 | int max = 0, i = 0; | 353 | int max = 0, i = 0; |
356 | u16 table_size; | 354 | u16 table_size; |
357 | u32 buf; | 355 | u32 buf; |
358 | 356 | ||
359 | mutex_lock(&c->lct_lock); | 357 | mutex_lock(&c->lct_lock); |
360 | 358 | ||
361 | kfree(c->lct); | 359 | kfree(c->lct); |
362 | 360 | ||
363 | buf = le32_to_cpu(*dlct++); | 361 | buf = le32_to_cpu(*dlct++); |
364 | table_size = buf & 0xffff; | 362 | table_size = buf & 0xffff; |
365 | 363 | ||
366 | lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); | 364 | lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); |
367 | if (!lct) { | 365 | if (!lct) { |
368 | mutex_unlock(&c->lct_lock); | 366 | mutex_unlock(&c->lct_lock); |
369 | return -ENOMEM; | 367 | return -ENOMEM; |
370 | } | 368 | } |
371 | 369 | ||
372 | lct->lct_ver = buf >> 28; | 370 | lct->lct_ver = buf >> 28; |
373 | lct->boot_tid = buf >> 16 & 0xfff; | 371 | lct->boot_tid = buf >> 16 & 0xfff; |
374 | lct->table_size = table_size; | 372 | lct->table_size = table_size; |
375 | lct->change_ind = le32_to_cpu(*dlct++); | 373 | lct->change_ind = le32_to_cpu(*dlct++); |
376 | lct->iop_flags = le32_to_cpu(*dlct++); | 374 | lct->iop_flags = le32_to_cpu(*dlct++); |
377 | 375 | ||
378 | table_size -= 3; | 376 | table_size -= 3; |
379 | 377 | ||
380 | pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max, | 378 | pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max, |
381 | lct->table_size); | 379 | lct->table_size); |
382 | 380 | ||
383 | while (table_size > 0) { | 381 | while (table_size > 0) { |
384 | i2o_lct_entry *entry = &lct->lct_entry[max]; | 382 | i2o_lct_entry *entry = &lct->lct_entry[max]; |
385 | int found = 0; | 383 | int found = 0; |
386 | 384 | ||
387 | buf = le32_to_cpu(*dlct++); | 385 | buf = le32_to_cpu(*dlct++); |
388 | entry->entry_size = buf & 0xffff; | 386 | entry->entry_size = buf & 0xffff; |
389 | entry->tid = buf >> 16 & 0xfff; | 387 | entry->tid = buf >> 16 & 0xfff; |
390 | 388 | ||
391 | entry->change_ind = le32_to_cpu(*dlct++); | 389 | entry->change_ind = le32_to_cpu(*dlct++); |
392 | entry->device_flags = le32_to_cpu(*dlct++); | 390 | entry->device_flags = le32_to_cpu(*dlct++); |
393 | 391 | ||
394 | buf = le32_to_cpu(*dlct++); | 392 | buf = le32_to_cpu(*dlct++); |
395 | entry->class_id = buf & 0xfff; | 393 | entry->class_id = buf & 0xfff; |
396 | entry->version = buf >> 12 & 0xf; | 394 | entry->version = buf >> 12 & 0xf; |
397 | entry->vendor_id = buf >> 16; | 395 | entry->vendor_id = buf >> 16; |
398 | 396 | ||
399 | entry->sub_class = le32_to_cpu(*dlct++); | 397 | entry->sub_class = le32_to_cpu(*dlct++); |
400 | 398 | ||
401 | buf = le32_to_cpu(*dlct++); | 399 | buf = le32_to_cpu(*dlct++); |
402 | entry->user_tid = buf & 0xfff; | 400 | entry->user_tid = buf & 0xfff; |
403 | entry->parent_tid = buf >> 12 & 0xfff; | 401 | entry->parent_tid = buf >> 12 & 0xfff; |
404 | entry->bios_info = buf >> 24; | 402 | entry->bios_info = buf >> 24; |
405 | 403 | ||
406 | memcpy(&entry->identity_tag, dlct, 8); | 404 | memcpy(&entry->identity_tag, dlct, 8); |
407 | dlct += 2; | 405 | dlct += 2; |
408 | 406 | ||
409 | entry->event_capabilities = le32_to_cpu(*dlct++); | 407 | entry->event_capabilities = le32_to_cpu(*dlct++); |
410 | 408 | ||
411 | /* add new devices, which are new in the LCT */ | 409 | /* add new devices, which are new in the LCT */ |
412 | list_for_each_entry_safe(dev, tmp, &c->devices, list) { | 410 | list_for_each_entry_safe(dev, tmp, &c->devices, list) { |
413 | if (entry->tid == dev->lct_data.tid) { | 411 | if (entry->tid == dev->lct_data.tid) { |
414 | found = 1; | 412 | found = 1; |
415 | break; | 413 | break; |
416 | } | 414 | } |
417 | } | 415 | } |
418 | 416 | ||
419 | if (!found) | 417 | if (!found) |
420 | i2o_device_add(c, entry); | 418 | i2o_device_add(c, entry); |
421 | 419 | ||
422 | table_size -= 9; | 420 | table_size -= 9; |
423 | max++; | 421 | max++; |
424 | } | 422 | } |
425 | 423 | ||
426 | /* remove devices, which are not in the LCT anymore */ | 424 | /* remove devices, which are not in the LCT anymore */ |
427 | list_for_each_entry_safe(dev, tmp, &c->devices, list) { | 425 | list_for_each_entry_safe(dev, tmp, &c->devices, list) { |
428 | int found = 0; | 426 | int found = 0; |
429 | 427 | ||
430 | for (i = 0; i < max; i++) { | 428 | for (i = 0; i < max; i++) { |
431 | if (lct->lct_entry[i].tid == dev->lct_data.tid) { | 429 | if (lct->lct_entry[i].tid == dev->lct_data.tid) { |
432 | found = 1; | 430 | found = 1; |
433 | break; | 431 | break; |
434 | } | 432 | } |
435 | } | 433 | } |
436 | 434 | ||
437 | if (!found) | 435 | if (!found) |
438 | i2o_device_remove(dev); | 436 | i2o_device_remove(dev); |
439 | } | 437 | } |
440 | 438 | ||
441 | mutex_unlock(&c->lct_lock); | 439 | mutex_unlock(&c->lct_lock); |
442 | 440 | ||
443 | return 0; | 441 | return 0; |
444 | } | 442 | } |
445 | 443 | ||
446 | /* | 444 | /* |
447 | * Run time support routines | 445 | * Run time support routines |
448 | */ | 446 | */ |
449 | 447 | ||
450 | /* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET | 448 | /* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET |
451 | * | 449 | * |
452 | * This function can be used for all UtilParamsGet/Set operations. | 450 | * This function can be used for all UtilParamsGet/Set operations. |
453 | * The OperationList is given in oplist-buffer, | 451 | * The OperationList is given in oplist-buffer, |
454 | * and results are returned in reslist-buffer. | 452 | * and results are returned in reslist-buffer. |
455 | * Note that the minimum sized reslist is 8 bytes and contains | 453 | * Note that the minimum sized reslist is 8 bytes and contains |
456 | * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. | 454 | * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. |
457 | */ | 455 | */ |
458 | int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, | 456 | int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, |
459 | int oplen, void *reslist, int reslen) | 457 | int oplen, void *reslist, int reslen) |
460 | { | 458 | { |
461 | struct i2o_message *msg; | 459 | struct i2o_message *msg; |
462 | int i = 0; | 460 | int i = 0; |
463 | int rc; | 461 | int rc; |
464 | struct i2o_dma res; | 462 | struct i2o_dma res; |
465 | struct i2o_controller *c = i2o_dev->iop; | 463 | struct i2o_controller *c = i2o_dev->iop; |
466 | struct device *dev = &c->pdev->dev; | 464 | struct device *dev = &c->pdev->dev; |
467 | 465 | ||
468 | res.virt = NULL; | 466 | res.virt = NULL; |
469 | 467 | ||
470 | if (i2o_dma_alloc(dev, &res, reslen)) | 468 | if (i2o_dma_alloc(dev, &res, reslen)) |
471 | return -ENOMEM; | 469 | return -ENOMEM; |
472 | 470 | ||
473 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); | 471 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); |
474 | if (IS_ERR(msg)) { | 472 | if (IS_ERR(msg)) { |
475 | i2o_dma_free(dev, &res); | 473 | i2o_dma_free(dev, &res); |
476 | return PTR_ERR(msg); | 474 | return PTR_ERR(msg); |
477 | } | 475 | } |
478 | 476 | ||
479 | i = 0; | 477 | i = 0; |
480 | msg->u.head[1] = | 478 | msg->u.head[1] = |
481 | cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid); | 479 | cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid); |
482 | msg->body[i++] = cpu_to_le32(0x00000000); | 480 | msg->body[i++] = cpu_to_le32(0x00000000); |
483 | msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */ | 481 | msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */ |
484 | memcpy(&msg->body[i], oplist, oplen); | 482 | memcpy(&msg->body[i], oplist, oplen); |
485 | i += (oplen / 4 + (oplen % 4 ? 1 : 0)); | 483 | i += (oplen / 4 + (oplen % 4 ? 1 : 0)); |
486 | msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */ | 484 | msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */ |
487 | msg->body[i++] = cpu_to_le32(res.phys); | 485 | msg->body[i++] = cpu_to_le32(res.phys); |
488 | 486 | ||
489 | msg->u.head[0] = | 487 | msg->u.head[0] = |
490 | cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | | 488 | cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | |
491 | SGL_OFFSET_5); | 489 | SGL_OFFSET_5); |
492 | 490 | ||
493 | rc = i2o_msg_post_wait_mem(c, msg, 10, &res); | 491 | rc = i2o_msg_post_wait_mem(c, msg, 10, &res); |
494 | 492 | ||
495 | /* This only looks like a memory leak - don't "fix" it. */ | 493 | /* This only looks like a memory leak - don't "fix" it. */ |
496 | if (rc == -ETIMEDOUT) | 494 | if (rc == -ETIMEDOUT) |
497 | return rc; | 495 | return rc; |
498 | 496 | ||
499 | memcpy(reslist, res.virt, res.len); | 497 | memcpy(reslist, res.virt, res.len); |
500 | i2o_dma_free(dev, &res); | 498 | i2o_dma_free(dev, &res); |
501 | 499 | ||
502 | return rc; | 500 | return rc; |
503 | } | 501 | } |
504 | 502 | ||
505 | /* | 503 | /* |
506 | * Query one field group value or a whole scalar group. | 504 | * Query one field group value or a whole scalar group. |
507 | */ | 505 | */ |
508 | int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, | 506 | int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, |
509 | void *buf, int buflen) | 507 | void *buf, int buflen) |
510 | { | 508 | { |
511 | u32 opblk[] = { cpu_to_le32(0x00000001), | 509 | u32 opblk[] = { cpu_to_le32(0x00000001), |
512 | cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET), | 510 | cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET), |
513 | cpu_to_le32((s16) field << 16 | 0x00000001) | 511 | cpu_to_le32((s16) field << 16 | 0x00000001) |
514 | }; | 512 | }; |
515 | u8 *resblk; /* 8 bytes for header */ | 513 | u8 *resblk; /* 8 bytes for header */ |
516 | int rc; | 514 | int rc; |
517 | 515 | ||
518 | resblk = kmalloc(buflen + 8, GFP_KERNEL); | 516 | resblk = kmalloc(buflen + 8, GFP_KERNEL); |
519 | if (!resblk) | 517 | if (!resblk) |
520 | return -ENOMEM; | 518 | return -ENOMEM; |
521 | 519 | ||
522 | rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, | 520 | rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, |
523 | sizeof(opblk), resblk, buflen + 8); | 521 | sizeof(opblk), resblk, buflen + 8); |
524 | 522 | ||
525 | memcpy(buf, resblk + 8, buflen); /* cut off header */ | 523 | memcpy(buf, resblk + 8, buflen); /* cut off header */ |
526 | 524 | ||
527 | kfree(resblk); | 525 | kfree(resblk); |
528 | 526 | ||
529 | return rc; | 527 | return rc; |
530 | } | 528 | } |
531 | 529 | ||
532 | /* | 530 | /* |
533 | * if oper == I2O_PARAMS_TABLE_GET, get from all rows | 531 | * if oper == I2O_PARAMS_TABLE_GET, get from all rows |
534 | * if fieldcount == -1 return all fields | 532 | * if fieldcount == -1 return all fields |
535 | * ibuf and ibuflen are unused (use NULL, 0) | 533 | * ibuf and ibuflen are unused (use NULL, 0) |
536 | * else return specific fields | 534 | * else return specific fields |
537 | * ibuf contains fieldindexes | 535 | * ibuf contains fieldindexes |
538 | * | 536 | * |
539 | * if oper == I2O_PARAMS_LIST_GET, get from specific rows | 537 | * if oper == I2O_PARAMS_LIST_GET, get from specific rows |
540 | * if fieldcount == -1 return all fields | 538 | * if fieldcount == -1 return all fields |
541 | * ibuf contains rowcount, keyvalues | 539 | * ibuf contains rowcount, keyvalues |
542 | * else return specific fields | 540 | * else return specific fields |
543 | * fieldcount is # of fieldindexes | 541 | * fieldcount is # of fieldindexes |
544 | * ibuf contains fieldindexes, rowcount, keyvalues | 542 | * ibuf contains fieldindexes, rowcount, keyvalues |
545 | * | 543 | * |
546 | * You could also use directly function i2o_issue_params(). | 544 | * You could also use directly function i2o_issue_params(). |
547 | */ | 545 | */ |
548 | int i2o_parm_table_get(struct i2o_device *dev, int oper, int group, | 546 | int i2o_parm_table_get(struct i2o_device *dev, int oper, int group, |
549 | int fieldcount, void *ibuf, int ibuflen, void *resblk, | 547 | int fieldcount, void *ibuf, int ibuflen, void *resblk, |
550 | int reslen) | 548 | int reslen) |
551 | { | 549 | { |
552 | u16 *opblk; | 550 | u16 *opblk; |
553 | int size; | 551 | int size; |
554 | 552 | ||
555 | size = 10 + ibuflen; | 553 | size = 10 + ibuflen; |
556 | if (size % 4) | 554 | if (size % 4) |
557 | size += 4 - size % 4; | 555 | size += 4 - size % 4; |
558 | 556 | ||
559 | opblk = kmalloc(size, GFP_KERNEL); | 557 | opblk = kmalloc(size, GFP_KERNEL); |
560 | if (opblk == NULL) { | 558 | if (opblk == NULL) { |
561 | printk(KERN_ERR "i2o: no memory for query buffer.\n"); | 559 | printk(KERN_ERR "i2o: no memory for query buffer.\n"); |
562 | return -ENOMEM; | 560 | return -ENOMEM; |
563 | } | 561 | } |
564 | 562 | ||
565 | opblk[0] = 1; /* operation count */ | 563 | opblk[0] = 1; /* operation count */ |
566 | opblk[1] = 0; /* pad */ | 564 | opblk[1] = 0; /* pad */ |
567 | opblk[2] = oper; | 565 | opblk[2] = oper; |
568 | opblk[3] = group; | 566 | opblk[3] = group; |
569 | opblk[4] = fieldcount; | 567 | opblk[4] = fieldcount; |
570 | memcpy(opblk + 5, ibuf, ibuflen); /* other params */ | 568 | memcpy(opblk + 5, ibuf, ibuflen); /* other params */ |
571 | 569 | ||
572 | size = i2o_parm_issue(dev, I2O_CMD_UTIL_PARAMS_GET, opblk, | 570 | size = i2o_parm_issue(dev, I2O_CMD_UTIL_PARAMS_GET, opblk, |
573 | size, resblk, reslen); | 571 | size, resblk, reslen); |
574 | 572 | ||
575 | kfree(opblk); | 573 | kfree(opblk); |
576 | if (size > reslen) | 574 | if (size > reslen) |
577 | return reslen; | 575 | return reslen; |
578 | 576 | ||
579 | return size; | 577 | return size; |
580 | } | 578 | } |
581 | 579 | ||
582 | EXPORT_SYMBOL(i2o_device_claim); | 580 | EXPORT_SYMBOL(i2o_device_claim); |
583 | EXPORT_SYMBOL(i2o_device_claim_release); | 581 | EXPORT_SYMBOL(i2o_device_claim_release); |
584 | EXPORT_SYMBOL(i2o_parm_field_get); | 582 | EXPORT_SYMBOL(i2o_parm_field_get); |
585 | EXPORT_SYMBOL(i2o_parm_table_get); | 583 | EXPORT_SYMBOL(i2o_parm_table_get); |
586 | EXPORT_SYMBOL(i2o_parm_issue); | 584 | EXPORT_SYMBOL(i2o_parm_issue); |
587 | 585 |
drivers/message/i2o/driver.c
1 | /* | 1 | /* |
2 | * Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs | 2 | * Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs |
3 | * | 3 | * |
4 | * Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.com> | 4 | * Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.com> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
8 | * Free Software Foundation; either version 2 of the License, or (at your | 8 | * Free Software Foundation; either version 2 of the License, or (at your |
9 | * option) any later version. | 9 | * option) any later version. |
10 | * | 10 | * |
11 | * Fixes/additions: | 11 | * Fixes/additions: |
12 | * Markus Lidel <Markus.Lidel@shadowconnect.com> | 12 | * Markus Lidel <Markus.Lidel@shadowconnect.com> |
13 | * initial version. | 13 | * initial version. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/rwsem.h> | 18 | #include <linux/rwsem.h> |
19 | #include <linux/i2o.h> | 19 | #include <linux/i2o.h> |
20 | #include <linux/workqueue.h> | 20 | #include <linux/workqueue.h> |
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include "core.h" | 23 | #include "core.h" |
24 | 24 | ||
25 | #define OSM_NAME "i2o" | 25 | #define OSM_NAME "i2o" |
26 | 26 | ||
27 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ | 27 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ |
28 | static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; | 28 | static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; |
29 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); | 29 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); |
30 | MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); | 30 | MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); |
31 | 31 | ||
32 | /* I2O drivers lock and array */ | 32 | /* I2O drivers lock and array */ |
33 | static spinlock_t i2o_drivers_lock; | 33 | static spinlock_t i2o_drivers_lock; |
34 | static struct i2o_driver **i2o_drivers; | 34 | static struct i2o_driver **i2o_drivers; |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM) | 37 | * i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM) |
38 | * @dev: device which should be verified | 38 | * @dev: device which should be verified |
39 | * @drv: the driver to match against | 39 | * @drv: the driver to match against |
40 | * | 40 | * |
41 | * Used by the bus to check if the driver wants to handle the device. | 41 | * Used by the bus to check if the driver wants to handle the device. |
42 | * | 42 | * |
43 | * Returns 1 if the class ids of the driver match the class id of the | 43 | * Returns 1 if the class ids of the driver match the class id of the |
44 | * device, otherwise 0. | 44 | * device, otherwise 0. |
45 | */ | 45 | */ |
46 | static int i2o_bus_match(struct device *dev, struct device_driver *drv) | 46 | static int i2o_bus_match(struct device *dev, struct device_driver *drv) |
47 | { | 47 | { |
48 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 48 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
49 | struct i2o_driver *i2o_drv = to_i2o_driver(drv); | 49 | struct i2o_driver *i2o_drv = to_i2o_driver(drv); |
50 | struct i2o_class_id *ids = i2o_drv->classes; | 50 | struct i2o_class_id *ids = i2o_drv->classes; |
51 | 51 | ||
52 | if (ids) | 52 | if (ids) |
53 | while (ids->class_id != I2O_CLASS_END) { | 53 | while (ids->class_id != I2O_CLASS_END) { |
54 | if (ids->class_id == i2o_dev->lct_data.class_id) | 54 | if (ids->class_id == i2o_dev->lct_data.class_id) |
55 | return 1; | 55 | return 1; |
56 | ids++; | 56 | ids++; |
57 | } | 57 | } |
58 | return 0; | 58 | return 0; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | /* I2O bus type */ | 61 | /* I2O bus type */ |
62 | struct bus_type i2o_bus_type = { | 62 | struct bus_type i2o_bus_type = { |
63 | .name = "i2o", | 63 | .name = "i2o", |
64 | .match = i2o_bus_match, | 64 | .match = i2o_bus_match, |
65 | .dev_attrs = i2o_device_attrs | 65 | .dev_attrs = i2o_device_attrs |
66 | }; | 66 | }; |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * i2o_driver_register - Register a I2O driver (OSM) in the I2O core | 69 | * i2o_driver_register - Register a I2O driver (OSM) in the I2O core |
70 | * @drv: I2O driver which should be registered | 70 | * @drv: I2O driver which should be registered |
71 | * | 71 | * |
72 | * Registers the OSM drv in the I2O core and creates an event queues if | 72 | * Registers the OSM drv in the I2O core and creates an event queues if |
73 | * necessary. | 73 | * necessary. |
74 | * | 74 | * |
75 | * Returns 0 on success or negative error code on failure. | 75 | * Returns 0 on success or negative error code on failure. |
76 | */ | 76 | */ |
77 | int i2o_driver_register(struct i2o_driver *drv) | 77 | int i2o_driver_register(struct i2o_driver *drv) |
78 | { | 78 | { |
79 | struct i2o_controller *c; | 79 | struct i2o_controller *c; |
80 | int i; | 80 | int i; |
81 | int rc = 0; | 81 | int rc = 0; |
82 | unsigned long flags; | 82 | unsigned long flags; |
83 | 83 | ||
84 | osm_debug("Register driver %s\n", drv->name); | 84 | osm_debug("Register driver %s\n", drv->name); |
85 | 85 | ||
86 | if (drv->event) { | 86 | if (drv->event) { |
87 | drv->event_queue = create_workqueue(drv->name); | 87 | drv->event_queue = create_workqueue(drv->name); |
88 | if (!drv->event_queue) { | 88 | if (!drv->event_queue) { |
89 | osm_err("Could not initialize event queue for driver " | 89 | osm_err("Could not initialize event queue for driver " |
90 | "%s\n", drv->name); | 90 | "%s\n", drv->name); |
91 | return -EFAULT; | 91 | return -EFAULT; |
92 | } | 92 | } |
93 | osm_debug("Event queue initialized for driver %s\n", drv->name); | 93 | osm_debug("Event queue initialized for driver %s\n", drv->name); |
94 | } else | 94 | } else |
95 | drv->event_queue = NULL; | 95 | drv->event_queue = NULL; |
96 | 96 | ||
97 | drv->driver.name = drv->name; | 97 | drv->driver.name = drv->name; |
98 | drv->driver.bus = &i2o_bus_type; | 98 | drv->driver.bus = &i2o_bus_type; |
99 | 99 | ||
100 | spin_lock_irqsave(&i2o_drivers_lock, flags); | 100 | spin_lock_irqsave(&i2o_drivers_lock, flags); |
101 | 101 | ||
102 | for (i = 0; i2o_drivers[i]; i++) | 102 | for (i = 0; i2o_drivers[i]; i++) |
103 | if (i >= i2o_max_drivers) { | 103 | if (i >= i2o_max_drivers) { |
104 | osm_err("too many drivers registered, increase " | 104 | osm_err("too many drivers registered, increase " |
105 | "max_drivers\n"); | 105 | "max_drivers\n"); |
106 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); | 106 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
107 | return -EFAULT; | 107 | return -EFAULT; |
108 | } | 108 | } |
109 | 109 | ||
110 | drv->context = i; | 110 | drv->context = i; |
111 | i2o_drivers[i] = drv; | 111 | i2o_drivers[i] = drv; |
112 | 112 | ||
113 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); | 113 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
114 | 114 | ||
115 | osm_debug("driver %s gets context id %d\n", drv->name, drv->context); | 115 | osm_debug("driver %s gets context id %d\n", drv->name, drv->context); |
116 | 116 | ||
117 | list_for_each_entry(c, &i2o_controllers, list) { | 117 | list_for_each_entry(c, &i2o_controllers, list) { |
118 | struct i2o_device *i2o_dev; | 118 | struct i2o_device *i2o_dev; |
119 | 119 | ||
120 | i2o_driver_notify_controller_add(drv, c); | 120 | i2o_driver_notify_controller_add(drv, c); |
121 | list_for_each_entry(i2o_dev, &c->devices, list) | 121 | list_for_each_entry(i2o_dev, &c->devices, list) |
122 | i2o_driver_notify_device_add(drv, i2o_dev); | 122 | i2o_driver_notify_device_add(drv, i2o_dev); |
123 | } | 123 | } |
124 | 124 | ||
125 | rc = driver_register(&drv->driver); | 125 | rc = driver_register(&drv->driver); |
126 | if (rc) { | 126 | if (rc) { |
127 | if (drv->event) { | 127 | if (drv->event) { |
128 | destroy_workqueue(drv->event_queue); | 128 | destroy_workqueue(drv->event_queue); |
129 | drv->event_queue = NULL; | 129 | drv->event_queue = NULL; |
130 | } | 130 | } |
131 | } | 131 | } |
132 | 132 | ||
133 | return rc; | 133 | return rc; |
134 | }; | 134 | }; |
135 | 135 | ||
136 | /** | 136 | /** |
137 | * i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core | 137 | * i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core |
138 | * @drv: I2O driver which should be unregistered | 138 | * @drv: I2O driver which should be unregistered |
139 | * | 139 | * |
140 | * Unregisters the OSM drv from the I2O core and cleanup event queues if | 140 | * Unregisters the OSM drv from the I2O core and cleanup event queues if |
141 | * necessary. | 141 | * necessary. |
142 | */ | 142 | */ |
143 | void i2o_driver_unregister(struct i2o_driver *drv) | 143 | void i2o_driver_unregister(struct i2o_driver *drv) |
144 | { | 144 | { |
145 | struct i2o_controller *c; | 145 | struct i2o_controller *c; |
146 | unsigned long flags; | 146 | unsigned long flags; |
147 | 147 | ||
148 | osm_debug("unregister driver %s\n", drv->name); | 148 | osm_debug("unregister driver %s\n", drv->name); |
149 | 149 | ||
150 | driver_unregister(&drv->driver); | 150 | driver_unregister(&drv->driver); |
151 | 151 | ||
152 | list_for_each_entry(c, &i2o_controllers, list) { | 152 | list_for_each_entry(c, &i2o_controllers, list) { |
153 | struct i2o_device *i2o_dev; | 153 | struct i2o_device *i2o_dev; |
154 | 154 | ||
155 | list_for_each_entry(i2o_dev, &c->devices, list) | 155 | list_for_each_entry(i2o_dev, &c->devices, list) |
156 | i2o_driver_notify_device_remove(drv, i2o_dev); | 156 | i2o_driver_notify_device_remove(drv, i2o_dev); |
157 | 157 | ||
158 | i2o_driver_notify_controller_remove(drv, c); | 158 | i2o_driver_notify_controller_remove(drv, c); |
159 | } | 159 | } |
160 | 160 | ||
161 | spin_lock_irqsave(&i2o_drivers_lock, flags); | 161 | spin_lock_irqsave(&i2o_drivers_lock, flags); |
162 | i2o_drivers[drv->context] = NULL; | 162 | i2o_drivers[drv->context] = NULL; |
163 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); | 163 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
164 | 164 | ||
165 | if (drv->event_queue) { | 165 | if (drv->event_queue) { |
166 | destroy_workqueue(drv->event_queue); | 166 | destroy_workqueue(drv->event_queue); |
167 | drv->event_queue = NULL; | 167 | drv->event_queue = NULL; |
168 | osm_debug("event queue removed for %s\n", drv->name); | 168 | osm_debug("event queue removed for %s\n", drv->name); |
169 | } | 169 | } |
170 | }; | 170 | }; |
171 | 171 | ||
172 | /** | 172 | /** |
173 | * i2o_driver_dispatch - dispatch an I2O reply message | 173 | * i2o_driver_dispatch - dispatch an I2O reply message |
174 | * @c: I2O controller of the message | 174 | * @c: I2O controller of the message |
175 | * @m: I2O message number | 175 | * @m: I2O message number |
176 | * @msg: I2O message to be delivered | ||
177 | * | 176 | * |
178 | * The reply is delivered to the driver from which the original message | 177 | * The reply is delivered to the driver from which the original message |
179 | * was. This function is only called from interrupt context. | 178 | * was. This function is only called from interrupt context. |
180 | * | 179 | * |
181 | * Returns 0 on success and the message should not be flushed. Returns > 0 | 180 | * Returns 0 on success and the message should not be flushed. Returns > 0 |
182 | * on success and if the message should be flushed afterwords. Returns | 181 | * on success and if the message should be flushed afterwords. Returns |
183 | * negative error code on failure (the message will be flushed too). | 182 | * negative error code on failure (the message will be flushed too). |
184 | */ | 183 | */ |
185 | int i2o_driver_dispatch(struct i2o_controller *c, u32 m) | 184 | int i2o_driver_dispatch(struct i2o_controller *c, u32 m) |
186 | { | 185 | { |
187 | struct i2o_driver *drv; | 186 | struct i2o_driver *drv; |
188 | struct i2o_message *msg = i2o_msg_out_to_virt(c, m); | 187 | struct i2o_message *msg = i2o_msg_out_to_virt(c, m); |
189 | u32 context = le32_to_cpu(msg->u.s.icntxt); | 188 | u32 context = le32_to_cpu(msg->u.s.icntxt); |
190 | unsigned long flags; | 189 | unsigned long flags; |
191 | 190 | ||
192 | if (unlikely(context >= i2o_max_drivers)) { | 191 | if (unlikely(context >= i2o_max_drivers)) { |
193 | osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, | 192 | osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, |
194 | context); | 193 | context); |
195 | return -EIO; | 194 | return -EIO; |
196 | } | 195 | } |
197 | 196 | ||
198 | spin_lock_irqsave(&i2o_drivers_lock, flags); | 197 | spin_lock_irqsave(&i2o_drivers_lock, flags); |
199 | drv = i2o_drivers[context]; | 198 | drv = i2o_drivers[context]; |
200 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); | 199 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
201 | 200 | ||
202 | if (unlikely(!drv)) { | 201 | if (unlikely(!drv)) { |
203 | osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, | 202 | osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, |
204 | context); | 203 | context); |
205 | return -EIO; | 204 | return -EIO; |
206 | } | 205 | } |
207 | 206 | ||
208 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { | 207 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { |
209 | struct i2o_device *dev, *tmp; | 208 | struct i2o_device *dev, *tmp; |
210 | struct i2o_event *evt; | 209 | struct i2o_event *evt; |
211 | u16 size; | 210 | u16 size; |
212 | u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff; | 211 | u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff; |
213 | 212 | ||
214 | osm_debug("event received from device %d\n", tid); | 213 | osm_debug("event received from device %d\n", tid); |
215 | 214 | ||
216 | if (!drv->event) | 215 | if (!drv->event) |
217 | return -EIO; | 216 | return -EIO; |
218 | 217 | ||
219 | /* cut of header from message size (in 32-bit words) */ | 218 | /* cut of header from message size (in 32-bit words) */ |
220 | size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; | 219 | size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; |
221 | 220 | ||
222 | evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); | 221 | evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); |
223 | if (!evt) | 222 | if (!evt) |
224 | return -ENOMEM; | 223 | return -ENOMEM; |
225 | 224 | ||
226 | evt->size = size; | 225 | evt->size = size; |
227 | evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); | 226 | evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); |
228 | evt->event_indicator = le32_to_cpu(msg->body[0]); | 227 | evt->event_indicator = le32_to_cpu(msg->body[0]); |
229 | memcpy(&evt->data, &msg->body[1], size * 4); | 228 | memcpy(&evt->data, &msg->body[1], size * 4); |
230 | 229 | ||
231 | list_for_each_entry_safe(dev, tmp, &c->devices, list) | 230 | list_for_each_entry_safe(dev, tmp, &c->devices, list) |
232 | if (dev->lct_data.tid == tid) { | 231 | if (dev->lct_data.tid == tid) { |
233 | evt->i2o_dev = dev; | 232 | evt->i2o_dev = dev; |
234 | break; | 233 | break; |
235 | } | 234 | } |
236 | 235 | ||
237 | INIT_WORK(&evt->work, drv->event); | 236 | INIT_WORK(&evt->work, drv->event); |
238 | queue_work(drv->event_queue, &evt->work); | 237 | queue_work(drv->event_queue, &evt->work); |
239 | return 1; | 238 | return 1; |
240 | } | 239 | } |
241 | 240 | ||
242 | if (unlikely(!drv->reply)) { | 241 | if (unlikely(!drv->reply)) { |
243 | osm_debug("%s: Reply to driver %s, but no reply function" | 242 | osm_debug("%s: Reply to driver %s, but no reply function" |
244 | " defined!\n", c->name, drv->name); | 243 | " defined!\n", c->name, drv->name); |
245 | return -EIO; | 244 | return -EIO; |
246 | } | 245 | } |
247 | 246 | ||
248 | return drv->reply(c, m, msg); | 247 | return drv->reply(c, m, msg); |
249 | } | 248 | } |
250 | 249 | ||
251 | /** | 250 | /** |
252 | * i2o_driver_notify_controller_add_all - Send notify of added controller | 251 | * i2o_driver_notify_controller_add_all - Send notify of added controller |
253 | * @c: newly added controller | 252 | * @c: newly added controller |
254 | * | 253 | * |
255 | * Send notifications to all registered drivers that a new controller was | 254 | * Send notifications to all registered drivers that a new controller was |
256 | * added. | 255 | * added. |
257 | */ | 256 | */ |
258 | void i2o_driver_notify_controller_add_all(struct i2o_controller *c) | 257 | void i2o_driver_notify_controller_add_all(struct i2o_controller *c) |
259 | { | 258 | { |
260 | int i; | 259 | int i; |
261 | struct i2o_driver *drv; | 260 | struct i2o_driver *drv; |
262 | 261 | ||
263 | for (i = 0; i < i2o_max_drivers; i++) { | 262 | for (i = 0; i < i2o_max_drivers; i++) { |
264 | drv = i2o_drivers[i]; | 263 | drv = i2o_drivers[i]; |
265 | 264 | ||
266 | if (drv) | 265 | if (drv) |
267 | i2o_driver_notify_controller_add(drv, c); | 266 | i2o_driver_notify_controller_add(drv, c); |
268 | } | 267 | } |
269 | } | 268 | } |
270 | 269 | ||
271 | /** | 270 | /** |
272 | * i2o_driver_notify_controller_remove_all - Send notify of removed controller | 271 | * i2o_driver_notify_controller_remove_all - Send notify of removed controller |
273 | * @c: controller that is being removed | 272 | * @c: controller that is being removed |
274 | * | 273 | * |
275 | * Send notifications to all registered drivers that a controller was | 274 | * Send notifications to all registered drivers that a controller was |
276 | * removed. | 275 | * removed. |
277 | */ | 276 | */ |
278 | void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) | 277 | void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) |
279 | { | 278 | { |
280 | int i; | 279 | int i; |
281 | struct i2o_driver *drv; | 280 | struct i2o_driver *drv; |
282 | 281 | ||
283 | for (i = 0; i < i2o_max_drivers; i++) { | 282 | for (i = 0; i < i2o_max_drivers; i++) { |
284 | drv = i2o_drivers[i]; | 283 | drv = i2o_drivers[i]; |
285 | 284 | ||
286 | if (drv) | 285 | if (drv) |
287 | i2o_driver_notify_controller_remove(drv, c); | 286 | i2o_driver_notify_controller_remove(drv, c); |
288 | } | 287 | } |
289 | } | 288 | } |
290 | 289 | ||
291 | /** | 290 | /** |
292 | * i2o_driver_notify_device_add_all - Send notify of added device | 291 | * i2o_driver_notify_device_add_all - Send notify of added device |
293 | * @i2o_dev: newly added I2O device | 292 | * @i2o_dev: newly added I2O device |
294 | * | 293 | * |
295 | * Send notifications to all registered drivers that a device was added. | 294 | * Send notifications to all registered drivers that a device was added. |
296 | */ | 295 | */ |
297 | void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) | 296 | void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) |
298 | { | 297 | { |
299 | int i; | 298 | int i; |
300 | struct i2o_driver *drv; | 299 | struct i2o_driver *drv; |
301 | 300 | ||
302 | for (i = 0; i < i2o_max_drivers; i++) { | 301 | for (i = 0; i < i2o_max_drivers; i++) { |
303 | drv = i2o_drivers[i]; | 302 | drv = i2o_drivers[i]; |
304 | 303 | ||
305 | if (drv) | 304 | if (drv) |
306 | i2o_driver_notify_device_add(drv, i2o_dev); | 305 | i2o_driver_notify_device_add(drv, i2o_dev); |
307 | } | 306 | } |
308 | } | 307 | } |
309 | 308 | ||
310 | /** | 309 | /** |
311 | * i2o_driver_notify_device_remove_all - Send notify of removed device | 310 | * i2o_driver_notify_device_remove_all - Send notify of removed device |
312 | * @i2o_dev: device that is being removed | 311 | * @i2o_dev: device that is being removed |
313 | * | 312 | * |
314 | * Send notifications to all registered drivers that a device was removed. | 313 | * Send notifications to all registered drivers that a device was removed. |
315 | */ | 314 | */ |
316 | void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) | 315 | void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) |
317 | { | 316 | { |
318 | int i; | 317 | int i; |
319 | struct i2o_driver *drv; | 318 | struct i2o_driver *drv; |
320 | 319 | ||
321 | for (i = 0; i < i2o_max_drivers; i++) { | 320 | for (i = 0; i < i2o_max_drivers; i++) { |
322 | drv = i2o_drivers[i]; | 321 | drv = i2o_drivers[i]; |
323 | 322 | ||
324 | if (drv) | 323 | if (drv) |
325 | i2o_driver_notify_device_remove(drv, i2o_dev); | 324 | i2o_driver_notify_device_remove(drv, i2o_dev); |
326 | } | 325 | } |
327 | } | 326 | } |
328 | 327 | ||
329 | /** | 328 | /** |
330 | * i2o_driver_init - initialize I2O drivers (OSMs) | 329 | * i2o_driver_init - initialize I2O drivers (OSMs) |
331 | * | 330 | * |
332 | * Registers the I2O bus and allocate memory for the array of OSMs. | 331 | * Registers the I2O bus and allocate memory for the array of OSMs. |
333 | * | 332 | * |
334 | * Returns 0 on success or negative error code on failure. | 333 | * Returns 0 on success or negative error code on failure. |
335 | */ | 334 | */ |
336 | int __init i2o_driver_init(void) | 335 | int __init i2o_driver_init(void) |
337 | { | 336 | { |
338 | int rc = 0; | 337 | int rc = 0; |
339 | 338 | ||
340 | spin_lock_init(&i2o_drivers_lock); | 339 | spin_lock_init(&i2o_drivers_lock); |
341 | 340 | ||
342 | if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) { | 341 | if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) { |
343 | osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n", | 342 | osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n", |
344 | i2o_max_drivers); | 343 | i2o_max_drivers); |
345 | i2o_max_drivers = I2O_MAX_DRIVERS; | 344 | i2o_max_drivers = I2O_MAX_DRIVERS; |
346 | } | 345 | } |
347 | osm_info("max drivers = %d\n", i2o_max_drivers); | 346 | osm_info("max drivers = %d\n", i2o_max_drivers); |
348 | 347 | ||
349 | i2o_drivers = | 348 | i2o_drivers = |
350 | kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL); | 349 | kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL); |
351 | if (!i2o_drivers) | 350 | if (!i2o_drivers) |
352 | return -ENOMEM; | 351 | return -ENOMEM; |
353 | 352 | ||
354 | rc = bus_register(&i2o_bus_type); | 353 | rc = bus_register(&i2o_bus_type); |
355 | 354 | ||
356 | if (rc < 0) | 355 | if (rc < 0) |
357 | kfree(i2o_drivers); | 356 | kfree(i2o_drivers); |
358 | 357 | ||
359 | return rc; | 358 | return rc; |
360 | }; | 359 | }; |
361 | 360 | ||
362 | /** | 361 | /** |
363 | * i2o_driver_exit - clean up I2O drivers (OSMs) | 362 | * i2o_driver_exit - clean up I2O drivers (OSMs) |
364 | * | 363 | * |
365 | * Unregisters the I2O bus and frees driver array. | 364 | * Unregisters the I2O bus and frees driver array. |
366 | */ | 365 | */ |
367 | void i2o_driver_exit(void) | 366 | void i2o_driver_exit(void) |
368 | { | 367 | { |
369 | bus_unregister(&i2o_bus_type); | 368 | bus_unregister(&i2o_bus_type); |
370 | kfree(i2o_drivers); | 369 | kfree(i2o_drivers); |
371 | }; | 370 | }; |
372 | 371 | ||
373 | EXPORT_SYMBOL(i2o_driver_register); | 372 | EXPORT_SYMBOL(i2o_driver_register); |
374 | EXPORT_SYMBOL(i2o_driver_unregister); | 373 | EXPORT_SYMBOL(i2o_driver_unregister); |
375 | EXPORT_SYMBOL(i2o_driver_notify_controller_add_all); | 374 | EXPORT_SYMBOL(i2o_driver_notify_controller_add_all); |
376 | EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all); | 375 | EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all); |
377 | EXPORT_SYMBOL(i2o_driver_notify_device_add_all); | 376 | EXPORT_SYMBOL(i2o_driver_notify_device_add_all); |
378 | EXPORT_SYMBOL(i2o_driver_notify_device_remove_all); | 377 | EXPORT_SYMBOL(i2o_driver_notify_device_remove_all); |
379 | 378 |