From 0b2d70764bb39242dcc49c0ebd10fcb8258ce5fa Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 25 Apr 2014 11:01:08 -0600 Subject: x86/PCI: Fix Broadcom CNB20LE unintended sign extension In the expression "word1 << 16", word1 starts as u16, but is promoted to a signed int, then sign-extended to resource_size_t, which is probably not what was intended. Cast to resource_size_t to avoid the sign extension. Found by Coverity (CID 138749, 138750). Signed-off-by: Bjorn Helgaas diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c index 614392c..bb461cf 100644 --- a/arch/x86/pci/broadcom_bus.c +++ b/arch/x86/pci/broadcom_bus.c @@ -60,8 +60,8 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func) word1 = read_pci_config_16(bus, slot, func, 0xc4); word2 = read_pci_config_16(bus, slot, func, 0xc6); if (word1 != word2) { - res.start = (word1 << 16) | 0x0000; - res.end = (word2 << 16) | 0xffff; + res.start = ((resource_size_t) word1 << 16) | 0x0000; + res.end = ((resource_size_t) word2 << 16) | 0xffff; res.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; update_res(info, res.start, res.end, res.flags, 0); } -- cgit v0.10.2 From 4e4ba9441fb431f3996de2454522342e0b1d9263 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Apr 2014 15:30:09 -0600 Subject: x86/PCI: Don't try to move IORESOURCE_PCI_FIXED resources Don't attempt to move resource marked IORESOURCE_PCI_FIXED, even if pci_claim_resource() fails. In some cases, these are legacy resources that cannot be moved. Signed-off-by: Bjorn Helgaas diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index db6b1ab..6db58d6 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -271,11 +271,16 @@ static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) "BAR %d: reserving %pr (d=%d, p=%d)\n", idx, r, disabled, pass); if (pci_claim_resource(dev, idx) < 0) { - /* We'll assign a new address later */ - pcibios_save_fw_addr(dev, - idx, r->start); - r->end -= r->start; - r->start = 0; + if (r->flags & IORESOURCE_PCI_FIXED) { + dev_info(&dev->dev, "BAR %d %pR is immovable\n", + idx, r); + } else { + /* We'll assign a new address later */ + pcibios_save_fw_addr(dev, + idx, r->start); + r->end -= r->start; + r->start = 0; + } } } } -- cgit v0.10.2 From 44c8bdbe32aa51fe673c7a86b1e8f45b952d7759 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Apr 2014 15:35:21 -0600 Subject: x86/PCI: Mark ATI SBx00 HPET BAR as IORESOURCE_PCI_FIXED Bodo reported that on the Asrock M3A UCC, v3.12.6 hangs during boot unless he uses "pci=nocrs". This regression was caused by 7bc5e3f2be32 ("x86/PCI: use host bridge _CRS info by default on 2008 and newer machines"), which appeared in v2.6.34. The reason is that the HPET address appears in a PCI device BAR, and this address is not contained in any of the host bridge windows. Linux moves the PCI BAR into a window, but the original address was published via the HPET table and an ACPI device, so changing the BAR is a bad idea. Here's the dmesg info: ACPI: HPET id: 0x43538301 base: 0xfed00000 pci_root PNP0A03:00: host bridge window [mem 0xd0000000-0xdfffffff] pci_root PNP0A03:00: host bridge window [mem 0xf0000000-0xfebfffff] pci 0000:00:14.0: [1002:4385] type 0 class 0x000c05 pci 0000:00:14.0: reg 14: [mem 0xfed00000-0xfed003ff] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0, 0 pnp 00:06: Plug and Play ACPI device, IDs PNP0103 (active) pnp 00:06: [mem 0xfed00000-0xfed003ff] When we notice the BAR is not in a host bridge window, we try to move it, but that causes a hang shortly thereafter: pci 0000:00:14.0: no compatible bridge window for [mem 0xfed00000-0xfed003ff] pci 0000:00:14.0: BAR 1: assigned [mem 0xf0000000-0xf00003ff] This patch marks the BAR as IORESOURCE_PCI_FIXED to prevent Linux from moving it. This depends on a previous patch ("x86/PCI: Don't try to move IORESOURCE_PCI_FIXED resources") to check for this flag when pci_claim_resource() fails. Link: https://bugzilla.kernel.org/show_bug.cgi?id=68591 Reported-and-tested-by: Bodo Eggert <7eggert@gmx.de> Signed-off-by: Bjorn Helgaas diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 94ae9ae..ef334a0 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -6,6 +6,7 @@ #include #include #include +#include #include static void pci_fixup_i450nx(struct pci_dev *d) @@ -526,6 +527,19 @@ static void sb600_disable_hpet_bar(struct pci_dev *dev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar); +#ifdef CONFIG_HPET_TIMER +static void sb600_hpet_quirk(struct pci_dev *dev) +{ + struct resource *r = &dev->resource[1]; + + if (r->flags & IORESOURCE_MEM && r->start == hpet_address) { + r->flags |= IORESOURCE_PCI_FIXED; + dev_info(&dev->dev, "reg 0x14 contains HPET; making it immovable\n"); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, 0x4385, sb600_hpet_quirk); +#endif + /* * Twinhead H12Y needs us to block out a region otherwise we map devices * there and any access kills the box. -- cgit v0.10.2 From dfc73e7acd9925b434a355eeeed86d44cb435f9c Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 17 Apr 2014 19:46:15 +0200 Subject: PCI: Move Open Firmware devspec attribute to PCI common code Move the devspec OF attribute to PCI common code's set of device attributes since it's not architecture dependent. As a side effect microblaze and powerpc no longer need to use pcibios_add_platform_entries(). [bhelgaas: fold in #include for compile error] Link: https://lkml.kernel.org/r/alpine.LFD.2.11.1404141101500.1529@denkbrett Signed-off-by: Sebastian Ott Signed-off-by: Bjorn Helgaas Acked-by: Benjamin Herrenschmidt diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index 70996cc..a59de1b 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -168,26 +168,6 @@ struct pci_controller *pci_find_hose_for_OF_device(struct device_node *node) return NULL; } -static ssize_t pci_show_devspec(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pci_dev *pdev; - struct device_node *np; - - pdev = to_pci_dev(dev); - np = pci_device_to_OF_node(pdev); - if (np == NULL || np->full_name == NULL) - return 0; - return sprintf(buf, "%s", np->full_name); -} -static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); - -/* Add sysfs properties */ -int pcibios_add_platform_entries(struct pci_dev *pdev) -{ - return device_create_file(&pdev->dev, &dev_attr_devspec); -} - void pcibios_set_master(struct pci_dev *dev) { /* No special bus mastering setup handling */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index d9476c1..24d342e 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -201,26 +201,6 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) return NULL; } -static ssize_t pci_show_devspec(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pci_dev *pdev; - struct device_node *np; - - pdev = to_pci_dev (dev); - np = pci_device_to_OF_node(pdev); - if (np == NULL || np->full_name == NULL) - return 0; - return sprintf(buf, "%s", np->full_name); -} -static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); - -/* Add sysfs properties */ -int pcibios_add_platform_entries(struct pci_dev *pdev) -{ - return device_create_file(&pdev->dev, &dev_attr_devspec); -} - /* * Reads the interrupt pin to determine if interrupt is use by card. * If the interrupt is used, then gets the interrupt line from the diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 4e0acef..3db1c7f 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "pci.h" static int sysfs_initialized; /* = 0 */ @@ -416,6 +417,20 @@ static ssize_t d3cold_allowed_show(struct device *dev, static DEVICE_ATTR_RW(d3cold_allowed); #endif +#ifdef CONFIG_OF +static ssize_t devspec_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct device_node *np = pci_device_to_OF_node(pdev); + + if (np == NULL || np->full_name == NULL) + return 0; + return sprintf(buf, "%s", np->full_name); +} +static DEVICE_ATTR_RO(devspec); +#endif + #ifdef CONFIG_PCI_IOV static ssize_t sriov_totalvfs_show(struct device *dev, struct device_attribute *attr, @@ -521,6 +536,9 @@ static struct attribute *pci_dev_attrs[] = { #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) &dev_attr_d3cold_allowed.attr, #endif +#ifdef CONFIG_OF + &dev_attr_devspec.attr, +#endif NULL, }; -- cgit v0.10.2 From 034cd97ebda4062eb4402a6cf963ccd262caa86a Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 14 Apr 2014 15:28:35 +0200 Subject: PCI/MSI: Remove pci_enable_msi_block() There are no users of pci_enable_msi_block() function left. Obsolete it in favor of pci_enable_msi_range() and pci_enable_msi_exact() functions. Previously, we called arch_setup_msi_irqs() once, requesting the same vector count we passed to arch_msi_check_device(). Now we may call it several times: if it returns failure, we may retry and request fewer vectors. We don't keep track of the vector count we initially passed to arch_msi_check_device(). We only keep track of the number of vectors successfully set up by arch_setup_msi_irqs(), and this is what we use to clean things up when disabling MSI. Therefore, we assume that arch_msi_check_device() does nothing that will have to be cleaned up later. [bhelgaas: changelog] Signed-off-by: Alexander Gordeev Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 04130c3..36dd0ca 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -879,50 +879,6 @@ int pci_msi_vec_count(struct pci_dev *dev) } EXPORT_SYMBOL(pci_msi_vec_count); -/** - * pci_enable_msi_block - configure device's MSI capability structure - * @dev: device to configure - * @nvec: number of interrupts to configure - * - * Allocate IRQs for a device with the MSI capability. - * This function returns a negative errno if an error occurs. If it - * is unable to allocate the number of interrupts requested, it returns - * the number of interrupts it might be able to allocate. If it successfully - * allocates at least the number of interrupts requested, it returns 0 and - * updates the @dev's irq member to the lowest new interrupt number; the - * other interrupt numbers allocated to this device are consecutive. - */ -int pci_enable_msi_block(struct pci_dev *dev, int nvec) -{ - int status, maxvec; - - if (dev->current_state != PCI_D0) - return -EINVAL; - - maxvec = pci_msi_vec_count(dev); - if (maxvec < 0) - return maxvec; - if (nvec > maxvec) - return maxvec; - - status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI); - if (status) - return status; - - WARN_ON(!!dev->msi_enabled); - - /* Check whether driver already requested MSI-X irqs */ - if (dev->msix_enabled) { - dev_info(&dev->dev, "can't enable MSI " - "(MSI-X already enabled)\n"); - return -EINVAL; - } - - status = msi_capability_init(dev, nvec); - return status; -} -EXPORT_SYMBOL(pci_enable_msi_block); - void pci_msi_shutdown(struct pci_dev *dev) { struct msi_desc *desc; @@ -1128,14 +1084,45 @@ void pci_msi_init_pci_dev(struct pci_dev *dev) **/ int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) { - int nvec = maxvec; + int nvec; int rc; + if (dev->current_state != PCI_D0) + return -EINVAL; + + WARN_ON(!!dev->msi_enabled); + + /* Check whether driver already requested MSI-X irqs */ + if (dev->msix_enabled) { + dev_info(&dev->dev, + "can't enable MSI (MSI-X already enabled)\n"); + return -EINVAL; + } + if (maxvec < minvec) return -ERANGE; + nvec = pci_msi_vec_count(dev); + if (nvec < 0) + return nvec; + else if (nvec < minvec) + return -EINVAL; + else if (nvec > maxvec) + nvec = maxvec; + + do { + rc = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI); + if (rc < 0) { + return rc; + } else if (rc > 0) { + if (rc < minvec) + return -ENOSPC; + nvec = rc; + } + } while (rc); + do { - rc = pci_enable_msi_block(dev, nvec); + rc = msi_capability_init(dev, nvec); if (rc < 0) { return rc; } else if (rc > 0) { diff --git a/include/linux/pci.h b/include/linux/pci.h index aab57b4..499755e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1158,7 +1158,6 @@ struct msix_entry { #ifdef CONFIG_PCI_MSI int pci_msi_vec_count(struct pci_dev *dev); -int pci_enable_msi_block(struct pci_dev *dev, int nvec); void pci_msi_shutdown(struct pci_dev *dev); void pci_disable_msi(struct pci_dev *dev); int pci_msix_vec_count(struct pci_dev *dev); @@ -1188,8 +1187,6 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev, } #else static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; } -static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec) -{ return -ENOSYS; } static inline void pci_msi_shutdown(struct pci_dev *dev) { } static inline void pci_disable_msi(struct pci_dev *dev) { } static inline int pci_msix_vec_count(struct pci_dev *dev) { return -ENOSYS; } @@ -1244,7 +1241,7 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { } static inline void pcie_ecrc_get_policy(char *str) { } #endif -#define pci_enable_msi(pdev) pci_enable_msi_block(pdev, 1) +#define pci_enable_msi(pdev) pci_enable_msi_exact(pdev, 1) #ifdef CONFIG_HT_IRQ /* The functions a driver should call */ -- cgit v0.10.2 From 3cb30b73ad71b384c6289243d4ccd31ab90bce6f Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 1 May 2014 14:36:31 -0600 Subject: PCI: Mark RTL8110SC INTx masking as broken INTx masking does not work on this device. To see this, configure the network device UP on an active network, note that the interrupt count continues to increment for the device in /proc/interrupts. Use setpci to set the PCI_COMMAND_INTX_DISABLE bit in the PCI_COMMAND register. As expected, the interrupt count ceases to increment. However, reading the PCI_STATUS_INTERRUPT bit of the PCI_STATUS register does not indicate that interrupts are pending and clearing PCI_COMMAND_INTX_DISABLE in the PCI_COMMAND register does not allow the device to continue operation. This does not affect operation of the host r8169 driver, but it does prevent the device from being functional when assigned to a VM, such as with QEMU and VFIO. The guest driver successfully probes the device, but there is no traffic. Mark INTx masking as broken, allowing the more restrictive APIC masking to be used instead. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5e4ac63..72faccf 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2991,6 +2991,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, 0x0030, quirk_broken_intx_masking); DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */ quirk_broken_intx_masking); +/* + * Realtek RTL8169 PCI Gigabit Ethernet Controller (rev 10) + * Subsystem: Realtek RTL8169/8110 Family PCI Gigabit Ethernet NIC + * + * RTL8110SC - Fails under PCI device assignment using DisINTx masking. + */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_REALTEK, 0x8169, + quirk_broken_intx_masking); static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) -- cgit v0.10.2 From 77f2ea2f8d0833f9e976368481fb9a0775acf9e7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 30 Apr 2014 11:20:53 -0600 Subject: DMA-API: Clarify physical/bus address distinction The DMA-API documentation sometimes refers to "physical addresses" when it really means "bus addresses." Sometimes these are identical, but they may be different if the bridge leading to the bus performs address translation. Update the documentation to use "bus address" when appropriate. Also, consistently capitalize "DMA", use parens with function names, use dev_printk() in examples, and reword a few sections for clarity. No functional change; documentation changes only. Signed-off-by: Bjorn Helgaas Acked-by: Greg Kroah-Hartman Acked-by: Arnd Bergmann Acked-by: James Bottomley Acked-by: Randy Dunlap diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt index 5e98303..fd3727b 100644 --- a/Documentation/DMA-API-HOWTO.txt +++ b/Documentation/DMA-API-HOWTO.txt @@ -9,16 +9,76 @@ This is a guide to device driver writers on how to use the DMA API with example pseudo-code. For a concise description of the API, see DMA-API.txt. -Most of the 64bit platforms have special hardware that translates bus -addresses (DMA addresses) into physical addresses. This is similar to -how page tables and/or a TLB translates virtual addresses to physical -addresses on a CPU. This is needed so that e.g. PCI devices can -access with a Single Address Cycle (32bit DMA address) any page in the -64bit physical address space. Previously in Linux those 64bit -platforms had to set artificial limits on the maximum RAM size in the -system, so that the virt_to_bus() static scheme works (the DMA address -translation tables were simply filled on bootup to map each bus -address to the physical page __pa(bus_to_virt())). + CPU and DMA addresses + +There are several kinds of addresses involved in the DMA API, and it's +important to understand the differences. + +The kernel normally uses virtual addresses. Any address returned by +kmalloc(), vmalloc(), and similar interfaces is a virtual address and can +be stored in a "void *". + +The virtual memory system (TLB, page tables, etc.) translates virtual +addresses to CPU physical addresses, which are stored as "phys_addr_t" or +"resource_size_t". The kernel manages device resources like registers as +physical addresses. These are the addresses in /proc/iomem. The physical +address is not directly useful to a driver; it must use ioremap() to map +the space and produce a virtual address. + +I/O devices use a third kind of address: a "bus address" or "DMA address". +If a device has registers at an MMIO address, or if it performs DMA to read +or write system memory, the addresses used by the device are bus addresses. +In some systems, bus addresses are identical to CPU physical addresses, but +in general they are not. IOMMUs and host bridges can produce arbitrary +mappings between physical and bus addresses. + +Here's a picture and some examples: + + CPU CPU Bus + Virtual Physical Address + Address Address Space + Space Space + + +-------+ +------+ +------+ + | | |MMIO | Offset | | + | | Virtual |Space | applied | | + C +-------+ --------> B +------+ ----------> +------+ A + | | mapping | | by host | | + +-----+ | | | | bridge | | +--------+ + | | | | +------+ | | | | + | CPU | | | | RAM | | | | Device | + | | | | | | | | | | + +-----+ +-------+ +------+ +------+ +--------+ + | | Virtual |Buffer| Mapping | | + X +-------+ --------> Y +------+ <---------- +------+ Z + | | mapping | RAM | by IOMMU + | | | | + | | | | + +-------+ +------+ + +During the enumeration process, the kernel learns about I/O devices and +their MMIO space and the host bridges that connect them to the system. For +example, if a PCI device has a BAR, the kernel reads the bus address (A) +from the BAR and converts it to a CPU physical address (B). The address B +is stored in a struct resource and usually exposed via /proc/iomem. When a +driver claims a device, it typically uses ioremap() to map physical address +B at a virtual address (C). It can then use, e.g., ioread32(C), to access +the device registers at bus address A. + +If the device supports DMA, the driver sets up a buffer using kmalloc() or +a similar interface, which returns a virtual address (X). The virtual +memory system maps X to a physical address (Y) in system RAM. The driver +can use virtual address X to access the buffer, but the device itself +cannot because DMA doesn't go through the CPU virtual memory system. + +In some simple systems, the device can do DMA directly to physical address +Y. But in many others, there is IOMMU hardware that translates bus +addresses to physical addresses, e.g., it translates Z to Y. This is part +of the reason for the DMA API: the driver can give a virtual address X to +an interface like dma_map_single(), which sets up any required IOMMU +mapping and returns the bus address Z. The driver then tells the device to +do DMA to Z, and the IOMMU maps it to the buffer at address Y in system +RAM. So that Linux can use the dynamic DMA mapping, it needs some help from the drivers, namely it has to take into account that DMA addresses should be @@ -29,17 +89,17 @@ The following API will work of course even on platforms where no such hardware exists. Note that the DMA API works with any bus independent of the underlying -microprocessor architecture. You should use the DMA API rather than -the bus specific DMA API (e.g. pci_dma_*). +microprocessor architecture. You should use the DMA API rather than the +bus-specific DMA API, i.e., use the dma_map_*() interfaces rather than the +pci_map_*() interfaces. First of all, you should make sure #include -is in your driver. This file will obtain for you the definition of the -dma_addr_t (which can hold any valid DMA address for the platform) -type which should be used everywhere you hold a DMA (bus) address -returned from the DMA mapping functions. +is in your driver, which provides the definition of dma_addr_t. This type +can hold any valid DMA or bus address for the platform and should be used +everywhere you hold a DMA address returned from the DMA mapping functions. What memory is DMA'able? @@ -123,9 +183,9 @@ Here, dev is a pointer to the device struct of your device, and mask is a bit mask describing which bits of an address your device supports. It returns zero if your card can perform DMA properly on the machine given the address mask you provided. In general, the -device struct of your device is embedded in the bus specific device -struct of your device. For example, a pointer to the device struct of -your PCI device is pdev->dev (pdev is a pointer to the PCI device +device struct of your device is embedded in the bus-specific device +struct of your device. For example, &pdev->dev is a pointer to the +device struct of a PCI device (pdev is a pointer to the PCI device struct of your device). If it returns non-zero, your device cannot perform DMA properly on @@ -147,8 +207,7 @@ exactly why. The standard 32-bit addressing device would do something like this: if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { - printk(KERN_WARNING - "mydev: No suitable DMA available.\n"); + dev_warn(dev, "mydev: No suitable DMA available\n"); goto ignore_this_device; } @@ -170,8 +229,7 @@ all 64-bits when accessing streaming DMA: } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) { using_dac = 0; } else { - printk(KERN_WARNING - "mydev: No suitable DMA available.\n"); + dev_warn(dev, "mydev: No suitable DMA available\n"); goto ignore_this_device; } @@ -187,8 +245,7 @@ the case would look like this: using_dac = 0; consistent_using_dac = 0; } else { - printk(KERN_WARNING - "mydev: No suitable DMA available.\n"); + dev_warn(dev, "mydev: No suitable DMA available\n"); goto ignore_this_device; } @@ -201,8 +258,7 @@ Finally, if your device can only drive the low 24-bits of address you might do something like: if (dma_set_mask(dev, DMA_BIT_MASK(24))) { - printk(KERN_WARNING - "mydev: 24-bit DMA addressing not available.\n"); + dev_warn(dev, "mydev: 24-bit DMA addressing not available\n"); goto ignore_this_device; } @@ -232,14 +288,14 @@ Here is pseudo-code showing how this might be done: card->playback_enabled = 1; } else { card->playback_enabled = 0; - printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n", + dev_warn(dev, "%s: Playback disabled due to DMA limitations\n", card->name); } if (!dma_set_mask(dev, RECORD_ADDRESS_BITS)) { card->record_enabled = 1; } else { card->record_enabled = 0; - printk(KERN_WARNING "%s: Record disabled due to DMA limitations.\n", + dev_warn(dev, "%s: Record disabled due to DMA limitations\n", card->name); } @@ -331,7 +387,7 @@ context with the GFP_ATOMIC flag. Size is the length of the region you want to allocate, in bytes. This routine will allocate RAM for that region, so it acts similarly to -__get_free_pages (but takes size instead of a page order). If your +__get_free_pages() (but takes size instead of a page order). If your driver needs regions sized smaller than a page, you may prefer using the dma_pool interface, described below. @@ -343,11 +399,11 @@ the consistent DMA mask has been explicitly changed via dma_set_coherent_mask(). This is true of the dma_pool interface as well. -dma_alloc_coherent returns two values: the virtual address which you +dma_alloc_coherent() returns two values: the virtual address which you can use to access it from the CPU and dma_handle which you pass to the card. -The cpu return address and the DMA bus master address are both +The CPU virtual address and the DMA bus address are both guaranteed to be aligned to the smallest PAGE_SIZE order which is greater than or equal to the requested size. This invariant exists (for example) to guarantee that if you allocate a chunk @@ -359,13 +415,13 @@ To unmap and free such a DMA region, you call: dma_free_coherent(dev, size, cpu_addr, dma_handle); where dev, size are the same as in the above call and cpu_addr and -dma_handle are the values dma_alloc_coherent returned to you. +dma_handle are the values dma_alloc_coherent() returned to you. This function may not be called in interrupt context. If your driver needs lots of smaller memory regions, you can write -custom code to subdivide pages returned by dma_alloc_coherent, +custom code to subdivide pages returned by dma_alloc_coherent(), or you can use the dma_pool API to do that. A dma_pool is like -a kmem_cache, but it uses dma_alloc_coherent not __get_free_pages. +a kmem_cache, but it uses dma_alloc_coherent(), not __get_free_pages(). Also, it understands common hardware constraints for alignment, like queue heads needing to be aligned on N byte boundaries. @@ -381,29 +437,29 @@ type of data is "align" (which is expressed in bytes, and must be a power of two). If your device has no boundary crossing restrictions, pass 0 for alloc; passing 4096 says memory allocated from this pool must not cross 4KByte boundaries (but at that time it may be better to -go for dma_alloc_coherent directly instead). +use dma_alloc_coherent() directly instead). -Allocate memory from a dma pool like this: +Allocate memory from a DMA pool like this: cpu_addr = dma_pool_alloc(pool, flags, &dma_handle); flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor -holding SMP locks), SLAB_ATOMIC otherwise. Like dma_alloc_coherent, +holding SMP locks), SLAB_ATOMIC otherwise. Like dma_alloc_coherent(), this returns two values, cpu_addr and dma_handle. Free memory that was allocated from a dma_pool like this: dma_pool_free(pool, cpu_addr, dma_handle); -where pool is what you passed to dma_pool_alloc, and cpu_addr and -dma_handle are the values dma_pool_alloc returned. This function +where pool is what you passed to dma_pool_alloc(), and cpu_addr and +dma_handle are the values dma_pool_alloc() returned. This function may be called in interrupt context. Destroy a dma_pool by calling: dma_pool_destroy(pool); -Make sure you've called dma_pool_free for all memory allocated +Make sure you've called dma_pool_free() for all memory allocated from a pool before you destroy the pool. This function may not be called in interrupt context. @@ -418,7 +474,7 @@ one of the following values: DMA_FROM_DEVICE DMA_NONE -One should provide the exact DMA direction if you know it. +You should provide the exact DMA direction if you know it. DMA_TO_DEVICE means "from main memory to the device" DMA_FROM_DEVICE means "from the device to main memory" @@ -489,14 +545,14 @@ and to unmap it: dma_unmap_single(dev, dma_handle, size, direction); You should call dma_mapping_error() as dma_map_single() could fail and return -error. Not all dma implementations support dma_mapping_error() interface. +error. Not all DMA implementations support the dma_mapping_error() interface. However, it is a good practice to call dma_mapping_error() interface, which will invoke the generic mapping error check interface. Doing so will ensure -that the mapping code will work correctly on all dma implementations without +that the mapping code will work correctly on all DMA implementations without any dependency on the specifics of the underlying implementation. Using the returned address without checking for errors could result in failures ranging from panics to silent data corruption. A couple of examples of incorrect ways -to check for errors that make assumptions about the underlying dma +to check for errors that make assumptions about the underlying DMA implementation are as follows and these are applicable to dma_map_page() as well. @@ -516,12 +572,12 @@ Incorrect example 2: goto map_error; } -You should call dma_unmap_single when the DMA activity is finished, e.g. +You should call dma_unmap_single() when the DMA activity is finished, e.g., from the interrupt which told you that the DMA transfer is done. -Using cpu pointers like this for single mappings has a disadvantage, +Using cpu pointers like this for single mappings has a disadvantage: you cannot reference HIGHMEM memory in this way. Thus, there is a -map/unmap interface pair akin to dma_{map,unmap}_single. These +map/unmap interface pair akin to dma_{map,unmap}_single(). These interfaces deal with page/offset pairs instead of cpu pointers. Specifically: @@ -550,7 +606,7 @@ Here, "offset" means byte offset within the given page. You should call dma_mapping_error() as dma_map_page() could fail and return error as outlined under the dma_map_single() discussion. -You should call dma_unmap_page when the DMA activity is finished, e.g. +You should call dma_unmap_page() when the DMA activity is finished, e.g., from the interrupt which told you that the DMA transfer is done. With scatterlists, you map a region gathered from several regions by: @@ -588,18 +644,16 @@ PLEASE NOTE: The 'nents' argument to the dma_unmap_sg call must be it should _NOT_ be the 'count' value _returned_ from the dma_map_sg call. -Every dma_map_{single,sg} call should have its dma_unmap_{single,sg} -counterpart, because the bus address space is a shared resource (although -in some ports the mapping is per each BUS so less devices contend for the -same bus address space) and you could render the machine unusable by eating -all bus addresses. +Every dma_map_{single,sg}() call should have its dma_unmap_{single,sg}() +counterpart, because the bus address space is a shared resource and +you could render the machine unusable by consuming all bus addresses. If you need to use the same streaming DMA region multiple times and touch the data in between the DMA transfers, the buffer needs to be synced -properly in order for the cpu and device to see the most uptodate and +properly in order for the cpu and device to see the most up-to-date and correct copy of the DMA buffer. -So, firstly, just map it with dma_map_{single,sg}, and after each DMA +So, firstly, just map it with dma_map_{single,sg}(), and after each DMA transfer call either: dma_sync_single_for_cpu(dev, dma_handle, size, direction); @@ -623,9 +677,9 @@ or: as appropriate. After the last DMA transfer call one of the DMA unmap routines -dma_unmap_{single,sg}. If you don't touch the data from the first dma_map_* -call till dma_unmap_*, then you don't have to call the dma_sync_* -routines at all. +dma_unmap_{single,sg}(). If you don't touch the data from the first +dma_map_*() call till dma_unmap_*(), then you don't have to call the +dma_sync_*() routines at all. Here is pseudo code which shows a situation in which you would need to use the dma_sync_*() interfaces. @@ -690,12 +744,12 @@ to use the dma_sync_*() interfaces. } } -Drivers converted fully to this interface should not use virt_to_bus any -longer, nor should they use bus_to_virt. Some drivers have to be changed a -little bit, because there is no longer an equivalent to bus_to_virt in the +Drivers converted fully to this interface should not use virt_to_bus() any +longer, nor should they use bus_to_virt(). Some drivers have to be changed a +little bit, because there is no longer an equivalent to bus_to_virt() in the dynamic DMA mapping scheme - you have to always store the DMA addresses -returned by the dma_alloc_coherent, dma_pool_alloc, and dma_map_single -calls (dma_map_sg stores them in the scatterlist itself if the platform +returned by the dma_alloc_coherent(), dma_pool_alloc(), and dma_map_single() +calls (dma_map_sg() stores them in the scatterlist itself if the platform supports dynamic DMA mapping in hardware) in your driver structures and/or in the card registers. @@ -709,9 +763,9 @@ as it is impossible to correctly support them. DMA address space is limited on some architectures and an allocation failure can be determined by: -- checking if dma_alloc_coherent returns NULL or dma_map_sg returns 0 +- checking if dma_alloc_coherent() returns NULL or dma_map_sg returns 0 -- checking the returned dma_addr_t of dma_map_single and dma_map_page +- checking the dma_addr_t returned from dma_map_single() and dma_map_page() by using dma_mapping_error(): dma_addr_t dma_handle; @@ -794,7 +848,7 @@ Example 2: (if buffers are allocated in a loop, unmap all mapped buffers when dma_unmap_single(array[i].dma_addr); } -Networking drivers must call dev_kfree_skb to free the socket buffer +Networking drivers must call dev_kfree_skb() to free the socket buffer and return NETDEV_TX_OK if the DMA mapping fails on the transmit hook (ndo_start_xmit). This means that the socket buffer is just dropped in the failure case. @@ -831,7 +885,7 @@ transform some example code. DEFINE_DMA_UNMAP_LEN(len); }; -2) Use dma_unmap_{addr,len}_set to set these values. +2) Use dma_unmap_{addr,len}_set() to set these values. Example, before: ringp->mapping = FOO; @@ -842,7 +896,7 @@ transform some example code. dma_unmap_addr_set(ringp, mapping, FOO); dma_unmap_len_set(ringp, len, BAR); -3) Use dma_unmap_{addr,len} to access these values. +3) Use dma_unmap_{addr,len}() to access these values. Example, before: dma_unmap_single(dev, ringp->mapping, ringp->len, diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index e865279..1147eba 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -4,22 +4,26 @@ James E.J. Bottomley This document describes the DMA API. For a more gentle introduction -of the API (and actual examples) see -Documentation/DMA-API-HOWTO.txt. +of the API (and actual examples), see Documentation/DMA-API-HOWTO.txt. -This API is split into two pieces. Part I describes the API. Part II -describes the extensions to the API for supporting non-consistent -memory machines. Unless you know that your driver absolutely has to -support non-consistent platforms (this is usually only legacy -platforms) you should only use the API described in part I. +This API is split into two pieces. Part I describes the basic API. +Part II describes extensions for supporting non-consistent memory +machines. Unless you know that your driver absolutely has to support +non-consistent platforms (this is usually only legacy platforms) you +should only use the API described in part I. Part I - dma_ API ------------------------------------- -To get the dma_ API, you must #include +To get the dma_ API, you must #include . This +provides dma_addr_t and the interfaces described below. +A dma_addr_t can hold any valid DMA or bus address for the platform. It +can be given to a device to use as a DMA source or target. A cpu cannot +reference a dma_addr_t directly because there may be translation between +its physical address space and the bus address space. -Part Ia - Using large dma-coherent buffers +Part Ia - Using large DMA-coherent buffers ------------------------------------------ void * @@ -33,20 +37,21 @@ to make sure to flush the processor's write buffers before telling devices to read that memory.) This routine allocates a region of bytes of consistent memory. -It also returns a which may be cast to an unsigned -integer the same width as the bus and used as the physical address -base of the region. -Returns: a pointer to the allocated region (in the processor's virtual +It returns a pointer to the allocated region (in the processor's virtual address space) or NULL if the allocation failed. +It also returns a which may be cast to an unsigned integer the +same width as the bus and given to the device as the bus address base of +the region. + Note: consistent memory can be expensive on some platforms, and the minimum allocation length may be as big as a page, so you should consolidate your requests for consistent memory as much as possible. The simplest way to do that is to use the dma_pool calls (see below). -The flag parameter (dma_alloc_coherent only) allows the caller to -specify the GFP_ flags (see kmalloc) for the allocation (the +The flag parameter (dma_alloc_coherent() only) allows the caller to +specify the GFP_ flags (see kmalloc()) for the allocation (the implementation may choose to ignore flags that affect the location of the returned memory, like GFP_DMA). @@ -61,24 +66,24 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle) -Free the region of consistent memory you previously allocated. dev, -size and dma_handle must all be the same as those passed into the -consistent allocate. cpu_addr must be the virtual address returned by -the consistent allocate. +Free a region of consistent memory you previously allocated. dev, +size and dma_handle must all be the same as those passed into +dma_alloc_coherent(). cpu_addr must be the virtual address returned by +the dma_alloc_coherent(). Note that unlike their sibling allocation calls, these routines may only be called with IRQs enabled. -Part Ib - Using small dma-coherent buffers +Part Ib - Using small DMA-coherent buffers ------------------------------------------ To get this part of the dma_ API, you must #include -Many drivers need lots of small dma-coherent memory regions for DMA +Many drivers need lots of small DMA-coherent memory regions for DMA descriptors or I/O buffers. Rather than allocating in units of a page or more using dma_alloc_coherent(), you can use DMA pools. These work -much like a struct kmem_cache, except that they use the dma-coherent allocator, +much like a struct kmem_cache, except that they use the DMA-coherent allocator, not __get_free_pages(). Also, they understand common hardware constraints for alignment, like queue heads needing to be aligned on N-byte boundaries. @@ -87,7 +92,7 @@ for alignment, like queue heads needing to be aligned on N-byte boundaries. dma_pool_create(const char *name, struct device *dev, size_t size, size_t align, size_t alloc); -The pool create() routines initialize a pool of dma-coherent buffers +dma_pool_create() initializes a pool of DMA-coherent buffers for use with a given device. It must be called in a context which can sleep. @@ -102,25 +107,26 @@ from this pool must not cross 4KByte boundaries. void *dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags, dma_addr_t *dma_handle); -This allocates memory from the pool; the returned memory will meet the size -and alignment requirements specified at creation time. Pass GFP_ATOMIC to -prevent blocking, or if it's permitted (not in_interrupt, not holding SMP locks), -pass GFP_KERNEL to allow blocking. Like dma_alloc_coherent(), this returns -two values: an address usable by the cpu, and the dma address usable by the -pool's device. +This allocates memory from the pool; the returned memory will meet the +size and alignment requirements specified at creation time. Pass +GFP_ATOMIC to prevent blocking, or if it's permitted (not +in_interrupt, not holding SMP locks), pass GFP_KERNEL to allow +blocking. Like dma_alloc_coherent(), this returns two values: an +address usable by the cpu, and the DMA address usable by the pool's +device. void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t addr); This puts memory back into the pool. The pool is what was passed to -the pool allocation routine; the cpu (vaddr) and dma addresses are what +dma_pool_alloc(); the cpu (vaddr) and DMA addresses are what were returned when that routine allocated the memory being freed. void dma_pool_destroy(struct dma_pool *pool); -The pool destroy() routines free the resources of the pool. They must be +dma_pool_destroy() frees the resources of the pool. It must be called in a context which can sleep. Make sure you've freed all allocated memory back to the pool before you destroy it. @@ -187,9 +193,9 @@ dma_map_single(struct device *dev, void *cpu_addr, size_t size, enum dma_data_direction direction) Maps a piece of processor virtual memory so it can be accessed by the -device and returns the physical handle of the memory. +device and returns the bus address of the memory. -The direction for both api's may be converted freely by casting. +The direction for both APIs may be converted freely by casting. However the dma_ API uses a strongly typed enumerator for its direction: @@ -198,31 +204,30 @@ DMA_TO_DEVICE data is going from the memory to the device DMA_FROM_DEVICE data is coming from the device to the memory DMA_BIDIRECTIONAL direction isn't known -Notes: Not all memory regions in a machine can be mapped by this -API. Further, regions that appear to be physically contiguous in -kernel virtual space may not be contiguous as physical memory. Since -this API does not provide any scatter/gather capability, it will fail -if the user tries to map a non-physically contiguous piece of memory. -For this reason, it is recommended that memory mapped by this API be -obtained only from sources which guarantee it to be physically contiguous -(like kmalloc). - -Further, the physical address of the memory must be within the -dma_mask of the device (the dma_mask represents a bit mask of the -addressable region for the device. I.e., if the physical address of -the memory anded with the dma_mask is still equal to the physical -address, then the device can perform DMA to the memory). In order to +Notes: Not all memory regions in a machine can be mapped by this API. +Further, contiguous kernel virtual space may not be contiguous as +physical memory. Since this API does not provide any scatter/gather +capability, it will fail if the user tries to map a non-physically +contiguous piece of memory. For this reason, memory to be mapped by +this API should be obtained from sources which guarantee it to be +physically contiguous (like kmalloc). + +Further, the bus address of the memory must be within the +dma_mask of the device (the dma_mask is a bit mask of the +addressable region for the device, i.e., if the bus address of +the memory ANDed with the dma_mask is still equal to the bus +address, then the device can perform DMA to the memory). To ensure that the memory allocated by kmalloc is within the dma_mask, the driver may specify various platform-dependent flags to restrict -the physical memory range of the allocation (e.g. on x86, GFP_DMA -guarantees to be within the first 16Mb of available physical memory, +the bus address range of the allocation (e.g., on x86, GFP_DMA +guarantees to be within the first 16MB of available bus addresses, as required by ISA devices). Note also that the above constraints on physical contiguity and dma_mask may not apply if the platform has an IOMMU (a device which -supplies a physical to virtual mapping between the I/O memory bus and -the device). However, to be portable, device driver writers may *not* -assume that such an IOMMU exists. +maps an I/O bus address to a physical memory address). However, to be +portable, device driver writers may *not* assume that such an IOMMU +exists. Warnings: Memory coherency operates at a granularity called the cache line width. In order for memory mapped by this API to operate @@ -281,9 +286,9 @@ cache width is. int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) -In some circumstances dma_map_single and dma_map_page will fail to create +In some circumstances dma_map_single() and dma_map_page() will fail to create a mapping. A driver can check for these errors by testing the returned -dma address with dma_mapping_error(). A non-zero return value means the mapping +DMA address with dma_mapping_error(). A non-zero return value means the mapping could not be created and the driver should take appropriate action (e.g. reduce current DMA mapping usage or delay and try again later). @@ -291,7 +296,7 @@ reduce current DMA mapping usage or delay and try again later). dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction) -Returns: the number of physical segments mapped (this may be shorter +Returns: the number of bus address segments mapped (this may be shorter than passed in if some elements of the scatter/gather list are physically or virtually adjacent and an IOMMU maps them with a single entry). @@ -299,7 +304,7 @@ entry). Please note that the sg cannot be mapped again if it has been mapped once. The mapping process is allowed to destroy information in the sg. -As with the other mapping interfaces, dma_map_sg can fail. When it +As with the other mapping interfaces, dma_map_sg() can fail. When it does, 0 is returned and a driver must take appropriate action. It is critical that the driver do something, in the case of a block driver aborting the request or even oopsing is better than doing nothing and @@ -335,7 +340,7 @@ must be the same as those and passed in to the scatter/gather mapping API. Note: must be the number you passed in, *not* the number of -physical entries returned. +bus address entries returned. void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, @@ -391,10 +396,10 @@ The four functions above are just like the counterpart functions without the _attrs suffixes, except that they pass an optional struct dma_attrs*. -struct dma_attrs encapsulates a set of "dma attributes". For the +struct dma_attrs encapsulates a set of "DMA attributes". For the definition of struct dma_attrs see linux/dma-attrs.h. -The interpretation of dma attributes is architecture-specific, and +The interpretation of DMA attributes is architecture-specific, and each attribute should be documented in Documentation/DMA-attributes.txt. If struct dma_attrs* is NULL, the semantics of each of these @@ -458,7 +463,7 @@ Note: where the platform can return consistent memory, it will guarantee that the sync points become nops. Warning: Handling non-consistent memory is a real pain. You should -only ever use this API if you positively know your driver will be +only use this API if you positively know your driver will be required to work on one of the rare (usually non-PCI) architectures that simply cannot make consistent memory. @@ -496,26 +501,26 @@ dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, dma_addr_t device_addr, size_t size, int flags) -Declare region of memory to be handed out by dma_alloc_coherent when +Declare region of memory to be handed out by dma_alloc_coherent() when it's asked for coherent memory for this device. bus_addr is the physical address to which the memory is currently assigned in the bus responding region (this will be used by the platform to perform the mapping). -device_addr is the physical address the device needs to be programmed +device_addr is the bus address the device needs to be programmed with actually to address this memory (this will be handed out as the dma_addr_t in dma_alloc_coherent()). size is the size of the area (must be multiples of PAGE_SIZE). -flags can be or'd together and are: +flags can be ORed together and are: DMA_MEMORY_MAP - request that the memory returned from dma_alloc_coherent() be directly writable. DMA_MEMORY_IO - request that the memory returned from -dma_alloc_coherent() be addressable using read/write/memcpy_toio etc. +dma_alloc_coherent() be addressable using read()/write()/memcpy_toio() etc. One or both of these flags must be present. @@ -572,7 +577,7 @@ region is occupied. Part III - Debug drivers use of the DMA-API ------------------------------------------- -The DMA-API as described above as some constraints. DMA addresses must be +The DMA-API as described above has some constraints. DMA addresses must be released with the corresponding function with the same size for example. With the advent of hardware IOMMUs it becomes more and more important that drivers do not violate those constraints. In the worst case such a violation can @@ -690,11 +695,11 @@ architectural default. void debug_dmap_mapping_error(struct device *dev, dma_addr_t dma_addr); dma-debug interface debug_dma_mapping_error() to debug drivers that fail -to check dma mapping errors on addresses returned by dma_map_single() and +to check DMA mapping errors on addresses returned by dma_map_single() and dma_map_page() interfaces. This interface clears a flag set by debug_dma_map_page() to indicate that dma_mapping_error() has been called by the driver. When driver does unmap, debug_dma_unmap() checks the flag and if this flag is still set, prints warning message that includes call trace that leads up to the unmap. This interface can be called from dma_mapping_error() -routines to enable dma mapping error check debugging. +routines to enable DMA mapping error check debugging. diff --git a/Documentation/DMA-ISA-LPC.txt b/Documentation/DMA-ISA-LPC.txt index e767805..b1a1983 100644 --- a/Documentation/DMA-ISA-LPC.txt +++ b/Documentation/DMA-ISA-LPC.txt @@ -16,7 +16,7 @@ To do ISA style DMA you need to include two headers: #include The first is the generic DMA API used to convert virtual addresses to -physical addresses (see Documentation/DMA-API.txt for details). +bus addresses (see Documentation/DMA-API.txt for details). The second contains the routines specific to ISA DMA transfers. Since this is not present on all platforms make sure you construct your @@ -50,7 +50,7 @@ early as possible and not release it until the driver is unloaded.) Part III - Address translation ------------------------------ -To translate the virtual address to a physical use the normal DMA +To translate the virtual address to a bus address, use the normal DMA API. Do _not_ use isa_virt_to_phys() even though it does the same thing. The reason for this is that the function isa_virt_to_phys() will require a Kconfig dependency to ISA, not just ISA_DMA_API which diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index fd4aee2..b9aa2b9 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -8,6 +8,12 @@ #include #include +/* + * A dma_addr_t can hold any valid DMA or bus address for the platform. + * It can be given to a device to use as a DMA source or target. A CPU cannot + * reference a dma_addr_t directly because there may be translation between + * its physical address space and the bus address space. + */ struct dma_map_ops { void* (*alloc)(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, diff --git a/include/linux/types.h b/include/linux/types.h index 4d118ba..a0bb704 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -142,6 +142,7 @@ typedef unsigned long blkcnt_t; #define pgoff_t unsigned long #endif +/* A dma_addr_t can hold any valid DMA or bus address for the platform */ #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT typedef u64 dma_addr_t; #else -- cgit v0.10.2 From 88a984ba0795f14a3847edbd7fabe652289ea89b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 20 May 2014 16:54:22 -0600 Subject: DMA-API: Change dma_declare_coherent_memory() CPU address to phys_addr_t dma_declare_coherent_memory() takes two addresses for a region of memory: a "bus_addr" and a "device_addr". I think the intent is that "bus_addr" is the physical address a *CPU* would use to access the region, and "device_addr" is the bus address the *device* would use to address the region. Rename "bus_addr" to "phys_addr" and change its type to phys_addr_t. Most callers already supply a phys_addr_t for this argument. The others supply a 32-bit integer (a constant, unsigned int, or __u32) and need no change. Use "unsigned long", not phys_addr_t, to hold PFNs. No functional change (this could theoretically fix a truncation in a config with 32-bit dma_addr_t and 64-bit phys_addr_t, but I don't think there are any such cases involving this code). Signed-off-by: Bjorn Helgaas Acked-by: Arnd Bergmann Acked-by: Greg Kroah-Hartman Acked-by: James Bottomley Acked-by: Randy Dunlap diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 1147eba..4f1cdc5 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -497,19 +497,18 @@ continuing on for size. Again, you *must* observe the cache line boundaries when doing this. int -dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, +dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags) Declare region of memory to be handed out by dma_alloc_coherent() when it's asked for coherent memory for this device. -bus_addr is the physical address to which the memory is currently -assigned in the bus responding region (this will be used by the -platform to perform the mapping). +phys_addr is the cpu physical address to which the memory is currently +assigned (this will be ioremapped so the cpu can access the region). device_addr is the bus address the device needs to be programmed -with actually to address this memory (this will be handed out as the +with to actually address this memory (this will be handed out as the dma_addr_t in dma_alloc_coherent()). size is the size of the area (must be multiples of PAGE_SIZE). diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index bc256b6..7d6e84a 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -10,13 +10,13 @@ struct dma_coherent_mem { void *virt_base; dma_addr_t device_base; - phys_addr_t pfn_base; + unsigned long pfn_base; int size; int flags; unsigned long *bitmap; }; -int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, +int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags) { void __iomem *mem_base = NULL; @@ -32,7 +32,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ - mem_base = ioremap(bus_addr, size); + mem_base = ioremap(phys_addr, size); if (!mem_base) goto out; @@ -45,7 +45,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, dev->dma_mem->virt_base = mem_base; dev->dma_mem->device_base = device_addr; - dev->dma_mem->pfn_base = PFN_DOWN(bus_addr); + dev->dma_mem->pfn_base = PFN_DOWN(phys_addr); dev->dma_mem->size = pages; dev->dma_mem->flags = flags; @@ -208,7 +208,7 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, *ret = -ENXIO; if (off < count && user_count <= count - off) { - unsigned pfn = mem->pfn_base + start + off; + unsigned long pfn = mem->pfn_base + start + off; *ret = remap_pfn_range(vma, vma->vm_start, pfn, user_count << PAGE_SHIFT, vma->vm_page_prot); diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c index 0ce39a3..6cd08e1 100644 --- a/drivers/base/dma-mapping.c +++ b/drivers/base/dma-mapping.c @@ -175,7 +175,7 @@ static void dmam_coherent_decl_release(struct device *dev, void *res) /** * dmam_declare_coherent_memory - Managed dma_declare_coherent_memory() * @dev: Device to declare coherent memory for - * @bus_addr: Bus address of coherent memory to be declared + * @phys_addr: Physical address of coherent memory to be declared * @device_addr: Device address of coherent memory to be declared * @size: Size of coherent memory to be declared * @flags: Flags @@ -185,7 +185,7 @@ static void dmam_coherent_decl_release(struct device *dev, void *res) * RETURNS: * 0 on success, -errno on failure. */ -int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, +int dmam_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags) { void *res; @@ -195,7 +195,7 @@ int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, if (!res) return -ENOMEM; - rc = dma_declare_coherent_memory(dev, bus_addr, device_addr, size, + rc = dma_declare_coherent_memory(dev, phys_addr, device_addr, size, flags); if (rc == 0) devres_add(dev, res); diff --git a/include/asm-generic/dma-coherent.h b/include/asm-generic/dma-coherent.h index 2be8a2d..0297e58 100644 --- a/include/asm-generic/dma-coherent.h +++ b/include/asm-generic/dma-coherent.h @@ -16,16 +16,13 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, * Standard interface */ #define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY -extern int -dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, - dma_addr_t device_addr, size_t size, int flags); +int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, + dma_addr_t device_addr, size_t size, int flags); -extern void -dma_release_declared_memory(struct device *dev); +void dma_release_declared_memory(struct device *dev); -extern void * -dma_mark_declared_memory_occupied(struct device *dev, - dma_addr_t device_addr, size_t size); +void *dma_mark_declared_memory_occupied(struct device *dev, + dma_addr_t device_addr, size_t size); #else #define dma_alloc_from_coherent(dev, size, handle, ret) (0) #define dma_release_from_coherent(dev, order, vaddr) (0) diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index b9aa2b9..0c3eab1 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -192,7 +192,7 @@ static inline int dma_get_cache_alignment(void) #ifndef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY static inline int -dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, +dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags) { return 0; @@ -223,13 +223,14 @@ extern void *dmam_alloc_noncoherent(struct device *dev, size_t size, extern void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle); #ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY -extern int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, +extern int dmam_declare_coherent_memory(struct device *dev, + phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags); extern void dmam_release_declared_memory(struct device *dev); #else /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */ static inline int dmam_declare_coherent_memory(struct device *dev, - dma_addr_t bus_addr, dma_addr_t device_addr, + phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, gfp_t gfp) { return 0; -- cgit v0.10.2 From ace4b3fd67e771951d495aa1f1b1000984083362 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 20 May 2014 16:54:23 -0600 Subject: sh/PCI: Pass GAPSPCI_DMA_BASE CPU & bus address to dma_declare_coherent_memory() dma_declare_coherent_memory() needs both the CPU physical address and the bus address of the device memory. They are the same on this platform, but in general we should use pcibios_resource_to_bus() to account for any address translation done by the PCI host bridge. This makes no difference on Dreamcast, but is safer if the usage is copied to future drivers. Signed-off-by: Bjorn Helgaas Acked-by: Arnd Bergmann CC: Magnus Damm CC: linux-sh@vger.kernel.org diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c index d6cde70..1d1c5a2 100644 --- a/arch/sh/drivers/pci/fixups-dreamcast.c +++ b/arch/sh/drivers/pci/fixups-dreamcast.c @@ -31,6 +31,8 @@ static void gapspci_fixup_resources(struct pci_dev *dev) { struct pci_channel *p = dev->sysdata; + struct resource res; + struct pci_bus_region region; printk(KERN_NOTICE "PCI: Fixing up device %s\n", pci_name(dev)); @@ -50,11 +52,21 @@ static void gapspci_fixup_resources(struct pci_dev *dev) /* * Redirect dma memory allocations to special memory window. + * + * If this GAPSPCI region were mapped by a BAR, the CPU + * phys_addr_t would be pci_resource_start(), and the bus + * address would be pci_bus_address(pci_resource_start()). + * But apparently there's no BAR mapping it, so we just + * "know" its CPU address is GAPSPCI_DMA_BASE. */ + res.start = GAPSPCI_DMA_BASE; + res.end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1; + res.flags = IORESOURCE_MEM; + pcibios_resource_to_bus(dev->bus, ®ion, &res); BUG_ON(!dma_declare_coherent_memory(&dev->dev, - GAPSPCI_DMA_BASE, - GAPSPCI_DMA_BASE, - GAPSPCI_DMA_SIZE, + res.start, + region.start, + resource_size(&res), DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)); break; -- cgit v0.10.2 From ef4858c64e836b0b9dbdb9ece13ce932d9fcd4ad Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 30 Apr 2014 14:50:09 -0600 Subject: s390/pci: use pdev->dev.groups for attribute creation Let the driver core handle attribute creation by putting all s390 specific pci attributes in an attribute group which is referenced by pdev->dev.groups in pcibios_add_device. Link: https://lkml.kernel.org/r/alpine.LFD.2.11.1404141101500.1529@denkbrett Reviewed-by: Gerald Schaefer Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 2583466..79b5f07 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -120,6 +120,8 @@ static inline bool zdev_enabled(struct zpci_dev *zdev) return (zdev->fh & (1UL << 31)) ? true : false; } +extern const struct attribute_group *zpci_attr_groups[]; + /* ----------------------------------------------------------------------------- Prototypes ----------------------------------------------------------------------------- */ @@ -166,10 +168,6 @@ static inline void zpci_exit_slot(struct zpci_dev *zdev) {} struct zpci_dev *get_zdev(struct pci_dev *); struct zpci_dev *get_zdev_by_fid(u32); -/* sysfs */ -int zpci_sysfs_add_device(struct device *); -void zpci_sysfs_remove_device(struct device *); - /* DMA */ int zpci_dma_init(void); void zpci_dma_exit(void); diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 1df1d29..bdf0257 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -530,11 +530,6 @@ static void zpci_unmap_resources(struct zpci_dev *zdev) } } -int pcibios_add_platform_entries(struct pci_dev *pdev) -{ - return zpci_sysfs_add_device(&pdev->dev); -} - static int __init zpci_irq_init(void) { int rc; @@ -671,6 +666,7 @@ int pcibios_add_device(struct pci_dev *pdev) int i; zdev->pdev = pdev; + pdev->dev.groups = zpci_attr_groups; zpci_map_resources(zdev); for (i = 0; i < PCI_BAR_COUNT; i++) { diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c index ab4a913..b56a395 100644 --- a/arch/s390/pci/pci_sysfs.c +++ b/arch/s390/pci/pci_sysfs.c @@ -72,36 +72,18 @@ static ssize_t store_recover(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(recover, S_IWUSR, NULL, store_recover); -static struct device_attribute *zpci_dev_attrs[] = { - &dev_attr_function_id, - &dev_attr_function_handle, - &dev_attr_pchid, - &dev_attr_pfgid, - &dev_attr_recover, +static struct attribute *zpci_dev_attrs[] = { + &dev_attr_function_id.attr, + &dev_attr_function_handle.attr, + &dev_attr_pchid.attr, + &dev_attr_pfgid.attr, + &dev_attr_recover.attr, + NULL, +}; +static struct attribute_group zpci_attr_group = { + .attrs = zpci_dev_attrs, +}; +const struct attribute_group *zpci_attr_groups[] = { + &zpci_attr_group, NULL, }; - -int zpci_sysfs_add_device(struct device *dev) -{ - int i, rc = 0; - - for (i = 0; zpci_dev_attrs[i]; i++) { - rc = device_create_file(dev, zpci_dev_attrs[i]); - if (rc) - goto error; - } - return 0; - -error: - while (--i >= 0) - device_remove_file(dev, zpci_dev_attrs[i]); - return rc; -} - -void zpci_sysfs_remove_device(struct device *dev) -{ - int i; - - for (i = 0; zpci_dev_attrs[i]; i++) - device_remove_file(dev, zpci_dev_attrs[i]); -} -- cgit v0.10.2 From 9edbcd2252b5ef148177c9f2c11a56469cf5db52 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 17 Apr 2014 19:48:07 +0200 Subject: PCI: Remove pcibios_add_platform_entries() Remove pcibios_add_platform_entries(). Architecture-specific attributes can be achieved by setting pdev->dev.groups. Link: https://lkml.kernel.org/r/alpine.LFD.2.11.1404141101500.1529@denkbrett Signed-off-by: Sebastian Ott Signed-off-by: Bjorn Helgaas Acked-by: Greg Kroah-Hartman diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 3db1c7f..b7333fa 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -1273,11 +1273,6 @@ static struct bin_attribute pcie_config_attr = { .write = pci_write_config, }; -int __weak pcibios_add_platform_entries(struct pci_dev *dev) -{ - return 0; -} - static ssize_t reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1393,11 +1388,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) pdev->rom_attr = attr; } - /* add platform-specific attributes */ - retval = pcibios_add_platform_entries(pdev); - if (retval) - goto err_rom_file; - /* add sysfs entries for various capabilities */ retval = pci_create_capabilities_sysfs(pdev); if (retval) diff --git a/include/linux/pci.h b/include/linux/pci.h index a95aac7..84182b1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1572,7 +1572,6 @@ extern unsigned long pci_hotplug_io_size; extern unsigned long pci_hotplug_mem_size; /* Architecture-specific versions may override these (weak) */ -int pcibios_add_platform_entries(struct pci_dev *dev); void pcibios_disable_device(struct pci_dev *dev); void pcibios_set_master(struct pci_dev *dev); int pcibios_set_pcie_reset_state(struct pci_dev *dev, -- cgit v0.10.2 From adc429d69937b3ef6fba2f8e8de9b7ce8347b662 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Apr 2014 16:13:48 -0600 Subject: x86/PCI: Move pcibios_assign_resources() annotation to definition Move the pcibios_assign_resources() fs_initcall annotation next to the function definition. No functional change. Signed-off-by: Bjorn Helgaas diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 6db58d6..a19ed92 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -361,6 +361,12 @@ static int __init pcibios_assign_resources(void) return 0; } +/** + * called in fs_initcall (one below subsys_initcall), + * give a chance for motherboard reserve resources + */ +fs_initcall(pcibios_assign_resources); + void pcibios_resource_survey_bus(struct pci_bus *bus) { dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n"); @@ -397,12 +403,6 @@ void __init pcibios_resource_survey(void) ioapic_insert_resources(); } -/** - * called in fs_initcall (one below subsys_initcall), - * give a chance for motherboard reserve resources - */ -fs_initcall(pcibios_assign_resources); - static const struct vm_operations_struct pci_mmap_ops = { .access = generic_access_phys, }; -- cgit v0.10.2 From a5d3244a0b1c16963fd7ceadf76da843df27c3c5 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 28 Apr 2014 15:16:33 -0600 Subject: x86/gart: Replace printk() with pr_info() Replace printk() with pr_info(), pr_err(), etc. Define pr_fmt() to prefix output with "AGP: ". No functional change except the addition of "AGP: " prefix in dmesg output. Signed-off-by: Bjorn Helgaas diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 9fa8aa0..b11edf2b 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -10,6 +10,8 @@ * * Copyright 2002 Andi Kleen, SuSE Labs. */ +#define pr_fmt(fmt) "AGP: " fmt + #include #include #include @@ -75,14 +77,13 @@ static u32 __init allocate_aperture(void) addr = memblock_find_in_range(GART_MIN_ADDR, GART_MAX_ADDR, aper_size, aper_size); if (!addr) { - printk(KERN_ERR - "Cannot allocate aperture memory hole (%lx,%uK)\n", - addr, aper_size>>10); + pr_err("Cannot allocate aperture memory hole (%lx,%uK)\n", + addr, aper_size>>10); return 0; } memblock_reserve(addr, aper_size); - printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n", - aper_size >> 10, addr); + pr_info("Mapping aperture over %d KB of RAM @ %lx\n", aper_size >> 10, + addr); register_nosave_region(addr >> PAGE_SHIFT, (addr+aper_size) >> PAGE_SHIFT); @@ -126,10 +127,10 @@ static u32 __init read_agp(int bus, int slot, int func, int cap, u32 *order) u64 aper; u32 old_order; - printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", bus, slot, func); + pr_info("AGP bridge at %02x:%02x:%02x\n", bus, slot, func); apsizereg = read_pci_config_16(bus, slot, func, cap + 0x14); if (apsizereg == 0xffffffff) { - printk(KERN_ERR "APSIZE in AGP bridge unreadable\n"); + pr_err("APSIZE in AGP bridge unreadable\n"); return 0; } @@ -153,16 +154,16 @@ static u32 __init read_agp(int bus, int slot, int func, int cap, u32 *order) * On some sick chips, APSIZE is 0. It means it wants 4G * so let double check that order, and lets trust AMD NB settings: */ - printk(KERN_INFO "Aperture from AGP @ %Lx old size %u MB\n", - aper, 32 << old_order); + pr_info("Aperture from AGP @ %Lx old size %u MB\n", + aper, 32 << old_order); if (aper + (32ULL<<(20 + *order)) > 0x100000000ULL) { - printk(KERN_INFO "Aperture size %u MB (APSIZE %x) is not right, using settings from NB\n", - 32 << *order, apsizereg); + pr_info("Aperture size %u MB (APSIZE %x) is not right, using settings from NB\n", + 32 << *order, apsizereg); *order = old_order; } - printk(KERN_INFO "Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", - aper, 32 << *order, apsizereg); + pr_info("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", aper, + 32 << *order, apsizereg); if (!aperture_valid(aper, (32*1024*1024) << *order, 32<<20)) return 0; @@ -218,7 +219,7 @@ static u32 __init search_agp_bridge(u32 *order, int *valid_agp) } } } - printk(KERN_INFO "No AGP bridge found\n"); + pr_info("No AGP bridge found\n"); return 0; } @@ -310,7 +311,7 @@ void __init early_gart_iommu_check(void) if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) { /* reserve it, so we can reuse it in second kernel */ - printk(KERN_INFO "update e820 for GART\n"); + pr_info("update e820 for GART\n"); e820_add_region(aper_base, aper_size, E820_RESERVED); update_e820(); } @@ -354,7 +355,7 @@ int __init gart_iommu_hole_init(void) !early_pci_allowed()) return -ENODEV; - printk(KERN_INFO "Checking aperture...\n"); + pr_info("Checking aperture...\n"); if (!fallback_aper_force) agp_aper_base = search_agp_bridge(&agp_aper_order, &valid_agp); @@ -395,8 +396,8 @@ int __init gart_iommu_hole_init(void) aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff; aper_base <<= 25; - printk(KERN_INFO "Node %d: aperture @ %Lx size %u MB\n", - node, aper_base, aper_size >> 20); + pr_info("Node %d: aperture @ %Lx size %u MB\n", + node, aper_base, aper_size >> 20); node++; if (!aperture_valid(aper_base, aper_size, 64<<20)) { @@ -407,9 +408,9 @@ int __init gart_iommu_hole_init(void) if (!no_iommu && max_pfn > MAX_DMA32_PFN && !printed_gart_size_msg) { - printk(KERN_ERR "you are using iommu with agp, but GART size is less than 64M\n"); - printk(KERN_ERR "please increase GART size in your BIOS setup\n"); - printk(KERN_ERR "if BIOS doesn't have that option, contact your HW vendor!\n"); + pr_err("you are using iommu with agp, but GART size is less than 64M\n"); + pr_err("please increase GART size in your BIOS setup\n"); + pr_err("if BIOS doesn't have that option, contact your HW vendor!\n"); printed_gart_size_msg = 1; } } else { @@ -446,13 +447,10 @@ out: force_iommu || valid_agp || fallback_aper_force) { - printk(KERN_INFO - "Your BIOS doesn't leave a aperture memory hole\n"); - printk(KERN_INFO - "Please enable the IOMMU option in the BIOS setup\n"); - printk(KERN_INFO - "This costs you %d MB of RAM\n", - 32 << fallback_aper_order); + pr_info("Your BIOS doesn't leave a aperture memory hole\n"); + pr_info("Please enable the IOMMU option in the BIOS setup\n"); + pr_info("This costs you %d MB of RAM\n", + 32 << fallback_aper_order); aper_order = fallback_aper_order; aper_alloc = allocate_aperture(); -- cgit v0.10.2 From c96ec95315b9242ec423b8348984c394d27a8135 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Apr 2014 15:29:19 -0600 Subject: x86/gart: Tidy messages and add bridge device info Print the AGP bridge info the same way as the rest of the kernel, e.g., "0000:00:04.0" instead of "00:04:00". Also print the AGP aperture address range the same way we print resources, and label it explicitly as a bus address range. No functional change except the message changes. Signed-off-by: Bjorn Helgaas diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index b11edf2b..76164e1 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -77,13 +77,13 @@ static u32 __init allocate_aperture(void) addr = memblock_find_in_range(GART_MIN_ADDR, GART_MAX_ADDR, aper_size, aper_size); if (!addr) { - pr_err("Cannot allocate aperture memory hole (%lx,%uK)\n", - addr, aper_size>>10); + pr_err("Cannot allocate aperture memory hole [mem %#010lx-%#010lx] (%uKB)\n", + addr, addr + aper_size - 1, aper_size >> 10); return 0; } memblock_reserve(addr, aper_size); - pr_info("Mapping aperture over %d KB of RAM @ %lx\n", aper_size >> 10, - addr); + pr_info("Mapping aperture over RAM [mem %#010lx-%#010lx] (%uKB)\n", + addr, addr + aper_size - 1, aper_size >> 10); register_nosave_region(addr >> PAGE_SHIFT, (addr+aper_size) >> PAGE_SHIFT); @@ -127,10 +127,11 @@ static u32 __init read_agp(int bus, int slot, int func, int cap, u32 *order) u64 aper; u32 old_order; - pr_info("AGP bridge at %02x:%02x:%02x\n", bus, slot, func); + pr_info("pci 0000:%02x:%02x:%02x: AGP bridge\n", bus, slot, func); apsizereg = read_pci_config_16(bus, slot, func, cap + 0x14); if (apsizereg == 0xffffffff) { - pr_err("APSIZE in AGP bridge unreadable\n"); + pr_err("pci 0000:%02x:%02x.%d: APSIZE unreadable\n", + bus, slot, func); return 0; } @@ -154,15 +155,17 @@ static u32 __init read_agp(int bus, int slot, int func, int cap, u32 *order) * On some sick chips, APSIZE is 0. It means it wants 4G * so let double check that order, and lets trust AMD NB settings: */ - pr_info("Aperture from AGP @ %Lx old size %u MB\n", - aper, 32 << old_order); + pr_info("pci 0000:%02x:%02x.%d: AGP aperture [bus addr %#010Lx-%#010Lx] (old size %uMB)\n", + bus, slot, func, aper, aper + (32ULL << (old_order + 20)) - 1, + 32 << old_order); if (aper + (32ULL<<(20 + *order)) > 0x100000000ULL) { - pr_info("Aperture size %u MB (APSIZE %x) is not right, using settings from NB\n", - 32 << *order, apsizereg); + pr_info("pci 0000:%02x:%02x.%d: AGP aperture size %uMB (APSIZE %#x) is not right, using settings from NB\n", + bus, slot, func, 32 << *order, apsizereg); *order = old_order; } - pr_info("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", aper, + pr_info("pci 0000:%02x:%02x.%d: AGP aperture [bus addr %#010Lx-%#010Lx] (%uMB, APSIZE %#x)\n", + bus, slot, func, aper, aper + (32ULL << (*order + 20)) - 1, 32 << *order, apsizereg); if (!aperture_valid(aper, (32*1024*1024) << *order, 32<<20)) @@ -311,7 +314,8 @@ void __init early_gart_iommu_check(void) if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) { /* reserve it, so we can reuse it in second kernel */ - pr_info("update e820 for GART\n"); + pr_info("e820: reserve [mem %#010Lx-%#010Lx] for GART\n", + aper_base, aper_base + aper_size - 1); e820_add_region(aper_base, aper_size, E820_RESERVED); update_e820(); } @@ -396,8 +400,9 @@ int __init gart_iommu_hole_init(void) aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff; aper_base <<= 25; - pr_info("Node %d: aperture @ %Lx size %u MB\n", - node, aper_base, aper_size >> 20); + pr_info("Node %d: aperture [bus addr %#010Lx-%#010Lx] (%uMB)\n", + node, aper_base, aper_base + aper_size - 1, + aper_size >> 20); node++; if (!aperture_valid(aper_base, aper_size, 64<<20)) { @@ -408,7 +413,7 @@ int __init gart_iommu_hole_init(void) if (!no_iommu && max_pfn > MAX_DMA32_PFN && !printed_gart_size_msg) { - pr_err("you are using iommu with agp, but GART size is less than 64M\n"); + pr_err("you are using iommu with agp, but GART size is less than 64MB\n"); pr_err("please increase GART size in your BIOS setup\n"); pr_err("if BIOS doesn't have that option, contact your HW vendor!\n"); printed_gart_size_msg = 1; @@ -449,7 +454,7 @@ out: fallback_aper_force) { pr_info("Your BIOS doesn't leave a aperture memory hole\n"); pr_info("Please enable the IOMMU option in the BIOS setup\n"); - pr_info("This costs you %d MB of RAM\n", + pr_info("This costs you %dMB of RAM\n", 32 << fallback_aper_order); aper_order = fallback_aper_order; -- cgit v0.10.2 From 23b13bc76f359e99140baf083dc44314f4eb1b87 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Apr 2014 15:25:54 -0600 Subject: PCI: Fail safely if we can't handle BARs larger than 4GB We can only handle BARs larger than 4GB if both dma_addr_t and resource_size_t are 64 bits wide. If dma_addr_t is 32 bits, we can't represent all the bus addresses, and if resource_size_t is 32 bits, we can't represent all the CPU addresses. Previously we cleared res->flags (at "fail:") for resources that were too large. That means we think the BAR doesn't exist at all, which in turn means that we could enable the device even though we can't keep track of where the BAR is and we can't make sure it doesn't overlap something else. This preserves the type flags (MEM/IO) so we can keep from enabling the device. Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ef09f5f..c7f8b71 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -171,6 +171,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, struct resource *res, unsigned int pos) { u32 l, sz, mask; + u64 l64, sz64, mask64; u16 orig_cmd; struct pci_bus_region region, inverted_region; bool bar_too_big = false, bar_disabled = false; @@ -226,9 +227,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, } if (res->flags & IORESOURCE_MEM_64) { - u64 l64 = l; - u64 sz64 = sz; - u64 mask64 = mask | (u64)~0 << 32; + l64 = l; + sz64 = sz; + mask64 = mask | (u64)~0 << 32; pci_read_config_dword(dev, pos + 4, &l); pci_write_config_dword(dev, pos + 4, ~0); @@ -243,9 +244,13 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, if (!sz64) goto fail; - if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { + if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && + sz64 > 0x100000000ULL) { + res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; + res->start = 0; + res->end = 0; bar_too_big = true; - goto fail; + goto out; } if ((sizeof(resource_size_t) < 8) && l) { @@ -303,7 +308,8 @@ out: pci_write_config_word(dev, PCI_COMMAND, orig_cmd); if (bar_too_big) - dev_err(&dev->dev, "reg 0x%x: can't handle 64-bit BAR\n", pos); + dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n", + pos, (unsigned long long) sz64); if (res->flags && !bar_disabled) dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); -- cgit v0.10.2 From d1a313e4b6ccbb61c746ee10ac198970516e9afc Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 29 Apr 2014 18:33:09 -0600 Subject: PCI: Reject BAR above 4GB if dma_addr_t is too small We can only handle BARs above 4GB if dma_addr_t (not resource_size_t) is 64 bits wide. If we have a 64-bit resource_size_t and a 32-bit dma_addr_t, we can't deal with BARs above 4GB. Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c7f8b71..afae3bf4 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -253,7 +253,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, goto out; } - if ((sizeof(resource_size_t) < 8) && l) { + if ((sizeof(dma_addr_t) < 8) && l) { /* Address above 32-bit boundary; disable the BAR */ pci_write_config_dword(dev, pos, 0); pci_write_config_dword(dev, pos + 4, 0); -- cgit v0.10.2 From 72dc5601fe5fec37cc1bd0efb19d99948fe7e54c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 29 Apr 2014 18:42:49 -0600 Subject: PCI: Don't convert BAR address to resource if dma_addr_t is too small If dma_addr_t is too small to represent the BAR value, pcibios_bus_to_resource() will fail, so just remember the BAR size directly in the resource. The resource is already marked UNSET, so we know the address isn't valid anyway. Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index afae3bf4..82cd75f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -258,9 +258,10 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, pci_write_config_dword(dev, pos, 0); pci_write_config_dword(dev, pos + 4, 0); res->flags |= IORESOURCE_UNSET; - region.start = 0; - region.end = sz64; + res->start = 0; + res->end = sz64; bar_disabled = true; + goto out; } else { region.start = l64; region.end = l64 + sz64; -- cgit v0.10.2 From 31e9dd2565a6e27a3e698d7e3adf929db8d6c767 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 29 Apr 2014 18:37:47 -0600 Subject: PCI: Don't set BAR to zero if dma_addr_t is too small If a BAR is above 4GB and our dma_addr_t is too small, don't clear the BAR to zero: that doesn't disable the BAR, and it makes it more likely that the BAR will conflict with things if we turn on the memory enable bit (as we will at "out:" if the device was already enabled at the handoff). We should also print the BAR info and its original size so we can follow the process when we try to assign space to it. Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 82cd75f..dd710b1 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -174,7 +174,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, u64 l64, sz64, mask64; u16 orig_cmd; struct pci_bus_region region, inverted_region; - bool bar_too_big = false, bar_disabled = false; + bool bar_too_big = false, bar_too_high = false; mask = type ? PCI_ROM_ADDRESS_MASK : ~0; @@ -254,13 +254,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, } if ((sizeof(dma_addr_t) < 8) && l) { - /* Address above 32-bit boundary; disable the BAR */ - pci_write_config_dword(dev, pos, 0); - pci_write_config_dword(dev, pos + 4, 0); + /* Above 32-bit boundary; try to reallocate */ res->flags |= IORESOURCE_UNSET; res->start = 0; res->end = sz64; - bar_disabled = true; + bar_too_high = true; goto out; } else { region.start = l64; @@ -311,7 +309,10 @@ out: if (bar_too_big) dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n", pos, (unsigned long long) sz64); - if (res->flags && !bar_disabled) + if (bar_too_high) + dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4G (bus address %#010llx)\n", + pos, (unsigned long long) l64); + if (res->flags) dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; -- cgit v0.10.2 From 26370fc6647b63eefb85a675382d661d0fed30a1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Apr 2014 15:26:50 -0600 Subject: PCI: Don't print anything while decoding is disabled If the console is a PCI device, and we try to print to it while its decoding is disabled, the system will hang. This particular printk hasn't caused a problem yet, but it could, so this fixes it. See also 0ff9514b579b ("PCI: Don't print anything while decoding is disabled"). Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index dd710b1..3bc149b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -174,7 +174,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, u64 l64, sz64, mask64; u16 orig_cmd; struct pci_bus_region region, inverted_region; - bool bar_too_big = false, bar_too_high = false; + bool bar_too_big = false, bar_too_high = false, bar_invalid = false; mask = type ? PCI_ROM_ADDRESS_MASK : ~0; @@ -289,11 +289,10 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, * be claimed by the device. */ if (inverted_region.start != region.start) { - dev_info(&dev->dev, "reg 0x%x: initial BAR value %pa invalid; forcing reassignment\n", - pos, ®ion.start); res->flags |= IORESOURCE_UNSET; - res->end -= res->start; res->start = 0; + res->end = region.end - region.start; + bar_invalid = true; } goto out; @@ -312,6 +311,9 @@ out: if (bar_too_high) dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4G (bus address %#010llx)\n", pos, (unsigned long long) l64); + if (bar_invalid) + dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n", + pos, (unsigned long long) region.start); if (res->flags) dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); -- cgit v0.10.2 From d739a099d0248c78d374b1b610cdb679c7bc052d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Apr 2014 16:10:54 -0600 Subject: PCI: Don't add disabled subtractive decode bus resources For a subtractive decode bridge, we previously added and printed all resources of the primary bus, even if they were not valid. In the example below, the bridge 00:1c.3 has no windows enabled, so there are no valid resources on bus 02. But since 02:00.0 is subtractive decode bridge, we add and print all those invalid resources, which don't really make sense: pci 0000:00:1c.3: PCI bridge to [bus 02-03] pci 0000:02:00.0: PCI bridge to [bus 03] (subtractive decode) pci 0000:02:00.0: bridge window [??? 0x00000000 flags 0x0] (subtractive decode) Add and print the subtractively-decoded resources only if they are valid. There's an example in the dmesg log attached to the bugzilla below (but this patch doesn't fix the bug reported there). Link: https://bugzilla.kernel.org/show_bug.cgi?id=73141 Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 3bc149b..9665140 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -475,7 +475,7 @@ void pci_read_bridge_bases(struct pci_bus *child) if (dev->transparent) { pci_bus_for_each_resource(child->parent, res, i) { - if (res) { + if (res && res->flags) { pci_bus_add_resource(child, res, PCI_SUBTRACTIVE_DECODE); dev_printk(KERN_DEBUG, &dev->dev, -- cgit v0.10.2 From e4c729664339e4be352d4c7434a5c6184285148d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Apr 2014 15:38:11 -0600 Subject: resources: Clarify sanity check message The resource map sanity check message is a bit confusing. Change it to be more readable: -resource map sanity check conflict: 0xfed10000 0xfed15fff 0xfed10000 0xfed13fff pnp 00:01 +resource sanity check: requesting [mem 0xfed10000-0xfed15fff], which spans more than pnp 00:01 [mem 0xfed10000-0xfed13fff] Signed-off-by: Bjorn Helgaas diff --git a/kernel/resource.c b/kernel/resource.c index 8957d68..3c2237a 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -1288,13 +1288,10 @@ int iomem_map_sanity_check(resource_size_t addr, unsigned long size) if (p->flags & IORESOURCE_BUSY) continue; - printk(KERN_WARNING "resource map sanity check conflict: " - "0x%llx 0x%llx 0x%llx 0x%llx %s\n", + printk(KERN_WARNING "resource sanity check: requesting [mem %#010llx-%#010llx], which spans more than %s %pR\n", (unsigned long long)addr, (unsigned long long)(addr + size - 1), - (unsigned long long)p->start, - (unsigned long long)p->end, - p->name); + p->name, p); err = -1; break; } -- cgit v0.10.2 From 14c8530dbc1b7cd5020c44b391e34bdb731fd098 Mon Sep 17 00:00:00 2001 From: Alan Date: Mon, 19 May 2014 14:03:14 +0100 Subject: PCI: Support BAR sizes up to 8GB This is needed for some of the Xeon Phi type systems. [bhelgaas: added Nikhil, use ARRAY_SIZE() to connect with decl, folded in Kevin's "order < 0" fix to ARRAY_SIZE() usage] Signed-off-by: Nikhil P Rao Signed-off-by: Alan Cox Signed-off-by: Kevin Hilman Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 138bdd6..9b3498c 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -921,7 +921,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, { struct pci_dev *dev; resource_size_t min_align, align, size, size0, size1; - resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ + resource_size_t aligns[14]; /* Alignments from 1Mb to 8Gb */ int order, max_order; struct resource *b_res = find_free_bus_resource(bus, type); unsigned int mem64_mask = 0; @@ -957,10 +957,17 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, continue; } #endif - /* For bridges size != alignment */ + /* + * aligns[0] is for 1MB (since bridge memory + * windows are always at least 1MB aligned), so + * keep "order" from being negative for smaller + * resources. + */ align = pci_resource_alignment(dev, r); order = __ffs(align) - 20; - if (order > 11) { + if (order < 0) + order = 0; + if (order >= ARRAY_SIZE(aligns)) { dev_warn(&dev->dev, "disabling BAR %d: %pR " "(bad alignment %#llx)\n", i, r, (unsigned long long) align); @@ -968,8 +975,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, continue; } size += r_size; - if (order < 0) - order = 0; /* Exclude ranges with size > align from calculation of the alignment. */ if (r_size == align) -- cgit v0.10.2 From 5b28541552ef5eeffc41d6936105f38c2508e566 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 19 May 2014 17:01:55 -0600 Subject: PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources This patch changes the way we handle 64-bit prefetchable bridge windows to make it more likely that we can assign space to all devices. Previously we put all prefetchable resources in the prefetchable bridge window. If any of those resources was 32-bit only, we restricted the window to be below 4GB. After this patch, we only put 64-bit prefetchable resources in a 64-bit prefetchable window. We put all 32-bit prefetchable resources in the non-prefetchable window, even if there are no 64-bit prefetchable resources. With the previous approach, if there was a 32-bit prefetchable resource behind a bridge, we forced the bridge's prefetchable window below 4GB, which meant that even if there was plenty of space above 4GB available, we couldn't use it, and assignment of large 64-bit resources could fail, as in the bugzilla below. The new strategy is: 1) If the prefetchable window is 64 bits wide, we put only 64-bit prefetchable resources in it. Any 32-bit prefetchable resources go in the non-prefetchable window. 2) If the prefetchable window is 32 bits wide, we put both 32- and 64-bit prefetchable resources in it. 3) If there is no prefetchable window, all MMIO resources go in the non-prefetchable window. This reduces performance for 32-bit prefetchable resources below a bridge with a 64-bit prefetchable window. We previously assigned prefetchable space, but now we'll assign non-prefetchable space. This is the case even if there are no 64-bit prefetchable resources, or if they would all fit below 4GB. In those cases, the old strategy would work and would have better performance. [bhelgaas: write changelog, add bugzilla link, fold in mem64_mask removal] Link: https://bugzilla.kernel.org/show_bug.cgi?id=74151 Tested-by: Guo Chao Tested-by: Wei Yang Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 9b3498c..b6585cb 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -713,12 +713,11 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) bus resource of a given type. Note: we intentionally skip the bus resources which have already been assigned (that is, have non-NULL parent resource). */ -static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type) +static struct resource *find_free_bus_resource(struct pci_bus *bus, + unsigned long type_mask, unsigned long type) { int i; struct resource *r; - unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | - IORESOURCE_PREFETCH; pci_bus_for_each_resource(bus, r, i) { if (r == &ioport_resource || r == &iomem_resource) @@ -815,7 +814,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, resource_size_t add_size, struct list_head *realloc_head) { struct pci_dev *dev; - struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); + struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO, + IORESOURCE_IO); resource_size_t size = 0, size0 = 0, size1 = 0; resource_size_t children_add_size = 0; resource_size_t min_align, align; @@ -907,6 +907,8 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns, * @bus : the bus * @mask: mask the resource flag, then compare it with type * @type: the type of free resource from bridge + * @type2: second match type + * @type3: third match type * @min_size : the minimum memory window that must to be allocated * @add_size : additional optional memory window * @realloc_head : track the additional memory window on this list @@ -915,16 +917,17 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns, * guarantees that all child resources fit in this size. */ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, - unsigned long type, resource_size_t min_size, - resource_size_t add_size, - struct list_head *realloc_head) + unsigned long type, unsigned long type2, + unsigned long type3, + resource_size_t min_size, resource_size_t add_size, + struct list_head *realloc_head) { struct pci_dev *dev; resource_size_t min_align, align, size, size0, size1; resource_size_t aligns[14]; /* Alignments from 1Mb to 8Gb */ int order, max_order; - struct resource *b_res = find_free_bus_resource(bus, type); - unsigned int mem64_mask = 0; + struct resource *b_res = find_free_bus_resource(bus, + mask | IORESOURCE_PREFETCH, type); resource_size_t children_add_size = 0; if (!b_res) @@ -934,9 +937,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, max_order = 0; size = 0; - mem64_mask = b_res->flags & IORESOURCE_MEM_64; - b_res->flags &= ~IORESOURCE_MEM_64; - list_for_each_entry(dev, &bus->devices, bus_list) { int i; @@ -944,7 +944,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, struct resource *r = &dev->resource[i]; resource_size_t r_size; - if (r->parent || (r->flags & mask) != type) + if (r->parent || ((r->flags & mask) != type && + (r->flags & mask) != type2 && + (r->flags & mask) != type3)) continue; r_size = resource_size(r); #ifdef CONFIG_PCI_IOV @@ -981,7 +983,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, aligns[order] += align; if (order > max_order) max_order = order; - mem64_mask &= r->flags & IORESOURCE_MEM_64; if (realloc_head) children_add_size += get_res_add_size(realloc_head, r); @@ -1006,7 +1007,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, } b_res->start = min_align; b_res->end = size0 + min_align - 1; - b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask; + b_res->flags |= IORESOURCE_STARTALIGN; if (size1 > size0 && realloc_head) { add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align); dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " @@ -1122,8 +1123,9 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head) { struct pci_dev *dev; - unsigned long mask, prefmask; + unsigned long mask, prefmask, type2 = 0, type3 = 0; resource_size_t additional_mem_size = 0, additional_io_size = 0; + struct resource *b_res; list_for_each_entry(dev, &bus->devices, bus_list) { struct pci_bus *b = dev->subordinate; @@ -1168,15 +1170,37 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, has already been allocated by arch code, try non-prefetchable range for both types of PCI memory resources. */ + b_res = &bus->self->resource[PCI_BRIDGE_RESOURCES]; mask = IORESOURCE_MEM; prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; - if (pbus_size_mem(bus, prefmask, prefmask, + if (b_res[2].flags & IORESOURCE_MEM_64) { + prefmask |= IORESOURCE_MEM_64; + if (pbus_size_mem(bus, prefmask, prefmask, + prefmask, prefmask, realloc_head ? 0 : additional_mem_size, - additional_mem_size, realloc_head)) - mask = prefmask; /* Success, size non-prefetch only. */ - else - additional_mem_size += additional_mem_size; - pbus_size_mem(bus, mask, IORESOURCE_MEM, + additional_mem_size, realloc_head)) { + /* + * Success, with pref mmio64, + * next will size non-pref or + * non-mmio64 */ + mask = prefmask; + type2 = prefmask & ~IORESOURCE_MEM_64; + type3 = prefmask & ~IORESOURCE_PREFETCH; + } + } + if (!type2) { + prefmask &= ~IORESOURCE_MEM_64; + if (pbus_size_mem(bus, prefmask, prefmask, + prefmask, prefmask, + realloc_head ? 0 : additional_mem_size, + additional_mem_size, realloc_head)) { + /* Success, next will size non-prefetch. */ + mask = prefmask; + } else + additional_mem_size += additional_mem_size; + type2 = type3 = IORESOURCE_MEM; + } + pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3, realloc_head ? 0 : additional_mem_size, additional_mem_size, realloc_head); break; @@ -1262,42 +1286,66 @@ static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge, static void pci_bridge_release_resources(struct pci_bus *bus, unsigned long type) { - int idx; - bool changed = false; - struct pci_dev *dev; + struct pci_dev *dev = bus->self; struct resource *r; unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | - IORESOURCE_PREFETCH; + IORESOURCE_PREFETCH | IORESOURCE_MEM_64; + unsigned old_flags = 0; + struct resource *b_res; + int idx = 1; - dev = bus->self; - for (idx = PCI_BRIDGE_RESOURCES; idx <= PCI_BRIDGE_RESOURCE_END; - idx++) { - r = &dev->resource[idx]; - if ((r->flags & type_mask) != type) - continue; - if (!r->parent) - continue; - /* - * if there are children under that, we should release them - * all - */ - release_child_resources(r); - if (!release_resource(r)) { - dev_printk(KERN_DEBUG, &dev->dev, - "resource %d %pR released\n", idx, r); - /* keep the old size */ - r->end = resource_size(r) - 1; - r->start = 0; - r->flags = 0; - changed = true; - } - } + b_res = &dev->resource[PCI_BRIDGE_RESOURCES]; + + /* + * 1. if there is io port assign fail, will release bridge + * io port. + * 2. if there is non pref mmio assign fail, release bridge + * nonpref mmio. + * 3. if there is 64bit pref mmio assign fail, and bridge pref + * is 64bit, release bridge pref mmio. + * 4. if there is pref mmio assign fail, and bridge pref is + * 32bit mmio, release bridge pref mmio + * 5. if there is pref mmio assign fail, and bridge pref is not + * assigned, release bridge nonpref mmio. + */ + if (type & IORESOURCE_IO) + idx = 0; + else if (!(type & IORESOURCE_PREFETCH)) + idx = 1; + else if ((type & IORESOURCE_MEM_64) && + (b_res[2].flags & IORESOURCE_MEM_64)) + idx = 2; + else if (!(b_res[2].flags & IORESOURCE_MEM_64) && + (b_res[2].flags & IORESOURCE_PREFETCH)) + idx = 2; + else + idx = 1; + + r = &b_res[idx]; + + if (!r->parent) + return; + + /* + * if there are children under that, we should release them + * all + */ + release_child_resources(r); + if (!release_resource(r)) { + type = old_flags = r->flags & type_mask; + dev_printk(KERN_DEBUG, &dev->dev, "resource %d %pR released\n", + PCI_BRIDGE_RESOURCES + idx, r); + /* keep the old size */ + r->end = resource_size(r) - 1; + r->start = 0; + r->flags = 0; - if (changed) { /* avoiding touch the one without PREF */ if (type & IORESOURCE_PREFETCH) type = IORESOURCE_PREFETCH; __pci_setup_bridge(bus, type); + /* for next child res under same bridge */ + r->flags = old_flags; } } @@ -1476,7 +1524,7 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) LIST_HEAD(fail_head); struct pci_dev_resource *fail_res; unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | - IORESOURCE_PREFETCH; + IORESOURCE_PREFETCH | IORESOURCE_MEM_64; int pci_try_num = 1; enum enable_type enable_local; diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 7eed671..2473f09 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -211,15 +211,31 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, /* First, try exact prefetching match.. */ ret = pci_bus_alloc_resource(bus, res, size, align, min, - IORESOURCE_PREFETCH, + IORESOURCE_PREFETCH | IORESOURCE_MEM_64, pcibios_align_resource, dev); - if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) { + if (ret < 0 && + (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) == + (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) { + /* + * That failed. + * + * Try 32bit pref + */ + ret = pci_bus_alloc_resource(bus, res, size, align, min, + IORESOURCE_PREFETCH, + pcibios_align_resource, dev); + } + + if (ret < 0 && + (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))) { /* * That failed. * * But a prefetching area can handle a non-prefetching * window (it will just not perform as well). + * + * Also can put 64bit under 32bit range. (below 4g). */ ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, pcibios_align_resource, dev); -- cgit v0.10.2 From 30afe8d00b994416b24c63f8c5bbf1c13869ec3c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 19 May 2014 18:28:37 -0600 Subject: PCI: Change pbus_size_mem() return values to be more conventional pbus_size_mem() previously returned 0 for failure and 1 for success. Change it to return -ENOSPC for failure and 0 for success. No functional change. Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index b6585cb..12ab50f 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -915,6 +915,10 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns, * * Calculate the size of the bus and minimal alignment which * guarantees that all child resources fit in this size. + * + * Returns -ENOSPC if there's no available bus resource of the desired type. + * Otherwise, sets the bus resource start/end to indicate the required + * size, adds things to realloc_head (if supplied), and returns 0. */ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type, unsigned long type2, @@ -931,7 +935,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, resource_size_t children_add_size = 0; if (!b_res) - return 0; + return -ENOSPC; memset(aligns, 0, sizeof(aligns)); max_order = 0; @@ -1003,7 +1007,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, "%pR to %pR (unused)\n", b_res, &bus->busn_res); b_res->flags = 0; - return 1; + return 0; } b_res->start = min_align; b_res->end = size0 + min_align - 1; @@ -1014,7 +1018,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, "%pR to %pR add_size %llx\n", b_res, &bus->busn_res, (unsigned long long)size1-size0); } - return 1; + return 0; } unsigned long pci_cardbus_resource_alignment(struct resource *res) @@ -1126,6 +1130,7 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, unsigned long mask, prefmask, type2 = 0, type3 = 0; resource_size_t additional_mem_size = 0, additional_io_size = 0; struct resource *b_res; + int ret; list_for_each_entry(dev, &bus->devices, bus_list) { struct pci_bus *b = dev->subordinate; @@ -1175,25 +1180,27 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; if (b_res[2].flags & IORESOURCE_MEM_64) { prefmask |= IORESOURCE_MEM_64; - if (pbus_size_mem(bus, prefmask, prefmask, + ret = pbus_size_mem(bus, prefmask, prefmask, prefmask, prefmask, realloc_head ? 0 : additional_mem_size, - additional_mem_size, realloc_head)) { - /* - * Success, with pref mmio64, - * next will size non-pref or - * non-mmio64 */ - mask = prefmask; - type2 = prefmask & ~IORESOURCE_MEM_64; - type3 = prefmask & ~IORESOURCE_PREFETCH; + additional_mem_size, realloc_head); + if (ret == 0) { + /* + * Success, with pref mmio64, + * next will size non-pref or + * non-mmio64 */ + mask = prefmask; + type2 = prefmask & ~IORESOURCE_MEM_64; + type3 = prefmask & ~IORESOURCE_PREFETCH; } } if (!type2) { prefmask &= ~IORESOURCE_MEM_64; - if (pbus_size_mem(bus, prefmask, prefmask, + ret = pbus_size_mem(bus, prefmask, prefmask, prefmask, prefmask, realloc_head ? 0 : additional_mem_size, - additional_mem_size, realloc_head)) { + additional_mem_size, realloc_head); + if (ret == 0) { /* Success, next will size non-prefetch. */ mask = prefmask; } else -- cgit v0.10.2 From d3689df04445c568c8b3dfcd8db4b562e1b18cfb Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 19 May 2014 18:39:07 -0600 Subject: PCI: Simplify __pci_assign_resource() coding style If an allocation succeeds, we can return success immediately. Then we don't have to test for success in the subsequent code. No functional change. Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 2473f09..3bdac9d 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -213,9 +213,10 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, ret = pci_bus_alloc_resource(bus, res, size, align, min, IORESOURCE_PREFETCH | IORESOURCE_MEM_64, pcibios_align_resource, dev); + if (ret == 0) + return 0; - if (ret < 0 && - (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) == + if ((res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) == (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) { /* * That failed. @@ -225,10 +226,11 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, ret = pci_bus_alloc_resource(bus, res, size, align, min, IORESOURCE_PREFETCH, pcibios_align_resource, dev); + if (ret == 0) + return 0; } - if (ret < 0 && - (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))) { + if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) { /* * That failed. * -- cgit v0.10.2 From 67d29b5c6c40e91b124695e9250c2fd24915e24a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 19 May 2014 18:32:18 -0600 Subject: PCI: Add resource allocation comments Add comments in the code to match the allocation strategy of 7c671426dfc3 ("PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources"). No functional change. Signed-off-by: Bjorn Helgaas diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 12ab50f..455ee03 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1164,17 +1164,16 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, additional_io_size = pci_hotplug_io_size; additional_mem_size = pci_hotplug_mem_size; } - /* - * Follow thru - */ + /* Fall through */ default: pbus_size_io(bus, realloc_head ? 0 : additional_io_size, additional_io_size, realloc_head); - /* If the bridge supports prefetchable range, size it - separately. If it doesn't, or its prefetchable window - has already been allocated by arch code, try - non-prefetchable range for both types of PCI memory - resources. */ + + /* + * If there's a 64-bit prefetchable MMIO window, compute + * the size required to put all 64-bit prefetchable + * resources in it. + */ b_res = &bus->self->resource[PCI_BRIDGE_RESOURCES]; mask = IORESOURCE_MEM; prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; @@ -1184,29 +1183,58 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, prefmask, prefmask, realloc_head ? 0 : additional_mem_size, additional_mem_size, realloc_head); + + /* + * If successful, all non-prefetchable resources + * and any 32-bit prefetchable resources will go in + * the non-prefetchable window. + */ if (ret == 0) { - /* - * Success, with pref mmio64, - * next will size non-pref or - * non-mmio64 */ mask = prefmask; type2 = prefmask & ~IORESOURCE_MEM_64; type3 = prefmask & ~IORESOURCE_PREFETCH; } } + + /* + * If there is no 64-bit prefetchable window, compute the + * size required to put all prefetchable resources in the + * 32-bit prefetchable window (if there is one). + */ if (!type2) { prefmask &= ~IORESOURCE_MEM_64; ret = pbus_size_mem(bus, prefmask, prefmask, prefmask, prefmask, realloc_head ? 0 : additional_mem_size, additional_mem_size, realloc_head); - if (ret == 0) { - /* Success, next will size non-prefetch. */ + + /* + * If successful, only non-prefetchable resources + * will go in the non-prefetchable window. + */ + if (ret == 0) mask = prefmask; - } else + else additional_mem_size += additional_mem_size; + type2 = type3 = IORESOURCE_MEM; } + + /* + * Compute the size required to put everything else in the + * non-prefetchable window. This includes: + * + * - all non-prefetchable resources + * - 32-bit prefetchable resources if there's a 64-bit + * prefetchable window or no prefetchable window at all + * - 64-bit prefetchable resources if there's no + * prefetchable window at all + * + * Note that the strategy in __pci_assign_resource() must + * match that used here. Specifically, we cannot put a + * 32-bit prefetchable resource in a 64-bit prefetchable + * window. + */ pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3, realloc_head ? 0 : additional_mem_size, additional_mem_size, realloc_head); diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 3bdac9d..3da2542 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -209,20 +209,25 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; - /* First, try exact prefetching match.. */ + /* + * First, try exact prefetching match. Even if a 64-bit + * prefetchable bridge window is below 4GB, we can't put a 32-bit + * prefetchable resource in it because pbus_size_mem() assumes a + * 64-bit window will contain no 32-bit resources. If we assign + * things differently than they were sized, not everything will fit. + */ ret = pci_bus_alloc_resource(bus, res, size, align, min, IORESOURCE_PREFETCH | IORESOURCE_MEM_64, pcibios_align_resource, dev); if (ret == 0) return 0; + /* + * If the prefetchable window is only 32 bits wide, we can put + * 64-bit prefetchable resources in it. + */ if ((res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) == (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) { - /* - * That failed. - * - * Try 32bit pref - */ ret = pci_bus_alloc_resource(bus, res, size, align, min, IORESOURCE_PREFETCH, pcibios_align_resource, dev); @@ -230,18 +235,16 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, return 0; } - if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) { - /* - * That failed. - * - * But a prefetching area can handle a non-prefetching - * window (it will just not perform as well). - * - * Also can put 64bit under 32bit range. (below 4g). - */ + /* + * If we didn't find a better match, we can put any memory resource + * in a non-prefetchable window. If this resource is 32 bits and + * non-prefetchable, the first call already tried the only possibility + * so we don't need to try again. + */ + if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, pcibios_align_resource, dev); - } + return ret; } -- cgit v0.10.2 From f311a724a79669ac0336932d0361325afdb54279 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 20 May 2014 16:56:27 -0600 Subject: DMA-API: Capitalize "CPU" consistently Sometimes we used "cpu," other times "CPU." Use "CPU" consistently. Suggested-by: Randy Dunlap Signed-off-by: Bjorn Helgaas diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt index fd3727b..f599553 100644 --- a/Documentation/DMA-API-HOWTO.txt +++ b/Documentation/DMA-API-HOWTO.txt @@ -575,10 +575,10 @@ Incorrect example 2: You should call dma_unmap_single() when the DMA activity is finished, e.g., from the interrupt which told you that the DMA transfer is done. -Using cpu pointers like this for single mappings has a disadvantage: +Using CPU pointers like this for single mappings has a disadvantage: you cannot reference HIGHMEM memory in this way. Thus, there is a map/unmap interface pair akin to dma_{map,unmap}_single(). These -interfaces deal with page/offset pairs instead of cpu pointers. +interfaces deal with page/offset pairs instead of CPU pointers. Specifically: struct device *dev = &my_dev->dev; @@ -650,7 +650,7 @@ you could render the machine unusable by consuming all bus addresses. If you need to use the same streaming DMA region multiple times and touch the data in between the DMA transfers, the buffer needs to be synced -properly in order for the cpu and device to see the most up-to-date and +properly in order for the CPU and device to see the most up-to-date and correct copy of the DMA buffer. So, firstly, just map it with dma_map_{single,sg}(), and after each DMA @@ -665,7 +665,7 @@ or: as appropriate. Then, if you wish to let the device get at the DMA area again, -finish accessing the data with the cpu, and then before actually +finish accessing the data with the CPU, and then before actually giving the buffer to the hardware call either: dma_sync_single_for_device(dev, dma_handle, size, direction); diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index 4f1cdc5..5208840 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -19,7 +19,7 @@ To get the dma_ API, you must #include . This provides dma_addr_t and the interfaces described below. A dma_addr_t can hold any valid DMA or bus address for the platform. It -can be given to a device to use as a DMA source or target. A cpu cannot +can be given to a device to use as a DMA source or target. A CPU cannot reference a dma_addr_t directly because there may be translation between its physical address space and the bus address space. @@ -112,7 +112,7 @@ size and alignment requirements specified at creation time. Pass GFP_ATOMIC to prevent blocking, or if it's permitted (not in_interrupt, not holding SMP locks), pass GFP_KERNEL to allow blocking. Like dma_alloc_coherent(), this returns two values: an -address usable by the cpu, and the DMA address usable by the pool's +address usable by the CPU, and the DMA address usable by the pool's device. @@ -120,7 +120,7 @@ device. dma_addr_t addr); This puts memory back into the pool. The pool is what was passed to -dma_pool_alloc(); the cpu (vaddr) and DMA addresses are what +dma_pool_alloc(); the CPU (vaddr) and DMA addresses are what were returned when that routine allocated the memory being freed. @@ -355,7 +355,7 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) -Synchronise a single contiguous or scatter/gather mapping for the cpu +Synchronise a single contiguous or scatter/gather mapping for the CPU and device. With the sync_sg API, all the parameters must be the same as those passed into the single mapping API. With the sync_single API, you can use dma_handle and size parameters that aren't identical to @@ -504,8 +504,8 @@ dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, Declare region of memory to be handed out by dma_alloc_coherent() when it's asked for coherent memory for this device. -phys_addr is the cpu physical address to which the memory is currently -assigned (this will be ioremapped so the cpu can access the region). +phys_addr is the CPU physical address to which the memory is currently +assigned (this will be ioremapped so the CPU can access the region). device_addr is the bus address the device needs to be programmed with to actually address this memory (this will be handed out as the -- cgit v0.10.2 From 34c815fbdc1257e823726f8c6bcd9255d495058d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Tue, 20 May 2014 16:54:22 -0600 Subject: DMA-API: Fix duplicated word in DMA-API-HOWTO.txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "coherent" is written twice when it should be just once. Signed-off-by: Emilio López Signed-off-by: Bjorn Helgaas diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt index f599553..b22ceff 100644 --- a/Documentation/DMA-API-HOWTO.txt +++ b/Documentation/DMA-API-HOWTO.txt @@ -249,10 +249,10 @@ the case would look like this: goto ignore_this_device; } -The coherent coherent mask will always be able to set the same or a -smaller mask as the streaming mask. However for the rare case that a -device driver only uses consistent allocations, one would have to -check the return value from dma_set_coherent_mask(). +The coherent mask will always be able to set the same or a smaller mask as +the streaming mask. However for the rare case that a device driver only +uses consistent allocations, one would have to check the return value from +dma_set_coherent_mask(). Finally, if your device can only drive the low 24-bits of address you might do something like: -- cgit v0.10.2 From 2af9da8638a139303b3cd535b458a1b2c80dd4f3 Mon Sep 17 00:00:00 2001 From: Gioh Kim Date: Tue, 20 May 2014 17:09:35 -0600 Subject: DMA-API: Update dma_pool_create ()and dma_pool_alloc() descriptions Use "boundary" to be more descriptive than "alloc" in the dma_pool_create() documentation. Replace "SLAB_KERNEL" and "SLAB_ATOMIC" with the correct "GFP_KERNEL" and "GFP_ATOMIC." [bhelgaas: changelog] Signed-off-by: Gioh Kim Signed-off-by: Bjorn Helgaas diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt index b22ceff..dcbbe36 100644 --- a/Documentation/DMA-API-HOWTO.txt +++ b/Documentation/DMA-API-HOWTO.txt @@ -429,13 +429,13 @@ Create a dma_pool like this: struct dma_pool *pool; - pool = dma_pool_create(name, dev, size, align, alloc); + pool = dma_pool_create(name, dev, size, align, boundary); The "name" is for diagnostics (like a kmem_cache name); dev and size are as above. The device's hardware alignment requirement for this type of data is "align" (which is expressed in bytes, and must be a power of two). If your device has no boundary crossing restrictions, -pass 0 for alloc; passing 4096 says memory allocated from this pool +pass 0 for boundary; passing 4096 says memory allocated from this pool must not cross 4KByte boundaries (but at that time it may be better to use dma_alloc_coherent() directly instead). @@ -443,8 +443,8 @@ Allocate memory from a DMA pool like this: cpu_addr = dma_pool_alloc(pool, flags, &dma_handle); -flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor -holding SMP locks), SLAB_ATOMIC otherwise. Like dma_alloc_coherent(), +flags are GFP_KERNEL if blocking is permitted (not in_interrupt nor +holding SMP locks), GFP_ATOMIC otherwise. Like dma_alloc_coherent(), this returns two values, cpu_addr and dma_handle. Free memory that was allocated from a dma_pool like this: -- cgit v0.10.2 From 14574674e461077a9f4dd5eae050f622e8b8c084 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 20 May 2014 16:54:23 -0600 Subject: iommu/exynos: Remove unnecessary "&" from function pointers Remove unnecessary "&" from function pointers in exynos_iommu_ops. Signed-off-by: Bjorn Helgaas Acked-by: Arnd Bergmann diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 0740189..2ca0744 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1011,13 +1011,13 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, } static struct iommu_ops exynos_iommu_ops = { - .domain_init = &exynos_iommu_domain_init, - .domain_destroy = &exynos_iommu_domain_destroy, - .attach_dev = &exynos_iommu_attach_device, - .detach_dev = &exynos_iommu_detach_device, - .map = &exynos_iommu_map, - .unmap = &exynos_iommu_unmap, - .iova_to_phys = &exynos_iommu_iova_to_phys, + .domain_init = exynos_iommu_domain_init, + .domain_destroy = exynos_iommu_domain_destroy, + .attach_dev = exynos_iommu_attach_device, + .detach_dev = exynos_iommu_detach_device, + .map = exynos_iommu_map, + .unmap = exynos_iommu_unmap, + .iova_to_phys = exynos_iommu_iova_to_phys, .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, }; -- cgit v0.10.2