diff options
Diffstat (limited to 'drivers/message/i2o/exec-osm.c')
-rw-r--r-- | drivers/message/i2o/exec-osm.c | 131 |
1 files changed, 95 insertions, 36 deletions
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 79c1cbfb8f44..bda2c62648ba 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/i2o.h> | 31 | #include <linux/i2o.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include "core.h" | ||
33 | 34 | ||
34 | #define OSM_NAME "exec-osm" | 35 | #define OSM_NAME "exec-osm" |
35 | 36 | ||
@@ -37,9 +38,6 @@ struct i2o_driver i2o_exec_driver; | |||
37 | 38 | ||
38 | static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); | 39 | static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); |
39 | 40 | ||
40 | /* Module internal functions from other sources */ | ||
41 | extern int i2o_device_parse_lct(struct i2o_controller *); | ||
42 | |||
43 | /* global wait list for POST WAIT */ | 41 | /* global wait list for POST WAIT */ |
44 | static LIST_HEAD(i2o_exec_wait_list); | 42 | static LIST_HEAD(i2o_exec_wait_list); |
45 | 43 | ||
@@ -50,7 +48,7 @@ struct i2o_exec_wait { | |||
50 | u32 tcntxt; /* transaction context from reply */ | 48 | u32 tcntxt; /* transaction context from reply */ |
51 | int complete; /* 1 if reply received otherwise 0 */ | 49 | int complete; /* 1 if reply received otherwise 0 */ |
52 | u32 m; /* message id */ | 50 | u32 m; /* message id */ |
53 | struct i2o_message __iomem *msg; /* pointer to the reply message */ | 51 | struct i2o_message *msg; /* pointer to the reply message */ |
54 | struct list_head list; /* node in global wait list */ | 52 | struct list_head list; /* node in global wait list */ |
55 | }; | 53 | }; |
56 | 54 | ||
@@ -108,7 +106,8 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) | |||
108 | * buffer must not be freed. Instead the event completion will free them | 106 | * buffer must not be freed. Instead the event completion will free them |
109 | * for you. In all other cases the buffer are your problem. | 107 | * for you. In all other cases the buffer are your problem. |
110 | * | 108 | * |
111 | * Returns 0 on success or negative error code on failure. | 109 | * Returns 0 on success, negative error code on timeout or positive error |
110 | * code from reply. | ||
112 | */ | 111 | */ |
113 | int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | 112 | int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long |
114 | timeout, struct i2o_dma *dma) | 113 | timeout, struct i2o_dma *dma) |
@@ -116,7 +115,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
116 | DECLARE_WAIT_QUEUE_HEAD(wq); | 115 | DECLARE_WAIT_QUEUE_HEAD(wq); |
117 | struct i2o_exec_wait *wait; | 116 | struct i2o_exec_wait *wait; |
118 | static u32 tcntxt = 0x80000000; | 117 | static u32 tcntxt = 0x80000000; |
119 | struct i2o_message __iomem *msg = c->in_queue.virt + m; | 118 | struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m); |
120 | int rc = 0; | 119 | int rc = 0; |
121 | 120 | ||
122 | wait = i2o_exec_wait_alloc(); | 121 | wait = i2o_exec_wait_alloc(); |
@@ -153,7 +152,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
153 | list_add(&wait->list, &i2o_exec_wait_list); | 152 | list_add(&wait->list, &i2o_exec_wait_list); |
154 | 153 | ||
155 | wait_event_interruptible_timeout(wq, wait->complete, | 154 | wait_event_interruptible_timeout(wq, wait->complete, |
156 | timeout * HZ); | 155 | timeout * HZ); |
157 | 156 | ||
158 | wait->wq = NULL; | 157 | wait->wq = NULL; |
159 | } | 158 | } |
@@ -161,8 +160,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
161 | barrier(); | 160 | barrier(); |
162 | 161 | ||
163 | if (wait->complete) { | 162 | if (wait->complete) { |
164 | if (readl(&wait->msg->body[0]) >> 24) | 163 | rc = le32_to_cpu(wait->msg->body[0]) >> 24; |
165 | rc = readl(&wait->msg->body[0]) & 0xff; | ||
166 | i2o_flush_reply(c, wait->m); | 164 | i2o_flush_reply(c, wait->m); |
167 | i2o_exec_wait_free(wait); | 165 | i2o_exec_wait_free(wait); |
168 | } else { | 166 | } else { |
@@ -187,6 +185,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
187 | * @c: I2O controller which answers | 185 | * @c: I2O controller which answers |
188 | * @m: message id | 186 | * @m: message id |
189 | * @msg: pointer to the I2O reply message | 187 | * @msg: pointer to the I2O reply message |
188 | * @context: transaction context of request | ||
190 | * | 189 | * |
191 | * This function is called in interrupt context only. If the reply reached | 190 | * This function is called in interrupt context only. If the reply reached |
192 | * before the timeout, the i2o_exec_wait struct is filled with the message | 191 | * before the timeout, the i2o_exec_wait struct is filled with the message |
@@ -201,16 +200,12 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long | |||
201 | * message must also be given back to the controller. | 200 | * message must also be given back to the controller. |
202 | */ | 201 | */ |
203 | static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | 202 | static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, |
204 | struct i2o_message __iomem *msg) | 203 | struct i2o_message *msg, u32 context) |
205 | { | 204 | { |
206 | struct i2o_exec_wait *wait, *tmp; | 205 | struct i2o_exec_wait *wait, *tmp; |
207 | static spinlock_t lock; | 206 | unsigned long flags; |
207 | static spinlock_t lock = SPIN_LOCK_UNLOCKED; | ||
208 | int rc = 1; | 208 | int rc = 1; |
209 | u32 context; | ||
210 | |||
211 | spin_lock_init(&lock); | ||
212 | |||
213 | context = readl(&msg->u.s.tcntxt); | ||
214 | 209 | ||
215 | /* | 210 | /* |
216 | * We need to search through the i2o_exec_wait_list to see if the given | 211 | * We need to search through the i2o_exec_wait_list to see if the given |
@@ -219,11 +214,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
219 | * already expired. Not much we can do about that except log it for | 214 | * already expired. Not much we can do about that except log it for |
220 | * debug purposes, increase timeout, and recompile. | 215 | * debug purposes, increase timeout, and recompile. |
221 | */ | 216 | */ |
222 | spin_lock(&lock); | 217 | spin_lock_irqsave(&lock, flags); |
223 | list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { | 218 | list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { |
224 | if (wait->tcntxt == context) { | 219 | if (wait->tcntxt == context) { |
225 | list_del(&wait->list); | 220 | list_del(&wait->list); |
226 | 221 | ||
222 | spin_unlock_irqrestore(&lock, flags); | ||
223 | |||
227 | wait->m = m; | 224 | wait->m = m; |
228 | wait->msg = msg; | 225 | wait->msg = msg; |
229 | wait->complete = 1; | 226 | wait->complete = 1; |
@@ -245,21 +242,63 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
245 | rc = -1; | 242 | rc = -1; |
246 | } | 243 | } |
247 | 244 | ||
248 | spin_unlock(&lock); | ||
249 | |||
250 | return rc; | 245 | return rc; |
251 | } | 246 | } |
252 | } | 247 | } |
253 | 248 | ||
254 | spin_unlock(&lock); | 249 | spin_unlock_irqrestore(&lock, flags); |
255 | 250 | ||
256 | pr_debug("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, | 251 | osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, |
257 | context); | 252 | context); |
258 | 253 | ||
259 | return -1; | 254 | return -1; |
260 | }; | 255 | }; |
261 | 256 | ||
262 | /** | 257 | /** |
258 | * i2o_exec_show_vendor_id - Displays Vendor ID of controller | ||
259 | * @d: device of which the Vendor ID should be displayed | ||
260 | * @buf: buffer into which the Vendor ID should be printed | ||
261 | * | ||
262 | * Returns number of bytes printed into buffer. | ||
263 | */ | ||
264 | static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf) | ||
265 | { | ||
266 | struct i2o_device *dev = to_i2o_device(d); | ||
267 | u16 id; | ||
268 | |||
269 | if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { | ||
270 | sprintf(buf, "0x%04x", id); | ||
271 | return strlen(buf) + 1; | ||
272 | } | ||
273 | |||
274 | return 0; | ||
275 | }; | ||
276 | |||
277 | /** | ||
278 | * i2o_exec_show_product_id - Displays Product ID of controller | ||
279 | * @d: device of which the Product ID should be displayed | ||
280 | * @buf: buffer into which the Product ID should be printed | ||
281 | * | ||
282 | * Returns number of bytes printed into buffer. | ||
283 | */ | ||
284 | static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf) | ||
285 | { | ||
286 | struct i2o_device *dev = to_i2o_device(d); | ||
287 | u16 id; | ||
288 | |||
289 | if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { | ||
290 | sprintf(buf, "0x%04x", id); | ||
291 | return strlen(buf) + 1; | ||
292 | } | ||
293 | |||
294 | return 0; | ||
295 | }; | ||
296 | |||
297 | /* Exec-OSM device attributes */ | ||
298 | static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL); | ||
299 | static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); | ||
300 | |||
301 | /** | ||
263 | * i2o_exec_probe - Called if a new I2O device (executive class) appears | 302 | * i2o_exec_probe - Called if a new I2O device (executive class) appears |
264 | * @dev: I2O device which should be probed | 303 | * @dev: I2O device which should be probed |
265 | * | 304 | * |
@@ -271,10 +310,16 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
271 | static int i2o_exec_probe(struct device *dev) | 310 | static int i2o_exec_probe(struct device *dev) |
272 | { | 311 | { |
273 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 312 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
313 | struct i2o_controller *c = i2o_dev->iop; | ||
274 | 314 | ||
275 | i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); | 315 | i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); |
276 | 316 | ||
277 | i2o_dev->iop->exec = i2o_dev; | 317 | c->exec = i2o_dev; |
318 | |||
319 | i2o_exec_lct_notify(c, c->lct->change_ind + 1); | ||
320 | |||
321 | device_create_file(dev, &dev_attr_vendor_id); | ||
322 | device_create_file(dev, &dev_attr_product_id); | ||
278 | 323 | ||
279 | return 0; | 324 | return 0; |
280 | }; | 325 | }; |
@@ -289,6 +334,9 @@ static int i2o_exec_probe(struct device *dev) | |||
289 | */ | 334 | */ |
290 | static int i2o_exec_remove(struct device *dev) | 335 | static int i2o_exec_remove(struct device *dev) |
291 | { | 336 | { |
337 | device_remove_file(dev, &dev_attr_product_id); | ||
338 | device_remove_file(dev, &dev_attr_vendor_id); | ||
339 | |||
292 | i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); | 340 | i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); |
293 | 341 | ||
294 | return 0; | 342 | return 0; |
@@ -300,12 +348,16 @@ static int i2o_exec_remove(struct device *dev) | |||
300 | * | 348 | * |
301 | * This function handles asynchronus LCT NOTIFY replies. It parses the | 349 | * This function handles asynchronus LCT NOTIFY replies. It parses the |
302 | * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY | 350 | * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY |
303 | * again. | 351 | * again, otherwise send LCT NOTIFY to get informed on next LCT change. |
304 | */ | 352 | */ |
305 | static void i2o_exec_lct_modified(struct i2o_controller *c) | 353 | static void i2o_exec_lct_modified(struct i2o_controller *c) |
306 | { | 354 | { |
307 | if (i2o_device_parse_lct(c) == -EAGAIN) | 355 | u32 change_ind = 0; |
308 | i2o_exec_lct_notify(c, 0); | 356 | |
357 | if (i2o_device_parse_lct(c) != -EAGAIN) | ||
358 | change_ind = c->lct->change_ind + 1; | ||
359 | |||
360 | i2o_exec_lct_notify(c, change_ind); | ||
309 | }; | 361 | }; |
310 | 362 | ||
311 | /** | 363 | /** |
@@ -325,8 +377,14 @@ static void i2o_exec_lct_modified(struct i2o_controller *c) | |||
325 | static int i2o_exec_reply(struct i2o_controller *c, u32 m, | 377 | static int i2o_exec_reply(struct i2o_controller *c, u32 m, |
326 | struct i2o_message *msg) | 378 | struct i2o_message *msg) |
327 | { | 379 | { |
328 | if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { // Fail bit is set | 380 | u32 context; |
329 | struct i2o_message __iomem *pmsg; /* preserved message */ | 381 | |
382 | if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { | ||
383 | /* | ||
384 | * If Fail bit is set we must take the transaction context of | ||
385 | * the preserved message to find the right request again. | ||
386 | */ | ||
387 | struct i2o_message __iomem *pmsg; | ||
330 | u32 pm; | 388 | u32 pm; |
331 | 389 | ||
332 | pm = le32_to_cpu(msg->body[3]); | 390 | pm = le32_to_cpu(msg->body[3]); |
@@ -335,15 +393,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, | |||
335 | 393 | ||
336 | i2o_report_status(KERN_INFO, "i2o_core", msg); | 394 | i2o_report_status(KERN_INFO, "i2o_core", msg); |
337 | 395 | ||
338 | /* Release the preserved msg by resubmitting it as a NOP */ | 396 | context = readl(&pmsg->u.s.tcntxt); |
339 | i2o_msg_nop(c, pm); | ||
340 | 397 | ||
341 | /* If reply to i2o_post_wait failed, return causes a timeout */ | 398 | /* Release the preserved msg */ |
342 | return -1; | 399 | i2o_msg_nop(c, pm); |
343 | } | 400 | } else |
401 | context = le32_to_cpu(msg->u.s.tcntxt); | ||
344 | 402 | ||
345 | if (le32_to_cpu(msg->u.s.tcntxt) & 0x80000000) | 403 | if (context & 0x80000000) |
346 | return i2o_msg_post_wait_complete(c, m, msg); | 404 | return i2o_msg_post_wait_complete(c, m, msg, context); |
347 | 405 | ||
348 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { | 406 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { |
349 | struct work_struct *work; | 407 | struct work_struct *work; |
@@ -381,8 +439,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, | |||
381 | */ | 439 | */ |
382 | static void i2o_exec_event(struct i2o_event *evt) | 440 | static void i2o_exec_event(struct i2o_event *evt) |
383 | { | 441 | { |
384 | osm_info("Event received from device: %d\n", | 442 | if (likely(evt->i2o_dev)) |
385 | evt->i2o_dev->lct_data.tid); | 443 | osm_debug("Event received from device: %d\n", |
444 | evt->i2o_dev->lct_data.tid); | ||
386 | kfree(evt); | 445 | kfree(evt); |
387 | }; | 446 | }; |
388 | 447 | ||