diff options
Diffstat (limited to 'drivers/message/i2o/driver.c')
-rw-r--r-- | drivers/message/i2o/driver.c | 89 |
1 files changed, 44 insertions, 45 deletions
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 91f4edbb2a27..c71e68f70e7d 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/rwsem.h> | 18 | #include <linux/rwsem.h> |
19 | #include <linux/i2o.h> | 19 | #include <linux/i2o.h> |
20 | 20 | ||
21 | #define OSM_NAME "core" | ||
22 | |||
21 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ | 23 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ |
22 | unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; | 24 | unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; |
23 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); | 25 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); |
@@ -182,62 +184,59 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m, | |||
182 | struct i2o_driver *drv; | 184 | struct i2o_driver *drv; |
183 | u32 context = readl(&msg->u.s.icntxt); | 185 | u32 context = readl(&msg->u.s.icntxt); |
184 | 186 | ||
185 | if (likely(context < i2o_max_drivers)) { | 187 | if (unlikely(context >= i2o_max_drivers)) { |
186 | spin_lock(&i2o_drivers_lock); | 188 | printk(KERN_WARNING "%s: Spurious reply to unknown driver " |
187 | drv = i2o_drivers[context]; | 189 | "%d\n", c->name, readl(&msg->u.s.icntxt)); |
188 | spin_unlock(&i2o_drivers_lock); | 190 | return -EIO; |
189 | 191 | } | |
190 | if (unlikely(!drv)) { | ||
191 | printk(KERN_WARNING "%s: Spurious reply to unknown " | ||
192 | "driver %d\n", c->name, context); | ||
193 | return -EIO; | ||
194 | } | ||
195 | 192 | ||
196 | if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { | 193 | spin_lock(&i2o_drivers_lock); |
197 | struct i2o_device *dev, *tmp; | 194 | drv = i2o_drivers[context]; |
198 | struct i2o_event *evt; | 195 | spin_unlock(&i2o_drivers_lock); |
199 | u16 size; | ||
200 | u16 tid; | ||
201 | 196 | ||
202 | tid = readl(&msg->u.head[1]) & 0x1fff; | 197 | if (unlikely(!drv)) { |
198 | osm_warn("Spurious reply to unknown driver %d\n", context); | ||
199 | return -EIO; | ||
200 | } | ||
203 | 201 | ||
204 | pr_debug("%s: event received from device %d\n", c->name, | 202 | if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { |
205 | tid); | 203 | struct i2o_device *dev, *tmp; |
204 | struct i2o_event *evt; | ||
205 | u16 size; | ||
206 | u16 tid = readl(&msg->u.head[1]) & 0xfff; | ||
206 | 207 | ||
207 | /* cut of header from message size (in 32-bit words) */ | 208 | osm_debug("event received from device %d\n", tid); |
208 | size = (readl(&msg->u.head[0]) >> 16) - 5; | ||
209 | 209 | ||
210 | evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); | 210 | /* cut of header from message size (in 32-bit words) */ |
211 | if (!evt) | 211 | size = (readl(&msg->u.head[0]) >> 16) - 5; |
212 | return -ENOMEM; | ||
213 | memset(evt, 0, size * 4 + sizeof(*evt)); | ||
214 | 212 | ||
215 | evt->size = size; | 213 | evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO); |
216 | memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, | 214 | if (!evt) |
217 | (size + 2) * 4); | 215 | return -ENOMEM; |
218 | 216 | ||
219 | list_for_each_entry_safe(dev, tmp, &c->devices, list) | 217 | evt->size = size; |
220 | if (dev->lct_data.tid == tid) { | 218 | evt->tcntxt = readl(&msg->u.s.tcntxt); |
221 | evt->i2o_dev = dev; | 219 | evt->event_indicator = readl(&msg->body[0]); |
222 | break; | 220 | memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, size * 4); |
223 | } | ||
224 | 221 | ||
225 | INIT_WORK(&evt->work, (void (*)(void *))drv->event, | 222 | list_for_each_entry_safe(dev, tmp, &c->devices, list) |
226 | evt); | 223 | if (dev->lct_data.tid == tid) { |
227 | queue_work(drv->event_queue, &evt->work); | 224 | evt->i2o_dev = dev; |
228 | return 1; | 225 | break; |
229 | } | 226 | } |
230 | 227 | ||
231 | if (likely(drv->reply)) | 228 | INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt); |
232 | return drv->reply(c, m, msg); | 229 | queue_work(drv->event_queue, &evt->work); |
233 | else | 230 | return 1; |
234 | pr_debug("%s: Reply to driver %s, but no reply function" | 231 | } |
235 | " defined!\n", c->name, drv->name); | 232 | |
233 | if (unlikely(!drv->reply)) { | ||
234 | pr_debug("%s: Reply to driver %s, but no reply function" | ||
235 | " defined!\n", c->name, drv->name); | ||
236 | return -EIO; | 236 | return -EIO; |
237 | } else | 237 | } |
238 | printk(KERN_WARNING "%s: Spurious reply to unknown driver " | 238 | |
239 | "%d\n", c->name, readl(&msg->u.s.icntxt)); | 239 | return drv->reply(c, m, msg); |
240 | return -EIO; | ||
241 | } | 240 | } |
242 | 241 | ||
243 | /** | 242 | /** |