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 | ||
