Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 347512
b: refs/heads/master
c: 9c6ecf6
h: refs/heads/master
v: v3
  • Loading branch information
Joerg Roedel committed Dec 16, 2012
1 parent 020a185 commit b48aad4
Show file tree
Hide file tree
Showing 222 changed files with 1,959 additions and 1,765 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 298ea44f211de93ce1b30dc4e2bd2d3b23e41556
refs/heads/master: 9c6ecf6a3ade2dc4b03a239af68058b22897af41
126 changes: 126 additions & 0 deletions trunk/Documentation/DMA-API-HOWTO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -468,11 +468,46 @@ To map a single region, you do:
size_t size = buffer->len;

dma_handle = dma_map_single(dev, addr, size, direction);
if (dma_mapping_error(dma_handle)) {
/*
* reduce current DMA mapping usage,
* delay and try again later or
* reset driver.
*/
goto map_error_handling;
}

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.
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
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. Couple of example of incorrect ways 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.

Incorrect example 1:
dma_addr_t dma_handle;

dma_handle = dma_map_single(dev, addr, size, direction);
if ((dma_handle & 0xffff != 0) || (dma_handle >= 0x1000000)) {
goto map_error;
}

Incorrect example 2:
dma_addr_t dma_handle;

dma_handle = dma_map_single(dev, addr, size, direction);
if (dma_handle == DMA_ERROR_CODE) {
goto map_error;
}

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.

Expand All @@ -489,13 +524,27 @@ Specifically:
size_t size = buffer->len;

dma_handle = dma_map_page(dev, page, offset, size, direction);
if (dma_mapping_error(dma_handle)) {
/*
* reduce current DMA mapping usage,
* delay and try again later or
* reset driver.
*/
goto map_error_handling;
}

...

dma_unmap_page(dev, dma_handle, size, direction);

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.
from the interrupt which told you that the DMA transfer is done.

With scatterlists, you map a region gathered from several regions by:

int i, count = dma_map_sg(dev, sglist, nents, direction);
Expand Down Expand Up @@ -578,6 +627,14 @@ to use the dma_sync_*() interfaces.
dma_addr_t mapping;

mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE);
if (dma_mapping_error(dma_handle)) {
/*
* reduce current DMA mapping usage,
* delay and try again later or
* reset driver.
*/
goto map_error_handling;
}

cp->rx_buf = buffer;
cp->rx_len = len;
Expand Down Expand Up @@ -658,6 +715,75 @@ failure can be determined by:
* delay and try again later or
* reset driver.
*/
goto map_error_handling;
}

- unmap pages that are already mapped, when mapping error occurs in the middle
of a multiple page mapping attempt. These example are applicable to
dma_map_page() as well.

Example 1:
dma_addr_t dma_handle1;
dma_addr_t dma_handle2;

dma_handle1 = dma_map_single(dev, addr, size, direction);
if (dma_mapping_error(dev, dma_handle1)) {
/*
* reduce current DMA mapping usage,
* delay and try again later or
* reset driver.
*/
goto map_error_handling1;
}
dma_handle2 = dma_map_single(dev, addr, size, direction);
if (dma_mapping_error(dev, dma_handle2)) {
/*
* reduce current DMA mapping usage,
* delay and try again later or
* reset driver.
*/
goto map_error_handling2;
}

...

map_error_handling2:
dma_unmap_single(dma_handle1);
map_error_handling1:

Example 2: (if buffers are allocated a loop, unmap all mapped buffers when
mapping error is detected in the middle)

dma_addr_t dma_addr;
dma_addr_t array[DMA_BUFFERS];
int save_index = 0;

for (i = 0; i < DMA_BUFFERS; i++) {

...

dma_addr = dma_map_single(dev, addr, size, direction);
if (dma_mapping_error(dev, dma_addr)) {
/*
* reduce current DMA mapping usage,
* delay and try again later or
* reset driver.
*/
goto map_error_handling;
}
array[i].dma_addr = dma_addr;
save_index++;
}

...

map_error_handling:

for (i = 0; i < save_index; i++) {

...

dma_unmap_single(array[i].dma_addr);
}

Networking drivers must call dev_kfree_skb to free the socket buffer
Expand Down
12 changes: 12 additions & 0 deletions trunk/Documentation/DMA-API.txt
Original file line number Diff line number Diff line change
Expand Up @@ -678,3 +678,15 @@ out of dma_debug_entries. These entries are preallocated at boot. The number
of preallocated entries is defined per architecture. If it is too low for you
boot with 'dma_debug_entries=<your_desired_number>' to overwrite the
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
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.

8 changes: 5 additions & 3 deletions trunk/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 7
SUBLEVEL = 0
EXTRAVERSION = -rc7
EXTRAVERSION =
NAME = Terrified Chipmunk

# *DOCUMENTATION*
Expand Down Expand Up @@ -1321,10 +1321,12 @@ kernelversion:

# Clear a bunch of variables before executing the submake
tools/: FORCE
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/
$(Q)mkdir -p $(objtree)/tools
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/

tools/%: FORCE
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $*
$(Q)mkdir -p $(objtree)/tools
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/ $*

# Single targets
# ---------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ config ARCH_KIRKWOOD
select CPU_FEROCEON
select GENERIC_CLOCKEVENTS
select PCI
select PCI_QUIRKS
select PLAT_ORION_LEGACY
help
Support for the following Marvell Kirkwood series SoCs:
Expand Down
14 changes: 13 additions & 1 deletion trunk/arch/arm/boot/compressed/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,15 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size
mov pc, lr
ENDPROC(__setup_mmu)

@ Enable unaligned access on v6, to allow better code generation
@ for the decompressor C code:
__armv6_mmu_cache_on:
mrc p15, 0, r0, c1, c0, 0 @ read SCTLR
bic r0, r0, #2 @ A (no unaligned access fault)
orr r0, r0, #1 << 22 @ U (v6 unaligned access model)
mcr p15, 0, r0, c1, c0, 0 @ write SCTLR
b __armv4_mmu_cache_on

__arm926ejs_mmu_cache_on:
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
mov r0, #4 @ put dcache in WT mode
Expand Down Expand Up @@ -694,6 +703,9 @@ __armv7_mmu_cache_on:
bic r0, r0, #1 << 28 @ clear SCTLR.TRE
orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
orr r0, r0, #0x003c @ write buffer
bic r0, r0, #2 @ A (no unaligned access fault)
orr r0, r0, #1 << 22 @ U (v6 unaligned access model)
@ (needed for ARM1176)
#ifdef CONFIG_MMU
#ifdef CONFIG_CPU_ENDIAN_BE8
orr r0, r0, #1 << 25 @ big-endian page tables
Expand Down Expand Up @@ -914,7 +926,7 @@ proc_types:

.word 0x0007b000 @ ARMv6
.word 0x000ff000
W(b) __armv4_mmu_cache_on
W(b) __armv6_mmu_cache_on
W(b) __armv4_mmu_cache_off
W(b) __armv6_mmu_cache_flush

Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/arm/common/timer-sp.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ static struct clock_event_device sp804_clockevent = {
.set_mode = sp804_set_mode,
.set_next_event = sp804_set_next_event,
.rating = 300,
.cpumask = cpu_all_mask,
};

static struct irqaction sp804_timer_irq = {
Expand All @@ -185,6 +184,7 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ);
evt->name = name;
evt->irq = irq;
evt->cpumask = cpu_possible_mask;

setup_irq(irq, &sp804_timer_irq);
clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/arm/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
*/
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
debug_dma_mapping_error(dev, dma_addr);
return dma_addr == DMA_ERROR_CODE;
}

Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/arm/mach-dove/include/mach/pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static inline int pmu_to_irq(int pin)

static inline int irq_to_pmu(int irq)
{
if (IRQ_DOVE_PMU_START < irq && irq < NR_IRQS)
if (IRQ_DOVE_PMU_START <= irq && irq < NR_IRQS)
return irq - IRQ_DOVE_PMU_START;

return -EINVAL;
Expand Down
14 changes: 13 additions & 1 deletion trunk/arch/arm/mach-dove/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,20 @@ static void pmu_irq_ack(struct irq_data *d)
int pin = irq_to_pmu(d->irq);
u32 u;

/*
* The PMU mask register is not RW0C: it is RW. This means that
* the bits take whatever value is written to them; if you write
* a '1', you will set the interrupt.
*
* Unfortunately this means there is NO race free way to clear
* these interrupts.
*
* So, let's structure the code so that the window is as small as
* possible.
*/
u = ~(1 << (pin & 31));
writel(u, PMU_INTERRUPT_CAUSE);
u &= readl_relaxed(PMU_INTERRUPT_CAUSE);
writel_relaxed(u, PMU_INTERRUPT_CAUSE);
}

static struct irq_chip pmu_irq_chip = {
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/arm/mach-ixp4xx/common-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ void __init ixp4xx_pci_preinit(void)
* Enable the IO window to be way up high, at 0xfffffc00
*/
local_write_config(PCI_BASE_ADDRESS_5, 4, 0xfffffc01);
local_write_config(0x40, 4, 0x000080FF); /* No TRDY time limit */
} else {
printk("PCI: IXP4xx is target - No bus scan performed\n");
}
Expand Down
13 changes: 5 additions & 8 deletions trunk/arch/arm/mach-ixp4xx/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,12 @@ static struct map_desc ixp4xx_io_desc[] __initdata = {
.pfn = __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
.length = IXP4XX_PCI_CFG_REGION_SIZE,
.type = MT_DEVICE
},
#ifdef CONFIG_DEBUG_LL
{ /* Debug UART mapping */
.virtual = (unsigned long)IXP4XX_DEBUG_UART_BASE_VIRT,
.pfn = __phys_to_pfn(IXP4XX_DEBUG_UART_BASE_PHYS),
.length = IXP4XX_DEBUG_UART_REGION_SIZE,
}, { /* Queue Manager */
.virtual = (unsigned long)IXP4XX_QMGR_BASE_VIRT,
.pfn = __phys_to_pfn(IXP4XX_QMGR_BASE_PHYS),
.length = IXP4XX_QMGR_REGION_SIZE,
.type = MT_DEVICE
}
#endif
},
};

void __init ixp4xx_map_io(void)
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/arm/mach-ixp4xx/goramo_mlr.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/pci.h>
#include <asm/system_info.h>

#define SLOT_ETHA 0x0B /* IDSEL = AD21 */
#define SLOT_ETHB 0x0C /* IDSEL = AD20 */
Expand Down Expand Up @@ -329,7 +330,7 @@ static struct platform_device device_hss_tab[] = {
};


static struct platform_device *device_tab[6] __initdata = {
static struct platform_device *device_tab[7] __initdata = {
&device_flash, /* index 0 */
};

Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
#else
mov \rp, #0
#endif
orr \rv, \rp, #0xff000000 @ virtual
orr \rv, \rv, #0x00b00000
orr \rv, \rp, #0xfe000000 @ virtual
orr \rv, \rv, #0x00f00000
orr \rp, \rp, #0xc8000000 @ physical
.endm

Expand Down
Loading

0 comments on commit b48aad4

Please sign in to comment.