aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2014-07-28 15:57:10 +0100
committerJames Hogan <james.hogan@imgtec.com>2015-11-12 00:18:32 +0000
commit541484f278bb584a7970f91b6c43ea6fa76fd209 (patch)
tree3b8da5f40598419d852da2d198d923c37ed4c813
parentf41e0d92a683a20eaa0ff80dbd45b0b362fa1fb6 (diff)
downloadmetag-legacy-master.tar.gz
metag: Fixes and updates up to Jul 28th 2014HEADmaster
Numerous fixes and updates to the official metag tree up to July 28th 2014. Signed-off-by: James Hogan <james.hogan@imgtec.com>
-rw-r--r--arch/metag/boards/TZ1090-01XX/setup.c28
-rw-r--r--arch/metag/include/asm/barrier.h3
-rw-r--r--arch/metag/include/asm/processor.h2
-rw-r--r--arch/metag/include/asm/soc-tz1090/defs.h2
-rw-r--r--arch/metag/include/asm/tbx.h19
-rw-r--r--arch/metag/include/uapi/asm/Kbuild2
-rw-r--r--arch/metag/include/uapi/asm/resource.h7
-rw-r--r--arch/metag/kernel/coremem.c41
-rw-r--r--arch/metag/kernel/dma.c5
-rw-r--r--arch/metag/kernel/setup.c6
-rw-r--r--arch/metag/kernel/traps.c7
-rw-r--r--arch/metag/mm/numa.c2
-rw-r--r--arch/metag/soc/tz1090/suspend.S28
-rw-r--r--arch/metag/tbx/tbidefr.S2
-rw-r--r--arch/parisc/include/asm/processor.h2
-rw-r--r--drivers/clk/clk-specified-rate.c2
-rw-r--r--drivers/clk/metag/clk-mux.c11
-rw-r--r--drivers/clk/tz1090/clk-tz1090-pll.c6
-rw-r--r--drivers/dma/img_mdc_dma.c251
-rw-r--r--drivers/dma/tz1090-mdc-dma.c5
-rw-r--r--drivers/gpio/gpio-tz1090.c9
-rw-r--r--drivers/gpio/gpiolib.c8
-rw-r--r--drivers/i2c/busses/i2c-img.c2
-rw-r--r--drivers/irqchip/irq-metag-ext.c2
-rw-r--r--drivers/irqchip/irq-metag.c2
-rw-r--r--drivers/media/rc/ir-img.c6
-rw-r--r--drivers/net/wireless/uccp310wlan/80211_if.c98
-rw-r--r--drivers/net/wireless/uccp310wlan/core.c69
-rw-r--r--drivers/net/wireless/uccp310wlan/hal_hostport.c7
-rw-r--r--drivers/net/wireless/uccp310wlan/hal_hostport.h3
-rw-r--r--drivers/net/wireless/uccp310wlan/lmac_if.c12
-rw-r--r--drivers/net/wireless/uccp310wlan/lmac_if.h2
-rw-r--r--drivers/net/wireless/uccp310wlan/umac.h7
-rw-r--r--drivers/net/wireless/uccp310wlan/umac_lmac_if.h63
-rw-r--r--drivers/net/wireless/uccp310wlan/version.h2
-rw-r--r--drivers/rtc/rtc-imgpdc.c16
-rw-r--r--drivers/spi/spi-img.c177
-rw-r--r--fs/exec.c6
-rw-r--r--include/linux/img_mdc_dma.h1
-rw-r--r--init/Kconfig1
-rw-r--r--net/mac80211/rc80211_minstrel.c3
-rw-r--r--sound/soc/codecs/si476x.c6
-rw-r--r--sound/soc/tz1090/tz1090-pcm.c2
43 files changed, 584 insertions, 351 deletions
diff --git a/arch/metag/boards/TZ1090-01XX/setup.c b/arch/metag/boards/TZ1090-01XX/setup.c
index 4f0a6357af6d4d..ceaaf244020a24 100644
--- a/arch/metag/boards/TZ1090-01XX/setup.c
+++ b/arch/metag/boards/TZ1090-01XX/setup.c
@@ -93,35 +93,13 @@ static int __init comet_01xx_init_usb(void)
return 0;
}
-/* Allocate all SDIO GPIOs and drive them low. */
-static struct gpio sd_temp_gpios[] = {
- { GPIO_SDIO_CMD, GPIOF_OUT_INIT_LOW, "SDIO_CMD"},
- { GPIO_SDIO_CLK, GPIOF_OUT_INIT_LOW, "SDIO_CLK"},
- { GPIO_SDIO_D0, GPIOF_OUT_INIT_LOW, "SDIO_D<0>"},
- { GPIO_SDIO_D1, GPIOF_OUT_INIT_LOW, "SDIO_D<1>"},
- { GPIO_SDIO_D2, GPIOF_OUT_INIT_LOW, "SDIO_D<2>"},
- { GPIO_SDIO_D3, GPIOF_OUT_INIT_LOW, "SDIO_D<3>"},
-};
-
/*
- * Toggle the power by switching off the power line, and driving the SD pins
- * low to ensure it switches off. NB switch only on rev2 onwards.
+ * Toggle the power by switching off the power line. NB switch only on rev2
+ * onwards.
*/
static void mci_setpower(u32 slot_id, u32 volt)
{
- int err;
- if (volt) {
- gpio_free_array(sd_temp_gpios, ARRAY_SIZE(sd_temp_gpios));
-
- gpio_set_value(GPIO_PDC_GPIO0, 1);
- } else {
- gpio_set_value(GPIO_PDC_GPIO0, 0);
-
- err = gpio_request_array(sd_temp_gpios,
- ARRAY_SIZE(sd_temp_gpios));
- if (err)
- pr_warn("SDIO pins already allocated. Can not pull low.\n");
- }
+ gpio_set_value(GPIO_PDC_GPIO0, volt);
}
/*
diff --git a/arch/metag/include/asm/barrier.h b/arch/metag/include/asm/barrier.h
index c90bfc6bf64892..e355a4c10968ee 100644
--- a/arch/metag/include/asm/barrier.h
+++ b/arch/metag/include/asm/barrier.h
@@ -15,6 +15,7 @@ static inline void wr_fence(void)
volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_FENCE;
barrier();
*flushptr = 0;
+ barrier();
}
#else /* CONFIG_METAG_META21 */
@@ -35,6 +36,7 @@ static inline void wr_fence(void)
*flushptr = 0;
*flushptr = 0;
*flushptr = 0;
+ barrier();
}
#endif /* !CONFIG_METAG_META21 */
@@ -68,6 +70,7 @@ static inline void fence(void)
volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_ATOMIC_UNLOCK;
barrier();
*flushptr = 0;
+ barrier();
}
#define smp_mb() fence()
#define smp_rmb() fence()
diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h
index f16477d1f571cb..3be8581af4956a 100644
--- a/arch/metag/include/asm/processor.h
+++ b/arch/metag/include/asm/processor.h
@@ -22,6 +22,8 @@
/* Add an extra page of padding at the top of the stack for the guard page. */
#define STACK_TOP (TASK_SIZE - PAGE_SIZE)
#define STACK_TOP_MAX STACK_TOP
+/* Maximum virtual space for stack */
+#define STACK_SIZE_MAX (1 << 28) /* 256 MB */
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
diff --git a/arch/metag/include/asm/soc-tz1090/defs.h b/arch/metag/include/asm/soc-tz1090/defs.h
index 4241405cdf0a82..2c538997a9533b 100644
--- a/arch/metag/include/asm/soc-tz1090/defs.h
+++ b/arch/metag/include/asm/soc-tz1090/defs.h
@@ -387,6 +387,8 @@
#define CR_TOP_CLKOUT1_3_EN_BIT 9
#define CR_TOP_CLKOUT0_3_EN_BIT 5
/* CR_TOP_SYSPLL_CTL1 */
+#define CR_TOP_SYSPLL_RESET_BIT 28
+#define CR_TOP_SYSPLL_FASTEN_BIT 27
#define CR_TOP_SYSPLL_PWRDN_BIT 24
/* CR_TOP_ADCPLL_CTL0 */
#define CR_TOP_ADCPLL_BWADJ_SHIFT 20
diff --git a/arch/metag/include/asm/tbx.h b/arch/metag/include/asm/tbx.h
index 287b36ff8ad1cf..703b9cb0ac5c13 100644
--- a/arch/metag/include/asm/tbx.h
+++ b/arch/metag/include/asm/tbx.h
@@ -150,11 +150,9 @@
#else
/* Reserved 0x04-0x09 */
#endif
-#define TBID_SIGNUM_SWS 0x0A /* KICK received with SigMask != 0 */
-#define TBID_SIGNUM_SWK 0x0B /* KICK received with SigMask == 0 */
-/* Reserved 0x0C-0x0F */
+/* Reserved 0x0A-0x0F */
#define TBID_SIGNUM_TRT 0x10 /* Timer trigger */
-#define TBID_SIGNUM_LWK 0x11 /* Low level kick (handler provided by TBI) */
+#define TBID_SIGNUM_LWK 0x11 /* Low level kick */
#define TBID_SIGNUM_XXF 0x12 /* Fault handler - receives ALL _xxF sigs */
#ifdef TBI_1_4
#define TBID_SIGNUM_DFR 0x13 /* Deferred Exception handler */
@@ -183,8 +181,7 @@
each hardware signal, sometimes this is a many-to-one relationship. */
#define TBI_TRIG_BIT(SigNum) (\
((SigNum) >= TBID_SIGNUM_TRT) ? 1<<((SigNum)-TBID_SIGNUM_TRT) :\
- ( ((SigNum) == TBID_SIGNUM_SWS) || \
- ((SigNum) == TBID_SIGNUM_SWK) ) ? \
+ ((SigNum) == TBID_SIGNUM_LWK) ? \
TXSTAT_KICK_BIT : TXSTATI_BGNDHALT_BIT )
/* Return the hardware trigger vector number for entries in the
@@ -687,10 +684,8 @@ typedef union _tbires_tag_ {
Triggers will indicate the status of TXSTAT or TXSTATI sampled by the
code that called the handler.
- InstOrSWSId is defined firstly as 'Inst' if the SigNum is TBID_SIGNUM_SWx
- and hold the actual SWITCH instruction detected, secondly if SigNum
- is TBID_SIGNUM_SWS the 'SWSId' is defined to hold the Id of the
- software signal detected, in other cases the value of this
+ Inst is defined as 'Inst' if the SigNum is TBID_SIGNUM_SWx and holds the
+ actual SWITCH instruction detected, in other cases the value of this
parameter is undefined.
pTBI points at the PTBI structure related to the thread and processing
@@ -709,7 +704,7 @@ typedef union _tbires_tag_ {
*/
typedef TBIRES (*PTBIAPIFN)( TBIRES State, int SigNum,
- int Triggers, int InstOrSWSId,
+ int Triggers, int Inst,
volatile struct _tbi_tag_ *pTBI );
#endif /* ifndef __ASSEMBLY__ */
@@ -757,7 +752,7 @@ typedef volatile struct _tbi_tag_ {
#ifndef __ASSEMBLY__
/* This handler should be used for TBID_SIGNUM_DFR */
extern TBIRES __TBIHandleDFR ( TBIRES State, int SigNum,
- int Triggers, int InstOrSWSId,
+ int Triggers, int Inst,
volatile struct _tbi_tag_ *pTBI );
#endif
#endif
diff --git a/arch/metag/include/uapi/asm/Kbuild b/arch/metag/include/uapi/asm/Kbuild
index 84e09feb4d546f..ab78be2b6eb050 100644
--- a/arch/metag/include/uapi/asm/Kbuild
+++ b/arch/metag/include/uapi/asm/Kbuild
@@ -4,11 +4,11 @@ include include/uapi/asm-generic/Kbuild.asm
header-y += byteorder.h
header-y += ech.h
header-y += ptrace.h
-header-y += resource.h
header-y += sigcontext.h
header-y += siginfo.h
header-y += swab.h
header-y += unistd.h
generic-y += mman.h
+generic-y += resource.h
generic-y += setup.h
diff --git a/arch/metag/include/uapi/asm/resource.h b/arch/metag/include/uapi/asm/resource.h
deleted file mode 100644
index 526d23cc30544a..00000000000000
--- a/arch/metag/include/uapi/asm/resource.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _UAPI_METAG_RESOURCE_H
-#define _UAPI_METAG_RESOURCE_H
-
-#define _STK_LIM_MAX (1 << 28)
-#include <asm-generic/resource.h>
-
-#endif /* _UAPI_METAG_RESOURCE_H */
diff --git a/arch/metag/kernel/coremem.c b/arch/metag/kernel/coremem.c
index 22b4d8ed0b06bd..236c6bdb7deaeb 100644
--- a/arch/metag/kernel/coremem.c
+++ b/arch/metag/kernel/coremem.c
@@ -128,26 +128,41 @@ unsigned long metag_cache_lock(unsigned int flags, unsigned long phys,
return 0;
}
- /* First take account of offset of memory in page */
- offset = offset_in_page(phys);
- rounded_size = size + offset;
+ /* Round down the physical address to a cache line boundary */
+ offset = phys & (DCACHE_LINE_BYTES - 1);
phys -= offset;
ccr += offset;
+ size += offset;
+ /* Round up the size to a cache line boundary */
+ size = (size + (DCACHE_LINE_BYTES - 1)) & -DCACHE_LINE_BYTES;
+
+ /* The size of the current global cache partition may be limited too */
+ if (size > ((flags & METAG_COREMEM_IMEM)
+ ? get_global_icache_size()
+ : get_global_dcache_size()))
+ return 0;
+
+ /*
+ * The physical address must be size aligned, so the size we choose
+ * depends on what boundaries the region crosses.
+ * A simple XOR will show which power of 2 boundaries the region
+ * crosses.
+ */
+ rounded_size_sh = ilog2(phys ^ (phys + size - 1)) + 1;
+ if (rounded_size_sh < MMCU_TnCCM_REGSZ0_POWER)
+ rounded_size_sh = MMCU_TnCCM_REGSZ0_POWER;
+ rounded_size = 1 << rounded_size_sh;
+ rounded_size_sh -= MMCU_TnCCM_REGSZ0_POWER;
- /* Get rounded up log2 of size */
- rounded_size_sh = ilog2((rounded_size<<1)-1) - MMCU_TnCCM_REGSZ0_POWER;
- if (rounded_size_sh < 0)
- rounded_size_sh = 0;
- rounded_size = (1 << MMCU_TnCCM_REGSZ0_POWER) << rounded_size_sh;
/* There's a maximum amount of lockable cache */
if (rounded_size > MMCU_TnCCM_REGSZ_MAXBYTES)
return 0;
- /* The size of the current global cache partition may be limited too */
- if (rounded_size > ((flags & METAG_COREMEM_IMEM)
- ? get_global_icache_size()
- : get_global_dcache_size()))
- return 0;
+
+ /* First take account of offset of memory in page */
+ offset = phys & (rounded_size - 1);
+ phys -= offset;
+ ccr += offset;
ccmctrl = metag_in32(ccmctrl_addr);
if (ccmctrl & MMCU_TnCCM_ENABLE_BIT)
diff --git a/arch/metag/kernel/dma.c b/arch/metag/kernel/dma.c
index 300feb523a3dab..26a33d7651cbd8 100644
--- a/arch/metag/kernel/dma.c
+++ b/arch/metag/kernel/dma.c
@@ -402,11 +402,6 @@ static int __init dma_alloc_init(void)
pgd = pgd_offset(&init_mm, CONSISTENT_START);
pud = pud_alloc(&init_mm, pgd, CONSISTENT_START);
pmd = pmd_alloc(&init_mm, pud, CONSISTENT_START);
- if (!pmd) {
- pr_err("%s: no pmd tables\n", __func__);
- ret = -ENOMEM;
- break;
- }
WARN_ON(!pmd_none(*pmd));
pte = pte_alloc_kernel(pmd, CONSISTENT_START);
diff --git a/arch/metag/kernel/setup.c b/arch/metag/kernel/setup.c
index 895c8d07441764..14085002337731 100644
--- a/arch/metag/kernel/setup.c
+++ b/arch/metag/kernel/setup.c
@@ -319,13 +319,9 @@ void __init setup_arch(char **cmdline_p)
* rather than the version from the bootloader. This makes call
* stacks easier to understand and may allow us to unmap the
* bootloader at some point.
- *
- * We need to keep the LWK handler that TBI installed in order to
- * be able to do inter-thread comms.
*/
for (i = 0; i <= TBID_SIGNUM_MAX; i++)
- if (i != TBID_SIGNUM_LWK)
- _pTBI->fnSigs[i] = __TBIUnExpXXX;
+ _pTBI->fnSigs[i] = __TBIUnExpXXX;
/* A Meta requirement is that the kernel is loaded (virtually)
* at the PAGE_OFFSET.
diff --git a/arch/metag/kernel/traps.c b/arch/metag/kernel/traps.c
index fab50e3a5c578e..cb338bcdc0f91a 100644
--- a/arch/metag/kernel/traps.c
+++ b/arch/metag/kernel/traps.c
@@ -1210,8 +1210,7 @@ void __cpuinit per_cpu_trap_init(unsigned long cpu)
set_trigger_mask(TBI_INTS_INIT(thread) | /* interrupts */
TBI_TRIG_BIT(TBID_SIGNUM_LWK) | /* low level kick */
- TBI_TRIG_BIT(TBID_SIGNUM_SW1) |
- TBI_TRIG_BIT(TBID_SIGNUM_SWS));
+ TBI_TRIG_BIT(TBID_SIGNUM_SW1));
/* non-priv - use current stack */
int_context.Sig.pCtx = NULL;
@@ -1254,14 +1253,14 @@ void __init trap_init(void)
_pTBI->fnSigs[TBID_SIGNUM_SW1] = switch1_wrapper;
_pTBI->fnSigs[TBID_SIGNUM_SW2] = switchx_wrapper;
_pTBI->fnSigs[TBID_SIGNUM_SW3] = switchx_wrapper;
- _pTBI->fnSigs[TBID_SIGNUM_SWK] = kick_wrapper;
+ _pTBI->fnSigs[TBID_SIGNUM_LWK] = kick_wrapper;
#else
_pTBI->fnSigs[TBID_SIGNUM_XXF] = fault_handler;
_pTBI->fnSigs[TBID_SIGNUM_SW0] = switchx_handler;
_pTBI->fnSigs[TBID_SIGNUM_SW1] = switch1_handler;
_pTBI->fnSigs[TBID_SIGNUM_SW2] = switchx_handler;
_pTBI->fnSigs[TBID_SIGNUM_SW3] = switchx_handler;
- _pTBI->fnSigs[TBID_SIGNUM_SWK] = kick_handler;
+ _pTBI->fnSigs[TBID_SIGNUM_LWK] = kick_handler;
#endif
#ifdef CONFIG_METAG_META21
diff --git a/arch/metag/mm/numa.c b/arch/metag/mm/numa.c
index 9ae578c9b620b5..b172aa45fcf820 100644
--- a/arch/metag/mm/numa.c
+++ b/arch/metag/mm/numa.c
@@ -34,7 +34,7 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
unsigned long pgdat_paddr;
/* Don't allow bogus node assignment */
- BUG_ON(nid > MAX_NUMNODES || nid <= 0);
+ BUG_ON(nid >= MAX_NUMNODES || nid <= 0);
start_pfn = start >> PAGE_SHIFT;
end_pfn = end >> PAGE_SHIFT;
diff --git a/arch/metag/soc/tz1090/suspend.S b/arch/metag/soc/tz1090/suspend.S
index 6599f53e40f4ab..764d203ba9e552 100644
--- a/arch/metag/soc/tz1090/suspend.S
+++ b/arch/metag/soc/tz1090/suspend.S
@@ -1,4 +1,4 @@
-! Copyright 2010 Imagination Technologies Ltd.
+! Copyright 2010-2014 Imagination Technologies Ltd.
!
! Functions for suspending the comet SoC.
@@ -130,8 +130,7 @@ ENTRY(_metag_comet_standby)
MOVT D0FrT, #HI(CR_TOP_SYSPLL_CTL1)
ADD D0FrT, D0FrT, #LO(CR_TOP_SYSPLL_CTL1)
GETD D0Ar6, [D0FrT]
- MOVT D0Ar4, #HI(1 << CR_TOP_SYSPLL_PWRDN_BIT)
- OR D0Ar6, D0Ar6, D0Ar4
+ ORT D0Ar6, D0Ar6, #HI(1 << CR_TOP_SYSPLL_PWRDN_BIT)
SETD [D0FrT], D0Ar6
#endif
#endif
@@ -162,17 +161,30 @@ ENTRY(_metag_comet_standby)
#endif
#ifdef META_PLL_BYPASS
- ! power up the PLL
+ ! power up the PLL, assert reset, and allow time to lock on
#ifdef META_PLL_PWRDN
- ! CR_TOP_SYSPLL_CTL1 ^= (1 << CR_TOP_SYSPLL_PWRDN_BIT)
MOVT D0FrT, #HI(CR_TOP_SYSPLL_CTL1)
ADD D0FrT, D0FrT, #LO(CR_TOP_SYSPLL_CTL1)
GETD D0Ar6, [D0FrT]
- MOVT D0Ar4, #HI(1 << CR_TOP_SYSPLL_PWRDN_BIT)
- XOR D0Ar6, D0Ar6, D0Ar4
+ ! CR_TOP_SYSPLL_CTL1 ^= PWRDN_BIT (clear) | RESET (set)
+ XORT D0Ar6, D0Ar6, #HI((1 << CR_TOP_SYSPLL_PWRDN_BIT) | \
+ (1 << CR_TOP_SYSPLL_RESET_BIT))
+ SETD [D0FrT], D0Ar6
+ ! wait for min 5uS reset pulse (max XTAL1 = 40MHz, 5uS = 200 cycles)
+ MPAUSE 2
+ ! CR_TOP_SYSPLL_CTL1 &= ~RESET
+ ANDMT D0Ar6, D0Ar6, #HI(~(1 << CR_TOP_SYSPLL_RESET_BIT))
+ ! CR_TOP_SYSPLL_CTL1 |= FASTEN
+ ORT D0Ar6, D0Ar6, #HI(1 << CR_TOP_SYSPLL_FASTEN_BIT)
SETD [D0FrT], D0Ar6
! wait for PLL to power back up and sort itself out
- MPAUSE 2000
+ ! May require up to 500 divided rclk cycles (assume divided XTAL1)
+ ! Max divider = 64, Meta clocked off XTAL1 too
+ ! Delay = 500*64 = 32000 cycles
+ MPAUSE 320
+ ! CR_TOP_SYSPLL_CTL1 &= ~FASTEN
+ ANDMT D0Ar6, D0Ar6, #HI(~(1 << CR_TOP_SYSPLL_FASTEN_BIT))
+ SETD [D0FrT], D0Ar6
#endif
! Switch system clock back to PLL
diff --git a/arch/metag/tbx/tbidefr.S b/arch/metag/tbx/tbidefr.S
index 3eb165ebf5408a..8f0902b22f7034 100644
--- a/arch/metag/tbx/tbidefr.S
+++ b/arch/metag/tbx/tbidefr.S
@@ -20,7 +20,7 @@
/* D1Ar1:D0Ar2 -- State
* D0Ar3 -- SigNum
* D0Ar4 -- Triggers
- * D1Ar5 -- InstOrSWSId
+ * D1Ar5 -- Inst
* D0Ar6 -- pTBI (volatile)
*/
___TBIHandleDFR:
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index cc2290a3cace1e..c6ee86542fecb7 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -53,6 +53,8 @@
#define STACK_TOP TASK_SIZE
#define STACK_TOP_MAX DEFAULT_TASK_SIZE
+#define STACK_SIZE_MAX (1 << 30) /* 1 GB */
+
#endif
#ifndef __ASSEMBLY__
diff --git a/drivers/clk/clk-specified-rate.c b/drivers/clk/clk-specified-rate.c
index 8f7803331bb613..c276a9daf485ea 100644
--- a/drivers/clk/clk-specified-rate.c
+++ b/drivers/clk/clk-specified-rate.c
@@ -163,7 +163,7 @@ void __init of_specified_clk_setup(struct device_node *node)
__func__, clk_name, len);
goto err_iounmap;
}
- num_rates = len / (sizeof(*rates)*2);
+ num_rates = len / sizeof(*rates);
rates = kzalloc(sizeof(*rates)*num_rates, GFP_KERNEL);
if (!rates) {
diff --git a/drivers/clk/metag/clk-mux.c b/drivers/clk/metag/clk-mux.c
index 0d3096d1e4ec21..868a1f45c42316 100644
--- a/drivers/clk/metag/clk-mux.c
+++ b/drivers/clk/metag/clk-mux.c
@@ -172,7 +172,7 @@ static void __init of_metag_mux_clk_setup(struct device_node *node)
if (!parent_names) {
pr_err("%s(%s): could not allocate %u parent names\n",
__func__, clk_name, num_parents);
- goto err_kfree;
+ goto out_kfree;
}
/* fill in the parent names */
@@ -190,7 +190,7 @@ static void __init of_metag_mux_clk_setup(struct device_node *node)
if (default_clock >= num_parents) {
pr_err("%s(%s): default-clock %u out of range (%u bits)\n",
__func__, clk_name, default_clock, width);
- goto err_kfree;
+ goto out_kfree;
}
} else {
default_clock = -1;
@@ -200,7 +200,7 @@ static void __init of_metag_mux_clk_setup(struct device_node *node)
if (!reg) {
pr_err("%s(%s): of_iomap failed\n",
__func__, clk_name);
- goto err_kfree;
+ goto out_kfree;
}
if (of_find_property(node, "linux,clk-set-rate-parent", NULL))
@@ -217,11 +217,12 @@ static void __init of_metag_mux_clk_setup(struct device_node *node)
of_clk_add_provider(node, of_clk_src_simple_get, clk);
- return;
+ /* parent_names is copied by clk_register(), so it can now be freed */
+ goto out_kfree;
err_iounmap:
iounmap(reg);
-err_kfree:
+out_kfree:
kfree(parent_names);
}
CLK_OF_DECLARE(metag_mux_clk, "img,meta-mux-clock", of_metag_mux_clk_setup);
diff --git a/drivers/clk/tz1090/clk-tz1090-pll.c b/drivers/clk/tz1090/clk-tz1090-pll.c
index 1447f3161ae160..c48b948a44b79a 100644
--- a/drivers/clk/tz1090/clk-tz1090-pll.c
+++ b/drivers/clk/tz1090/clk-tz1090-pll.c
@@ -199,14 +199,16 @@ static int clk_tz1090_pll_set_rate(struct clk_hw *hw, unsigned long rate,
/* allow 5us after clkf before deasserting reset */
udelay(5);
- /* take PLL out of reset */
+ /* take PLL out of reset and enable fasten */
ctl1 &= ~PLL_CTL1_RESET_B;
+ ctl1 |= PLL_CTL1_FASTEN_B;
writel(ctl1, pll->reg + PLL_CTL1);
/* count at least 500 divided ref clks to allow time to lock */
msleep(1 + 500*1000*(clkr+1)/parent_rate);
- /* take PLL out of bypass */
+ /* take PLL out of fasten / bypass */
+ ctl1 &= ~PLL_CTL1_FASTEN_B;
ctl1 &= ~PLL_CTL1_BYPASS_B;
writel(ctl1, pll->reg + PLL_CTL1);
diff --git a/drivers/dma/img_mdc_dma.c b/drivers/dma/img_mdc_dma.c
index f49fbae4d70679..fc2ee217f29820 100644
--- a/drivers/dma/img_mdc_dma.c
+++ b/drivers/dma/img_mdc_dma.c
@@ -53,6 +53,7 @@ struct mdc_chan {
/* List of current DMA descriptors */
struct list_head active_desc; /* Active descriptors */
struct list_head free_desc; /* Used descriptors */
+ struct list_head ready_desc;
bool sg; /* true for sg xfer */
bool cyclic; /* true for cyclic xfer */
bool is_list; /* list-based xfer */
@@ -90,6 +91,7 @@ struct mdc_dma_desc {
int buffer_size;
int sample_size;
int sample_count;
+ bool irq_acked;
};
/* Forward declaration for dma driver */
@@ -317,7 +319,7 @@ static void img_dma_reset(struct mdc_chan *mchan)
/*thread id used in tag for reads*/
MDC_SET_FIELD(rpconf, MDC_RTHREAD, mchan->thread);
/*thread id used in tag for writes*/
- MDC_SET_FIELD(rpconf, MDC_STHREAD, mchan->thread);
+ MDC_SET_FIELD(rpconf, MDC_WTHREAD, mchan->thread);
/*priority of transfers*/
MDC_SET_FIELD(rpconf, MDC_PRIORITY, mchan->priority);
@@ -348,6 +350,7 @@ static irqreturn_t mdc_handler_isr(int irq, void *chan_id)
u32 irq_status;
struct mdc_chan *mchan = chan_id;
+ struct mdc_dma_desc *desc;
spin_lock(&mchan->lock);
@@ -361,11 +364,19 @@ static irqreturn_t mdc_handler_isr(int irq, void *chan_id)
mchan->mdma->base_addr,
mchan->a_chan_nr, 0);
/* Skip tasklet? */
- if (mchan->skip_callback)
+ if (mchan->skip_callback) {
mchan->skip_callback = false;
- else
+ } else {
+ list_for_each_entry(desc, &mchan->active_desc, node) {
+ if (!desc->irq_acked || mchan->cyclic) {
+ desc->sample_count++;
+ desc->irq_acked = true;
+ break;
+ }
+ }
/* Schedule the tasklet */
tasklet_schedule(&mchan->tasklet);
+ }
}
spin_unlock(&mchan->lock);
@@ -383,10 +394,8 @@ static irqreturn_t mdc_handler_isr(int irq, void *chan_id)
static void mdc_dma_tasklet(unsigned long data)
{
struct mdc_chan *mchan = (struct mdc_chan *)data;
- struct mdc_dma_desc *desc;
+ struct mdc_dma_desc *desc, *safe;
unsigned long flags;
- dma_async_tx_callback callback = NULL;
- void *param = NULL;
spin_lock_irqsave(&mchan->lock, flags);
if (list_empty(&mchan->active_desc)) {
@@ -394,24 +403,48 @@ static void mdc_dma_tasklet(unsigned long data)
return;
}
- desc = list_first_entry(&mchan->active_desc, typeof(*desc), node);
- if (++desc->sample_count == desc->total_samples) {
- desc->sample_count = 0;
- mchan->finished = true;
- /* For cyclic, this descriptor will remain active */
- if (!mchan->cyclic)
- /* Move it back to the free list */
- list_move_tail(&desc->node, &mchan->free_desc);
- }
- if (desc->txd.callback) {
- callback = desc->txd.callback;
- param = desc->txd.callback_param;
+ list_for_each_entry_safe(desc, safe, &mchan->active_desc, node) {
+ dev_vdbg(mchan2dev(mchan),
+ "Tasklet descriptor\n"
+ "Address : 0x%p\n"
+ "Sample count : %d\n"
+ "Total count : %d\n"
+ "Acked : %d\n",
+ desc, desc->sample_count, desc->total_samples,
+ desc->irq_acked);
+ if (desc->sample_count >= desc->total_samples) {
+ if (desc->irq_acked) {
+ desc->sample_count = 0;
+ mchan->finished = true;
+ desc->irq_acked = false;
+ }
+ /*
+ * Move it to the ready list.
+ * For cyclic we keep it active.
+ */
+ if (!mchan->cyclic)
+ list_move_tail(&desc->node, &mchan->ready_desc);
+ }
}
spin_unlock_irqrestore(&mchan->lock, flags);
- /* We are safe to call the callback now */
- if (callback)
- callback(param);
+ /*
+ * If cyclic, that means we only have one descriptor so get it and
+ * see if there is a callback to call now
+ */
+ if (mchan->cyclic) {
+ desc = list_first_entry(&mchan->active_desc, typeof(*desc), node);
+ if (desc->txd.callback)
+ desc->txd.callback(desc->txd.callback_param);
+ } else {
+ list_for_each_entry_safe(desc, safe, &mchan->ready_desc, node) {
+ if (desc->txd.callback)
+ desc->txd.callback(desc->txd.callback_param);
+ async_tx_ack(&desc->txd);
+ /* Move it back to the free list */
+ list_move_tail(&desc->node, &mchan->free_desc);
+ }
+ }
}
/*
@@ -430,7 +463,7 @@ static dma_cookie_t mdc_dma_tx_submit(struct dma_async_tx_descriptor *txd)
cookie = dma_cookie_assign(&dma_desc->txd);
dma_desc->status = DMA_IN_PROGRESS;
/* Add descriptor to active list */
- list_add(&dma_desc->node, &mchan->active_desc);
+ list_add_tail(&dma_desc->node, &mchan->active_desc);
spin_unlock_irqrestore(&mchan->lock, flags);
@@ -537,7 +570,7 @@ static struct mdc_dma_desc *mdc_dma_get_desc(struct mdc_chan *chan,
}
/* We couldn't find a suitable descriptor */
spin_unlock_irqrestore(&chan->lock, irq_flags);
- desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+ desc = kzalloc(sizeof(*desc), GFP_ATOMIC);
if (!desc) {
dev_err(mchan2dev(chan),
"Failed to allocate DMA descriptor\n");
@@ -638,6 +671,7 @@ static struct dma_async_tx_descriptor *mdc_prep_memcpy(struct dma_chan *chan,
mchan->is_list = false;
mchan->cyclic = false;
/* tx defaults for tx_status. single transfer */
+ mdesc->irq_acked = false;
mdesc->sample_count = 0;
mdesc->sample_size = 1;
mdesc->total_samples = mdesc->buffer_size = 1;
@@ -720,6 +754,7 @@ static struct dma_async_tx_descriptor *mdc_prep_dma_cyclic(
if (!mdesc)
return NULL;
+ mdesc->irq_acked = false;
mdesc->sample_count = 0;
mdesc->total_samples = 0;
mdesc->sample_size = period_len;
@@ -825,6 +860,8 @@ static struct dma_async_tx_descriptor *mdc_prep_slave_sg(
struct img_dma_mdc_list *desc_list;
dma_addr_t list_base, next_list, addr;
int i, width, temp, burst_size_min, burst_size, req_width;
+ u32 genconf, rpconf;
+ dma_addr_t dst, src;
u32 len;
if (unlikely(!sg_len || !sgl || !mchan))
@@ -838,8 +875,10 @@ static struct dma_async_tx_descriptor *mdc_prep_slave_sg(
if (!mdesc)
return NULL;
- mchan->is_list = true;
+ mchan->is_list = (sg_len > 1);
+ mchan->cyclic = false;
mchan->sg = true;
+ mdesc->irq_acked = false;
mdesc->sample_count = 0;
mdesc->sample_size = 1; /* single list item */
mdesc->total_samples = mdesc->buffer_size = sg_len;
@@ -866,81 +905,136 @@ static struct dma_async_tx_descriptor *mdc_prep_slave_sg(
img_dma_reset(mchan);
- /* This is for the MDC linked-list */
- desc_list = (struct img_dma_mdc_list *)mchan->virt_addr;
- mdesc->start_list = list_base = next_list = mchan->dma_addr;
-
- /* Hand back the DMA buffer to the CPU */
- dma_sync_single_for_cpu(mchan->mdma->dma_slave.dev,
- mchan->dma_addr,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
-
burst_size_min = burst_size_lookup[mdma->config.bus_width & 0x7];
- for_each_sg(sgl, sg, sg_len, i) {
- /*
- * Each list item is a 32-byte packet represented by the
- * img_dma_mdc_list struct. Every member of that struct
- * corresponds to the channel register
- */
- next_list += sizeof(struct img_dma_mdc_list);
- len = sg_dma_len(sg);
- addr = sg_dma_address(sg);
+ if (!mchan->is_list) {
+ len = sg_dma_len(sgl);
+ addr = sg_dma_address(sgl);
width = check_widths(mchan->mdma, addr);
- desc_list->gen_conf = 0x30000088
+ genconf = 0x30000088
| ((mchan->a_chan_nr & 0x3f) << 20)
| ((mchan->access_delay & 0x7) << 16);
temp = (mchan->thread & 0xf);
- desc_list->readport_conf = 0x00000002 | temp << 2
+ rpconf = 0x00000002 | temp << 2
| temp << 24 | temp << 16;
- MDC_SET_FIELD(desc_list->readport_conf, MDC_PRIORITY,
+ MDC_SET_FIELD(rpconf, MDC_PRIORITY,
mchan->priority);
if (direction == DMA_MEM_TO_DEV) {
- MDC_SET_FIELD(desc_list->gen_conf, MDC_INC_R, 1);
- MDC_SET_FIELD(desc_list->gen_conf, MDC_WIDTH_R, width);
+ MDC_SET_FIELD(genconf, MDC_INC_R, 1);
+ MDC_SET_FIELD(genconf, MDC_WIDTH_R, width);
req_width = mchan->dma_config.dst_addr_width;
- MDC_SET_FIELD(desc_list->gen_conf, MDC_WIDTH_W,
+ MDC_SET_FIELD(genconf, MDC_WIDTH_W,
map_to_mdc_width(req_width));
- desc_list->read_addr = addr;
- desc_list->write_addr = mchan->dma_config.dst_addr;
+ src = addr;
+ dst = mchan->dma_config.dst_addr;
burst_size = mchan->dma_config.dst_maxburst;
- desc_list->readport_conf |=
- (burst_size < burst_size_min)
- ? (burst_size_min - 1) << 4
- : (burst_size - 1) << 4;
} else {
- MDC_SET_FIELD(desc_list->gen_conf, MDC_INC_W, 1);
- MDC_SET_FIELD(desc_list->gen_conf, MDC_WIDTH_W, width);
+ MDC_SET_FIELD(genconf, MDC_INC_W, 1);
+ MDC_SET_FIELD(genconf, MDC_WIDTH_W, width);
req_width = mchan->dma_config.src_addr_width;
- MDC_SET_FIELD(desc_list->gen_conf, MDC_WIDTH_R,
+ MDC_SET_FIELD(genconf, MDC_WIDTH_R,
map_to_mdc_width(req_width));
- desc_list->read_addr = mchan->dma_config.src_addr;
- desc_list->write_addr = addr;
+ src = mchan->dma_config.src_addr;
+ dst = addr;
burst_size = mchan->dma_config.src_maxburst;
+ }
+ rpconf |= (burst_size < burst_size_min)
+ ? (burst_size_min - 1) << 4
+ : (burst_size - 1) << 4;
+
+ /* Write the single sg entry to hardware */
+ MDC_RSET_READ_ADDRESS((unsigned long)mchan->mdma->base_addr,
+ mchan->a_chan_nr, src);
+ MDC_RSET_WRITE_ADDRESS((unsigned long)mchan->mdma->base_addr,
+ mchan->a_chan_nr, dst);
+ MDC_RSET_GENERAL_CONFIG((unsigned long)mchan->mdma->base_addr,
+ mchan->a_chan_nr, genconf);
+ MDC_RSET_READ_PORT_CONFIG((unsigned long)mchan->mdma->base_addr,
+ mchan->a_chan_nr, rpconf);
+ MDC_RSET_TRANSFER_SIZE((unsigned long)mchan->mdma->base_addr,
+ mchan->a_chan_nr, len - 1);
+ wmb();
+
+ } else {
+ /* This is for the MDC linked-list */
+ desc_list = (struct img_dma_mdc_list *)mchan->virt_addr;
+ mdesc->start_list = list_base = next_list = mchan->dma_addr;
+
+ /* Hand back the DMA buffer to the CPU */
+ dma_sync_single_for_cpu(mchan->mdma->dma_slave.dev,
+ mchan->dma_addr,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ /*
+ * Each list item is a 32-byte packet represented by the
+ * img_dma_mdc_list struct. Every member of that struct
+ * corresponds to the channel register
+ */
+ next_list += sizeof(struct img_dma_mdc_list);
+ len = sg_dma_len(sg);
+ addr = sg_dma_address(sg);
+ width = check_widths(mchan->mdma, addr);
+ desc_list->gen_conf = 0x30000088
+ | ((mchan->a_chan_nr & 0x3f) << 20)
+ | ((mchan->access_delay & 0x7) << 16);
+
+ temp = (mchan->thread & 0xf);
+ desc_list->readport_conf = 0x00000002 | temp << 2
+ | temp << 24 | temp << 16;
+
+ MDC_SET_FIELD(desc_list->readport_conf, MDC_PRIORITY,
+ mchan->priority);
+
+ if (direction == DMA_MEM_TO_DEV) {
+ MDC_SET_FIELD(desc_list->gen_conf, MDC_INC_R,
+ 1);
+ MDC_SET_FIELD(desc_list->gen_conf, MDC_WIDTH_R,
+ width);
+ req_width = mchan->dma_config.dst_addr_width;
+ MDC_SET_FIELD(desc_list->gen_conf, MDC_WIDTH_W,
+ map_to_mdc_width(req_width));
+ desc_list->read_addr = addr;
+ desc_list->write_addr =
+ mchan->dma_config.dst_addr;
+ burst_size = mchan->dma_config.dst_maxburst;
+ } else {
+ MDC_SET_FIELD(desc_list->gen_conf, MDC_INC_W,
+ 1);
+ MDC_SET_FIELD(desc_list->gen_conf, MDC_WIDTH_W,
+ width);
+ req_width = mchan->dma_config.src_addr_width;
+ MDC_SET_FIELD(desc_list->gen_conf, MDC_WIDTH_R,
+ map_to_mdc_width(req_width));
+ desc_list->read_addr =
+ mchan->dma_config.src_addr;
+ desc_list->write_addr = addr;
+ burst_size = mchan->dma_config.src_maxburst;
+ }
desc_list->readport_conf |=
(burst_size < burst_size_min)
? (burst_size_min - 1) << 4
: (burst_size - 1) << 4;
- }
- desc_list->xfer_size = len - 1;
- desc_list->node_addr = next_list;
- desc_list->cmds_done = 0;
- desc_list->ctrl_status = 0x11;
+ desc_list->xfer_size = len - 1;
+ desc_list->node_addr = next_list;
+ desc_list->cmds_done = 0;
+ desc_list->ctrl_status = 0x11;
- desc_list++;
- }
+ desc_list++;
+ }
- desc_list[-1].node_addr = 0;
+ desc_list[-1].node_addr = 0;
- /* we are done with the DMA buffer, give it back to the device */
- dma_sync_single_for_device(mchan->mdma->dma_slave.dev,
- mchan->dma_addr,
- PAGE_SIZE,
- DMA_BIDIRECTIONAL);
+ /* we are done with the DMA buffer, give it back to the device */
+ dma_sync_single_for_device(mchan->mdma->dma_slave.dev,
+ mchan->dma_addr,
+ PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ }
return &mdesc->txd;
}
@@ -1251,6 +1345,12 @@ static int mdc_terminate_all(struct dma_chan *chan)
kfree(desc);
}
+ /* Safe removal of list items */
+ list_for_each_entry_safe(desc, safe, &mchan->ready_desc, node) {
+ list_del(&desc->node);
+ kfree(desc);
+ }
+
/* Reset cookie for this channel */
dma_cookie_init(chan);
@@ -1392,7 +1492,9 @@ static void __init mdc_chan_init(struct mdc_dmadev *mdma,
mdc_chan->dchan.device = &mdma->dma_slave;
mdc_chan->a_chan_nr = i;
mdc_chan->periph = 0;
- if (i < mdma->config.dma_channels)
+ spin_lock_init(&mdc_chan->lock);
+ if ((i < mdma->config.dma_channels) &&
+ (mdma->callbacks->available(i)))
mdma->slave_channel[i].alloc_status =
IMG_DMA_CHANNEL_AVAILABLE;
else
@@ -1407,6 +1509,7 @@ static void __init mdc_chan_init(struct mdc_dmadev *mdma,
/* init the list of descriptors for this channel */
INIT_LIST_HEAD(&mdc_chan->active_desc);
INIT_LIST_HEAD(&mdc_chan->free_desc);
+ INIT_LIST_HEAD(&mdc_chan->ready_desc);
/* Add channel to the DMA channel linked-list */
list_add_tail(&mdc_chan->dchan.device_node,
@@ -1437,6 +1540,8 @@ int mdc_dma_probe(struct platform_device *pdev,
return -ENOMEM;
}
+ spin_lock_init(&mdma->lock);
+
mem_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mdma->base_addr = devm_request_and_ioremap(dev, mem_resource);
if (!mdma->base_addr) {
diff --git a/drivers/dma/tz1090-mdc-dma.c b/drivers/dma/tz1090-mdc-dma.c
index f0a465703087fd..84c26fe4e7cfd0 100644
--- a/drivers/dma/tz1090-mdc-dma.c
+++ b/drivers/dma/tz1090-mdc-dma.c
@@ -99,6 +99,10 @@ static void setup_dma_channel(int dmanr, unsigned int periph)
__global_unlock2(lstat);
}
+static int img_is_chan_available(int dmanr)
+{
+ return dma_channels[dmanr] == IMG_DMA_CHANNEL_AVAILABLE;
+}
static int img_request_dma(int dmanr, unsigned int periph)
{
@@ -267,6 +271,7 @@ device_initcall(proc_dma_init);
static struct img_mdc_soc_callbacks comet_dma_callbacks = {
.allocate = img_request_dma,
+ .available = img_is_chan_available,
.free = img_free_dma,
.suspend = img_dma_suspend,
.resume = img_dma_resume,
diff --git a/drivers/gpio/gpio-tz1090.c b/drivers/gpio/gpio-tz1090.c
index 5c42d610a47c8b..0cbf81996716b3 100644
--- a/drivers/gpio/gpio-tz1090.c
+++ b/drivers/gpio/gpio-tz1090.c
@@ -492,7 +492,7 @@ int comet_gpio_pullup_type(unsigned int gpio, unsigned int pullup)
{
struct tz1090_gpio_bank *bank = NULL;
struct comet_gpio_pullup *gpio_pullup;
- unsigned int offset = 0, value;
+ unsigned int offset = 0, index, value;
int idx;
int lstat;
@@ -501,15 +501,16 @@ int comet_gpio_pullup_type(unsigned int gpio, unsigned int pullup)
if (idx < 0)
return -EINVAL;
- bank = comet_gpio_chip[idx];
+ bank = comet_gpio_chip[0];
gpio_pullup = &gpio_pullup_table[gpio];
+ index = gpio_pullup->index << 2;
offset = gpio_pullup->offset;
__global_lock2(lstat);
- value = tz1090_gpio_read(bank, REG_GPIO_PU_PD);
+ value = tz1090_gpio_read(bank, REG_GPIO_PU_PD + index);
value &= ~(0x3 << offset);
value |= (pullup & 0x3) << offset;
- tz1090_gpio_write(bank, REG_GPIO_PU_PD, value);
+ tz1090_gpio_write(bank, REG_GPIO_PU_PD + index, value);
__global_unlock2(lstat);
return 0;
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index c2534d62911cfd..ff0fd655729f9e 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1214,15 +1214,14 @@ int gpiochip_add(struct gpio_chip *chip)
}
}
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
#ifdef CONFIG_PINCTRL
INIT_LIST_HEAD(&chip->pin_ranges);
#endif
of_gpiochip_add(chip);
-unlock:
- spin_unlock_irqrestore(&gpio_lock, flags);
-
if (status)
goto fail;
@@ -1235,6 +1234,9 @@ unlock:
chip->label ? : "generic");
return 0;
+
+unlock:
+ spin_unlock_irqrestore(&gpio_lock, flags);
fail:
/* failures here can mean systems won't boot... */
pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n",
diff --git a/drivers/i2c/busses/i2c-img.c b/drivers/i2c/busses/i2c-img.c
index 4749b113d38ac3..1a0144c127fa8a 100644
--- a/drivers/i2c/busses/i2c-img.c
+++ b/drivers/i2c/busses/i2c-img.c
@@ -80,7 +80,7 @@
#define INT_TIMING 0x40000
/* level interrupts need clearing after handling instead of before */
-#define INT_LEVEL 0x01e00
+#define INT_LEVEL 0x00600
/* don't allow any interrupts while the clock may be off */
#define INT_ENABLE_MASK_INACTIVE 0x00000
diff --git a/drivers/irqchip/irq-metag-ext.c b/drivers/irqchip/irq-metag-ext.c
index 13d9aa8de87c5e..cf3ef3c4a57e36 100644
--- a/drivers/irqchip/irq-metag-ext.c
+++ b/drivers/irqchip/irq-metag-ext.c
@@ -516,7 +516,7 @@ static int meta_intc_set_affinity(struct irq_data *data,
* one cpu (the interrupt code doesn't support it), so we just
* pick the first cpu we find in 'cpumask'.
*/
- cpu = cpumask_any(cpumask);
+ cpu = cpumask_any_and(cpumask, cpu_online_mask);
thread = cpu_2_hwthread_id[cpu];
metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr);
diff --git a/drivers/irqchip/irq-metag.c b/drivers/irqchip/irq-metag.c
index 8e94d7a3b20d27..c16c186d97d35f 100644
--- a/drivers/irqchip/irq-metag.c
+++ b/drivers/irqchip/irq-metag.c
@@ -201,7 +201,7 @@ static int metag_internal_irq_set_affinity(struct irq_data *data,
* one cpu (the interrupt code doesn't support it), so we just
* pick the first cpu we find in 'cpumask'.
*/
- cpu = cpumask_any(cpumask);
+ cpu = cpumask_any_and(cpumask, cpu_online_mask);
thread = cpu_2_hwthread_id[cpu];
metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)),
diff --git a/drivers/media/rc/ir-img.c b/drivers/media/rc/ir-img.c
index b4509aff99012b..de8694f2ae687c 100644
--- a/drivers/media/rc/ir-img.c
+++ b/drivers/media/rc/ir-img.c
@@ -638,10 +638,12 @@ static void img_ir_set_decoder(struct img_ir_priv *priv,
if (ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2)) {
ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2);
img_ir_write(priv, IMG_IR_STATUS, ir_status);
- img_ir_read(priv, IMG_IR_DATA_LW);
- img_ir_read(priv, IMG_IR_DATA_UP);
}
+ /* always read data to clear buffer if IR wakes the device */
+ img_ir_read(priv, IMG_IR_DATA_LW);
+ img_ir_read(priv, IMG_IR_DATA_UP);
+
/* clear the scancode filters */
priv->sc_filter.data = 0;
priv->sc_filter.mask = 0;
diff --git a/drivers/net/wireless/uccp310wlan/80211_if.c b/drivers/net/wireless/uccp310wlan/80211_if.c
index e68ef8df89479f..a5eee74424024f 100644
--- a/drivers/net/wireless/uccp310wlan/80211_if.c
+++ b/drivers/net/wireless/uccp310wlan/80211_if.c
@@ -45,6 +45,8 @@
#define _80211IF_DEBUG(...) do { } while (0)
#endif
+extern int reset_hal_params(void);
+
static char *mac_addr = DEFAULT_MAC_ADDRESS;
/* Its value will be the default mac address and it can only be updated with the
@@ -149,6 +151,27 @@ static struct ieee80211_supported_band band_5ghz = {
.n_bitrates = ARRAY_SIZE(ofdm_rates),
};
+static const struct ieee80211_iface_limit if_limit1[] = {{ .max = 4, .types = BIT(NL80211_IFTYPE_STATION)} };
+static const struct ieee80211_iface_limit if_limit2[] = {{ .max = 2, .types = BIT(NL80211_IFTYPE_STATION)} };
+static const struct ieee80211_iface_limit if_limit3[] = {{ .max = 1, .types = BIT(NL80211_IFTYPE_STATION),},
+ { .max = 1, .types = BIT(NL80211_IFTYPE_AP)|
+ BIT(NL80211_IFTYPE_P2P_CLIENT)|
+ BIT(NL80211_IFTYPE_ADHOC)|
+ BIT(NL80211_IFTYPE_P2P_GO)} };
+static const struct ieee80211_iface_limit if_limit4[] = {{ .max = 1, .types = BIT(NL80211_IFTYPE_AP)},
+ { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_GO)} };
+
+static const struct ieee80211_iface_limit if_limit5[] = {{ .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC)},
+ { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT)} };
+
+static const struct ieee80211_iface_combination if_comb[] = {
+ { .limits = if_limit1, .n_limits = ARRAY_SIZE(if_limit1), .max_interfaces = 4, .num_different_channels = 1},
+ { .limits = if_limit2, .n_limits = ARRAY_SIZE(if_limit2), .max_interfaces = 2, .num_different_channels = 1},
+ { .limits = if_limit3, .n_limits = ARRAY_SIZE(if_limit3), .max_interfaces = 2, .num_different_channels = 1},
+ { .limits = if_limit4, .n_limits = ARRAY_SIZE(if_limit4), .max_interfaces = 2, .num_different_channels = 1},
+ { .limits = if_limit5, .n_limits = ARRAY_SIZE(if_limit5), .max_interfaces = 2, .num_different_channels = 1}
+};
+
static int conv_str_to_byte(unsigned char *byte,
unsigned char *str,
int len)
@@ -204,7 +227,7 @@ static unsigned char get_ps_info(unsigned char *ie_data,
}
static void tx(struct ieee80211_hw *hw,
- struct ieee80211_tx_control *control,
+ struct ieee80211_tx_control *tx_control,
struct sk_buff *skb)
{
struct mac80211_dev *dev = hw->priv;
@@ -295,7 +318,7 @@ static int add_interface(struct ieee80211_hw *hw,
iftype = vif->type;
v = vif;
- vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+
if (!(iftype == NL80211_IFTYPE_STATION ||
iftype == NL80211_IFTYPE_ADHOC ||
iftype == NL80211_IFTYPE_AP)) {
@@ -677,18 +700,24 @@ static void sw_scan_start(struct ieee80211_hw *hw)
{
_80211IF_DEBUG("%s-80211IF: scan started\n", ((struct mac80211_dev *)(hw->priv))->name);
- /*
- * TODO::
- */
+ uccp310wlan_prog_scan_ind(1);
}
static void sw_scan_complete(struct ieee80211_hw *hw)
{
+ struct mac80211_dev *dev = hw->priv;
+ struct ieee80211_vif *vif;
+ int vif_index;
+
_80211IF_DEBUG("%s-80211IF: scan stopped\n", ((struct mac80211_dev *)(hw->priv))->name);
- /*
- * TODO::
- */
+ if (dev->active_vifs == 1) {
+ for (vif_index = 0; vif_index < wifi->params.num_vifs; vif_index++) {
+ vif = (struct ieee80211_vif *)rcu_dereference(dev->vifs[vif_index]);
+ if (vif && (vif->type == NL80211_IFTYPE_STATION) && (vif->bss_conf.assoc))
+ uccp310wlan_prog_scan_ind(0);
+ }
+ }
}
static void init_hw(struct ieee80211_hw *hw)
@@ -696,12 +725,19 @@ static void init_hw(struct ieee80211_hw *hw)
struct mac80211_dev *dev = (struct mac80211_dev *)hw->priv;
/* Supported Interface Types and other Default values*/
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
+ if (wifi->params.num_vifs > 1) {
+ hw->wiphy->iface_combinations = if_comb;
+ hw->wiphy->n_iface_combinations = sizeof(if_comb)/sizeof(struct ieee80211_iface_combination);
+ }
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS ; /* umac */
hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
hw->flags |= IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
hw->flags |= IEEE80211_HW_SUPPORTS_PER_STA_GTK;
+ hw->flags |= IEEE80211_HW_CONNECTION_MONITOR;
+
+ hw->flags |= IEEE80211_HW_MFP_CAPABLE;
hw->max_listen_interval = 10; /* umac */
hw->max_rates = 4; /* umac */
@@ -728,6 +764,8 @@ static void init_hw(struct ieee80211_hw *hw)
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+ hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+
}
static struct ieee80211_ops ops = {
.tx = tx,
@@ -827,6 +865,7 @@ out:
static ssize_t proc_read(struct seq_file *m, void *v)
{
+
seq_printf(m, "************* PARAMS ***********\n");
seq_printf(m, "dot11a_support = %d\n", wifi->params.dot11a_support);
seq_printf(m, "sensitivity = %d\n", wifi->params.ed_sensitivity);
@@ -835,6 +874,7 @@ static ssize_t proc_read(struct seq_file *m, void *v)
seq_printf(m, "production_test = %d\n", wifi->params.production_test);
seq_printf(m, "show_phy_stats = %d\n", wifi->params.show_phy_stats);
seq_printf(m, "num_vifs = %d\n", wifi->params.num_vifs);
+ seq_printf(m, "max_bcn_loss = %d\n", wifi->params.max_bcn_loss);
seq_printf(m, "************* STATS ***********\n");
seq_printf(m, "rx_packet_count = %d\n", wifi->stats.rx_packet_count);
if (wifi->params.show_phy_stats) {
@@ -896,11 +936,17 @@ static ssize_t proc_read(struct seq_file *m, void *v)
seq_printf(m, "\n");
}
#endif
+ seq_printf(m, "TS1 = %llu\n", (unsigned long long)get_unaligned_le64(wifi->params.ts1));
+ seq_printf(m, "TS2 = %lu\n", (unsigned long)get_unaligned_le32(wifi->params.ts2));
+ seq_printf(m, "BSSID = %pM\n", (wifi->params.bssid));
+
return 0;
}
-static ssize_t proc_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *ppos)
+static ssize_t proc_write(struct file *file,
+ const char __user *buffer,
+ size_t count,
+ loff_t *ppos)
{
char buf[100];
int ret;
@@ -931,6 +977,12 @@ static ssize_t proc_write(struct file *file, const char __user *buffer,
printk(KERN_ERR "Invalid parameter value.\n");
else
wifi->params.ed_sensitivity = sval;
+ } else if (!strncmp(buf, "dyn_ed_ceiling=", 15)) {
+ ret = kstrtol(buf+15, 0, &sval);
+ if (sval > -51 || sval < -96 || (sval % 3 != 0))
+ printk(KERN_ERR "Invalid parameter value.\n");
+ else
+ wifi->params.dyn_ed_ceiling = sval;
} else if (!strncmp(buf, "auto_sensitivity=", 17)) {
ret = kstrtoul(buf+17, 0, &val);
if ((val == 0) || (val == 1))
@@ -990,6 +1042,23 @@ static ssize_t proc_write(struct file *file, const char __user *buffer,
printk(KERN_ERR "Invalid parameter value.\n");
} else if (!strncmp(buf, "get_rx_stats=", 13)) {
uccp310wlan_prog_mib_stats();
+ } else if (!strncmp(buf, "reset_hal_params=", 17)) {
+ ret = kstrtoul(buf+17, 0, &val);
+ if (((struct mac80211_dev *)(wifi->hw->priv))->state != STARTED) {
+ if (val != 1)
+ printk(KERN_ERR "Invalid parameter value.\n");
+ else
+ reset_hal_params();
+ } else {
+ printk(KERN_ERR "HAL parameters reset can be done only when all interface are down\n");
+ }
+ } else if (!strncmp(buf, "max_bcn_loss=", 13)) {
+ ret = kstrtoul(buf+13, 0, &val);
+ if (val >= 5)
+ wifi->params.max_bcn_loss = val;
+ else
+ printk(KERN_ERR "Invalid parameter value (should be >=5)");
+
} else {
printk(KERN_ERR "Invalid parameter name.\n");
}
@@ -1001,11 +1070,12 @@ static int proc_open(struct inode *inode, struct file *file)
return single_open(file, proc_read, NULL);
}
-static const struct file_operations params_fops = {
+static const struct file_operations proc_fops = {
.open = proc_open,
.read = seq_read,
.llseek = seq_lseek,
- .write = proc_write,
+ .release = single_release,
+ .write = proc_write
};
static int proc_init(void)
@@ -1027,7 +1097,7 @@ static int proc_init(void)
}
entry = proc_create("params", 0644, wifi->umac_proc_dir_entry,
- &params_fops);
+ &proc_fops);
if (!entry) {
printk(KERN_ERR "Failed to create proc entry\n");
err = -ENOMEM;
@@ -1038,9 +1108,11 @@ static int proc_init(void)
memset(&wifi->params, 0, sizeof(struct wifi_params));
memset(wifi->params.rf_params, 0xff, sizeof(wifi->params.rf_params));
wifi->params.ed_sensitivity = -84;
+ wifi->params.dyn_ed_ceiling = -51;
wifi->params.rf_params[0] = 0x3B;
wifi->params.auto_sensitivity = 1;
wifi->params.num_vifs = 1;
+ wifi->params.max_bcn_loss = MAX_BEACON_LOSS_COUNT;
return err;
diff --git a/drivers/net/wireless/uccp310wlan/core.c b/drivers/net/wireless/uccp310wlan/core.c
index b7496c5f3052a5..3ede750b1327d6 100644
--- a/drivers/net/wireless/uccp310wlan/core.c
+++ b/drivers/net/wireless/uccp310wlan/core.c
@@ -70,15 +70,29 @@ static void vif_bcn_timer_expiry(unsigned long data)
if (!ieee80211_sdata_running(sdata))
return;
- if (uvif->vif->bss_conf.enable_beacon == false)
+
+ if (uvif->vif->bss_conf.enable_beacon == false) {
+ if (uvif->vif->type == NL80211_IFTYPE_STATION &&
+ uvif->vif->bss_conf.assoc) {
+ ieee80211_connection_loss(uvif->vif);
+ printk(KERN_DEBUG "Maximum Beacon Loss count exceeded..............Disconnecting\n");
+ del_timer(&uvif->bcn_timer);
+ }
return;
+ }
+
if (uvif->vif->type == NL80211_IFTYPE_AP) {
skb_queue_head_init(&bcast_frames);
temp = skb = ieee80211_beacon_get(uvif->dev->hw, uvif->vif);
- skb->priority = 1;
- skb_queue_tail(&bcast_frames, skb);
+
+ if (skb) {
+ skb->priority = 1;
+ skb_queue_tail(&bcast_frames, skb);
+ } else {
+ goto reschedule_timer;
+ }
skb = ieee80211_get_buffered_bc(uvif->dev->hw, uvif->vif);
while (skb) {
@@ -87,8 +101,8 @@ static void vif_bcn_timer_expiry(unsigned long data)
temp = skb;
skb = ieee80211_get_buffered_bc(uvif->dev->hw, uvif->vif);
}
-
- temp->priority = 0;
+ if (temp)
+ temp->priority = 0;
spin_lock_irqsave(&uvif->dev->bcast_lock, flags);
while ((skb = skb_dequeue(&bcast_frames)))
@@ -96,11 +110,15 @@ static void vif_bcn_timer_expiry(unsigned long data)
spin_unlock_irqrestore(&uvif->dev->bcast_lock, flags);
} else {
skb = ieee80211_beacon_get(uvif->dev->hw, uvif->vif);
- uccp310wlan_tx_frame(skb, uvif->dev, true);
+ if (skb)
+ uccp310wlan_tx_frame(skb, uvif->dev, true);
+ else
+ goto reschedule_timer;
/* TODO: IBSS PS handling */
}
+reschedule_timer:
mod_timer(&uvif->bcn_timer, jiffies + msecs_to_jiffies(uvif->vif->bss_conf.beacon_int));
}
@@ -124,6 +142,7 @@ int uccp310wlan_core_init(struct mac80211_dev *dev)
512, /* Tx MSDU life time in msecs */
dev->params->ed_sensitivity,
dev->params->auto_sensitivity,
+ dev->params->dyn_ed_ceiling,
dev->params->rf_params);
uccp310wlan_prog_txpower(dev->txpower);
@@ -165,6 +184,9 @@ void uccp310wlan_vif_add(struct umac_vif *uvif)
type = IF_MODE_STA_BSS;
uvif->noa_active = 0;
skb_queue_head_init(&uvif->noa_que);
+ init_timer(&uvif->bcn_timer);
+ uvif->bcn_timer.data = (unsigned long)uvif;
+ uvif->bcn_timer.function = vif_bcn_timer_expiry;
break;
case NL80211_IFTYPE_ADHOC:
type = IF_MODE_STA_IBSS;
@@ -202,8 +224,6 @@ void uccp310wlan_vif_add(struct umac_vif *uvif)
uvif->config.edca_params[queue].txop,
uvif->config.edca_params[queue].cwmin,
uvif->config.edca_params[queue].cwmax);
-
-
}
}
@@ -217,6 +237,7 @@ void uccp310wlan_vif_remove(struct umac_vif *uvif)
switch (uvif->vif->type) {
case NL80211_IFTYPE_STATION:
type = IF_MODE_STA_BSS;
+ del_timer(&uvif->bcn_timer);
break;
case NL80211_IFTYPE_ADHOC:
type = IF_MODE_STA_IBSS;
@@ -335,6 +356,12 @@ void uccp310wlan_vif_bss_info_changed(struct umac_vif *uvif, struct ieee80211_bs
switch (uvif->vif->type) {
case NL80211_IFTYPE_STATION:
if (changed & BSS_CHANGED_ASSOC) {
+ if (uvif->dev->active_vifs == 1) {
+ if (uvif->vif->bss_conf.assoc)
+ uccp310wlan_prog_scan_ind(0);
+ else
+ uccp310wlan_prog_scan_ind(1);
+ }
if (bss_conf->assoc) {
UMAC_DEBUG("%s-UMAC: AID %d, CAPS 0x%04x\n", uvif->dev->name, bss_conf->aid, bss_conf->assoc_capability |
(bss->wmm_used << 9));
@@ -345,6 +372,9 @@ void uccp310wlan_vif_bss_info_changed(struct umac_vif *uvif, struct ieee80211_bs
uvif->vif->addr,
bss_conf->assoc_capability | (bss->wmm_used << 9));
uvif->noa_active = 0;
+ mod_timer(&uvif->bcn_timer, (jiffies + msecs_to_jiffies(uvif->dev->params->max_bcn_loss * uvif->vif->bss_conf.beacon_int)));
+ } else {
+ del_timer(&uvif->bcn_timer);
}
}
break;
@@ -479,10 +509,14 @@ void uccp310wlan_rx_frame(struct sk_buff *skb, void *context)
struct ieee80211_hdr *hdr;
struct ieee80211_rx_status rx_status;
int i;
+ struct ieee80211_vif *vif = NULL;
+ struct umac_vif *uvif;
+ int vif_index;
+
dev->stats->rx_packet_count++;
- skb_pull(skb, 32); /* Remove RX control information */
+ skb_pull(skb, 44); /* Remove RX control information */
#ifdef CONFIG_RX_DEBUG
printk(KERN_DEBUG "%s-RX: RX frame, length = %d, RSSI = %d, rate = %d\n", dev->name, rx->buff_len, rx->rssi, rx->rate);
@@ -519,7 +553,22 @@ void uccp310wlan_rx_frame(struct sk_buff *skb, void *context)
if (((hdr->frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
((hdr->frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)) {
rx_status.mactime = get_unaligned_le64(rx->timestamp);
- rx_status.flag |= RX_FLAG_MACTIME_START;
+ rx_status.flag |= RX_FLAG_MACTIME_END;
+ for (vif_index = 0; vif_index < dev->params->num_vifs; vif_index++) {
+ vif = (struct ieee80211_vif *)rcu_dereference(dev->vifs[vif_index]);
+ if (vif && (vif->type == NL80211_IFTYPE_STATION) && (vif->bss_conf.assoc) &&
+ (!memcmp((vif_to_sdata(vif))->u.mgd.bssid, hdr->addr3, ETH_ALEN))) {
+ uvif = (struct umac_vif *)vif->drv_priv;
+ mod_timer(&uvif->bcn_timer, (jiffies +
+ msecs_to_jiffies(uvif->dev->params->max_bcn_loss * vif->bss_conf.beacon_int)));
+ }
+ if (vif && !compare_ether_addr(hdr->addr2, (vif_to_sdata(vif))->u.mgd.bssid)) {
+ memcpy(dev->params->ts1, rx->ts1, sizeof(rx->ts1));
+ memcpy(dev->params->ts2, rx->ts2, sizeof(rx->ts2));
+ memcpy(dev->params->bssid, (vif_to_sdata(vif))->u.mgd.bssid, ETH_ALEN);
+ }
+
+ }
}
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
diff --git a/drivers/net/wireless/uccp310wlan/hal_hostport.c b/drivers/net/wireless/uccp310wlan/hal_hostport.c
index b8f4afd0a4f9b4..7ea761258863a4 100644
--- a/drivers/net/wireless/uccp310wlan/hal_hostport.c
+++ b/drivers/net/wireless/uccp310wlan/hal_hostport.c
@@ -53,6 +53,13 @@ unsigned int irq_ts_index;
spinlock_t timing_lock;
#endif
+int reset_hal_params(void)
+{
+ hpriv->cmd_cnt = COMMAND_START_MAGIC;
+ hpriv->event_cnt = 0;
+ return 0;
+}
+
static int hal_ready(void)
{
unsigned int value = 0;
diff --git a/drivers/net/wireless/uccp310wlan/hal_hostport.h b/drivers/net/wireless/uccp310wlan/hal_hostport.h
index fb1a08240a1e2a..00ecd71a64a7e2 100644
--- a/drivers/net/wireless/uccp310wlan/hal_hostport.h
+++ b/drivers/net/wireless/uccp310wlan/hal_hostport.h
@@ -98,7 +98,7 @@ void _uccp310wlan_80211if_exit(void);
/******************************************************************************************************/
#define HAL_SHARED_MEM_OFFSET 0x30000
#define HAL_WLAN_BULK_RAM_START (HAL_META_BULK_RAM + (hpriv->shm_offset))
-#define HAL_WLAN_BULK_RAM_LEN 0x00012000
+#define HAL_WLAN_BULK_RAM_LEN 0x00016000
/* Command, Event and Buff mappping offsets */
#define HAL_COMMAND_OFFSET (0)
@@ -107,6 +107,7 @@ void _uccp310wlan_80211if_exit(void);
#define HAL_BULK_RAM_CMD_START ((hpriv->bulk_ram_mem_addr) + HAL_COMMAND_OFFSET)
#define HAL_BULK_RAM_EVENT_START ((hpriv->bulk_ram_mem_addr) + HAL_EVENT_OFFSET)
+
#define HAL_IRQ_LINE external_irq_map(UCC0_IRQ_NUM)
#if defined(__cplusplus)
diff --git a/drivers/net/wireless/uccp310wlan/lmac_if.c b/drivers/net/wireless/uccp310wlan/lmac_if.c
index 058d8c08682428..9f45032bd36c8b 100644
--- a/drivers/net/wireless/uccp310wlan/lmac_if.c
+++ b/drivers/net/wireless/uccp310wlan/lmac_if.c
@@ -89,6 +89,16 @@ int uccp310wlan_prog_reset(unsigned int reset_type)
sizeof(struct umac_cmd_reset));
}
+int uccp310wlan_prog_scan_ind(unsigned int scan_start)
+{
+ struct umac_cmd_scan_ind scan;
+
+ scan.hdr.id = scan_start ? CMD_SCAN_START : CMD_SCAN_STOP;
+ scan.hdr.flags = 0;
+ return uccp310wlan_send_cmd((unsigned char *) &scan,
+ sizeof(struct umac_cmd_scan_ind));
+}
+
int uccp310wlan_prog_vif_ctrl(int index,
unsigned char *mac_addr,
unsigned int vif_type,
@@ -299,6 +309,7 @@ int uccp310wlan_prog_global_cfg(unsigned int rx_msdu_lifetime,
unsigned int tx_msdu_lifetime,
unsigned int sensitivity,
unsigned int dyn_ed_enable,
+ unsigned int dyn_ed_ceiling,
unsigned char *rf_params)
{
struct umac_cmd_global_cfg gbl_config;
@@ -310,6 +321,7 @@ int uccp310wlan_prog_global_cfg(unsigned int rx_msdu_lifetime,
gbl_config.tx_msdu_lifetime = tx_msdu_lifetime;
gbl_config.ed_sensitivity = sensitivity;
gbl_config.dynamic_ed_enable = dyn_ed_enable;
+ gbl_config.dynamic_ed_ceiling = dyn_ed_ceiling;
memcpy(gbl_config.rf_params, rf_params, 8);
return uccp310wlan_send_cmd((unsigned char *) &gbl_config,
diff --git a/drivers/net/wireless/uccp310wlan/lmac_if.h b/drivers/net/wireless/uccp310wlan/lmac_if.h
index f07a2de77f88f7..4641be38a37e18 100644
--- a/drivers/net/wireless/uccp310wlan/lmac_if.h
+++ b/drivers/net/wireless/uccp310wlan/lmac_if.h
@@ -43,6 +43,7 @@ struct umac_key {
/* Commands */
extern int uccp310wlan_prog_reset(unsigned int reset_type);
+extern int uccp310wlan_prog_scan_ind(unsigned int scan_ind);
extern int uccp310wlan_prog_vif_ctrl(int index,
unsigned char *vif_addr,
unsigned int vif_type,
@@ -85,6 +86,7 @@ extern int uccp310wlan_prog_global_cfg(unsigned int rx_msdu_lifetime,
unsigned int tx_msdu_lifetime,
unsigned int sensitivity,
unsigned int dyn_ed_enabled,
+ unsigned int dyn_ed_ceiling,
unsigned char *rf_params);
extern int uccp310wlan_prog_txpower(unsigned int txpower);
extern int uccp310wlan_prog_mcast_addr_cfg(unsigned char *mcast_addr,
diff --git a/drivers/net/wireless/uccp310wlan/umac.h b/drivers/net/wireless/uccp310wlan/umac.h
index 9d8ab259725144..fb27481d468bf8 100644
--- a/drivers/net/wireless/uccp310wlan/umac.h
+++ b/drivers/net/wireless/uccp310wlan/umac.h
@@ -63,15 +63,22 @@ extern spinlock_t timing_lock;
#define SUPPORTED_FILTERS (FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC)
#define MAX_BUFF_POOL_ELEMENTS 9 /* Must be alteast 6, one for each AC + two for BCN queue + spares*/
#define MAX_TX_QUEUE_LEN 20
+#define MAX_BEACON_LOSS_COUNT 20 /*Beacon loss timeout is calculated as N frames times the advertised beacon interval*/
struct wifi_params {
int ed_sensitivity;
+ int dyn_ed_ceiling;
int num_vifs;
unsigned char auto_sensitivity;
unsigned char rf_params[8];
unsigned char show_phy_stats;
unsigned char production_test;
unsigned int dot11a_support;
+ unsigned int max_bcn_loss;
+ unsigned char ts1[8];
+ unsigned char ts2[4];
+ unsigned char bssid[ETH_ALEN];
+
};
struct wifi_stats {
diff --git a/drivers/net/wireless/uccp310wlan/umac_lmac_if.h b/drivers/net/wireless/uccp310wlan/umac_lmac_if.h
index 7470fd7309740b..0b82e0a36dd8f2 100644
--- a/drivers/net/wireless/uccp310wlan/umac_lmac_if.h
+++ b/drivers/net/wireless/uccp310wlan/umac_lmac_if.h
@@ -30,6 +30,8 @@
#ifndef _UCCP310WLAN_UMAC_LMAC_IF_H_
#define _UCCP310WLAN_UMAC_LMAC_IF_H_
+#include <linux/compiler.h>
+
#define MICHAEL_LEN 8
#define MAX_KEY_LEN 16
@@ -37,8 +39,6 @@
#define WEP104_KEYLEN 13
#define MAX_WEP_KEY_LEN 13
-#define _PACKED_ __attribute__((__packed__))
-
enum UMAC_QUEUE_NUM {
WLAN_AC_BK = 0,
WLAN_AC_BE,
@@ -51,7 +51,7 @@ enum UMAC_QUEUE_NUM {
struct umac_lmac_msg_hdr {
unsigned int id;
unsigned int flags;
-} _PACKED_;
+} __packed;
/* Commands */
enum UMAC_CMD {
@@ -73,6 +73,8 @@ enum UMAC_CMD {
CMD_MIB_STATS,
CMD_PHY_STATS,
CMD_TEST, /* Can be used by hardware abstraction layer(s) */
+ CMD_SCAN_START,
+ CMD_SCAN_STOP,
CMD_LAST
};
/* UMAC commands */
@@ -86,7 +88,11 @@ struct umac_cmd_reset {
#define LMAC_ENABLE 0
#define LMAC_DISABLE 1
unsigned int reset_type;
-} _PACKED_;
+} __packed;
+
+struct umac_cmd_scan_ind {
+ struct umac_lmac_msg_hdr hdr;
+} __packed;
struct umac_cmd_vif_ctrl {
struct umac_lmac_msg_hdr hdr;
@@ -120,7 +126,7 @@ struct umac_cmd_vif_ctrl {
* interface address to add or delete
*/
unsigned char mac_addr[ETH_ALEN];
-} _PACKED_;
+} __packed;
struct umac_cmd_vif_cfg {
struct umac_lmac_msg_hdr hdr;
@@ -200,7 +206,7 @@ struct umac_cmd_vif_cfg {
/* bssid of interface */
unsigned char bssid[ETH_ALEN];
-} _PACKED_;
+} __packed;
struct umac_cmd_global_cfg {
struct umac_lmac_msg_hdr hdr;
@@ -211,6 +217,7 @@ struct umac_cmd_global_cfg {
unsigned int tx_msdu_lifetime;
int ed_sensitivity;
+ int dynamic_ed_ceiling;
/*
* dynamic_ed_enable -
@@ -222,12 +229,12 @@ struct umac_cmd_global_cfg {
unsigned int dynamic_ed_enable;
unsigned char rf_params[8];
-} _PACKED_ ;
+} __packed;
struct umac_cmd_txpower {
struct umac_lmac_msg_hdr hdr;
unsigned int txpower; /* In dbm */
-} _PACKED_;
+} __packed;
struct umac_cmd_mcst_filter_cfg {
struct umac_lmac_msg_hdr hdr;
@@ -245,7 +252,7 @@ struct umac_cmd_mcst_filter_cfg {
*/
unsigned char addr[ETH_ALEN];
-} _PACKED_;
+} __packed;
struct umac_cmd_mcst_filter_ctrl {
struct umac_lmac_msg_hdr hdr;
@@ -258,7 +265,7 @@ struct umac_cmd_mcst_filter_ctrl {
#define MCAST_FILTER_DISABLE 0
#define MCAST_FILTER_ENABLE 1
unsigned int ctrl;
-} _PACKED_ ;
+} __packed;
struct umac_cmd_rcv_bcn_mode {
struct umac_lmac_msg_hdr hdr;
@@ -271,7 +278,7 @@ struct umac_cmd_rcv_bcn_mode {
#define RCV_NETWORK_BCNS 1
#define RCV_NO_BCNS 2
unsigned int mode;
-} _PACKED_ ;
+} __packed;
struct umac_cmd_txq_params {
struct umac_lmac_msg_hdr hdr;
@@ -309,7 +316,7 @@ struct umac_cmd_txq_params {
*/
unsigned char vif_addr[ETH_ALEN];
-} _PACKED_;
+} __packed;
struct umac_cmd_ps_cfg {
struct umac_lmac_msg_hdr hdr;
@@ -332,12 +339,12 @@ struct umac_cmd_ps_cfg {
*/
unsigned char vif_addr[ETH_ALEN];
-} _PACKED_ ;
+} __packed;
struct umac_cmd_channel {
struct umac_lmac_msg_hdr hdr;
unsigned int channel;
-} _PACKED_ ;
+} __packed;
struct umac_cmd_peer_key_cfg {
struct umac_lmac_msg_hdr hdr;
@@ -388,7 +395,7 @@ struct umac_cmd_peer_key_cfg {
unsigned char rx_mic[MICHAEL_LEN];
-} _PACKED_ ;
+} __packed;
struct umac_cmd_if_key_cfg {
struct umac_lmac_msg_hdr hdr;
@@ -427,7 +434,7 @@ struct umac_cmd_if_key_cfg {
} rsn_grp_key;
} key;
-} _PACKED_ ;
+} __packed;
struct umac_cmd_tx {
struct umac_lmac_msg_hdr hdr;
@@ -502,15 +509,15 @@ struct umac_cmd_tx {
*/
unsigned int force_encrypt;
-} _PACKED_;
+} __packed;
struct umac_cmd_mib_stats {
struct umac_lmac_msg_hdr hdr;
-} _PACKED_ ;
+} __packed;
struct umac_cmd_phy_stats {
struct umac_lmac_msg_hdr hdr;
-} _PACKED_ ;
+} __packed;
/* Events */
@@ -537,7 +544,7 @@ struct umac_event_lmac_error {
* LMAC will send the unexpected errors in this event..
*/
unsigned int error;
-} _PACKED_ ;
+} __packed;
struct umac_event_noa {
struct umac_lmac_msg_hdr hdr;
@@ -552,12 +559,12 @@ struct umac_event_noa {
#define ABSENCE_START 0 /* Indicates AP is absent */
#define ABSENCE_STOP 1 /* Indicates AP is present */
unsigned int ap_present;
-} _PACKED_ ;
+} __packed;
struct umac_event_reset_complete {
struct umac_lmac_msg_hdr hdr;
char version[6];
-} _PACKED_ ;
+} __packed;
struct umac_event_rx {
struct umac_lmac_msg_hdr hdr;
@@ -567,8 +574,12 @@ struct umac_event_rx {
unsigned char timestamp[8];
#define RX_MIC_SUCCESS 0 /* No MIC error in frame */
#define RX_MIC_FAILURE 1 /* MIC error in frame */
- unsigned int status;
-} _PACKED_ ;
+ unsigned int status;
+ unsigned char ts1[8];
+ unsigned char ts2[4];
+
+
+} __packed;
struct umac_event_tx_done {
@@ -596,7 +607,7 @@ struct umac_event_tx_done {
unsigned int retries_num;
unsigned int rate;
unsigned int queue;
-} _PACKED_ ;
+} __packed;
struct umac_event_mib_stats {
struct umac_lmac_msg_hdr hdr;
@@ -618,7 +629,7 @@ struct umac_event_mib_stats {
unsigned int tx_ack_pkt_cnt;
unsigned int frag_success_cnt;
int sensitivity;
-} _PACKED_;
+} __packed;
struct umac_event_phy_stats {
struct umac_lmac_msg_hdr hdr;
diff --git a/drivers/net/wireless/uccp310wlan/version.h b/drivers/net/wireless/uccp310wlan/version.h
index 0f9cc148acbf93..338a16356f1bc0 100644
--- a/drivers/net/wireless/uccp310wlan/version.h
+++ b/drivers/net/wireless/uccp310wlan/version.h
@@ -27,7 +27,7 @@
*END**************************************************************************/
#ifndef _UCCP310WLAN_VERSION_H
#define _UCCP310WLAN_VERSION_H
-#define UMAC_VERSION "2_3_1"
+#define UMAC_VERSION "2_3_4"
#endif /* _UCCP310WLAN_VERSION_H */
/* EOF */
diff --git a/drivers/rtc/rtc-imgpdc.c b/drivers/rtc/rtc-imgpdc.c
index b95c0acd5f00c8..730d6284d54921 100644
--- a/drivers/rtc/rtc-imgpdc.c
+++ b/drivers/rtc/rtc-imgpdc.c
@@ -220,7 +220,11 @@ start_again:
*updating = upd;
}
-/* caller must hold lock. does handle read during time update. */
+/*
+ * caller must hold lock.
+ * does handle read during time update.
+ * does not initialise tm->wday, tm->yday, or tm->tm_isdst
+ */
static void _pdc_rtc_read_time(struct pdc_rtc_priv *priv, struct rtc_time *tm)
{
int upd;
@@ -417,7 +421,7 @@ static void pdc_rtc_stop_alarm(struct pdc_rtc_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
if (priv->alarm_irq_delay) {
- pdc_rtc_read_time(priv->dev, &tm);
+ _pdc_rtc_read_time(priv, &tm);
rtc_tm_to_time(&tm, &now);
}
_pdc_rtc_stop_alarm(priv, now);
@@ -462,7 +466,7 @@ static int _pdc_rtc_set_alarm(struct pdc_rtc_priv *priv, bool temporary,
if (priv->alarm_irq_delay) {
alrm_adj = *alrm;
- pdc_rtc_read_time(priv->dev, &tm);
+ _pdc_rtc_read_time(priv, &tm);
rtc_tm_to_time(&tm, &now);
try_again_locked:
@@ -576,7 +580,7 @@ try_again_locked:
*/
spin_lock_irqsave(&priv->lock, flags);
if (!priv->alarm_pending) {
- pdc_rtc_read_time(priv->dev, &tm);
+ _pdc_rtc_read_time(priv, &tm);
rtc_tm_to_time(&tm, &now);
/* If it's too late, immediately trigger the alarm */
if (scheduled <= now) {
@@ -717,7 +721,7 @@ static irqreturn_t pdc_rtc_isr(int irq, void *dev_id)
priv->hardstop_time = 0;
if (events & RTC_AF) {
if (!now && priv->alarm_irq_delay) {
- pdc_rtc_read_time(priv->dev, &tm);
+ _pdc_rtc_read_time(priv, &tm);
rtc_tm_to_time(&tm, &now);
}
priv->alarm_pending = 1;
@@ -726,7 +730,7 @@ static irqreturn_t pdc_rtc_isr(int irq, void *dev_id)
} else {
/* make absolutely sure that the alarm is properly stopped */
if (priv->alarm_irq_delay) {
- pdc_rtc_read_time(priv->dev, &tm);
+ _pdc_rtc_read_time(priv, &tm);
rtc_tm_to_time(&tm, &now);
}
_pdc_rtc_stop_alarm(priv, now);
diff --git a/drivers/spi/spi-img.c b/drivers/spi/spi-img.c
index 79012f52afd8f3..3f18e988ac783e 100644
--- a/drivers/spi/spi-img.c
+++ b/drivers/spi/spi-img.c
@@ -46,42 +46,11 @@
* The FIFO is 16 bytes deep. If we can fit the transfer in the FIFO
* it's more efficient to do that and avoid the overhead of setting
* up DMA.
- *
- *
- * NOTE: This is set to zero to disable PIO for now. It works with mmc but not
- * the Marvell 88W8686 wifi chip for reasons that are unknown at present.
*/
-#define DMA_MIN_SIZE 0 /*16 if if worked for all devices*/
-
-#if defined(CONFIG_META_DMA_CONTROLLER)
+#define DMA_MIN_SIZE 32
-/* BURST SIZE is in bytes for MDC */
+/* BURST SIZE is in bytes */
#define BURST_SIZE 8 /*Fifo is 16 bytes deep so burst this many*/
-#define BURST_BYTES (BURST_SIZE*8)
-
-#define BURST_MASK (~(BURST_BYTES - 1))
-
-#else /* DMAC */
-
-/* We have to work around a hardware bug. When DMAing from external memory to
- * the SPI controller the DMAC creates a byte mask for the first and last
- * transfers. Unfortunately it uses the end byte mask for every burst, not just
- * the final burst. The workaround is to make sure we only DMA whole bursts
- * (so the end byte mask is all 1s) or single bursts if we're transferring
- * less than a whole burst.
- *
- * The burst size is defined in bus-width terms so 1 is a 64-bit burst.
- */
-#define BURST_SIZE 1
-#define BURST_BYTES (BURST_SIZE*8)
-#define BURST_MASK (~(BURST_BYTES - 1))
-
-/* The DMAC also cannot do DMA from unaligned buffers thus we copy the data to
- * a dma-able bounce buffer first.
- */
-#define NEED_BOUNCE_BUFFERS 1
-
-#endif
/* SPI - Device Registers */
#define SPI_DEV0_REG 0x000 /* Device 0*/
@@ -106,12 +75,20 @@
#define SPI_SDTRIG_EN 0x1
-#define SPI_GDTRIG 0x1
+#define SPI_GDTRIG 0x01
+#define SPI_GDFUL 0x08
#define SPI_ALLDONE_TRIG 0x10
#define SPI_WRITE_INT_MASK 0x1f
#define SPI_READ_INT_MASK 0x1f
+#define SPI_DI_GDFUL BIT(19) /* RX FIFO full */
+#define SPI_DI_GDHF BIT(18) /* RX FIFO half full */
+#define SPI_DI_GDEX BIT(17) /* RX FIFO not empty */
+#define SPI_DI_SDFUL BIT(3) /* TX FIFO full */
+#define SPI_DI_SDHF BIT(2) /* TX FIFO half full */
+#define SPI_DI_SDEX BIT(1) /* TX FIFO not empty */
+
#define START_STATE ((void *)0)
#define RUNNING_STATE ((void *)1)
#define DONE_STATE ((void *)2)
@@ -138,6 +115,7 @@ struct driver_data {
/* Clocks */
struct clk *clk;
+ unsigned long clk_rate;
struct img_spi_master *master_info;
@@ -160,11 +138,6 @@ struct driver_data {
/* Length of the current DMA */
size_t len;
- /* Length of any subsequent DMA needed to clean up after the bug
- * mentioned above.
- */
- size_t tail_len;
-
/* Total length of the transfer */
size_t map_len;
@@ -234,7 +207,7 @@ static u8 hz_to_clk_div(struct driver_data *drv_data, u32 speed_hz)
{
/* Register value is:
* Fout = (Fin * reg / 512) MHz */
- u8 val = min_t(unsigned int, speed_hz/(clk_get_rate(drv_data->clk)/512),
+ u8 val = min_t(unsigned int, speed_hz/((drv_data->clk_rate)/512),
0xffU);
/* Clamp value at 1 as 0 is invalid (we get no clock) */
@@ -316,8 +289,7 @@ static void start_dma(struct driver_data *drv_data, struct chip_data *chip)
transaction |= (chip_select << 16);
- if ((drv_data->tail_len) ||
- (!drv_data->cs_change && !drv_data->last_transfer))
+ if (!drv_data->cs_change && !drv_data->last_transfer)
transaction |= SPI_TRANS_REG_CONT_BIT;
/* Ensure all writes to the tx buffer have completed. */
@@ -419,8 +391,11 @@ static void start_pio(struct driver_data *drv_data, struct chip_data *chip)
{
unsigned int transaction = 0;
unsigned int chip_select = drv_data->cur_chip->chip_select_num;
- unsigned int i;
- uint32_t irq_status;
+ unsigned int tx, rx = 0;
+ const u8 *write_buf = drv_data->tx;
+ u8 *read_buf = drv_data->rx;
+ uint32_t di;
+ int can_tx, can_rx;
if (chip->cs_high)
chip_select |= 0x1;
@@ -433,12 +408,14 @@ static void start_pio(struct driver_data *drv_data, struct chip_data *chip)
if (!drv_data->cs_change && !drv_data->last_transfer)
transaction |= SPI_TRANS_REG_CONT_BIT;
- /* Fill up the FIFO */
- for (i = 0; i < drv_data->map_len; i++) {
- const u8 *write_buf = drv_data->tx;
+ /* Prime the FIFO */
+ for (tx = 0; tx < drv_data->map_len; tx++) {
u8 write_byte;
+ /* until FIFO is half full */
+ if (spi_readl(drv_data, SPI_DI_STATUS) & SPI_DI_SDHF)
+ break;
if (write_buf)
- write_byte = write_buf[i];
+ write_byte = write_buf[tx];
else
write_byte = 0x00;
spi_writeb(write_byte, drv_data, DMA_SPIO_SENDDAT);
@@ -447,17 +424,42 @@ static void start_pio(struct driver_data *drv_data, struct chip_data *chip)
/* Start the transaction */
spi_writel(transaction, drv_data, SPI_TRANS_REG);
- /* Wait for the data we're going to read to fill the FIFO */
- irq_status = 0;
- while (!((irq_status & SPI_GDTRIG) || (irq_status & SPI_ALLDONE_TRIG)))
- irq_status = spi_readl(drv_data, DMA_SPII_INT_STAT);
-
- /* Read from FIFO */
- for (i = 0; i < drv_data->map_len; i++) {
- u8 *read_buf = drv_data->rx;
- u8 read_byte = spi_readb(drv_data, DMA_SPII_GETDAT);
- if (read_buf)
- read_buf[i] = read_byte;
+ /* Maintain FIFOs until transfer is complete */
+ can_tx = (tx < drv_data->map_len);
+ can_rx = (rx < drv_data->map_len);
+ while (can_tx || can_rx || !(spi_readl(drv_data, DMA_SPII_INT_STAT) &
+ (SPI_GDTRIG | SPI_ALLDONE_TRIG))) {
+ di = spi_readl(drv_data, SPI_DI_STATUS);
+ /*
+ * Top up TX unless both RX and TX are half full,
+ * in which case RX needs draining more urgently.
+ */
+ if (can_tx && !(di & SPI_DI_SDFUL) &&
+ (!can_rx || ((di & (SPI_DI_SDHF | SPI_DI_GDHF)) !=
+ (SPI_DI_SDHF | SPI_DI_GDHF)))) {
+ /* Write to TX FIFO */
+ u8 write_byte;
+ if (write_buf)
+ write_byte = write_buf[tx];
+ else
+ write_byte = 0x00;
+ spi_writeb(write_byte, drv_data, DMA_SPIO_SENDDAT);
+ ++tx;
+ can_tx = (tx < drv_data->map_len);
+ }
+ /*
+ * Drain RX unless neither RX or TX are half full,
+ * in which case TX needs filling more urgently.
+ */
+ if (can_rx && (di & SPI_DI_GDEX) &&
+ (!can_tx || (di & (SPI_DI_SDHF | SPI_DI_GDHF)))) {
+ /* Read from RX FIFO */
+ u8 read_byte = spi_readb(drv_data, DMA_SPII_GETDAT);
+ if (read_buf)
+ read_buf[rx] = read_byte;
+ ++rx;
+ can_rx = (rx < drv_data->map_len);
+ }
}
/* Clear any interrupts we generated */
@@ -503,27 +505,6 @@ static irqreturn_t spi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
- if (drv_data->tail_len) {
- if (drv_data->rx_dma)
- drv_data->rx_dma += drv_data->len;
-
- if (drv_data->tx_dma)
- drv_data->tx_dma += drv_data->len;
-
- drv_data->len = drv_data->tail_len;
-
- drv_data->tail_len = 0;
-
- start_dma(drv_data, drv_data->cur_chip);
-
- return IRQ_HANDLED;
- }
-
-#ifdef NEED_BOUNCE_BUFFERS
- if (drv_data->rx)
- memcpy(drv_data->rx, drv_data->rx_buf, drv_data->map_len);
-#else
-
if (drv_data->tx_mapped_by_us) {
dma_unmap_single(&drv_data->pdev->dev, drv_data->tx_dma,
@@ -548,7 +529,6 @@ static irqreturn_t spi_irq(int irq, void *dev_id)
(u32)drv_data->rx_dma,
drv_data->len);*/
}
-#endif
dev_dbg(&drv_data->pdev->dev, "interrupt di status: %#x\n",
spi_readl(drv_data, SPI_DI_STATUS));
@@ -576,7 +556,6 @@ static irqreturn_t spi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-#ifndef NEED_BOUNCE_BUFFERS
/* Helper:*/
static int map_buffers(struct driver_data *drv_data,
struct spi_message *message,
@@ -661,7 +640,6 @@ static int map_buffers(struct driver_data *drv_data,
}
return 0;
}
-#endif
static void pump_transfers(unsigned long data)
{
@@ -728,28 +706,6 @@ static void pump_transfers(unsigned long data)
wmb();
}
-#ifdef NEED_BOUNCE_BUFFERS
- /* Copy data to bounce buffer due to DMAC bug */
- if (transfer->len > DMA_MIN_SIZE) {
- if (drv_data->tx)
- memcpy(drv_data->tx_buf, drv_data->tx, transfer->len);
- else
- /*send out zeros*/
- memset(drv_data->tx_buf, 0x00, transfer->len);
-
- drv_data->rx_dma = drv_data->rx_dma_start;
- drv_data->tx_dma = drv_data->tx_dma_start;
-
- }
-
- if (transfer->len > BURST_BYTES)
- drv_data->len = transfer->len & BURST_MASK;
- else
- drv_data->len = transfer->len;
-
- drv_data->tail_len = transfer->len - drv_data->len;
-
-#else /* MDC */
/* setup dma mappings for buffers, no need for
* the bounce buffer!
*/
@@ -761,9 +717,7 @@ static void pump_transfers(unsigned long data)
return;
}
drv_data->len = transfer->len;
- drv_data->tail_len = 0;
}
-#endif
drv_data->map_len = transfer->len;
@@ -1179,7 +1133,6 @@ static int __init img_spi_probe(struct platform_device *pdev)
struct driver_data *drv_data = NULL;
struct resource *irq_resource, *mem_resource;
int status = 0;
- unsigned long clk_rate;
/* Allocate master with space for drv_data */
master = spi_alloc_master(dev, sizeof(struct driver_data));
@@ -1230,13 +1183,15 @@ static int __init img_spi_probe(struct platform_device *pdev)
/* try setting the clock to the requested rate */
if (platform_info->clk_rate) {
status = clk_set_rate(drv_data->clk, platform_info->clk_rate);
- clk_rate = clk_get_rate(drv_data->clk);
- if (clk_rate != platform_info->clk_rate) {
+ drv_data->clk_rate = clk_get_rate(drv_data->clk);
+ if (drv_data->clk_rate != platform_info->clk_rate) {
dev_warn(dev,
"SPI clock requested: %lu HZ. Actual SPI clock: %lu (status=%d)\n",
- platform_info->clk_rate, clk_rate, status);
+ platform_info->clk_rate, drv_data->clk_rate, status);
}
status = 0;
+ } else {
+ drv_data->clk_rate = clk_get_rate(drv_data->clk);
}
/* try enabling the clock */
diff --git a/fs/exec.c b/fs/exec.c
index ffd7a813ad3d06..3ddb02cbad6f1a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -654,10 +654,10 @@ int setup_arg_pages(struct linux_binprm *bprm,
unsigned long rlim_stack;
#ifdef CONFIG_STACK_GROWSUP
- /* Limit stack size to 1GB */
+ /* Limit stack size */
stack_base = rlimit_max(RLIMIT_STACK);
- if (stack_base > (1 << 30))
- stack_base = 1 << 30;
+ if (stack_base > STACK_SIZE_MAX)
+ stack_base = STACK_SIZE_MAX;
/* Make sure we didn't let the argument array grow too large. */
if (vma->vm_end - vma->vm_start > stack_base)
diff --git a/include/linux/img_mdc_dma.h b/include/linux/img_mdc_dma.h
index 800429b672df46..da14c11c0068df 100644
--- a/include/linux/img_mdc_dma.h
+++ b/include/linux/img_mdc_dma.h
@@ -45,6 +45,7 @@ struct mdc_dma_cookie {
/* Platform data for SOC DMA callbacks */
struct img_mdc_soc_callbacks {
int (*allocate) (int, unsigned int); /* allocate a DMA channel */
+ int (*available) (int); /* Check if DMA channel is available */
int (*free) (int); /* free a DMA channel */
/*
* SOC DMA specific callbacks for suspend_noirq and resume_noirq.
diff --git a/init/Kconfig b/init/Kconfig
index 2d9b83104dcf71..38fca0ee68c1a3 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -441,6 +441,7 @@ config TREE_RCU
config TREE_PREEMPT_RCU
bool "Preemptible tree-based hierarchical RCU"
depends on PREEMPT
+ select IRQ_WORK
help
This option selects the RCU implementation that is
designed for very large SMP systems with hundreds or
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index ac7ef5414bdede..e6512e2ffd2002 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -290,7 +290,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
struct minstrel_rate *msr, *mr;
unsigned int ndx;
bool mrr_capable;
- bool prev_sample = mi->prev_sample;
+ bool prev_sample;
int delta;
int sampling_ratio;
@@ -314,6 +314,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
(mi->sample_count + mi->sample_deferred / 2);
/* delta < 0: no sampling required */
+ prev_sample = mi->prev_sample;
mi->prev_sample = false;
if (delta < 0 || (!mrr_capable && prev_sample))
return;
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 721587c9cd847e..73e205c892a0d0 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -38,9 +38,9 @@ enum si476x_digital_io_output_format {
SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT = 8,
};
-#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK ((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
- (0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))
-#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK (0b1111110)
+#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK ((0x7 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
+ (0x7 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))
+#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK (0x7e)
enum si476x_daudio_formats {
SI476X_DAUDIO_MODE_I2S = (0x0 << 1),
diff --git a/sound/soc/tz1090/tz1090-pcm.c b/sound/soc/tz1090/tz1090-pcm.c
index 6d860a28214fcf..ac790b4ae4cbe2 100644
--- a/sound/soc/tz1090/tz1090-pcm.c
+++ b/sound/soc/tz1090/tz1090-pcm.c
@@ -118,7 +118,7 @@ out:
/*Called on stream close */
static int comet_pcm_close(struct snd_pcm_substream *substream)
{
- snd_dmaengine_pcm_close(substream);
+ snd_dmaengine_pcm_close_release_chan(substream);
return 0;
}