static void pci_fixup_video(struct pci_dev *pdev) { struct pci_dev *bridge; struct pci_bus *bus; u16 config; /* Is VGA routed to us? */ bus = pdev->bus; while (bus) { bridge = bus->self; /* * From information provided by * "David Miller" <*****@*****.**> * The bridge control register is valid for PCI header * type BRIDGE, or CARDBUS. Host to PCI controllers use * PCI header type NORMAL. */ if (bridge && (pci_is_bridge(bridge))) { pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &config); if (!(config & PCI_BRIDGE_CTL_VGA)) return; } bus = bus->parent; } if (!vga_default_device() || pdev == vga_default_device()) { pci_read_config_word(pdev, PCI_COMMAND, &config); if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n"); } } }
static int pci_endpoint_test_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int i; int err; int irq = 0; int id; char name[20]; enum pci_barno bar; void __iomem *base; struct device *dev = &pdev->dev; struct pci_endpoint_test *test; struct pci_endpoint_test_data *data; enum pci_barno test_reg_bar = BAR_0; struct miscdevice *misc_device; if (pci_is_bridge(pdev)) return -ENODEV; test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL); if (!test) return -ENOMEM; test->test_reg_bar = 0; test->alignment = 0; test->pdev = pdev; data = (struct pci_endpoint_test_data *)ent->driver_data; if (data) { test_reg_bar = data->test_reg_bar; test->alignment = data->alignment; no_msi = data->no_msi; } init_completion(&test->irq_raised); mutex_init(&test->mutex); err = pci_enable_device(pdev); if (err) { dev_err(dev, "Cannot enable PCI device\n"); return err; } err = pci_request_regions(pdev, DRV_MODULE_NAME); if (err) { dev_err(dev, "Cannot obtain PCI resources\n"); goto err_disable_pdev; } pci_set_master(pdev); if (!no_msi) { irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); if (irq < 0) dev_err(dev, "failed to get MSI interrupts\n"); } err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, IRQF_SHARED, DRV_MODULE_NAME, test); if (err) { dev_err(dev, "failed to request IRQ %d\n", pdev->irq); goto err_disable_msi; } for (i = 1; i < irq; i++) { err = devm_request_irq(dev, pdev->irq + i, pci_endpoint_test_irqhandler, IRQF_SHARED, DRV_MODULE_NAME, test); if (err) dev_err(dev, "failed to request IRQ %d for MSI %d\n", pdev->irq + i, i + 1); } for (bar = BAR_0; bar <= BAR_5; bar++) { base = pci_ioremap_bar(pdev, bar); if (!base) { dev_err(dev, "failed to read BAR%d\n", bar); WARN_ON(bar == test_reg_bar); } test->bar[bar] = base; } test->base = test->bar[test_reg_bar]; if (!test->base) { dev_err(dev, "Cannot perform PCI test without BAR%d\n", test_reg_bar); goto err_iounmap; } pci_set_drvdata(pdev, test); id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL); if (id < 0) { dev_err(dev, "unable to get id\n"); goto err_iounmap; } snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id); misc_device = &test->miscdev; misc_device->minor = MISC_DYNAMIC_MINOR; misc_device->name = name; misc_device->fops = &pci_endpoint_test_fops, err = misc_register(misc_device); if (err) { dev_err(dev, "failed to register device\n"); goto err_ida_remove; } return 0; err_ida_remove: ida_simple_remove(&pci_endpoint_test_ida, id); err_iounmap: for (bar = BAR_0; bar <= BAR_5; bar++) { if (test->bar[bar]) pci_iounmap(pdev, test->bar[bar]); } err_disable_msi: pci_disable_msi(pdev); pci_release_regions(pdev); err_disable_pdev: pci_disable_device(pdev); return err; }