From 893f0879fa36107ff5d5ab23565cd79af29a1814 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 5 Dec 2011 16:05:06 +0000 Subject: [PATCH] brcmsmac: Fix I/O functions for MIPS and for big-endian architectures svn path=/dists/sid/linux-2.6/; revision=18356 --- debian/changelog | 1 + ...1-fixed-build-issue-for-big-endian-p.patch | 67 +++++++++ ...1-simplified-register-access-macro-s.patch | 137 ++++++++++++++++++ ...1-Remove-swaps-in-R_REG-and-W_REG-ma.patch | 71 +++++++++ ...1-restrict-register-access-method-fo.patch | 62 ++++++++ ...1-restrict-MIPS-dma-bug-workaround-t.patch | 56 +++++++ debian/patches/series/base | 6 + 7 files changed, 400 insertions(+) create mode 100644 debian/patches/bugfix/all/0001-staging-brcm80211-fixed-build-issue-for-big-endian-p.patch create mode 100644 debian/patches/bugfix/all/0002-staging-brcm80211-simplified-register-access-macro-s.patch create mode 100644 debian/patches/bugfix/all/0003-staging-brcm80211-Remove-swaps-in-R_REG-and-W_REG-ma.patch create mode 100644 debian/patches/bugfix/all/0004-staging-brcm80211-restrict-register-access-method-fo.patch create mode 100644 debian/patches/bugfix/all/0005-staging-brcm80211-restrict-MIPS-dma-bug-workaround-t.patch diff --git a/debian/changelog b/debian/changelog index af6d77ae8..1377528e8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,6 +10,7 @@ linux-2.6 (3.1.4-2) UNRELEASED; urgency=low * USB: EHCI: fix HUB TT scheduling issue with iso transfer (Closes: #651015) * [x86] Enable MEMTEST (Closes: #613321, #646361) - If bad RAM is detected, WARN and recommend a more thorough test + * brcmsmac: Fix I/O functions for MIPS and for big-endian architectures -- Bastian Blank Thu, 01 Dec 2011 13:17:34 +0100 diff --git a/debian/patches/bugfix/all/0001-staging-brcm80211-fixed-build-issue-for-big-endian-p.patch b/debian/patches/bugfix/all/0001-staging-brcm80211-fixed-build-issue-for-big-endian-p.patch new file mode 100644 index 000000000..62ddefaab --- /dev/null +++ b/debian/patches/bugfix/all/0001-staging-brcm80211-fixed-build-issue-for-big-endian-p.patch @@ -0,0 +1,67 @@ +From: Roland Vossen +Date: Mon, 8 Aug 2011 15:58:22 +0200 +Subject: [PATCH 1/5] staging: brcm80211: fixed build issue for big endian + platforms + +commit 98ff86e37d1d1c3ebcaa124dfa9a900eb0e1fa77 upstream. + +Driver now builds for big endian mips platform, possibly also for other +big endian platforms. A change was made to the R_REG and W_REG macro's. +These macro's perform an xor (^) operation for endianess swap purposes. +Gcc complained because an xor operation is not allowed on a pointer type. +Fixed this by casting the pointer to an unsigned long. + +Reviewed-by: Pieter-Paul Giesberts +Signed-off-by: Arend van Spriel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/brcm80211/brcmsmac/dma.h | 1 + + drivers/staging/brcm80211/brcmsmac/types.h | 8 ++++---- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/brcm80211/brcmsmac/dma.h b/drivers/staging/brcm80211/brcmsmac/dma.h +index 3ff109f..334f2eb 100644 +--- a/drivers/staging/brcm80211/brcmsmac/dma.h ++++ b/drivers/staging/brcm80211/brcmsmac/dma.h +@@ -17,6 +17,7 @@ + #ifndef _BRCM_DMA_H_ + #define _BRCM_DMA_H_ + ++#include + #include "types.h" /* forward structure declarations */ + + /* DMA structure: +diff --git a/drivers/staging/brcm80211/brcmsmac/types.h b/drivers/staging/brcm80211/brcmsmac/types.h +index e0880a0..ab97718 100644 +--- a/drivers/staging/brcm80211/brcmsmac/types.h ++++ b/drivers/staging/brcm80211/brcmsmac/types.h +@@ -305,11 +305,11 @@ do { \ + switch (sizeof(*(r))) { \ + case sizeof(u8): \ + __osl_v = \ +- readb((u8 *)((r)^3)); \ ++ readb((u8 *)((unsigned long)(r)^3)); \ + break; \ + case sizeof(u16): \ + __osl_v = \ +- readw((u16 *)((r)^2)); \ ++ readw((u16 *)((unsigned long)(r)^2)); \ + break; \ + case sizeof(u32): \ + __osl_v = readl((u32 *)(r)); \ +@@ -322,10 +322,10 @@ do { \ + switch (sizeof(*(r))) { \ + case sizeof(u8): \ + writeb((u8)(v), \ +- (u8 *)((r)^3)); break; \ ++ (u8 *)((unsigned long)(r)^3)); break; \ + case sizeof(u16): \ + writew((u16)(v), \ +- (u16 *)((r)^2)); break; \ ++ (u16 *)((unsigned long)(r)^2)); break; \ + case sizeof(u32): \ + writel((u32)(v), \ + (u32 *)(r)); break; \ +-- +1.7.7.3 + diff --git a/debian/patches/bugfix/all/0002-staging-brcm80211-simplified-register-access-macro-s.patch b/debian/patches/bugfix/all/0002-staging-brcm80211-simplified-register-access-macro-s.patch new file mode 100644 index 000000000..e9c2b8a37 --- /dev/null +++ b/debian/patches/bugfix/all/0002-staging-brcm80211-simplified-register-access-macro-s.patch @@ -0,0 +1,137 @@ +From: Roland Vossen +Date: Mon, 8 Aug 2011 15:58:49 +0200 +Subject: [PATCH 2/5] staging: brcm80211: simplified register access macro's in + softmac + +commit b60987a15628046259be17471fd80ba92cf35ed2 upstream. + +Code cleanup. Removed MIPS specific 'sync' instruction since this is not +required for the chips that this driver supports. MIPS specific macro's +were now the same as non-MIPS register access macro's and thus have been +deleted. Also added comment that makes clearer what the benefit of these +macro's is. Unified big and little end register access macro's. + +Reported-by: Dan Carpenter +Reported-by: Julian Calaby +Reviewed-by: Pieter-Paul Giesberts +Signed-off-by: Arend van Spriel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/brcm80211/brcmsmac/types.h | 81 ++++++++++------------------ + 1 files changed, 29 insertions(+), 52 deletions(-) + +diff --git a/drivers/staging/brcm80211/brcmsmac/types.h b/drivers/staging/brcm80211/brcmsmac/types.h +index 360795f..16a1c6a 100644 +--- a/drivers/staging/brcm80211/brcmsmac/types.h ++++ b/drivers/staging/brcm80211/brcmsmac/types.h +@@ -320,60 +320,38 @@ do { \ + + #define WL_ERROR_ON() (brcm_msg_level & LOG_ERROR_VAL) + +-/* register access macros */ ++/* ++ * Register access macros. ++ * ++ * These macro's take a pointer to the address to read as one of their ++ * arguments. The macro itself deduces the size of the IO transaction (u8, u16 ++ * or u32). Advantage of this approach in combination with using a struct to ++ * define the registers in a register block, is that access size and access ++ * location are defined in only one spot. This reduces the risk of the ++ * programmer trying to use an unsupported transaction size on a register. ++ * ++ * For big endian operation, a byte swap has to be done. Eg, when attempting ++ * to read byte address 0, byte 3 should be read. This is accomplished ++ * using an xor ('^') operator. ++ */ ++ + #ifndef __BIG_ENDIAN +-#ifndef __mips__ +-#define R_REG(r) \ +- ({\ +- sizeof(*(r)) == sizeof(u8) ? \ +- readb((u8 *)(r)) : \ +- sizeof(*(r)) == sizeof(u16) ? readw((u16 *)(r)) : \ +- readl((u32 *)(r)); \ +- }) +-#else /* __mips__ */ +-#define R_REG(r) \ +- ({ \ +- __typeof(*(r)) __osl_v; \ +- __asm__ __volatile__("sync"); \ +- switch (sizeof(*(r))) { \ +- case sizeof(u8): \ +- __osl_v = readb((u8 *)(r)); \ +- break; \ +- case sizeof(u16): \ +- __osl_v = readw((u16 *)(r)); \ +- break; \ +- case sizeof(u32): \ +- __osl_v = \ +- readl((u32 *)(r)); \ +- break; \ +- } \ +- __asm__ __volatile__("sync"); \ +- __osl_v; \ +- }) +-#endif /* __mips__ */ ++#define SWP2(r) (r) ++#define SWP3(r) (r) ++#else ++#define SWP2(r) ((unsigned long)(r)^2) ++#define SWP3(r) ((unsigned long)(r)^3) ++#endif /* __BIG_ENDIAN */ + +-#define W_REG(r, v) do { \ +- switch (sizeof(*(r))) { \ +- case sizeof(u8): \ +- writeb((u8)(v), (u8 *)(r)); break; \ +- case sizeof(u16): \ +- writew((u16)(v), (u16 *)(r)); break; \ +- case sizeof(u32): \ +- writel((u32)(v), (u32 *)(r)); break; \ +- }; \ +- } while (0) +-#else /* __BIG_ENDIAN */ + #define R_REG(r) \ + ({ \ + __typeof(*(r)) __osl_v; \ + switch (sizeof(*(r))) { \ + case sizeof(u8): \ +- __osl_v = \ +- readb((u8 *)((unsigned long)(r)^3)); \ ++ __osl_v = readb((u8 *)(SWP3(r))); \ + break; \ + case sizeof(u16): \ +- __osl_v = \ +- readw((u16 *)((unsigned long)(r)^2)); \ ++ __osl_v = readw((u16 *)(SWP2(r))); \ + break; \ + case sizeof(u32): \ + __osl_v = readl((u32 *)(r)); \ +@@ -385,17 +363,16 @@ do { \ + #define W_REG(r, v) do { \ + switch (sizeof(*(r))) { \ + case sizeof(u8): \ +- writeb((u8)(v), \ +- (u8 *)((unsigned long)(r)^3)); break; \ ++ writeb((u8)(v), (u8 *)(SWP3(r))); \ ++ break; \ + case sizeof(u16): \ +- writew((u16)(v), \ +- (u16 *)((unsigned long)(r)^2)); break; \ ++ writew((u16)(v), (u16 *)(SWP2(r))); \ ++ break; \ + case sizeof(u32): \ +- writel((u32)(v), \ +- (u32 *)(r)); break; \ ++ writel((u32)(v), (u32 *)(r)); \ ++ break; \ + } \ + } while (0) +-#endif /* __BIG_ENDIAN */ + + #ifdef __mips__ + /* +-- +1.7.7.3 + diff --git a/debian/patches/bugfix/all/0003-staging-brcm80211-Remove-swaps-in-R_REG-and-W_REG-ma.patch b/debian/patches/bugfix/all/0003-staging-brcm80211-Remove-swaps-in-R_REG-and-W_REG-ma.patch new file mode 100644 index 000000000..8940e6e10 --- /dev/null +++ b/debian/patches/bugfix/all/0003-staging-brcm80211-Remove-swaps-in-R_REG-and-W_REG-ma.patch @@ -0,0 +1,71 @@ +From: Henry Ptasinski +Date: Mon, 15 Aug 2011 15:34:22 +0200 +Subject: [PATCH 3/5] staging: brcm80211: Remove swaps in R_REG and W_REG macros + +commit ba1fff7f705ed15e9d5a5922614aa4a259e9f8bc upstream. + +Swapping the addresses is unnecessary, since the swaps are handled by the +underlying platform code (i.e. readb() etc. handle any necessary swapping). + +Tested on Mac G5 PPC and BCM63281. + +Signed-off-by: Henry Ptasinski +Reviewed-by: Arend van Spriel +Tested-by: Jonas Gorski +Signed-off-by: Arend van Spriel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/brcm80211/brcmsmac/types.h | 19 ++++--------------- + 1 files changed, 4 insertions(+), 15 deletions(-) + +diff --git a/drivers/staging/brcm80211/brcmsmac/types.h b/drivers/staging/brcm80211/brcmsmac/types.h +index c0d41cc..ad874a7 100644 +--- a/drivers/staging/brcm80211/brcmsmac/types.h ++++ b/drivers/staging/brcm80211/brcmsmac/types.h +@@ -329,28 +329,17 @@ do { \ + * location are defined in only one spot. This reduces the risk of the + * programmer trying to use an unsupported transaction size on a register. + * +- * For big endian operation, a byte swap has to be done. Eg, when attempting +- * to read byte address 0, byte 3 should be read. This is accomplished +- * using an xor ('^') operator. + */ + +-#ifndef __BIG_ENDIAN +-#define SWP2(r) (r) +-#define SWP3(r) (r) +-#else +-#define SWP2(r) ((unsigned long)(r)^2) +-#define SWP3(r) ((unsigned long)(r)^3) +-#endif /* __BIG_ENDIAN */ +- + #define R_REG(r) \ + ({ \ + __typeof(*(r)) __osl_v; \ + switch (sizeof(*(r))) { \ + case sizeof(u8): \ +- __osl_v = readb((u8 *)(SWP3(r))); \ ++ __osl_v = readb((u8 *)(r)); \ + break; \ + case sizeof(u16): \ +- __osl_v = readw((u16 *)(SWP2(r))); \ ++ __osl_v = readw((u16 *)(r)); \ + break; \ + case sizeof(u32): \ + __osl_v = readl((u32 *)(r)); \ +@@ -362,10 +351,10 @@ do { \ + #define W_REG(r, v) do { \ + switch (sizeof(*(r))) { \ + case sizeof(u8): \ +- writeb((u8)(v), (u8 *)(SWP3(r))); \ ++ writeb((u8)(v), (u8 *)(r)); \ + break; \ + case sizeof(u16): \ +- writew((u16)(v), (u16 *)(SWP2(r))); \ ++ writew((u16)(v), (u16 *)(r)); \ + break; \ + case sizeof(u32): \ + writel((u32)(v), (u32 *)(r)); \ +-- +1.7.7.3 + diff --git a/debian/patches/bugfix/all/0004-staging-brcm80211-restrict-register-access-method-fo.patch b/debian/patches/bugfix/all/0004-staging-brcm80211-restrict-register-access-method-fo.patch new file mode 100644 index 000000000..e0aa98fa5 --- /dev/null +++ b/debian/patches/bugfix/all/0004-staging-brcm80211-restrict-register-access-method-fo.patch @@ -0,0 +1,62 @@ +From: Arend van Spriel +Date: Mon, 15 Aug 2011 15:34:25 +0200 +Subject: [PATCH 4/5] staging: brcm80211: restrict register access method for + bcm47xx + +commit 3bd8ef6799524fd48044a83aab38da57d9a98dbc upstream. + +The driver contained conditional code for resolving issue with +dma transaction reordering. This code was conditionalized using +__mips__ macro, but it actually is specific to bcm47xx chips. +This patch replaces it for the more speficic CONFIG_BCM47XX macro. + +Tested on BCM63281. + +Reviewed-by: Henry Ptasinski +Reviewed-by: Roland Vossen +Tested-by: Jonas Gorski +Signed-off-by: Arend van Spriel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c | 2 +- + drivers/staging/brcm80211/brcmsmac/types.h | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c +index c00178d..448afae 100644 +--- a/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c ++++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_cmn.c +@@ -380,7 +380,7 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) + + regs = pi->regs; + +-#ifdef __mips__ ++#ifdef CONFIG_BCM47XX + W_REG_FLUSH(®s->phyregaddr, addr); + W_REG(®s->phyregdata, val); + if (addr == 0x72) +diff --git a/drivers/staging/brcm80211/brcmsmac/types.h b/drivers/staging/brcm80211/brcmsmac/types.h +index ad874a7..d44db56 100644 +--- a/drivers/staging/brcm80211/brcmsmac/types.h ++++ b/drivers/staging/brcm80211/brcmsmac/types.h +@@ -362,7 +362,7 @@ do { \ + } \ + } while (0) + +-#ifdef __mips__ ++#ifdef CONFIG_BCM47XX + /* + * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder + * transactions. As a fix, a read after write is performed on certain places +@@ -371,7 +371,7 @@ do { \ + #define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); }) + #else + #define W_REG_FLUSH(r, v) W_REG((r), (v)) +-#endif /* __mips__ */ ++#endif /* CONFIG_BCM47XX */ + + #define AND_REG(r, v) W_REG((r), R_REG(r) & (v)) + #define OR_REG(r, v) W_REG((r), R_REG(r) | (v)) +-- +1.7.7.3 + diff --git a/debian/patches/bugfix/all/0005-staging-brcm80211-restrict-MIPS-dma-bug-workaround-t.patch b/debian/patches/bugfix/all/0005-staging-brcm80211-restrict-MIPS-dma-bug-workaround-t.patch new file mode 100644 index 000000000..a73e3bada --- /dev/null +++ b/debian/patches/bugfix/all/0005-staging-brcm80211-restrict-MIPS-dma-bug-workaround-t.patch @@ -0,0 +1,56 @@ +From: Arend van Spriel +Date: Mon, 15 Aug 2011 15:34:26 +0200 +Subject: [PATCH 5/5] staging: brcm80211: restrict MIPS dma bug workaround to + BCM47XX + +commit adf27befdc79a9403bfba82ee84f02a47bcd546c upstream. + +The inline function dma_spin_for_len() was defined for MIPS platforms +but the problem only occurs with dma of the PCI core in bcm47xx chips. +This patch restricts the function further to BCM47XX platforms only. + +Tested on BCM63281. + +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Henry Ptasinski +Reviewed-by: Roland Vossen +Tested-by: Jonas Gorski +Signed-off-by: Arend van Spriel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/brcm80211/brcmsmac/dma.h | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/brcm80211/brcmsmac/dma.h b/drivers/staging/brcm80211/brcmsmac/dma.h +index 134402c..2ce59638 100644 +--- a/drivers/staging/brcm80211/brcmsmac/dma.h ++++ b/drivers/staging/brcm80211/brcmsmac/dma.h +@@ -100,21 +100,21 @@ void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc) + (void *pkt, void *arg_a), void *arg_a); + + /* +- * DMA(Bug) on some chips seems to declare that the packet is ready, but the +- * packet length is not updated yet (by DMA) on the expected time. ++ * DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but ++ * the packet length is not updated yet (by DMA) on the expected time. + * Workaround is to hold processor till DMA updates the length, and stay off + * the bus to allow DMA update the length in buffer + */ + static inline void dma_spin_for_len(uint len, struct sk_buff *head) + { +-#if defined(__mips__) ++#if defined(CONFIG_BCM47XX) + if (!len) { + while (!(len = *(u16 *) KSEG1ADDR(head->data))) + udelay(1); + + *(u16 *) (head->data) = cpu_to_le16((u16) len); + } +-#endif /* defined(__mips__) */ ++#endif /* defined(CONFIG_BCM47XX) */ + } + + #endif /* _BRCM_DMA_H_ */ +-- +1.7.7.3 + diff --git a/debian/patches/series/base b/debian/patches/series/base index cc7393f56..241483bac 100644 --- a/debian/patches/series/base +++ b/debian/patches/series/base @@ -83,3 +83,9 @@ + bugfix/all/USB-EHCI-fix-HUB-TT-scheduling-issue-with-iso-transf.patch + bugfix/all/EHCI-Fix-a-regression-in-the-ISO-scheduler.patch + debian/x86-memtest-WARN-if-bad-RAM-found.patch + ++ bugfix/all/0001-staging-brcm80211-fixed-build-issue-for-big-endian-p.patch ++ bugfix/all/0002-staging-brcm80211-simplified-register-access-macro-s.patch ++ bugfix/all/0003-staging-brcm80211-Remove-swaps-in-R_REG-and-W_REG-ma.patch ++ bugfix/all/0004-staging-brcm80211-restrict-register-access-method-fo.patch ++ bugfix/all/0005-staging-brcm80211-restrict-MIPS-dma-bug-workaround-t.patch