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 |