X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=drivers%2Fmisc%2Fioc4.c;h=60b0b1a4fb3a8ff7817c14d59a490f2665f4e933;hb=9e42d0cf5020aaf217433cad1a224745241d212a;hp=05172d2613d66d3f980c2b2c148bd40992c4e64d;hpb=90d8dabf74179e6615bd4688a118e12ec29ab7aa;p=linux-2.6-omap-h63xx.git diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 05172d2613d..60b0b1a4fb3 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c @@ -75,7 +75,7 @@ ioc4_register_submodule(struct ioc4_submodule *is) printk(KERN_WARNING "%s: IOC4 submodule %s probe failed " "for pci_dev %s", - __FUNCTION__, module_name(is->is_owner), + __func__, module_name(is->is_owner), pci_name(idd->idd_pdev)); } } @@ -102,7 +102,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is) printk(KERN_WARNING "%s: IOC4 submodule %s remove failed " "for pci_dev %s.\n", - __FUNCTION__, module_name(is->is_owner), + __func__, module_name(is->is_owner), pci_name(idd->idd_pdev)); } } @@ -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) @@ -282,7 +292,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) if ((ret = pci_enable_device(pdev))) { printk(KERN_WARNING "%s: Failed to enable IOC4 device for pci_dev %s.\n", - __FUNCTION__, pci_name(pdev)); + __func__, pci_name(pdev)); goto out; } pci_set_master(pdev); @@ -292,7 +302,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) if (!idd) { printk(KERN_WARNING "%s: Failed to allocate IOC4 data for pci_dev %s.\n", - __FUNCTION__, pci_name(pdev)); + __func__, pci_name(pdev)); ret = -ENODEV; goto out_idd; } @@ -307,7 +317,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) printk(KERN_WARNING "%s: Unable to find IOC4 misc resource " "for pci_dev %s.\n", - __FUNCTION__, pci_name(idd->idd_pdev)); + __func__, pci_name(idd->idd_pdev)); ret = -ENODEV; goto out_pci; } @@ -316,7 +326,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) printk(KERN_WARNING "%s: Unable to request IOC4 misc region " "for pci_dev %s.\n", - __FUNCTION__, pci_name(idd->idd_pdev)); + __func__, pci_name(idd->idd_pdev)); ret = -ENODEV; goto out_pci; } @@ -326,7 +336,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) printk(KERN_WARNING "%s: Unable to remap IOC4 misc region " "for pci_dev %s.\n", - __FUNCTION__, pci_name(idd->idd_pdev)); + __func__, pci_name(idd->idd_pdev)); ret = -ENODEV; goto out_misc_region; } @@ -372,12 +382,36 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) printk(KERN_WARNING "%s: IOC4 submodule 0x%s probe failed " "for pci_dev %s.\n", - __FUNCTION__, module_name(is->is_owner), + __func__, module_name(is->is_owner), pci_name(idd->idd_pdev)); } } 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: @@ -406,7 +440,7 @@ ioc4_remove(struct pci_dev *pdev) printk(KERN_WARNING "%s: IOC4 submodule 0x%s remove failed " "for pci_dev %s.\n", - __FUNCTION__, module_name(is->is_owner), + __func__, module_name(is->is_owner), pci_name(idd->idd_pdev)); } } @@ -418,7 +452,7 @@ ioc4_remove(struct pci_dev *pdev) printk(KERN_WARNING "%s: Unable to get IOC4 misc mapping for pci_dev %s. " "Device removal may be incomplete.\n", - __FUNCTION__, pci_name(idd->idd_pdev)); + __func__, pci_name(idd->idd_pdev)); } release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs)); @@ -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); }