aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/i2o/driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/i2o/driver.c')
-rw-r--r--drivers/message/i2o/driver.c130
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 */
22unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; 25static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
23module_param_named(max_drivers, i2o_max_drivers, uint, 0); 26module_param_named(max_drivers, i2o_max_drivers, uint, 0);
24MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); 27MODULE_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 */
179int i2o_driver_dispatch(struct i2o_controller *c, u32 m, 179int 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);