diff options
Diffstat (limited to 'drivers/message/i2o/driver.c')
| -rw-r--r-- | drivers/message/i2o/driver.c | 130 |
1 files changed, 66 insertions, 64 deletions
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 91f4edbb2a27..739bfdef0c6d 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c | |||
| @@ -17,9 +17,12 @@ | |||
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/rwsem.h> | 18 | #include <linux/rwsem.h> |
| 19 | #include <linux/i2o.h> | 19 | #include <linux/i2o.h> |
| 20 | #include "core.h" | ||
| 21 | |||
| 22 | #define OSM_NAME "i2o" | ||
| 20 | 23 | ||
| 21 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ | 24 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ |
| 22 | unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; | 25 | static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; |
| 23 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); | 26 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); |
| 24 | MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); | 27 | MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); |
| 25 | 28 | ||
| @@ -76,17 +79,16 @@ int i2o_driver_register(struct i2o_driver *drv) | |||
| 76 | int rc = 0; | 79 | int rc = 0; |
| 77 | unsigned long flags; | 80 | unsigned long flags; |
| 78 | 81 | ||
| 79 | pr_debug("i2o: Register driver %s\n", drv->name); | 82 | osm_debug("Register driver %s\n", drv->name); |
| 80 | 83 | ||
| 81 | if (drv->event) { | 84 | if (drv->event) { |
| 82 | drv->event_queue = create_workqueue(drv->name); | 85 | drv->event_queue = create_workqueue(drv->name); |
| 83 | if (!drv->event_queue) { | 86 | if (!drv->event_queue) { |
| 84 | printk(KERN_ERR "i2o: Could not initialize event queue " | 87 | osm_err("Could not initialize event queue for driver " |
| 85 | "for driver %s\n", drv->name); | 88 | "%s\n", drv->name); |
| 86 | return -EFAULT; | 89 | return -EFAULT; |
| 87 | } | 90 | } |
| 88 | pr_debug("i2o: Event queue initialized for driver %s\n", | 91 | osm_debug("Event queue initialized for driver %s\n", drv->name); |
| 89 | drv->name); | ||
| 90 | } else | 92 | } else |
| 91 | drv->event_queue = NULL; | 93 | drv->event_queue = NULL; |
| 92 | 94 | ||
| @@ -97,8 +99,8 @@ int i2o_driver_register(struct i2o_driver *drv) | |||
| 97 | 99 | ||
| 98 | for (i = 0; i2o_drivers[i]; i++) | 100 | for (i = 0; i2o_drivers[i]; i++) |
| 99 | if (i >= i2o_max_drivers) { | 101 | if (i >= i2o_max_drivers) { |
| 100 | printk(KERN_ERR "i2o: too many drivers registered, " | 102 | osm_err("too many drivers registered, increase " |
| 101 | "increase max_drivers\n"); | 103 | "max_drivers\n"); |
| 102 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); | 104 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
| 103 | return -EFAULT; | 105 | return -EFAULT; |
| 104 | } | 106 | } |
| @@ -108,18 +110,16 @@ int i2o_driver_register(struct i2o_driver *drv) | |||
| 108 | 110 | ||
| 109 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); | 111 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
| 110 | 112 | ||
| 111 | pr_debug("i2o: driver %s gets context id %d\n", drv->name, | 113 | osm_debug("driver %s gets context id %d\n", drv->name, drv->context); |
| 112 | drv->context); | ||
| 113 | 114 | ||
| 114 | list_for_each_entry(c, &i2o_controllers, list) { | 115 | list_for_each_entry(c, &i2o_controllers, list) { |
| 115 | struct i2o_device *i2o_dev; | 116 | struct i2o_device *i2o_dev; |
| 116 | 117 | ||
| 117 | i2o_driver_notify_controller_add(drv, c); | 118 | i2o_driver_notify_controller_add(drv, c); |
| 118 | list_for_each_entry(i2o_dev, &c->devices, list) | 119 | list_for_each_entry(i2o_dev, &c->devices, list) |
| 119 | i2o_driver_notify_device_add(drv, i2o_dev); | 120 | i2o_driver_notify_device_add(drv, i2o_dev); |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | |||
| 123 | rc = driver_register(&drv->driver); | 123 | rc = driver_register(&drv->driver); |
| 124 | if (rc) | 124 | if (rc) |
| 125 | destroy_workqueue(drv->event_queue); | 125 | destroy_workqueue(drv->event_queue); |
| @@ -139,7 +139,7 @@ void i2o_driver_unregister(struct i2o_driver *drv) | |||
| 139 | struct i2o_controller *c; | 139 | struct i2o_controller *c; |
| 140 | unsigned long flags; | 140 | unsigned long flags; |
| 141 | 141 | ||
| 142 | pr_debug("i2o: unregister driver %s\n", drv->name); | 142 | osm_debug("unregister driver %s\n", drv->name); |
| 143 | 143 | ||
| 144 | driver_unregister(&drv->driver); | 144 | driver_unregister(&drv->driver); |
| 145 | 145 | ||
| @@ -159,7 +159,7 @@ void i2o_driver_unregister(struct i2o_driver *drv) | |||
| 159 | if (drv->event_queue) { | 159 | if (drv->event_queue) { |
| 160 | destroy_workqueue(drv->event_queue); | 160 | destroy_workqueue(drv->event_queue); |
| 161 | drv->event_queue = NULL; | 161 | drv->event_queue = NULL; |
| 162 | pr_debug("i2o: event queue removed for %s\n", drv->name); | 162 | osm_debug("event queue removed for %s\n", drv->name); |
| 163 | } | 163 | } |
| 164 | }; | 164 | }; |
| 165 | 165 | ||
| @@ -176,68 +176,70 @@ void i2o_driver_unregister(struct i2o_driver *drv) | |||
| 176 | * on success and if the message should be flushed afterwords. Returns | 176 | * on success and if the message should be flushed afterwords. Returns |
| 177 | * negative error code on failure (the message will be flushed too). | 177 | * negative error code on failure (the message will be flushed too). |
| 178 | */ | 178 | */ |
| 179 | int i2o_driver_dispatch(struct i2o_controller *c, u32 m, | 179 | int i2o_driver_dispatch(struct i2o_controller *c, u32 m) |
| 180 | struct i2o_message __iomem *msg) | ||
| 181 | { | 180 | { |
| 182 | struct i2o_driver *drv; | 181 | struct i2o_driver *drv; |
| 183 | u32 context = readl(&msg->u.s.icntxt); | 182 | struct i2o_message *msg = i2o_msg_out_to_virt(c, m); |
| 183 | u32 context = le32_to_cpu(msg->u.s.icntxt); | ||
| 184 | unsigned long flags; | ||
| 184 | 185 | ||
| 185 | if (likely(context < i2o_max_drivers)) { | 186 | if (unlikely(context >= i2o_max_drivers)) { |
| 186 | spin_lock(&i2o_drivers_lock); | 187 | osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, |
| 187 | drv = i2o_drivers[context]; | 188 | context); |
| 188 | spin_unlock(&i2o_drivers_lock); | 189 | return -EIO; |
| 190 | } | ||
| 189 | 191 | ||
| 190 | if (unlikely(!drv)) { | 192 | spin_lock_irqsave(&i2o_drivers_lock, flags); |
| 191 | printk(KERN_WARNING "%s: Spurious reply to unknown " | 193 | drv = i2o_drivers[context]; |
| 192 | "driver %d\n", c->name, context); | 194 | spin_unlock_irqrestore(&i2o_drivers_lock, flags); |
| 193 | return -EIO; | ||
| 194 | } | ||
| 195 | 195 | ||
| 196 | if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { | 196 | if (unlikely(!drv)) { |
| 197 | struct i2o_device *dev, *tmp; | 197 | osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, |
| 198 | struct i2o_event *evt; | 198 | context); |
| 199 | u16 size; | 199 | return -EIO; |
| 200 | u16 tid; | 200 | } |
| 201 | 201 | ||
| 202 | tid = readl(&msg->u.head[1]) & 0x1fff; | 202 | if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { |
| 203 | struct i2o_device *dev, *tmp; | ||
| 204 | struct i2o_event *evt; | ||
| 205 | u16 size; | ||
| 206 | u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff; | ||
| 203 | 207 | ||
| 204 | pr_debug("%s: event received from device %d\n", c->name, | 208 | osm_debug("event received from device %d\n", tid); |
| 205 | tid); | ||
| 206 | 209 | ||
| 207 | /* cut of header from message size (in 32-bit words) */ | 210 | if (!drv->event) |
| 208 | size = (readl(&msg->u.head[0]) >> 16) - 5; | 211 | return -EIO; |
| 209 | 212 | ||
| 210 | evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); | 213 | /* cut of header from message size (in 32-bit words) */ |
| 211 | if (!evt) | 214 | size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; |
| 212 | return -ENOMEM; | ||
| 213 | memset(evt, 0, size * 4 + sizeof(*evt)); | ||
| 214 | 215 | ||
| 215 | evt->size = size; | 216 | evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO); |
| 216 | memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, | 217 | if (!evt) |
| 217 | (size + 2) * 4); | 218 | return -ENOMEM; |
| 218 | 219 | ||
| 219 | list_for_each_entry_safe(dev, tmp, &c->devices, list) | 220 | evt->size = size; |
| 220 | if (dev->lct_data.tid == tid) { | 221 | evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); |
| 221 | evt->i2o_dev = dev; | 222 | evt->event_indicator = le32_to_cpu(msg->body[0]); |
| 222 | break; | 223 | memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4); |
| 223 | } | ||
| 224 | 224 | ||
| 225 | INIT_WORK(&evt->work, (void (*)(void *))drv->event, | 225 | list_for_each_entry_safe(dev, tmp, &c->devices, list) |
| 226 | evt); | 226 | if (dev->lct_data.tid == tid) { |
| 227 | queue_work(drv->event_queue, &evt->work); | 227 | evt->i2o_dev = dev; |
| 228 | return 1; | 228 | break; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | if (likely(drv->reply)) | 231 | INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt); |
| 232 | return drv->reply(c, m, msg); | 232 | queue_work(drv->event_queue, &evt->work); |
| 233 | else | 233 | return 1; |
| 234 | pr_debug("%s: Reply to driver %s, but no reply function" | 234 | } |
| 235 | " defined!\n", c->name, drv->name); | 235 | |
| 236 | if (unlikely(!drv->reply)) { | ||
| 237 | osm_debug("%s: Reply to driver %s, but no reply function" | ||
| 238 | " defined!\n", c->name, drv->name); | ||
| 236 | return -EIO; | 239 | return -EIO; |
| 237 | } else | 240 | } |
| 238 | printk(KERN_WARNING "%s: Spurious reply to unknown driver " | 241 | |
| 239 | "%d\n", c->name, readl(&msg->u.s.icntxt)); | 242 | return drv->reply(c, m, msg); |
| 240 | return -EIO; | ||
| 241 | } | 243 | } |
| 242 | 244 | ||
| 243 | /** | 245 | /** |
| @@ -334,11 +336,11 @@ int __init i2o_driver_init(void) | |||
| 334 | if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) || | 336 | if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) || |
| 335 | ((i2o_max_drivers ^ (i2o_max_drivers - 1)) != | 337 | ((i2o_max_drivers ^ (i2o_max_drivers - 1)) != |
| 336 | (2 * i2o_max_drivers - 1))) { | 338 | (2 * i2o_max_drivers - 1))) { |
| 337 | printk(KERN_WARNING "i2o: max_drivers set to %d, but must be " | 339 | osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and " |
| 338 | ">=2 and <= 64 and a power of 2\n", i2o_max_drivers); | 340 | "a power of 2\n", i2o_max_drivers); |
| 339 | i2o_max_drivers = I2O_MAX_DRIVERS; | 341 | i2o_max_drivers = I2O_MAX_DRIVERS; |
| 340 | } | 342 | } |
| 341 | printk(KERN_INFO "i2o: max drivers = %d\n", i2o_max_drivers); | 343 | osm_info("max drivers = %d\n", i2o_max_drivers); |
| 342 | 344 | ||
| 343 | i2o_drivers = | 345 | i2o_drivers = |
| 344 | kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL); | 346 | kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL); |
