diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
commit | 62b8c978ee6b8d135d9e7953221de58000dba986 (patch) | |
tree | 683b04b2e627f6710c22c151b23c8cc9a165315e /arch/s390/pci/pci.c | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz |
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r-- | arch/s390/pci/pci.c | 280 |
1 files changed, 122 insertions, 158 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index bf7c73d..f17a834 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -120,17 +120,26 @@ EXPORT_SYMBOL_GPL(pci_proc_domain); static int zpci_set_airq(struct zpci_dev *zdev) { u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT); - struct zpci_fib fib = {0}; + struct zpci_fib *fib; + int rc; + + fib = (void *) get_zeroed_page(GFP_KERNEL); + if (!fib) + return -ENOMEM; - fib.isc = PCI_ISC; - fib.sum = 1; /* enable summary notifications */ - fib.noi = airq_iv_end(zdev->aibv); - fib.aibv = (unsigned long) zdev->aibv->vector; - fib.aibvo = 0; /* each zdev has its own interrupt vector */ - fib.aisb = (unsigned long) zpci_aisb_iv->vector + (zdev->aisb/64)*8; - fib.aisbo = zdev->aisb & 63; + fib->isc = PCI_ISC; + fib->sum = 1; /* enable summary notifications */ + fib->noi = airq_iv_end(zdev->aibv); + fib->aibv = (unsigned long) zdev->aibv->vector; + fib->aibvo = 0; /* each zdev has its own interrupt vector */ + fib->aisb = (unsigned long) zpci_aisb_iv->vector + (zdev->aisb/64)*8; + fib->aisbo = zdev->aisb & 63; - return zpci_mod_fc(req, &fib); + rc = zpci_mod_fc(req, fib); + pr_debug("%s mpcifc returned noi: %d\n", __func__, fib->noi); + + free_page((unsigned long) fib); + return rc; } struct mod_pci_args { @@ -143,14 +152,22 @@ struct mod_pci_args { static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args *args) { u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, fn); - struct zpci_fib fib = {0}; + struct zpci_fib *fib; + int rc; + + /* The FIB must be available even if it's not used */ + fib = (void *) get_zeroed_page(GFP_KERNEL); + if (!fib) + return -ENOMEM; - fib.pba = args->base; - fib.pal = args->limit; - fib.iota = args->iota; - fib.fmb_addr = args->fmb_addr; + fib->pba = args->base; + fib->pal = args->limit; + fib->iota = args->iota; + fib->fmb_addr = args->fmb_addr; - return zpci_mod_fc(req, &fib); + rc = zpci_mod_fc(req, fib); + free_page((unsigned long) fib); + return rc; } /* Modify PCI: Register I/O address translation parameters */ @@ -407,6 +424,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) struct msi_msg msg; int rc; + pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec); if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI) return -EINVAL; msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX); @@ -471,6 +489,7 @@ out_msi: out_si: airq_iv_free_bit(zpci_aisb_iv, aisb); out: + dev_err(&pdev->dev, "register MSI failed with: %d\n", rc); return rc; } @@ -480,10 +499,14 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev) struct msi_desc *msi; int rc; + pr_info("%s: on pdev: %p\n", __func__, pdev); + /* Disable adapter interrupts */ rc = zpci_clear_airq(zdev); - if (rc) + if (rc) { + dev_err(&pdev->dev, "deregister MSI failed with: %d\n", rc); return; + } /* Release MSI interrupts */ list_for_each_entry(msi, &pdev->msi_list, list) { @@ -530,6 +553,20 @@ static void zpci_unmap_resources(struct zpci_dev *zdev) } } +struct zpci_dev *zpci_alloc_device(void) +{ + struct zpci_dev *zdev; + + /* Alloc memory for our private pci device data */ + zdev = kzalloc(sizeof(*zdev), GFP_KERNEL); + return zdev ? : ERR_PTR(-ENOMEM); +} + +void zpci_free_device(struct zpci_dev *zdev) +{ + kfree(zdev); +} + int pcibios_add_platform_entries(struct pci_dev *pdev) { return zpci_sysfs_add_device(&pdev->dev); @@ -565,6 +602,34 @@ static void zpci_irq_exit(void) unregister_adapter_interrupt(&zpci_airq); } +static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size, + unsigned long flags, int domain) +{ + struct resource *r; + char *name; + int rc; + + r = kzalloc(sizeof(*r), GFP_KERNEL); + if (!r) + return ERR_PTR(-ENOMEM); + r->start = start; + r->end = r->start + size - 1; + r->flags = flags; + r->parent = &iomem_resource; + name = kmalloc(18, GFP_KERNEL); + if (!name) { + kfree(r); + return ERR_PTR(-ENOMEM); + } + sprintf(name, "PCI Bus: %04x:%02x", domain, ZPCI_BUS_NR); + r->name = name; + + rc = request_resource(&iomem_resource, r); + if (rc) + pr_debug("request resource %pR failed\n", r); + return r; +} + static int zpci_alloc_iomap(struct zpci_dev *zdev) { int entry; @@ -588,82 +653,6 @@ static void zpci_free_iomap(struct zpci_dev *zdev, int entry) spin_unlock(&zpci_iomap_lock); } -static struct resource *__alloc_res(struct zpci_dev *zdev, unsigned long start, - unsigned long size, unsigned long flags) -{ - struct resource *r; - - r = kzalloc(sizeof(*r), GFP_KERNEL); - if (!r) - return NULL; - - r->start = start; - r->end = r->start + size - 1; - r->flags = flags; - r->name = zdev->res_name; - - if (request_resource(&iomem_resource, r)) { - kfree(r); - return NULL; - } - return r; -} - -static int zpci_setup_bus_resources(struct zpci_dev *zdev, - struct list_head *resources) -{ - unsigned long addr, size, flags; - struct resource *res; - int i, entry; - - snprintf(zdev->res_name, sizeof(zdev->res_name), - "PCI Bus %04x:%02x", zdev->domain, ZPCI_BUS_NR); - - for (i = 0; i < PCI_BAR_COUNT; i++) { - if (!zdev->bars[i].size) - continue; - entry = zpci_alloc_iomap(zdev); - if (entry < 0) - return entry; - zdev->bars[i].map_idx = entry; - - /* only MMIO is supported */ - flags = IORESOURCE_MEM; - if (zdev->bars[i].val & 8) - flags |= IORESOURCE_PREFETCH; - if (zdev->bars[i].val & 4) - flags |= IORESOURCE_MEM_64; - - addr = ZPCI_IOMAP_ADDR_BASE + ((u64) entry << 48); - - size = 1UL << zdev->bars[i].size; - - res = __alloc_res(zdev, addr, size, flags); - if (!res) { - zpci_free_iomap(zdev, entry); - return -ENOMEM; - } - zdev->bars[i].res = res; - pci_add_resource(resources, res); - } - - return 0; -} - -static void zpci_cleanup_bus_resources(struct zpci_dev *zdev) -{ - int i; - - for (i = 0; i < PCI_BAR_COUNT; i++) { - if (!zdev->bars[i].size) - continue; - - zpci_free_iomap(zdev, zdev->bars[i].map_idx); - release_resource(zdev->bars[i].res); - kfree(zdev->bars[i].res); - } -} - int pcibios_add_device(struct pci_dev *pdev) { struct zpci_dev *zdev = get_zdev(pdev); @@ -719,46 +708,51 @@ void pcibios_disable_device(struct pci_dev *pdev) zdev->pdev = NULL; } -#ifdef CONFIG_HIBERNATE_CALLBACKS -static int zpci_restore(struct device *dev) +static int zpci_scan_bus(struct zpci_dev *zdev) { - struct zpci_dev *zdev = get_zdev(to_pci_dev(dev)); - int ret = 0; + struct resource *res; + LIST_HEAD(resources); + int i; - if (zdev->state != ZPCI_FN_STATE_ONLINE) - goto out; + /* allocate mapping entry for each used bar */ + for (i = 0; i < PCI_BAR_COUNT; i++) { + unsigned long addr, size, flags; + int entry; - ret = clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES); - if (ret) - goto out; + if (!zdev->bars[i].size) + continue; + entry = zpci_alloc_iomap(zdev); + if (entry < 0) + return entry; + zdev->bars[i].map_idx = entry; - zpci_map_resources(zdev); - zpci_register_ioat(zdev, 0, zdev->start_dma + PAGE_OFFSET, - zdev->start_dma + zdev->iommu_size - 1, - (u64) zdev->dma_table); + /* only MMIO is supported */ + flags = IORESOURCE_MEM; + if (zdev->bars[i].val & 8) + flags |= IORESOURCE_PREFETCH; + if (zdev->bars[i].val & 4) + flags |= IORESOURCE_MEM_64; -out: - return ret; -} + addr = ZPCI_IOMAP_ADDR_BASE + ((u64) entry << 48); -static int zpci_freeze(struct device *dev) -{ - struct zpci_dev *zdev = get_zdev(to_pci_dev(dev)); + size = 1UL << zdev->bars[i].size; - if (zdev->state != ZPCI_FN_STATE_ONLINE) - return 0; + res = zpci_alloc_bus_resource(addr, size, flags, zdev->domain); + if (IS_ERR(res)) { + zpci_free_iomap(zdev, entry); + return PTR_ERR(res); + } + pci_add_resource(&resources, res); + } - zpci_unregister_ioat(zdev, 0); - return clp_disable_fh(zdev); -} + zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops, + zdev, &resources); + if (!zdev->bus) + return -EIO; -struct dev_pm_ops pcibios_pm_ops = { - .thaw_noirq = zpci_restore, - .freeze_noirq = zpci_freeze, - .restore_noirq = zpci_restore, - .poweroff_noirq = zpci_freeze, -}; -#endif /* CONFIG_HIBERNATE_CALLBACKS */ + zdev->bus->max_bus_speed = zdev->max_bus_speed; + return 0; +} static int zpci_alloc_domain(struct zpci_dev *zdev) { @@ -780,41 +774,6 @@ static void zpci_free_domain(struct zpci_dev *zdev) spin_unlock(&zpci_domain_lock); } -void pcibios_remove_bus(struct pci_bus *bus) -{ - struct zpci_dev *zdev = get_zdev_by_bus(bus); - - zpci_exit_slot(zdev); - zpci_cleanup_bus_resources(zdev); - zpci_free_domain(zdev); - - spin_lock(&zpci_list_lock); - list_del(&zdev->entry); - spin_unlock(&zpci_list_lock); - - kfree(zdev); -} - -static int zpci_scan_bus(struct zpci_dev *zdev) -{ - LIST_HEAD(resources); - int ret; - - ret = zpci_setup_bus_resources(zdev, &resources); - if (ret) - return ret; - - zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops, - zdev, &resources); - if (!zdev->bus) { - zpci_cleanup_bus_resources(zdev); - return -EIO; - } - - zdev->bus->max_bus_speed = zdev->max_bus_speed; - return 0; -} - int zpci_enable_device(struct zpci_dev *zdev) { int rc; @@ -822,6 +781,7 @@ int zpci_enable_device(struct zpci_dev *zdev) rc = clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES); if (rc) goto out; + pr_info("Enabled fh: 0x%x fid: 0x%x\n", zdev->fh, zdev->fid); rc = zpci_dma_init_device(zdev); if (rc) @@ -941,6 +901,10 @@ static int __init pci_base_init(void) || !test_facility(71) || !test_facility(72)) return 0; + pr_info("Probing PCI hardware: PCI:%d SID:%d AEN:%d\n", + test_facility(69), test_facility(70), + test_facility(71)); + rc = zpci_debug_init(); if (rc) goto out; |