From fb55f4d1fa252ba1e479284b79da1049d658c371 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 10 May 2008 13:42:06 +0200 Subject: rt2x00: Fix TX status reporting The tx_status enumeration was broken since the introduction of rt61pci. That driver uses different values to report the status of the tx action. This would lead to frames that were reported as success but actually failed to be send out, or frames that were neither successfull or failure which were reported as failure. Fix this by change the TX status reporting and more explicitely check for failure or success. Note that a third possibility is added "unknown". Not all hardware (USB) can report the actual TX status, for rt61pci some frames will receive this status because the TXdone handler is never called for those frames. This unknown will now be handled as neither success or failure, so we no longer increment the failure counter while this conclusion could not be determined from the real status of the frame. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00reg.h | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00reg.h') diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 0325bed2fbf..3f255df58b7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -26,17 +26,6 @@ #ifndef RT2X00REG_H #define RT2X00REG_H -/* - * TX result flags. - */ -enum tx_status { - TX_SUCCESS = 0, - TX_SUCCESS_RETRY = 1, - TX_FAIL_RETRY = 2, - TX_FAIL_INVALID = 3, - TX_FAIL_OTHER = 4, -}; - /* * Antenna values */ -- cgit v1.2.3 From 9dad92b9ba49eaab72513d821ae43298bcf93b90 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 3 Jun 2008 22:45:35 +0200 Subject: rt2x00: Calculate register offset during compile time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By using __ffs() the register offsets were always calculated at run-time which all FIELD32/FIELD16 definitions were builtin constants. This means we can heavily optimize the register handling by allowing GCC to do all the work during compilation. Add some compile_ffs() macros to perform the calculation at compile time. After this each rt2x00 module size is reduced by ~2500 bytes. And the stack size of several functions is reduced as well which further limits the number of rt2x00 results in 'make checkstack'. v2: Merge GertJan's bugfix of patch [1/11] directly into this patch       instead of providing it as seperate patch. v3: Add extra parentheses when bitshifting __x Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00reg.h | 59 +++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00reg.h') diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 3f255df58b7..b0d27edcc33 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -130,40 +130,71 @@ struct rt2x00_field32 { /* * Power of two check, this will check - * if the mask that has been given contains - * and contiguous set of bits. + * if the mask that has been given contains and contiguous set of bits. + * Note that we cannot use the is_power_of_2() function since this + * check must be done at compile-time. */ #define is_power_of_two(x) ( !((x) & ((x)-1)) ) #define low_bit_mask(x) ( ((x)-1) & ~(x) ) #define is_valid_mask(x) is_power_of_two(1 + (x) + low_bit_mask(x)) +/* + * Macro's to find first set bit in a variable. + * These macro's behaves the same as the __ffs() function with + * the most important difference that this is done during + * compile-time rather then run-time. + */ +#define compile_ffs2(__x) \ + ( ((__x) & 0x1) ? 0 : 1 ) + +#define compile_ffs4(__x) \ + ( ((__x) & 0x3) ? \ + compile_ffs2(__x) : (compile_ffs2((__x) >> 2) + 2) ) + +#define compile_ffs8(__x) \ + ( ((__x) & 0xf) ? \ + compile_ffs4(__x) : (compile_ffs4((__x) >> 4) + 4) ) + +#define compile_ffs16(__x) \ + ( ((__x) & 0xff) ? \ + compile_ffs8(__x) : (compile_ffs8((__x) >> 8) + 8) ) + +#define compile_ffs32(__x) \ + ( ((__x) & 0xffff) ? \ + compile_ffs16(__x) : (compile_ffs16((__x) >> 16) + 16) ) + +/* + * This macro will check the requirements for the FIELD{8,16,32} macros + * The mask should be a constant non-zero contiguous set of bits which + * does not exceed the given typelimit. + */ +#define FIELD_CHECK(__mask, __type) \ + BUILD_BUG_ON(!__builtin_constant_p(__mask) || \ + !(__mask) || \ + !is_valid_mask(__mask) || \ + (__mask) != (__type)(__mask)) \ + #define FIELD8(__mask) \ ({ \ - BUILD_BUG_ON(!(__mask) || \ - !is_valid_mask(__mask) || \ - (__mask) != (u8)(__mask)); \ + FIELD_CHECK(__mask, u8); \ (struct rt2x00_field8) { \ - __ffs(__mask), (__mask) \ + compile_ffs8(__mask), (__mask) \ }; \ }) #define FIELD16(__mask) \ ({ \ - BUILD_BUG_ON(!(__mask) || \ - !is_valid_mask(__mask) || \ - (__mask) != (u16)(__mask));\ + FIELD_CHECK(__mask, u16); \ (struct rt2x00_field16) { \ - __ffs(__mask), (__mask) \ + compile_ffs16(__mask), (__mask) \ }; \ }) #define FIELD32(__mask) \ ({ \ - BUILD_BUG_ON(!(__mask) || \ - !is_valid_mask(__mask) || \ - (__mask) != (u32)(__mask));\ + FIELD_CHECK(__mask, u32); \ (struct rt2x00_field32) { \ - __ffs(__mask), (__mask) \ + compile_ffs32(__mask), (__mask) \ }; \ }) -- cgit v1.2.3 From c483bb4cbdeb24d9d3bc0dc4248fdcb1f4c55244 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 3 Jun 2008 20:29:43 +0200 Subject: rt2x00: Make rt2x00_set/get_field macros The rt2x00_set_field functions are very often used, but GCC is better able to optimize them when they are macros instead of static inline functions. After changing it to macro's each rt2x00 driver will loose about ~3500 bytes in size. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00reg.h | 71 ++++++++++++++------------------- 1 file changed, 30 insertions(+), 41 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00reg.h') diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index b0d27edcc33..c3f1202404d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -198,46 +198,35 @@ struct rt2x00_field32 { }; \ }) -static inline void rt2x00_set_field32(u32 *reg, - const struct rt2x00_field32 field, - const u32 value) -{ - *reg &= ~(field.bit_mask); - *reg |= (value << field.bit_offset) & field.bit_mask; -} - -static inline u32 rt2x00_get_field32(const u32 reg, - const struct rt2x00_field32 field) -{ - return (reg & field.bit_mask) >> field.bit_offset; -} - -static inline void rt2x00_set_field16(u16 *reg, - const struct rt2x00_field16 field, - const u16 value) -{ - *reg &= ~(field.bit_mask); - *reg |= (value << field.bit_offset) & field.bit_mask; -} - -static inline u16 rt2x00_get_field16(const u16 reg, - const struct rt2x00_field16 field) -{ - return (reg & field.bit_mask) >> field.bit_offset; -} - -static inline void rt2x00_set_field8(u8 *reg, - const struct rt2x00_field8 field, - const u8 value) -{ - *reg &= ~(field.bit_mask); - *reg |= (value << field.bit_offset) & field.bit_mask; -} - -static inline u8 rt2x00_get_field8(const u8 reg, - const struct rt2x00_field8 field) -{ - return (reg & field.bit_mask) >> field.bit_offset; -} +#define SET_FIELD(__reg, __type, __field, __value)\ +({ \ + typecheck(__type, __field); \ + *(__reg) &= ~((__field).bit_mask); \ + *(__reg) |= ((__value) << \ + ((__field).bit_offset)) & \ + ((__field).bit_mask); \ +}) + +#define GET_FIELD(__reg, __type, __field) \ +({ \ + typecheck(__type, __field); \ + ((__reg) & ((__field).bit_mask)) >> \ + ((__field).bit_offset); \ +}) + +#define rt2x00_set_field32(__reg, __field, __value) \ + SET_FIELD(__reg, struct rt2x00_field32, __field, __value) +#define rt2x00_get_field32(__reg, __field) \ + GET_FIELD(__reg, struct rt2x00_field32, __field) + +#define rt2x00_set_field16(__reg, __field, __value) \ + SET_FIELD(__reg, struct rt2x00_field16, __field, __value) +#define rt2x00_get_field16(__reg, __field) \ + GET_FIELD(__reg, struct rt2x00_field16, __field) + +#define rt2x00_set_field8(__reg, __field, __value) \ + SET_FIELD(__reg, struct rt2x00_field8, __field, __value) +#define rt2x00_get_field8(__reg, __field) \ + GET_FIELD(__reg, struct rt2x00_field8, __field) #endif /* RT2X00REG_H */ -- cgit v1.2.3 From 4ae1168199021dacedacd32274eef402c5059841 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 6 Jun 2008 22:58:29 +0200 Subject: rt2x00: Use __builtin_choose_expr() instead of ?: To really force the FIELD macros to determine the first bit of the register field we should use the __builtin_choose_expr() function. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00reg.h | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00reg.h') diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index c3f1202404d..7e88ce5651b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -145,23 +145,27 @@ struct rt2x00_field32 { * compile-time rather then run-time. */ #define compile_ffs2(__x) \ - ( ((__x) & 0x1) ? 0 : 1 ) + __builtin_choose_expr(((__x) & 0x1), 0, 1) #define compile_ffs4(__x) \ - ( ((__x) & 0x3) ? \ - compile_ffs2(__x) : (compile_ffs2((__x) >> 2) + 2) ) + __builtin_choose_expr(((__x) & 0x3), \ + (compile_ffs2((__x))), \ + (compile_ffs2((__x) >> 2) + 2)) #define compile_ffs8(__x) \ - ( ((__x) & 0xf) ? \ - compile_ffs4(__x) : (compile_ffs4((__x) >> 4) + 4) ) + __builtin_choose_expr(((__x) & 0xf), \ + (compile_ffs4((__x))), \ + (compile_ffs4((__x) >> 4) + 4)) #define compile_ffs16(__x) \ - ( ((__x) & 0xff) ? \ - compile_ffs8(__x) : (compile_ffs8((__x) >> 8) + 8) ) + __builtin_choose_expr(((__x) & 0xff), \ + (compile_ffs8((__x))), \ + (compile_ffs8((__x) >> 8) + 8)) #define compile_ffs32(__x) \ - ( ((__x) & 0xffff) ? \ - compile_ffs16(__x) : (compile_ffs16((__x) >> 16) + 16) ) + __builtin_choose_expr(((__x) & 0xffff), \ + (compile_ffs16((__x))), \ + (compile_ffs16((__x) >> 16) + 16)) /* * This macro will check the requirements for the FIELD{8,16,32} macros -- cgit v1.2.3