aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message
diff options
context:
space:
mode:
authorMarkus Lidel <Markus.Lidel@shadowconnect.com>2006-06-10 12:54:14 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-10 14:02:05 -0400
commit57a62fed871eb2a95f296fe6c5c250ce21b81a79 (patch)
tree0e399966d58f7177e1c34a765e768e0865fc5813 /drivers/message
parenta913f50706b21c7933f53cec678bb9a1c2383499 (diff)
[PATCH] I2O: Bugfixes to get I2O working again
From: Markus Lidel <Markus.Lidel@shadowconnect.com> - Fixed locking of struct i2o_exec_wait in Executive-OSM - Removed LCT Notify in i2o_exec_probe() which caused freeing memory and accessing freed memory during first enumeration of I2O devices - Added missing locking in i2o_exec_lct_notify() - removed put_device() of I2O controller in i2o_iop_remove() which caused the controller structure get freed to early - Fixed size of mempool in i2o_iop_alloc() - Fixed access to freed memory in i2o_msg_get() See http://bugzilla.kernel.org/show_bug.cgi?id=6561 Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/message')
-rw-r--r--drivers/message/i2o/exec-osm.c72
-rw-r--r--drivers/message/i2o/iop.c4
2 files changed, 38 insertions, 38 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);
322static int i2o_exec_probe(struct device *dev) 325static 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
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 492167446936..febbdd4e0605 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -804,8 +804,6 @@ void i2o_iop_remove(struct i2o_controller *c)
804 804
805 /* Ask the IOP to switch to RESET state */ 805 /* Ask the IOP to switch to RESET state */
806 i2o_iop_reset(c); 806 i2o_iop_reset(c);
807
808 put_device(&c->device);
809} 807}
810 808
811/** 809/**
@@ -1059,7 +1057,7 @@ struct i2o_controller *i2o_iop_alloc(void)
1059 1057
1060 snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name); 1058 snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);
1061 if (i2o_pool_alloc 1059 if (i2o_pool_alloc
1062 (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4, 1060 (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32),
1063 I2O_MSG_INPOOL_MIN)) { 1061 I2O_MSG_INPOOL_MIN)) {
1064 kfree(c); 1062 kfree(c);
1065 return ERR_PTR(-ENOMEM); 1063 return ERR_PTR(-ENOMEM);