diff options
author | David S. Miller <davem@davemloft.net> | 2009-01-08 14:05:59 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-08 14:05:59 -0500 |
commit | 7f46b1343f723f98634a5dcee47856b2000079ed (patch) | |
tree | ed22b6298c8dd2f687890a0d79abcd1d273b5f81 /drivers/misc/ioc4.c | |
parent | b8c31da64165b8566fc6e1c9c826f76e7b98ff02 (diff) | |
parent | 9e42d0cf5020aaf217433cad1a224745241d212a (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/misc/ioc4.c')
-rw-r--r-- | drivers/misc/ioc4.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 6f76573e7c8a..60b0b1a4fb3a 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c | |||
@@ -269,6 +269,16 @@ ioc4_variant(struct ioc4_driver_data *idd) | |||
269 | return IOC4_VARIANT_PCI_RT; | 269 | return IOC4_VARIANT_PCI_RT; |
270 | } | 270 | } |
271 | 271 | ||
272 | static void | ||
273 | ioc4_load_modules(struct work_struct *work) | ||
274 | { | ||
275 | /* arg just has to be freed */ | ||
276 | |||
277 | request_module("sgiioc4"); | ||
278 | |||
279 | kfree(work); | ||
280 | } | ||
281 | |||
272 | /* Adds a new instance of an IOC4 card */ | 282 | /* Adds a new instance of an IOC4 card */ |
273 | static int | 283 | static int |
274 | ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | 284 | ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) |
@@ -378,6 +388,30 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | |||
378 | } | 388 | } |
379 | mutex_unlock(&ioc4_mutex); | 389 | mutex_unlock(&ioc4_mutex); |
380 | 390 | ||
391 | /* Request sgiioc4 IDE driver on boards that bring that functionality | ||
392 | * off of IOC4. The root filesystem may be hosted on a drive connected | ||
393 | * to IOC4, so we need to make sure the sgiioc4 driver is loaded as it | ||
394 | * won't be picked up by modprobes due to the ioc4 module owning the | ||
395 | * PCI device. | ||
396 | */ | ||
397 | if (idd->idd_variant != IOC4_VARIANT_PCI_RT) { | ||
398 | struct work_struct *work; | ||
399 | work = kzalloc(sizeof(struct work_struct), GFP_KERNEL); | ||
400 | if (!work) { | ||
401 | printk(KERN_WARNING | ||
402 | "%s: IOC4 unable to allocate memory for " | ||
403 | "load of sub-modules.\n", __func__); | ||
404 | } else { | ||
405 | /* Request the module from a work procedure as the | ||
406 | * modprobe goes out to a userland helper and that | ||
407 | * will hang if done directly from ioc4_probe(). | ||
408 | */ | ||
409 | printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n"); | ||
410 | INIT_WORK(work, ioc4_load_modules); | ||
411 | schedule_work(work); | ||
412 | } | ||
413 | } | ||
414 | |||
381 | return 0; | 415 | return 0; |
382 | 416 | ||
383 | out_misc_region: | 417 | out_misc_region: |
@@ -462,6 +496,8 @@ ioc4_init(void) | |||
462 | static void __devexit | 496 | static void __devexit |
463 | ioc4_exit(void) | 497 | ioc4_exit(void) |
464 | { | 498 | { |
499 | /* Ensure ioc4_load_modules() has completed before exiting */ | ||
500 | flush_scheduled_work(); | ||
465 | pci_unregister_driver(&ioc4_driver); | 501 | pci_unregister_driver(&ioc4_driver); |
466 | } | 502 | } |
467 | 503 | ||