diff options
author | David Vrabel <david.vrabel@csr.com> | 2009-01-07 13:45:25 +0300 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2009-01-07 13:45:25 +0300 |
commit | a23e66f3b8cfdedec14541e71ef29a754870a20c (patch) | |
tree | f8ac23572982e92e6f8ae09c4039db627bdf53ee /drivers/misc/ioc4.c | |
parent | 04c470adb01c62bb9bd663cfc4875cf0a4eb01ab (diff) | |
parent | ede6f5aea054d3fb67c78857f7abdee602302043 (diff) | |
download | linux-a23e66f3b8cfdedec14541e71ef29a754870a20c.tar.xz |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-upstream
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) return IOC4_VARIANT_PCI_RT; } +static void +ioc4_load_modules(struct work_struct *work) +{ + /* arg just has to be freed */ + + request_module("sgiioc4"); + + kfree(work); +} + /* Adds a new instance of an IOC4 card */ static int 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) } mutex_unlock(&ioc4_mutex); + /* Request sgiioc4 IDE driver on boards that bring that functionality + * off of IOC4. The root filesystem may be hosted on a drive connected + * to IOC4, so we need to make sure the sgiioc4 driver is loaded as it + * won't be picked up by modprobes due to the ioc4 module owning the + * PCI device. + */ + if (idd->idd_variant != IOC4_VARIANT_PCI_RT) { + struct work_struct *work; + work = kzalloc(sizeof(struct work_struct), GFP_KERNEL); + if (!work) { + printk(KERN_WARNING + "%s: IOC4 unable to allocate memory for " + "load of sub-modules.\n", __func__); + } else { + /* Request the module from a work procedure as the + * modprobe goes out to a userland helper and that + * will hang if done directly from ioc4_probe(). + */ + printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n"); + INIT_WORK(work, ioc4_load_modules); + schedule_work(work); + } + } + return 0; out_misc_region: @@ -462,6 +496,8 @@ ioc4_init(void) static void __devexit ioc4_exit(void) { + /* Ensure ioc4_load_modules() has completed before exiting */ + flush_scheduled_work(); pci_unregister_driver(&ioc4_driver); } |