diff options
Diffstat (limited to 'drivers/message/i2o/exec-osm.c')
| -rw-r--r-- | drivers/message/i2o/exec-osm.c | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 5ea133c59afb..7bd4d85d0b42 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c | |||
| @@ -55,6 +55,7 @@ struct i2o_exec_wait { | |||
| 55 | u32 m; /* message id */ | 55 | u32 m; /* message id */ |
| 56 | struct i2o_message *msg; /* pointer to the reply message */ | 56 | struct i2o_message *msg; /* pointer to the reply message */ |
| 57 | struct list_head list; /* node in global wait list */ | 57 | struct list_head list; /* node in global wait list */ |
| 58 | spinlock_t lock; /* lock before modifying */ | ||
| 58 | }; | 59 | }; |
| 59 | 60 | ||
| 60 | /* Work struct needed to handle LCT NOTIFY replies */ | 61 | /* Work struct needed to handle LCT NOTIFY replies */ |
| @@ -87,6 +88,7 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void) | |||
| 87 | return NULL; | 88 | return NULL; |
| 88 | 89 | ||
| 89 | INIT_LIST_HEAD(&wait->list); | 90 | INIT_LIST_HEAD(&wait->list); |
| 91 | spin_lock_init(&wait->lock); | ||
| 90 | 92 | ||
| 91 | return wait; | 93 | return wait; |
| 92 | }; | 94 | }; |
| @@ -125,6 +127,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, | |||
| 125 | DECLARE_WAIT_QUEUE_HEAD(wq); | 127 | DECLARE_WAIT_QUEUE_HEAD(wq); |
| 126 | struct i2o_exec_wait *wait; | 128 | struct i2o_exec_wait *wait; |
| 127 | static u32 tcntxt = 0x80000000; | 129 | static u32 tcntxt = 0x80000000; |
| 130 | long flags; | ||
| 128 | int rc = 0; | 131 | int rc = 0; |
| 129 | 132 | ||
| 130 | wait = i2o_exec_wait_alloc(); | 133 | wait = i2o_exec_wait_alloc(); |
| @@ -146,33 +149,28 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, | |||
| 146 | wait->tcntxt = tcntxt++; | 149 | wait->tcntxt = tcntxt++; |
| 147 | msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt); | 150 | msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt); |
| 148 | 151 | ||
| 152 | wait->wq = &wq; | ||
| 153 | /* | ||
| 154 | * we add elements to the head, because if a entry in the list will | ||
| 155 | * never be removed, we have to iterate over it every time | ||
| 156 | */ | ||
| 157 | list_add(&wait->list, &i2o_exec_wait_list); | ||
| 158 | |||
| 149 | /* | 159 | /* |
| 150 | * Post the message to the controller. At some point later it will | 160 | * Post the message to the controller. At some point later it will |
| 151 | * return. If we time out before it returns then complete will be zero. | 161 | * return. If we time out before it returns then complete will be zero. |
| 152 | */ | 162 | */ |
| 153 | i2o_msg_post(c, msg); | 163 | i2o_msg_post(c, msg); |
| 154 | 164 | ||
| 155 | if (!wait->complete) { | 165 | wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ); |
| 156 | wait->wq = &wq; | ||
| 157 | /* | ||
| 158 | * we add elements add the head, because if a entry in the list | ||
| 159 | * will never be removed, we have to iterate over it every time | ||
| 160 | */ | ||
| 161 | list_add(&wait->list, &i2o_exec_wait_list); | ||
| 162 | |||
| 163 | wait_event_interruptible_timeout(wq, wait->complete, | ||
| 164 | timeout * HZ); | ||
| 165 | 166 | ||
| 166 | wait->wq = NULL; | 167 | spin_lock_irqsave(&wait->lock, flags); |
| 167 | } | ||
| 168 | 168 | ||
| 169 | barrier(); | 169 | wait->wq = NULL; |
| 170 | 170 | ||
| 171 | if (wait->complete) { | 171 | if (wait->complete) |
| 172 | rc = le32_to_cpu(wait->msg->body[0]) >> 24; | 172 | rc = le32_to_cpu(wait->msg->body[0]) >> 24; |
| 173 | i2o_flush_reply(c, wait->m); | 173 | else { |
| 174 | i2o_exec_wait_free(wait); | ||
| 175 | } else { | ||
| 176 | /* | 174 | /* |
| 177 | * We cannot remove it now. This is important. When it does | 175 | * We cannot remove it now. This is important. When it does |
| 178 | * terminate (which it must do if the controller has not | 176 | * terminate (which it must do if the controller has not |
| @@ -186,6 +184,13 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, | |||
| 186 | rc = -ETIMEDOUT; | 184 | rc = -ETIMEDOUT; |
| 187 | } | 185 | } |
| 188 | 186 | ||
| 187 | spin_unlock_irqrestore(&wait->lock, flags); | ||
| 188 | |||
| 189 | if (rc != -ETIMEDOUT) { | ||
| 190 | i2o_flush_reply(c, wait->m); | ||
| 191 | i2o_exec_wait_free(wait); | ||
| 192 | } | ||
| 193 | |||
| 189 | return rc; | 194 | return rc; |
| 190 | }; | 195 | }; |
| 191 | 196 | ||
| @@ -213,7 +218,6 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
| 213 | { | 218 | { |
| 214 | struct i2o_exec_wait *wait, *tmp; | 219 | struct i2o_exec_wait *wait, *tmp; |
| 215 | unsigned long flags; | 220 | unsigned long flags; |
| 216 | static spinlock_t lock = SPIN_LOCK_UNLOCKED; | ||
| 217 | int rc = 1; | 221 | int rc = 1; |
| 218 | 222 | ||
| 219 | /* | 223 | /* |
| @@ -223,23 +227,24 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
| 223 | * already expired. Not much we can do about that except log it for | 227 | * already expired. Not much we can do about that except log it for |
| 224 | * debug purposes, increase timeout, and recompile. | 228 | * debug purposes, increase timeout, and recompile. |
| 225 | */ | 229 | */ |
| 226 | spin_lock_irqsave(&lock, flags); | ||
| 227 | list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { | 230 | list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { |
| 228 | if (wait->tcntxt == context) { | 231 | if (wait->tcntxt == context) { |
| 229 | list_del(&wait->list); | 232 | spin_lock_irqsave(&wait->lock, flags); |
| 230 | 233 | ||
| 231 | spin_unlock_irqrestore(&lock, flags); | 234 | list_del(&wait->list); |
| 232 | 235 | ||
| 233 | wait->m = m; | 236 | wait->m = m; |
| 234 | wait->msg = msg; | 237 | wait->msg = msg; |
| 235 | wait->complete = 1; | 238 | wait->complete = 1; |
| 236 | 239 | ||
| 237 | barrier(); | 240 | if (wait->wq) |
| 238 | |||
| 239 | if (wait->wq) { | ||
| 240 | wake_up_interruptible(wait->wq); | ||
| 241 | rc = 0; | 241 | rc = 0; |
| 242 | } else { | 242 | else |
| 243 | rc = -1; | ||
| 244 | |||
| 245 | spin_unlock_irqrestore(&wait->lock, flags); | ||
| 246 | |||
| 247 | if (rc) { | ||
| 243 | struct device *dev; | 248 | struct device *dev; |
| 244 | 249 | ||
| 245 | dev = &c->pdev->dev; | 250 | dev = &c->pdev->dev; |
| @@ -248,15 +253,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
| 248 | c->name); | 253 | c->name); |
| 249 | i2o_dma_free(dev, &wait->dma); | 254 | i2o_dma_free(dev, &wait->dma); |
| 250 | i2o_exec_wait_free(wait); | 255 | i2o_exec_wait_free(wait); |
| 251 | rc = -1; | 256 | } else |
| 252 | } | 257 | wake_up_interruptible(wait->wq); |
| 253 | 258 | ||
| 254 | return rc; | 259 | return rc; |
| 255 | } | 260 | } |
| 256 | } | 261 | } |
| 257 | 262 | ||
| 258 | spin_unlock_irqrestore(&lock, flags); | ||
| 259 | |||
| 260 | osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, | 263 | osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, |
| 261 | context); | 264 | context); |
| 262 | 265 | ||
| @@ -322,14 +325,9 @@ static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); | |||
| 322 | static int i2o_exec_probe(struct device *dev) | 325 | static int i2o_exec_probe(struct device *dev) |
| 323 | { | 326 | { |
| 324 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 327 | struct i2o_device *i2o_dev = to_i2o_device(dev); |
| 325 | struct i2o_controller *c = i2o_dev->iop; | ||
| 326 | 328 | ||
| 327 | i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); | 329 | i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); |
| 328 | 330 | ||
| 329 | c->exec = i2o_dev; | ||
| 330 | |||
| 331 | i2o_exec_lct_notify(c, c->lct->change_ind + 1); | ||
| 332 | |||
| 333 | device_create_file(dev, &dev_attr_vendor_id); | 331 | device_create_file(dev, &dev_attr_vendor_id); |
| 334 | device_create_file(dev, &dev_attr_product_id); | 332 | device_create_file(dev, &dev_attr_product_id); |
| 335 | 333 | ||
| @@ -523,6 +521,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) | |||
| 523 | struct device *dev; | 521 | struct device *dev; |
| 524 | struct i2o_message *msg; | 522 | struct i2o_message *msg; |
| 525 | 523 | ||
| 524 | down(&c->lct_lock); | ||
| 525 | |||
| 526 | dev = &c->pdev->dev; | 526 | dev = &c->pdev->dev; |
| 527 | 527 | ||
| 528 | if (i2o_dma_realloc | 528 | if (i2o_dma_realloc |
| @@ -545,6 +545,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) | |||
| 545 | 545 | ||
| 546 | i2o_msg_post(c, msg); | 546 | i2o_msg_post(c, msg); |
| 547 | 547 | ||
| 548 | up(&c->lct_lock); | ||
| 549 | |||
| 548 | return 0; | 550 | return 0; |
| 549 | }; | 551 | }; |
| 550 | 552 | ||
