diff options
| -rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 9 | ||||
| -rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 59 | ||||
| -rw-r--r-- | include/linux/ipmi_smi.h | 16 |
3 files changed, 54 insertions, 30 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 40eb005b9d77..a0b6f797d97d 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
| @@ -2305,8 +2305,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
| 2305 | void *send_info, | 2305 | void *send_info, |
| 2306 | struct ipmi_device_id *device_id, | 2306 | struct ipmi_device_id *device_id, |
| 2307 | struct device *si_dev, | 2307 | struct device *si_dev, |
| 2308 | unsigned char slave_addr, | 2308 | unsigned char slave_addr) |
| 2309 | ipmi_smi_t *new_intf) | ||
| 2310 | { | 2309 | { |
| 2311 | int i, j; | 2310 | int i, j; |
| 2312 | int rv; | 2311 | int rv; |
| @@ -2388,9 +2387,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
| 2388 | if (rv) | 2387 | if (rv) |
| 2389 | goto out; | 2388 | goto out; |
| 2390 | 2389 | ||
| 2391 | /* FIXME - this is an ugly kludge, this sets the intf for the | 2390 | rv = handlers->start_processing(send_info, intf); |
| 2392 | caller before sending any messages with it. */ | 2391 | if (rv) |
| 2393 | *new_intf = intf; | 2392 | goto out; |
| 2394 | 2393 | ||
| 2395 | get_guid(intf); | 2394 | get_guid(intf); |
| 2396 | 2395 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 35fbd4d8ed4b..d48d86bd2c2b 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
| @@ -972,10 +972,37 @@ static irqreturn_t si_bt_irq_handler(int irq, void *data, struct pt_regs *regs) | |||
| 972 | return si_irq_handler(irq, data, regs); | 972 | return si_irq_handler(irq, data, regs); |
| 973 | } | 973 | } |
| 974 | 974 | ||
| 975 | static int smi_start_processing(void *send_info, | ||
| 976 | ipmi_smi_t intf) | ||
| 977 | { | ||
| 978 | struct smi_info *new_smi = send_info; | ||
| 979 | |||
| 980 | new_smi->intf = intf; | ||
| 981 | |||
| 982 | /* Set up the timer that drives the interface. */ | ||
| 983 | setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi); | ||
| 984 | new_smi->last_timeout_jiffies = jiffies; | ||
| 985 | mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES); | ||
| 986 | |||
| 987 | if (new_smi->si_type != SI_BT) { | ||
| 988 | new_smi->thread = kthread_run(ipmi_thread, new_smi, | ||
| 989 | "kipmi%d", new_smi->intf_num); | ||
| 990 | if (IS_ERR(new_smi->thread)) { | ||
| 991 | printk(KERN_NOTICE "ipmi_si_intf: Could not start" | ||
| 992 | " kernel thread due to error %ld, only using" | ||
| 993 | " timers to drive the interface\n", | ||
| 994 | PTR_ERR(new_smi->thread)); | ||
| 995 | new_smi->thread = NULL; | ||
| 996 | } | ||
| 997 | } | ||
| 998 | |||
| 999 | return 0; | ||
| 1000 | } | ||
| 975 | 1001 | ||
| 976 | static struct ipmi_smi_handlers handlers = | 1002 | static struct ipmi_smi_handlers handlers = |
| 977 | { | 1003 | { |
| 978 | .owner = THIS_MODULE, | 1004 | .owner = THIS_MODULE, |
| 1005 | .start_processing = smi_start_processing, | ||
| 979 | .sender = sender, | 1006 | .sender = sender, |
| 980 | .request_events = request_events, | 1007 | .request_events = request_events, |
| 981 | .set_run_to_completion = set_run_to_completion, | 1008 | .set_run_to_completion = set_run_to_completion, |
| @@ -2162,9 +2189,13 @@ static void setup_xaction_handlers(struct smi_info *smi_info) | |||
| 2162 | 2189 | ||
| 2163 | static inline void wait_for_timer_and_thread(struct smi_info *smi_info) | 2190 | static inline void wait_for_timer_and_thread(struct smi_info *smi_info) |
| 2164 | { | 2191 | { |
| 2165 | if (smi_info->thread != NULL && smi_info->thread != ERR_PTR(-ENOMEM)) | 2192 | if (smi_info->intf) { |
| 2166 | kthread_stop(smi_info->thread); | 2193 | /* The timer and thread are only running if the |
| 2167 | del_timer_sync(&smi_info->si_timer); | 2194 | interface has been started up and registered. */ |
| 2195 | if (smi_info->thread != NULL) | ||
| 2196 | kthread_stop(smi_info->thread); | ||
| 2197 | del_timer_sync(&smi_info->si_timer); | ||
| 2198 | } | ||
| 2168 | } | 2199 | } |
| 2169 | 2200 | ||
| 2170 | static struct ipmi_default_vals | 2201 | static struct ipmi_default_vals |
| @@ -2341,21 +2372,6 @@ static int try_smi_init(struct smi_info *new_smi) | |||
| 2341 | if (new_smi->irq) | 2372 | if (new_smi->irq) |
| 2342 | new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; | 2373 | new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; |
| 2343 | 2374 | ||
| 2344 | /* The ipmi_register_smi() code does some operations to | ||
| 2345 | determine the channel information, so we must be ready to | ||
| 2346 | handle operations before it is called. This means we have | ||
| 2347 | to stop the timer if we get an error after this point. */ | ||
| 2348 | init_timer(&(new_smi->si_timer)); | ||
| 2349 | new_smi->si_timer.data = (long) new_smi; | ||
| 2350 | new_smi->si_timer.function = smi_timeout; | ||
| 2351 | new_smi->last_timeout_jiffies = jiffies; | ||
| 2352 | new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | ||
| 2353 | |||
| 2354 | add_timer(&(new_smi->si_timer)); | ||
| 2355 | if (new_smi->si_type != SI_BT) | ||
| 2356 | new_smi->thread = kthread_run(ipmi_thread, new_smi, | ||
| 2357 | "kipmi%d", new_smi->intf_num); | ||
| 2358 | |||
| 2359 | if (!new_smi->dev) { | 2375 | if (!new_smi->dev) { |
| 2360 | /* If we don't already have a device from something | 2376 | /* If we don't already have a device from something |
| 2361 | * else (like PCI), then register a new one. */ | 2377 | * else (like PCI), then register a new one. */ |
| @@ -2365,7 +2381,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
| 2365 | printk(KERN_ERR | 2381 | printk(KERN_ERR |
| 2366 | "ipmi_si_intf:" | 2382 | "ipmi_si_intf:" |
| 2367 | " Unable to allocate platform device\n"); | 2383 | " Unable to allocate platform device\n"); |
| 2368 | goto out_err_stop_timer; | 2384 | goto out_err; |
| 2369 | } | 2385 | } |
| 2370 | new_smi->dev = &new_smi->pdev->dev; | 2386 | new_smi->dev = &new_smi->pdev->dev; |
| 2371 | new_smi->dev->driver = &ipmi_driver; | 2387 | new_smi->dev->driver = &ipmi_driver; |
| @@ -2377,7 +2393,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
| 2377 | " Unable to register system interface device:" | 2393 | " Unable to register system interface device:" |
| 2378 | " %d\n", | 2394 | " %d\n", |
| 2379 | rv); | 2395 | rv); |
| 2380 | goto out_err_stop_timer; | 2396 | goto out_err; |
| 2381 | } | 2397 | } |
| 2382 | new_smi->dev_registered = 1; | 2398 | new_smi->dev_registered = 1; |
| 2383 | } | 2399 | } |
| @@ -2386,8 +2402,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
| 2386 | new_smi, | 2402 | new_smi, |
| 2387 | &new_smi->device_id, | 2403 | &new_smi->device_id, |
| 2388 | new_smi->dev, | 2404 | new_smi->dev, |
| 2389 | new_smi->slave_addr, | 2405 | new_smi->slave_addr); |
| 2390 | &(new_smi->intf)); | ||
| 2391 | if (rv) { | 2406 | if (rv) { |
| 2392 | printk(KERN_ERR | 2407 | printk(KERN_ERR |
| 2393 | "ipmi_si: Unable to register device: error %d\n", | 2408 | "ipmi_si: Unable to register device: error %d\n", |
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index 53571288a9fc..6d9c7e4da472 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h | |||
| @@ -82,6 +82,13 @@ struct ipmi_smi_handlers | |||
| 82 | { | 82 | { |
| 83 | struct module *owner; | 83 | struct module *owner; |
| 84 | 84 | ||
| 85 | /* The low-level interface cannot start sending messages to | ||
| 86 | the upper layer until this function is called. This may | ||
| 87 | not be NULL, the lower layer must take the interface from | ||
| 88 | this call. */ | ||
| 89 | int (*start_processing)(void *send_info, | ||
| 90 | ipmi_smi_t new_intf); | ||
| 91 | |||
| 85 | /* Called to enqueue an SMI message to be sent. This | 92 | /* Called to enqueue an SMI message to be sent. This |
| 86 | operation is not allowed to fail. If an error occurs, it | 93 | operation is not allowed to fail. If an error occurs, it |
| 87 | should report back the error in a received message. It may | 94 | should report back the error in a received message. It may |
| @@ -157,13 +164,16 @@ static inline void ipmi_demangle_device_id(unsigned char *data, | |||
| 157 | } | 164 | } |
| 158 | 165 | ||
| 159 | /* Add a low-level interface to the IPMI driver. Note that if the | 166 | /* Add a low-level interface to the IPMI driver. Note that if the |
| 160 | interface doesn't know its slave address, it should pass in zero. */ | 167 | interface doesn't know its slave address, it should pass in zero. |
| 168 | The low-level interface should not deliver any messages to the | ||
| 169 | upper layer until the start_processing() function in the handlers | ||
| 170 | is called, and the lower layer must get the interface from that | ||
| 171 | call. */ | ||
| 161 | int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | 172 | int ipmi_register_smi(struct ipmi_smi_handlers *handlers, |
| 162 | void *send_info, | 173 | void *send_info, |
| 163 | struct ipmi_device_id *device_id, | 174 | struct ipmi_device_id *device_id, |
| 164 | struct device *dev, | 175 | struct device *dev, |
| 165 | unsigned char slave_addr, | 176 | unsigned char slave_addr); |
| 166 | ipmi_smi_t *intf); | ||
| 167 | 177 | ||
| 168 | /* | 178 | /* |
| 169 | * Remove a low-level interface from the IPMI driver. This will | 179 | * Remove a low-level interface from the IPMI driver. This will |
