diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-08 08:24:38 +0900 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-08 08:24:38 +0900 |
commit | 280c84d1c1726be7ada045735858acdc8cfdd65a (patch) | |
tree | b9afa3fb97b08272b6952d5c8d1fe31f6a8092fa /arch/s390/pci/pci.c | |
parent | 8efdf2b759409f85953b84d52a14ea4d39c80474 (diff) | |
parent | de9587a2f54d2d0063f0dbc775328129b9daaaa2 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky:
"The bulk of the patches for the 3.13 merge window.
Heiko spent quite a bit of work to improve the code generation for the
kernel. That includes the exploitation of the interlocked-access
facility for the atomics and bitops implementation and the improvement
for the -march and -mtune compiler settings.
Another important change is the removal of the user_mode=home option,
user processes now always run in primary space. The storage keys are
not initialized at system startup any more, with that the storage key
removal work is complete. For the PCI support the hibernation hooks
have been implemented.
And as usual cleanup and fixes"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (62 commits)
s390/scm_blk: fix endless loop for requests != REQ_TYPE_FS
s390/mm,tlb: correct tlb flush on page table upgrade
s390/mm: page_table_realloc returns failure
s390: allow to set gcc -mtune flag
s390/percpu: remove this_cpu_xor() implementation
s390/vtime: correct idle time calculation
s390/time: fix get_tod_clock_ext inline assembly
tty/hvc_iucv: remove redundant NULL check
s390/dasd: Write to profile data area only if it is available
s390: convert use of typedef ctl_table to struct ctl_table
s390/pci: cleanup function information block
s390/pci: remove CONFIG_PCI_DEBUG dependancy
s390/pci: message cleanup
Update default configuration
s390: add a couple of useful defconfigs
s390/percpu: make use of interlocked-access facility 1 instructions
s390/percpu: use generic percpu ops for CONFIG_32BIT
s390/compat: make psw32_user_bits a constant value again
s390: fix handling of runtime instrumentation psw bit
s390: fix save and restore of the floating-point-control register
...
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r-- | arch/s390/pci/pci.c | 108 |
1 files changed, 62 insertions, 46 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index f17a8343e360..0c9a17780e4b 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -120,26 +120,17 @@ 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; - int rc; - - fib = (void *) get_zeroed_page(GFP_KERNEL); - if (!fib) - return -ENOMEM; + struct zpci_fib fib = {0}; - 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; - rc = zpci_mod_fc(req, fib); - pr_debug("%s mpcifc returned noi: %d\n", __func__, fib->noi); - - free_page((unsigned long) fib); - return rc; + return zpci_mod_fc(req, &fib); } struct mod_pci_args { @@ -152,22 +143,14 @@ 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; - int rc; - - /* The FIB must be available even if it's not used */ - fib = (void *) get_zeroed_page(GFP_KERNEL); - if (!fib) - return -ENOMEM; + struct zpci_fib fib = {0}; - 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; - rc = zpci_mod_fc(req, fib); - free_page((unsigned long) fib); - return rc; + return zpci_mod_fc(req, &fib); } /* Modify PCI: Register I/O address translation parameters */ @@ -424,7 +407,6 @@ 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); @@ -489,7 +471,6 @@ 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; } @@ -499,14 +480,10 @@ 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) { - dev_err(&pdev->dev, "deregister MSI failed with: %d\n", rc); + if (rc) return; - } /* Release MSI interrupts */ list_for_each_entry(msi, &pdev->msi_list, list) { @@ -625,8 +602,11 @@ static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned lo r->name = name; rc = request_resource(&iomem_resource, r); - if (rc) - pr_debug("request resource %pR failed\n", r); + if (rc) { + kfree(r->name); + kfree(r); + return ERR_PTR(-ENOMEM); + } return r; } @@ -708,6 +688,47 @@ void pcibios_disable_device(struct pci_dev *pdev) zdev->pdev = NULL; } +#ifdef CONFIG_HIBERNATE_CALLBACKS +static int zpci_restore(struct device *dev) +{ + struct zpci_dev *zdev = get_zdev(to_pci_dev(dev)); + int ret = 0; + + if (zdev->state != ZPCI_FN_STATE_ONLINE) + goto out; + + ret = clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES); + if (ret) + goto out; + + 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); + +out: + return ret; +} + +static int zpci_freeze(struct device *dev) +{ + struct zpci_dev *zdev = get_zdev(to_pci_dev(dev)); + + if (zdev->state != ZPCI_FN_STATE_ONLINE) + return 0; + + zpci_unregister_ioat(zdev, 0); + return clp_disable_fh(zdev); +} + +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 */ + static int zpci_scan_bus(struct zpci_dev *zdev) { struct resource *res; @@ -781,7 +802,6 @@ 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) @@ -901,10 +921,6 @@ 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; |