/** * mei_probe - Device Initialization Routine * * @pdev: PCI device structure * @ent: entry in kcs_pci_tbl * * returns 0 on success, <0 on failure. */ static int __devinit mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct mei_device *dev; int err; mutex_lock(&mei_mutex); if (mei_device) { err = -EEXIST; goto end; } /* enable pci dev */ err = pci_enable_device(pdev); if (err) { printk(KERN_ERR "mei: Failed to enable pci device.\n"); goto end; } /* set PCI host mastering */ pci_set_master(pdev); /* pci request regions for mei driver */ err = pci_request_regions(pdev, mei_driver_name); if (err) { printk(KERN_ERR "mei: Failed to get pci regions.\n"); goto disable_device; } /* allocates and initializes the mei dev structure */ dev = init_mei_device(pdev); if (!dev) { err = -ENOMEM; goto release_regions; } /* mapping IO device memory */ dev->mem_addr = pci_iomap(pdev, 0, 0); if (!dev->mem_addr) { printk(KERN_ERR "mei: mapping I/O device memory failure.\n"); err = -ENOMEM; goto free_device; } /* request and enable interrupt */ err = request_threaded_irq(pdev->irq, mei_interrupt_quick_handler, mei_interrupt_thread_handler, IRQF_SHARED, mei_driver_name, dev); if (err) { printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n", pdev->irq); goto unmap_memory; } INIT_DELAYED_WORK(&dev->wd_work, mei_wd_timer); if (mei_hw_init(dev)) { printk(KERN_ERR "mei: Init hw failure.\n"); err = -ENODEV; goto release_irq; } mei_device = pdev; pci_set_drvdata(pdev, dev); schedule_delayed_work(&dev->wd_work, HZ); mutex_unlock(&mei_mutex); pr_debug("mei: Driver initialization successful.\n"); return 0; release_irq: /* disable interrupts */ dev->host_hw_state = mei_hcsr_read(dev); mei_disable_interrupts(dev); flush_scheduled_work(); free_irq(pdev->irq, dev); unmap_memory: pci_iounmap(pdev, dev->mem_addr); free_device: kfree(dev); release_regions: pci_release_regions(pdev); disable_device: pci_disable_device(pdev); end: mutex_unlock(&mei_mutex); printk(KERN_ERR "mei: Driver initialization failed.\n"); return err; }
/** * mei_probe - Device Initialization Routine * * @pdev: PCI device structure * @ent: entry in kcs_pci_tbl * * returns 0 on success, <0 on failure. */ static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct mei_device *dev; struct mei_me_hw *hw; int err; mutex_lock(&mei_mutex); if (!mei_quirk_probe(pdev, ent)) { err = -ENODEV; goto end; } if (mei_pdev) { err = -EEXIST; goto end; } /* enable pci dev */ err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "failed to enable pci device.\n"); goto end; } /* set PCI host mastering */ pci_set_master(pdev); /* pci request regions for mei driver */ err = pci_request_regions(pdev, KBUILD_MODNAME); if (err) { dev_err(&pdev->dev, "failed to get pci regions.\n"); goto disable_device; } /* allocates and initializes the mei dev structure */ dev = mei_me_dev_init(pdev); if (!dev) { err = -ENOMEM; goto release_regions; } hw = to_me_hw(dev); /* mapping IO device memory */ hw->mem_addr = pci_iomap(pdev, 0, 0); if (!hw->mem_addr) { dev_err(&pdev->dev, "mapping I/O device memory failure.\n"); err = -ENOMEM; goto free_device; } pci_enable_msi(pdev); /* request and enable interrupt */ if (pci_dev_msi_enabled(pdev)) err = request_threaded_irq(pdev->irq, NULL, mei_me_irq_thread_handler, IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, mei_me_irq_quick_handler, mei_me_irq_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n", pdev->irq); goto disable_msi; } if (mei_hw_init(dev)) { dev_err(&pdev->dev, "init hw failure.\n"); err = -ENODEV; goto release_irq; } err = mei_register(&pdev->dev); if (err) goto release_irq; mei_pdev = pdev; pci_set_drvdata(pdev, dev); schedule_delayed_work(&dev->timer_work, HZ); mutex_unlock(&mei_mutex); pr_debug("initialization successful.\n"); return 0; release_irq: mei_disable_interrupts(dev); flush_scheduled_work(); free_irq(pdev->irq, dev); disable_msi: pci_disable_msi(pdev); pci_iounmap(pdev, hw->mem_addr); free_device: kfree(dev); release_regions: pci_release_regions(pdev); disable_device: pci_disable_device(pdev); end: mutex_unlock(&mei_mutex); dev_err(&pdev->dev, "initialization failed.\n"); return err; }