linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] ath5k descriptor cleanup + ibss beacon fix
@ 2008-03-05  9:34 Bruno Randolf
  2008-03-05  9:35 ` [PATCH 1/4] ath5k: struct ath5k_desc cleanups Bruno Randolf
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Bruno Randolf @ 2008-03-05  9:34 UTC (permalink / raw)
  To: ath5k-devel; +Cc: mcgrof, jirislaby, mickflemm, linux-wireless, linville

hello!

here are some patches, some i have had lying around for a while.

especially the first two touch the very core of the driver, so please review
them. i have been careful and i don't think it creates a problem, but i have
tested it only with ar5212 because i don't have a 5210 to test with
unfortunately.

the other ones are just about rx timestamps and a workaround for some hardware
bugs in ibss mode.

Bruno Randolf (4):
      ath5k: work around wrong beacon rx timestamp in IBSS mode
      ath5k: add notes about rx timestamp
      ath5k: move rx and tx status structures out of hardware descriptor
      ath5k: struct ath5k_desc cleanups


 drivers/net/wireless/ath5k/ath5k.h |   35 ++--
 drivers/net/wireless/ath5k/base.c  |  144 ++++++++++------
 drivers/net/wireless/ath5k/debug.c |   31 ++-
 drivers/net/wireless/ath5k/debug.h |    6 -
 drivers/net/wireless/ath5k/hw.c    |  331 ++++++++++++++++++------------------
 drivers/net/wireless/ath5k/hw.h    |  150 ++++++++++------
 6 files changed, 379 insertions(+), 318 deletions(-)

-- 
Signature

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/4] ath5k: struct ath5k_desc cleanups
  2008-03-05  9:34 [PATCH 0/4] ath5k descriptor cleanup + ibss beacon fix Bruno Randolf
@ 2008-03-05  9:35 ` Bruno Randolf
  2008-03-05  9:57   ` [PATCH] " Bruno Randolf
  2008-03-05  9:35 ` [PATCH 2/4] ath5k: move rx and tx status structures out of hardware descriptor Bruno Randolf
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Bruno Randolf @ 2008-03-05  9:35 UTC (permalink / raw)
  To: ath5k-devel; +Cc: mcgrof, jirislaby, mickflemm, linux-wireless, linville

From: Bruno Randolf <br1@einfach.org>

* make struct ath5k_desc clearer by directly including unions of structures,
  which correspond to the hardware descriptors of different HW versions (5210
  and 5212). before they were casted at onto ath5k_desc at different points
  (e.g.  ds_hw[2]).

* rename some structures and variable names to make their use clearer, e.g.
  struct ath5k_hw_4w_tx_desc to ath5k_hw_4w_tx_ctl.

* substitute "old" with "5210" and "new" with "5212" (eg. rename
  ath5k_hw_proc_new_rx_status() to ath5k_hw_proc_5212_rx_status()) because old
  and new are relative and we might have a newer structure at some point.

* unify structs ath5k_hw_old_rx_status and ath5k_hw_new_rx_status into one
  ath5k_hw_rx_status, because they only differ in the flags and masks.

drivers/net/wireless/ath5k/ath5k.h:     Changes-licensed-under: ISC
drivers/net/wireless/ath5k/debug.c:     Changes-licensed-under: GPL
drivers/net/wireless/ath5k/hw.c:        Changes-licensed-under: ISC
drivers/net/wireless/ath5k/hw.h:        Changes-licensed-under: ISC

Signed-off-by: Bruno Randolf <bruno@thinktube.com>
---

 drivers/net/wireless/ath5k/ath5k.h |   23 ++--
 drivers/net/wireless/ath5k/debug.c |   12 +-
 drivers/net/wireless/ath5k/hw.c    |  212 +++++++++++++++++-------------------
 drivers/net/wireless/ath5k/hw.h    |  150 +++++++++++++++----------
 4 files changed, 210 insertions(+), 187 deletions(-)


diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index 18223d9..e2f889b 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -268,12 +268,13 @@ enum ath5k_driver_mode {
 #define SHPREAMBLE_FLAG(_ix) \
 	(HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
 
+
 /****************\
   TX DEFINITIONS
 \****************/
 
 /*
- * Tx Descriptor
+ * TX Status
  */
 struct ath5k_tx_status {
 	u16	ts_seqnum;
@@ -421,7 +422,7 @@ enum ath5k_dmasize {
 \****************/
 
 /*
- * Rx Descriptor
+ * RX Status
  */
 struct ath5k_rx_status {
 	u16	rs_datalen;
@@ -452,8 +453,6 @@ struct ath5k_mib_stats {
 };
 
 
-
-
 /**************************\
  BEACON TIMERS DEFINITIONS
 \**************************/
@@ -495,20 +494,22 @@ struct ath5k_beacon_state {
 #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
 
 
-
 /********************\
   COMMON DEFINITIONS
 \********************/
 
 /*
- * Atheros descriptor
+ * Atheros hardware descriptor
  */
 struct ath5k_desc {
-	u32	ds_link;
-	u32	ds_data;
-	u32	ds_ctl0;
-	u32	ds_ctl1;
-	u32	ds_hw[4];
+	u32	ds_link;	/* physical address of the next descriptor */
+	u32	ds_data;	/* physical address of data buffer (skb) */
+
+	union {
+		struct ath5k_hw_5210_tx_desc	ds_tx5210;
+		struct ath5k_hw_5212_tx_desc	ds_tx5212;
+		struct ath5k_hw_all_rx_desc	ds_rx;
+	} ud;
 
 	union {
 		struct ath5k_rx_status rx;
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
index 05bf4fb..9301494 100644
--- a/drivers/net/wireless/ath5k/debug.c
+++ b/drivers/net/wireless/ath5k/debug.c
@@ -500,11 +500,13 @@ static inline void
 ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
 {
 	struct ath5k_desc *ds = bf->desc;
+	struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
 
 	printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
 		ds, (unsigned long long)bf->daddr,
-		ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
-		ds->ds_hw[0], ds->ds_hw[1],
+		ds->ds_link, ds->ds_data,
+		rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
+		rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
 		!done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
 }
 
@@ -554,14 +556,16 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc,
 			struct ath5k_buf *bf, int done)
 {
 	struct ath5k_desc *ds = bf->desc;
+	struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
 
 	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
 		return;
 
 	printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
 		"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
-		ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
-		ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
+		ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
+		td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
+		td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
 		!done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
 }
 
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
index eec2b80..bcd6041 100644
--- a/drivers/net/wireless/ath5k/hw.c
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -54,8 +54,8 @@ static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
 	unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
 	unsigned int, unsigned int);
 static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *);
-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *);
 static int ath5k_hw_get_capabilities(struct ath5k_hw *);
 
 static int ath5k_eeprom_init(struct ath5k_hw *);
@@ -174,9 +174,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
 	}
 
 	if (ah->ah_version == AR5K_AR5212)
-		ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status;
+		ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
 	else if (ah->ah_version <= AR5K_AR5211)
-		ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status;
+		ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
 
 	/* Bring device out of sleep and reset it's units */
 	ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
@@ -3456,10 +3456,10 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	unsigned int rtscts_rate, unsigned int rtscts_duration)
 {
 	u32 frame_type;
-	struct ath5k_hw_2w_tx_desc *tx_desc;
+	struct ath5k_hw_2w_tx_ctl *tx_ctl;
 	unsigned int frame_len;
 
-	tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
+	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
 
 	/*
 	 * Validate input
@@ -3478,12 +3478,8 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 		return -EINVAL;
 	}
 
-	/* Clear status descriptor */
-	memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status));
-
-	/* Initialize control descriptor */
-	tx_desc->tx_control_0 = 0;
-	tx_desc->tx_control_1 = 0;
+	/* Clear descriptor */
+	memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
 
 	/* Setup control descriptor */
 
@@ -3495,7 +3491,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
 		return -EINVAL;
 
-	tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+	tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
 
 	/* Verify and set buffer length */
 
@@ -3506,7 +3502,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
 		return -EINVAL;
 
-	tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+	tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
 
 	/*
 	 * Verify and set header length
@@ -3515,7 +3511,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	if (ah->ah_version == AR5K_AR5210) {
 		if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
 			return -EINVAL;
-		tx_desc->tx_control_0 |=
+		tx_ctl->tx_control_0 |=
 			AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
 	}
 
@@ -3531,19 +3527,19 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 			frame_type = type /*<< 2 ?*/;
 		}
 
-		tx_desc->tx_control_0 |=
+		tx_ctl->tx_control_0 |=
 			AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
 			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
 	} else {
-		tx_desc->tx_control_0 |=
+		tx_ctl->tx_control_0 |=
 			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
 			AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
-		tx_desc->tx_control_1 |=
+		tx_ctl->tx_control_1 |=
 			AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
 	}
 #define _TX_FLAGS(_c, _flag)						\
 	if (flags & AR5K_TXDESC_##_flag)				\
-		tx_desc->tx_control_##_c |=				\
+		tx_ctl->tx_control_##_c |=				\
 			AR5K_2W_TX_DESC_CTL##_c##_##_flag
 
 	_TX_FLAGS(0, CLRDMASK);
@@ -3558,9 +3554,9 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	 * WEP crap
 	 */
 	if (key_index != AR5K_TXKEYIX_INVALID) {
-		tx_desc->tx_control_0 |=
+		tx_ctl->tx_control_0 |=
 			AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-		tx_desc->tx_control_1 |=
+		tx_ctl->tx_control_1 |=
 			AR5K_REG_SM(key_index,
 			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
 	}
@@ -3570,7 +3566,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	 */
 	if ((ah->ah_version == AR5K_AR5210) &&
 			(flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
-		tx_desc->tx_control_1 |= rtscts_duration &
+		tx_ctl->tx_control_1 |= rtscts_duration &
 				AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
 
 	return 0;
@@ -3586,13 +3582,11 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
 	unsigned int rtscts_duration)
 {
-	struct ath5k_hw_4w_tx_desc *tx_desc;
-	struct ath5k_hw_tx_status *tx_status;
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
 	unsigned int frame_len;
 
 	ATH5K_TRACE(ah->ah_sc);
-	tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
-	tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
+	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
 
 	/*
 	 * Validate input
@@ -3611,14 +3605,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 		return -EINVAL;
 	}
 
-	/* Clear status descriptor */
-	memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status));
-
-	/* Initialize control descriptor */
-	tx_desc->tx_control_0 = 0;
-	tx_desc->tx_control_1 = 0;
-	tx_desc->tx_control_2 = 0;
-	tx_desc->tx_control_3 = 0;
+	/* Clear descriptor */
+	memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
 
 	/* Setup control descriptor */
 
@@ -3630,7 +3618,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
 		return -EINVAL;
 
-	tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+	tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
 
 	/* Verify and set buffer length */
 
@@ -3641,20 +3629,20 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
 		return -EINVAL;
 
-	tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+	tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
 
-	tx_desc->tx_control_0 |=
+	tx_ctl->tx_control_0 |=
 		AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
 		AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
-	tx_desc->tx_control_1 |= AR5K_REG_SM(type,
+	tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
 					AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
-	tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+	tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
 					AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
-	tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+	tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
 
 #define _TX_FLAGS(_c, _flag)			\
 	if (flags & AR5K_TXDESC_##_flag)	\
-		tx_desc->tx_control_##_c |=	\
+		tx_ctl->tx_control_##_c |=	\
 			AR5K_4W_TX_DESC_CTL##_c##_##_flag
 
 	_TX_FLAGS(0, CLRDMASK);
@@ -3670,8 +3658,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	 * WEP crap
 	 */
 	if (key_index != AR5K_TXKEYIX_INVALID) {
-		tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-		tx_desc->tx_control_1 |= AR5K_REG_SM(key_index,
+		tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+		tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
 				AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
 	}
 
@@ -3682,9 +3670,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 		if ((flags & AR5K_TXDESC_RTSENA) &&
 				(flags & AR5K_TXDESC_CTSENA))
 			return -EINVAL;
-		tx_desc->tx_control_2 |= rtscts_duration &
+		tx_ctl->tx_control_2 |= rtscts_duration &
 				AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
-		tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+		tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
 				AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
 	}
 
@@ -3699,7 +3687,7 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
 	unsigned int tx_rate3, u_int tx_tries3)
 {
-	struct ath5k_hw_4w_tx_desc *tx_desc;
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
 
 	/*
 	 * Rates can be 0 as long as the retry count is 0 too.
@@ -3716,14 +3704,14 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	}
 
 	if (ah->ah_version == AR5K_AR5212) {
-		tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+		tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
 
 #define _XTX_TRIES(_n)							\
 	if (tx_tries##_n) {						\
-		tx_desc->tx_control_2 |=				\
+		tx_ctl->tx_control_2 |=				\
 		    AR5K_REG_SM(tx_tries##_n,				\
 		    AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n);		\
-		tx_desc->tx_control_3 |=				\
+		tx_ctl->tx_control_3 |=				\
 		    AR5K_REG_SM(tx_rate##_n,				\
 		    AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n);		\
 	}
@@ -3746,11 +3734,13 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
 		struct ath5k_desc *desc)
 {
+	struct ath5k_hw_2w_tx_ctl *tx_ctl;
 	struct ath5k_hw_tx_status *tx_status;
-	struct ath5k_hw_2w_tx_desc *tx_desc;
 
-	tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
-	tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0];
+	ATH5K_TRACE(ah->ah_sc);
+
+	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+	tx_status = &desc->ud.ds_tx5210.tx_stat;
 
 	/* No frame has been send or error */
 	if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
@@ -3772,7 +3762,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
 		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
 	desc->ds_us.tx.ts_antenna = 1;
 	desc->ds_us.tx.ts_status = 0;
-	desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0,
+	desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
 		AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
 
 	if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
@@ -3796,12 +3786,13 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
 static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 		struct ath5k_desc *desc)
 {
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
 	struct ath5k_hw_tx_status *tx_status;
-	struct ath5k_hw_4w_tx_desc *tx_desc;
 
 	ATH5K_TRACE(ah->ah_sc);
-	tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
-	tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
+
+	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+	tx_status = &desc->ud.ds_tx5212.tx_stat;
 
 	/* No frame has been send or error */
 	if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
@@ -3827,25 +3818,25 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 	switch (AR5K_REG_MS(tx_status->tx_status_1,
 			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
 	case 0:
-		desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
+		desc->ds_us.tx.ts_rate = tx_ctl->tx_control_3 &
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
 		break;
 	case 1:
-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
-		desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+		desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
 		break;
 	case 2:
-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
-		desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+		desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
 		break;
 	case 3:
-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
-		desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+		desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
 		break;
 	}
@@ -3875,31 +3866,27 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 			u32 size, unsigned int flags)
 {
-	struct ath5k_rx_desc *rx_desc;
+	struct ath5k_hw_rx_ctl *rx_ctl;
 
 	ATH5K_TRACE(ah->ah_sc);
-	rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0;
+	rx_ctl = &desc->ud.ds_rx.rx_ctl;
 
 	/*
-	 *Clear ds_hw
+	 * Clear the descriptor
 	 * If we don't clean the status descriptor,
 	 * while scanning we get too many results,
 	 * most of them virtual, after some secs
 	 * of scanning system hangs. M.F.
 	*/
-	memset(desc->ds_hw, 0, sizeof(desc->ds_hw));
-
-	/*Initialize rx descriptor*/
-	rx_desc->rx_control_0 = 0;
-	rx_desc->rx_control_1 = 0;
+	memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
 
 	/* Setup descriptor */
-	rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
-	if (unlikely(rx_desc->rx_control_1 != size))
+	rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+	if (unlikely(rx_ctl->rx_control_1 != size))
 		return -EINVAL;
 
 	if (flags & AR5K_RXDESC_INTREQ)
-		rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+		rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
 
 	return 0;
 }
@@ -3907,15 +3894,15 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 /*
  * Proccess the rx status descriptor on 5210/5211
  */
-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
 		struct ath5k_desc *desc)
 {
-	struct ath5k_hw_old_rx_status *rx_status;
+	struct ath5k_hw_rx_status *rx_status;
 
-	rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0];
+	rx_status = &desc->ud.ds_rx.u.rx_stat;
 
 	/* No frame received / not ready */
-	if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE)
+	if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE)
 				== 0))
 		return -EINPROGRESS;
 
@@ -3923,50 +3910,51 @@ static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
 	 * Frame receive status
 	 */
 	desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
-		AR5K_OLD_RX_DESC_STATUS0_DATA_LEN;
+		AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
 	desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
 	desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE);
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
 	desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
-		AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
 	desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
-		AR5K_OLD_RX_DESC_STATUS0_MORE;
+		AR5K_5210_RX_DESC_STATUS0_MORE;
 	desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-		AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+		AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
 	desc->ds_us.rx.rs_status = 0;
 
 	/*
 	 * Key table status
 	 */
-	if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID)
+	if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
 		desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-			AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX);
+			AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
 	else
 		desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
 
 	/*
 	 * Receive/descriptor errors
 	 */
-	if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK)
-			== 0) {
-		if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR)
+	if ((rx_status->rx_status_1 &
+			AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
+		if (rx_status->rx_status_1 &
+				AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
 
 		if (rx_status->rx_status_1 &
-				AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN)
+				AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
 
 		if (rx_status->rx_status_1 &
-				AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) {
+				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
 			desc->ds_us.rx.rs_phyerr =
 				AR5K_REG_MS(rx_status->rx_status_1,
-					AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR);
+					AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
 		}
 
 		if (rx_status->rx_status_1 &
-				AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+				AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
 	}
 
@@ -3976,20 +3964,20 @@ static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
 /*
  * Proccess the rx status descriptor on 5212
  */
-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
 		struct ath5k_desc *desc)
 {
-	struct ath5k_hw_new_rx_status *rx_status;
+	struct ath5k_hw_rx_status *rx_status;
 	struct ath5k_hw_rx_error *rx_err;
 
 	ATH5K_TRACE(ah->ah_sc);
-	rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0];
+	rx_status = &desc->ud.ds_rx.u.rx_stat;
 
 	/* Overlay on error */
-	rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0];
+	rx_err = &desc->ud.ds_rx.u.rx_err;
 
 	/* No frame received / not ready */
-	if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE)
+	if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE)
 				== 0))
 		return -EINPROGRESS;
 
@@ -3997,25 +3985,25 @@ static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
 	 * Frame receive status
 	 */
 	desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
-		AR5K_NEW_RX_DESC_STATUS0_DATA_LEN;
+		AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
 	desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
 	desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE);
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
 	desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
-		AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
 	desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
-		AR5K_NEW_RX_DESC_STATUS0_MORE;
+		AR5K_5212_RX_DESC_STATUS0_MORE;
 	desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-		AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+		AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
 	desc->ds_us.rx.rs_status = 0;
 
 	/*
 	 * Key table status
 	 */
-	if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID)
+	if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
 		desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-				AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX);
+				AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
 	else
 		desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
 
@@ -4023,12 +4011,13 @@ static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
 	 * Receive/descriptor errors
 	 */
 	if ((rx_status->rx_status_1 &
-			AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
-		if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR)
+			AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
+		if (rx_status->rx_status_1 &
+				AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
 
 		if (rx_status->rx_status_1 &
-				AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) {
+				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
 			desc->ds_us.rx.rs_phyerr =
 				AR5K_REG_MS(rx_err->rx_error_1,
@@ -4036,10 +4025,11 @@ static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
 		}
 
 		if (rx_status->rx_status_1 &
-				AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+				AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
 
-		if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR)
+		if (rx_status->rx_status_1 &
+				AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
 	}
 
diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/hw.h
index d9a7c09..64fca8d 100644
--- a/drivers/net/wireless/ath5k/hw.h
+++ b/drivers/net/wireless/ath5k/hw.h
@@ -173,7 +173,10 @@ struct ath5k_eeprom_info {
  * (rX: reserved fields possibily used by future versions of the ar5k chipset)
  */
 
-struct ath5k_rx_desc {
+/*
+ * common hardware RX control descriptor
+ */
+struct ath5k_hw_rx_ctl {
 	u32	rx_control_0; /* RX control word 0 */
 
 #define AR5K_DESC_RX_CTL0			0x00000000
@@ -185,69 +188,63 @@ struct ath5k_rx_desc {
 } __packed;
 
 /*
- * 5210/5211 rx status descriptor
+ * common hardware RX status descriptor
+ * 5210/11 and 5212 differ only in the flags defined below
  */
-struct ath5k_hw_old_rx_status {
+struct ath5k_hw_rx_status {
 	u32	rx_status_0; /* RX status word 0 */
-
-#define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN		0x00000fff
-#define AR5K_OLD_RX_DESC_STATUS0_MORE			0x00001000
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE		0x00078000
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S		15
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL		0x07f80000
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	19
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA	0x38000000
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	27
-
 	u32	rx_status_1; /* RX status word 1 */
-
-#define AR5K_OLD_RX_DESC_STATUS1_DONE			0x00000001
-#define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
-#define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR		0x00000004
-#define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN		0x00000008
-#define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010
-#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR		0x000000e0
-#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S		5
-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX		0x00007e00
-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S		9
-#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000
-#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
-#define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS		0x10000000
 } __packed;
 
+/* 5210/5211 */
+#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN		0x00000fff
+#define AR5K_5210_RX_DESC_STATUS0_MORE			0x00001000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE		0x00078000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S	15
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x07f80000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	19
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA	0x38000000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	27
+#define AR5K_5210_RX_DESC_STATUS1_DONE			0x00000001
+#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
+#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR		0x00000004
+#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN		0x00000008
+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR		0x000000e0
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S		5
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S		9
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
+#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS	0x10000000
+
+/* 5212 */
+#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN		0x00000fff
+#define AR5K_5212_RX_DESC_STATUS0_MORE			0x00001000
+#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR	0x00002000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE		0x000f8000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S	15
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x0ff00000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	20
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA	0xf0000000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	28
+#define AR5K_5212_RX_DESC_STATUS1_DONE			0x00000001
+#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
+#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR		0x00000004
+#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000008
+#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR		0x00000010
+#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR		0x00000020
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX		0x0000fe00
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S		9
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x7fff0000
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	16
+#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS	0x80000000
+
 /*
- * 5212 rx status descriptor
+ * common hardware RX error descriptor
  */
-struct ath5k_hw_new_rx_status {
-	u32	rx_status_0; /* RX status word 0 */
-
-#define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN		0x00000fff
-#define AR5K_NEW_RX_DESC_STATUS0_MORE			0x00001000
-#define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR	0x00002000
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE		0x000f8000
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S		15
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL		0x0ff00000
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	20
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA	0xf0000000
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	28
-
-	u32	rx_status_1; /* RX status word 1 */
-
-#define AR5K_NEW_RX_DESC_STATUS1_DONE			0x00000001
-#define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
-#define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR		0x00000004
-#define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000008
-#define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR		0x00000010
-#define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR		0x00000020
-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX		0x0000fe00
-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S		9
-#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x7fff0000
-#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	16
-#define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS		0x80000000
-} __packed;
-
 struct ath5k_hw_rx_error {
 	u32	rx_error_0; /* RX error word 0 */
 
@@ -268,7 +265,10 @@ struct ath5k_hw_rx_error {
 #define AR5K_DESC_RX_PHY_ERROR_SERVICE		0xc0
 #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR	0xe0
 
-struct ath5k_hw_2w_tx_desc {
+/*
+ * 5210/5211 hardware 2-word TX control descriptor
+ */
+struct ath5k_hw_2w_tx_ctl {
 	u32	tx_control_0; /* TX control word 0 */
 
 #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
@@ -314,9 +314,9 @@ struct ath5k_hw_2w_tx_desc {
 #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS     0x10
 
 /*
- * 5212 4-word tx control descriptor
+ * 5212 hardware 4-word TX control descriptor
  */
-struct ath5k_hw_4w_tx_desc {
+struct ath5k_hw_4w_tx_ctl {
 	u32	tx_control_0; /* TX control word 0 */
 
 #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
@@ -374,7 +374,7 @@ struct ath5k_hw_4w_tx_desc {
 } __packed;
 
 /*
- * Common tx status descriptor
+ * Common TX status descriptor
  */
 struct ath5k_hw_tx_status {
 	u32	tx_status_0; /* TX status word 0 */
@@ -415,6 +415,34 @@ struct ath5k_hw_tx_status {
 
 
 /*
+ * 5210/5211 hardware TX descriptor
+ */
+struct ath5k_hw_5210_tx_desc {
+	struct ath5k_hw_2w_tx_ctl	tx_ctl;
+	struct ath5k_hw_tx_status	tx_stat;
+} __packed;
+
+/*
+ * 5212 hardware TX descriptor
+ */
+struct ath5k_hw_5212_tx_desc {
+	struct ath5k_hw_4w_tx_ctl	tx_ctl;
+	struct ath5k_hw_tx_status	tx_stat;
+} __packed;
+
+/*
+ * common hardware RX descriptor
+ */
+struct ath5k_hw_all_rx_desc {
+	struct ath5k_hw_rx_ctl			rx_ctl;
+	union {
+		struct ath5k_hw_rx_status	rx_stat;
+		struct ath5k_hw_rx_error	rx_err;
+	} u;
+} __packed;
+
+
+/*
  * AR5K REGISTER ACCESS
  */
 


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4] ath5k: move rx and tx status structures out of hardware descriptor
  2008-03-05  9:34 [PATCH 0/4] ath5k descriptor cleanup + ibss beacon fix Bruno Randolf
  2008-03-05  9:35 ` [PATCH 1/4] ath5k: struct ath5k_desc cleanups Bruno Randolf
@ 2008-03-05  9:35 ` Bruno Randolf
  2008-03-05  9:36 ` [PATCH 3/4] ath5k: add notes about rx timestamp Bruno Randolf
  2008-03-05  9:36 ` [PATCH 4/4] ath5k: work around wrong beacon rx timestamp in IBSS mode Bruno Randolf
  3 siblings, 0 replies; 6+ messages in thread
From: Bruno Randolf @ 2008-03-05  9:35 UTC (permalink / raw)
  To: ath5k-devel; +Cc: mcgrof, jirislaby, mickflemm, linux-wireless, linville

move ath5k_tx_status and ath5k_rx_status structures out of the hardware
descriptor since they are not accessed by the hardware at all. they just
contain converted information from the hardware descriptor. since they are only
used in the rx and tx tasklets there is also no use to keep them for each
descriptor.

drivers/net/wireless/ath5k/ath5k.h:     Changes-licensed-under: ISC
drivers/net/wireless/ath5k/base.c:      Changes-licensed-under: 3-Clause-BSD
drivers/net/wireless/ath5k/debug.c:     Changes-licensed-under: GPL
drivers/net/wireless/ath5k/debug.h:     Changes-licensed-under: GPL
drivers/net/wireless/ath5k/hw.c:        Changes-licensed-under: ISC

Signed-off-by: Bruno Randolf <bruno@thinktube.com>
---

 drivers/net/wireless/ath5k/ath5k.h |   16 +---
 drivers/net/wireless/ath5k/base.c  |   74 +++++++++----------
 drivers/net/wireless/ath5k/debug.c |   19 +++--
 drivers/net/wireless/ath5k/debug.h |    6 +-
 drivers/net/wireless/ath5k/hw.c    |  141 ++++++++++++++++++------------------
 5 files changed, 126 insertions(+), 130 deletions(-)


diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index e2f889b..09b9852 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -500,6 +500,7 @@ struct ath5k_beacon_state {
 
 /*
  * Atheros hardware descriptor
+ * This is read and written to by the hardware
  */
 struct ath5k_desc {
 	u32	ds_link;	/* physical address of the next descriptor */
@@ -510,15 +511,6 @@ struct ath5k_desc {
 		struct ath5k_hw_5212_tx_desc	ds_tx5212;
 		struct ath5k_hw_all_rx_desc	ds_rx;
 	} ud;
-
-	union {
-		struct ath5k_rx_status rx;
-		struct ath5k_tx_status tx;
-	} ds_us;
-
-#define ds_rxstat ds_us.rx
-#define ds_txstat ds_us.tx
-
 } __packed;
 
 #define AR5K_RXDESC_INTREQ	0x0020
@@ -1037,8 +1029,10 @@ struct ath5k_hw {
 	int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
 		unsigned int, unsigned int, unsigned int, unsigned int,
 		unsigned int, unsigned int);
-	int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *);
-	int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *);
+	int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+		struct ath5k_tx_status *);
+	int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+		struct ath5k_rx_status *);
 };
 
 /*
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 393b5f3..777bc4a 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -280,7 +280,8 @@ static int 	ath5k_rx_start(struct ath5k_softc *sc);
 static void 	ath5k_rx_stop(struct ath5k_softc *sc);
 static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
 					struct ath5k_desc *ds,
-					struct sk_buff *skb);
+					struct sk_buff *skb,
+					struct ath5k_rx_status *rs);
 static void 	ath5k_tasklet_rx(unsigned long data);
 /* Tx handling */
 static void 	ath5k_tx_processq(struct ath5k_softc *sc,
@@ -1560,8 +1561,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 	 */
 	spin_lock_bh(&txq->lock);
 	list_for_each_entry_safe(bf, bf0, &txq->q, list) {
-		ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah,
-					bf->desc));
+		ath5k_debug_printtxbuf(sc, bf);
 
 		ath5k_txbuf_free(sc, bf);
 
@@ -1686,20 +1686,20 @@ ath5k_rx_stop(struct ath5k_softc *sc)
 
 static unsigned int
 ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
-		struct sk_buff *skb)
+		struct sk_buff *skb, struct ath5k_rx_status *rs)
 {
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb);
 
-	if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
-			ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID)
+	if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
+			rs->rs_keyix != AR5K_RXKEYIX_INVALID)
 		return RX_FLAG_DECRYPTED;
 
 	/* Apparently when a default key is used to decrypt the packet
 	   the hw does not set the index used to decrypt.  In such cases
 	   get the index from the packet. */
 	if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) &&
-			!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
+			!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
 			skb->len >= hlen + 4) {
 		keyix = skb->data[hlen + 3] >> 6;
 
@@ -1742,12 +1742,11 @@ static void
 ath5k_tasklet_rx(unsigned long data)
 {
 	struct ieee80211_rx_status rxs = {};
+	struct ath5k_rx_status rs = {};
 	struct sk_buff *skb;
 	struct ath5k_softc *sc = (void *)data;
 	struct ath5k_buf *bf;
 	struct ath5k_desc *ds;
-	u16 len;
-	u8 stat;
 	int ret;
 	int hdrlen;
 	int pad;
@@ -1770,7 +1769,7 @@ ath5k_tasklet_rx(unsigned long data)
 		if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */
 			break;
 
-		ret = sc->ah->ah_proc_rx_desc(sc->ah, ds);
+		ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
 		if (unlikely(ret == -EINPROGRESS))
 			break;
 		else if (unlikely(ret)) {
@@ -1779,16 +1778,15 @@ ath5k_tasklet_rx(unsigned long data)
 			return;
 		}
 
-		if (unlikely(ds->ds_rxstat.rs_more)) {
+		if (unlikely(rs.rs_more)) {
 			ATH5K_WARN(sc, "unsupported jumbo\n");
 			goto next;
 		}
 
-		stat = ds->ds_rxstat.rs_status;
-		if (unlikely(stat)) {
-			if (stat & AR5K_RXERR_PHY)
+		if (unlikely(rs.rs_status)) {
+			if (rs.rs_status & AR5K_RXERR_PHY)
 				goto next;
-			if (stat & AR5K_RXERR_DECRYPT) {
+			if (rs.rs_status & AR5K_RXERR_DECRYPT) {
 				/*
 				 * Decrypt error.  If the error occurred
 				 * because there was no hardware key, then
@@ -1799,30 +1797,29 @@ ath5k_tasklet_rx(unsigned long data)
 				 *
 				 * XXX do key cache faulting
 				 */
-				if (ds->ds_rxstat.rs_keyix ==
-						AR5K_RXKEYIX_INVALID &&
-						!(stat & AR5K_RXERR_CRC))
+				if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
+				    !(rs.rs_status & AR5K_RXERR_CRC))
 					goto accept;
 			}
-			if (stat & AR5K_RXERR_MIC) {
+			if (rs.rs_status & AR5K_RXERR_MIC) {
 				rxs.flag |= RX_FLAG_MMIC_ERROR;
 				goto accept;
 			}
 
 			/* let crypto-error packets fall through in MNTR */
-			if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
+			if ((rs.rs_status &
+				~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
 					sc->opmode != IEEE80211_IF_TYPE_MNTR)
 				goto next;
 		}
 accept:
-		len = ds->ds_rxstat.rs_datalen;
-		pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len,
-				PCI_DMA_FROMDEVICE);
+		pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr,
+				rs.rs_datalen, PCI_DMA_FROMDEVICE);
 		pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
 				PCI_DMA_FROMDEVICE);
 		bf->skb = NULL;
 
-		skb_put(skb, len);
+		skb_put(skb, rs.rs_datalen);
 
 		/*
 		 * the hardware adds a padding to 4 byte boundaries between
@@ -1845,7 +1842,7 @@ accept:
 		 * 32768usec (about 32ms). it might be necessary to move this to
 		 * the interrupt handler, like it is done in madwifi.
 		 */
-		rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
+		rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
 		rxs.flag |= RX_FLAG_TSFT;
 
 		rxs.freq = sc->curchan->center_freq;
@@ -1859,17 +1856,16 @@ accept:
 		/* noise floor in dBm, from the last noise calibration */
 		rxs.noise = sc->ah->ah_noise_floor;
 		/* signal level in dBm */
-		rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi;
+		rxs.ssi = rxs.noise + rs.rs_rssi;
 		/*
 		 * "signal" is actually displayed as Link Quality by iwconfig
 		 * we provide a percentage based on rssi (assuming max rssi 64)
 		 */
-		rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
+		rxs.signal = rs.rs_rssi * 100 / 64;
 
-		rxs.antenna = ds->ds_rxstat.rs_antenna;
-		rxs.rate_idx = ath5k_hw_to_driver_rix(sc,
-			ds->ds_rxstat.rs_rate);
-		rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);
+		rxs.antenna = rs.rs_antenna;
+		rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
+		rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
 
 		ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
 
@@ -1878,7 +1874,7 @@ accept:
 			ath5k_check_ibss_hw_merge(sc, skb);
 
 		__ieee80211_rx(sc->hw, skb, &rxs);
-		sc->led_rxrate = ds->ds_rxstat.rs_rate;
+		sc->led_rxrate = rs.rs_rate;
 		ath5k_led_event(sc, ATH_LED_RX);
 next:
 		list_move_tail(&bf->list, &sc->rxbuf);
@@ -1897,6 +1893,7 @@ static void
 ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 {
 	struct ieee80211_tx_status txs = {};
+	struct ath5k_tx_status ts = {};
 	struct ath5k_buf *bf, *bf0;
 	struct ath5k_desc *ds;
 	struct sk_buff *skb;
@@ -1909,7 +1906,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 		/* TODO only one segment */
 		pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
 				sc->desc_len, PCI_DMA_FROMDEVICE);
-		ret = sc->ah->ah_proc_tx_desc(sc->ah, ds);
+		ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
 		if (unlikely(ret == -EINPROGRESS))
 			break;
 		else if (unlikely(ret)) {
@@ -1924,17 +1921,16 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 				PCI_DMA_TODEVICE);
 
 		txs.control = bf->ctl;
-		txs.retry_count = ds->ds_txstat.ts_shortretry +
-			ds->ds_txstat.ts_longretry / 6;
-		if (unlikely(ds->ds_txstat.ts_status)) {
+		txs.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
+		if (unlikely(ts.ts_status)) {
 			sc->ll_stats.dot11ACKFailureCount++;
-			if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY)
+			if (ts.ts_status & AR5K_TXERR_XRETRY)
 				txs.excessive_retries = 1;
-			else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT)
+			else if (ts.ts_status & AR5K_TXERR_FILT)
 				txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
 		} else {
 			txs.flags |= IEEE80211_TX_STATUS_ACK;
-			txs.ack_signal = ds->ds_txstat.ts_rssi;
+			txs.ack_signal = ts.ts_rssi;
 		}
 
 		ieee80211_tx_status(sc->hw, skb, &txs);
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
index 9301494..d3eb9e8 100644
--- a/drivers/net/wireless/ath5k/debug.c
+++ b/drivers/net/wireless/ath5k/debug.c
@@ -497,7 +497,8 @@ ath5k_debug_dump_bands(struct ath5k_softc *sc)
 }
 
 static inline void
-ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
+ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
+		       struct ath5k_rx_status *rs)
 {
 	struct ath5k_desc *ds = bf->desc;
 	struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
@@ -507,7 +508,7 @@ ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
 		ds->ds_link, ds->ds_data,
 		rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
 		rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
-		!done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
+		!done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
 }
 
 void
@@ -515,6 +516,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
 {
 	struct ath5k_desc *ds;
 	struct ath5k_buf *bf;
+	struct ath5k_rx_status rs = {};
 	int status;
 
 	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
@@ -526,9 +528,9 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
 	spin_lock_bh(&sc->rxbuflock);
 	list_for_each_entry(bf, &sc->rxbuf, list) {
 		ds = bf->desc;
-		status = ah->ah_proc_rx_desc(ah, ds);
+		status = ah->ah_proc_rx_desc(ah, ds, &rs);
 		if (!status)
-			ath5k_debug_printrxbuf(bf, status == 0);
+			ath5k_debug_printrxbuf(bf, status == 0, &rs);
 	}
 	spin_unlock_bh(&sc->rxbuflock);
 }
@@ -552,21 +554,24 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc,
 }
 
 void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc,
-			struct ath5k_buf *bf, int done)
+ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
 {
 	struct ath5k_desc *ds = bf->desc;
 	struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
+	struct ath5k_tx_status ts = {};
+	int done;
 
 	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
 		return;
 
+	done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
+
 	printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
 		"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
 		ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
 		td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
 		td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
-		!done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
+		done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
 }
 
 #endif /* ifdef CONFIG_ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h
index 8c0b5c5..2cf8d18 100644
--- a/drivers/net/wireless/ath5k/debug.h
+++ b/drivers/net/wireless/ath5k/debug.h
@@ -160,8 +160,7 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc,
 			struct sk_buff *skb, const char *prefix, int tx);
 
 void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc,
-			struct ath5k_buf *bf, int done);
+ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
 
 #else /* no debugging */
 
@@ -199,8 +198,7 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc,
 			struct sk_buff *skb, const char *prefix, int tx) {}
 
 static inline void
-ath5k_debug_printtxbuf(struct ath5k_softc *sc,
-			struct ath5k_buf *bf, int done) {}
+ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
 
 #endif /* ifdef CONFIG_ATH5K_DEBUG */
 
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
index bcd6041..53744c2 100644
--- a/drivers/net/wireless/ath5k/hw.c
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -48,14 +48,18 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
 static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
 	unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
 	unsigned int);
-static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
+					 struct ath5k_tx_status *);
 static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
 	unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
 	unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
 	unsigned int, unsigned int);
-static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
-static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *);
-static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
+					 struct ath5k_tx_status *);
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *,
+					struct ath5k_rx_status *);
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *,
+					struct ath5k_rx_status *);
 static int ath5k_hw_get_capabilities(struct ath5k_hw *);
 
 static int ath5k_eeprom_init(struct ath5k_hw *);
@@ -3732,7 +3736,7 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
  * Proccess the tx status descriptor on 5210/5211
  */
 static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
-		struct ath5k_desc *desc)
+		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
 {
 	struct ath5k_hw_2w_tx_ctl *tx_ctl;
 	struct ath5k_hw_tx_status *tx_status;
@@ -3749,32 +3753,32 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
 	/*
 	 * Get descriptor status
 	 */
-	desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
 		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
-	desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
 		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
-	desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
 		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
-	/*TODO: desc->ds_us.tx.ts_virtcol + test*/
-	desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+	/*TODO: ts->ts_virtcol + test*/
+	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
 		AR5K_DESC_TX_STATUS1_SEQ_NUM);
-	desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
 		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
-	desc->ds_us.tx.ts_antenna = 1;
-	desc->ds_us.tx.ts_status = 0;
-	desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
+	ts->ts_antenna = 1;
+	ts->ts_status = 0;
+	ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
 		AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
 
 	if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
 		if (tx_status->tx_status_0 &
 				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
-			desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
+			ts->ts_status |= AR5K_TXERR_XRETRY;
 
 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
-			desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
+			ts->ts_status |= AR5K_TXERR_FIFO;
 
 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
-			desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
+			ts->ts_status |= AR5K_TXERR_FILT;
 	}
 
 	return 0;
@@ -3784,7 +3788,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
  * Proccess a tx descriptor on 5212
  */
 static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
-		struct ath5k_desc *desc)
+		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
 {
 	struct ath5k_hw_4w_tx_ctl *tx_ctl;
 	struct ath5k_hw_tx_status *tx_status;
@@ -3801,42 +3805,42 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 	/*
 	 * Get descriptor status
 	 */
-	desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
 		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
-	desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
 		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
-	desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
 		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
-	desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
 		AR5K_DESC_TX_STATUS1_SEQ_NUM);
-	desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
 		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
-	desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 &
+	ts->ts_antenna = (tx_status->tx_status_1 &
 		AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
-	desc->ds_us.tx.ts_status = 0;
+	ts->ts_status = 0;
 
 	switch (AR5K_REG_MS(tx_status->tx_status_1,
 			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
 	case 0:
-		desc->ds_us.tx.ts_rate = tx_ctl->tx_control_3 &
+		ts->ts_rate = tx_ctl->tx_control_3 &
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
 		break;
 	case 1:
-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+		ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
-		desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+		ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
 		break;
 	case 2:
-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+		ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
-		desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+		ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
 		break;
 	case 3:
-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+		ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
-		desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+		ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
 		break;
 	}
@@ -3844,13 +3848,13 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 	if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
 		if (tx_status->tx_status_0 &
 				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
-			desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
+			ts->ts_status |= AR5K_TXERR_XRETRY;
 
 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
-			desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
+			ts->ts_status |= AR5K_TXERR_FIFO;
 
 		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
-			desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
+			ts->ts_status |= AR5K_TXERR_FILT;
 	}
 
 	return 0;
@@ -3895,7 +3899,7 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
  * Proccess the rx status descriptor on 5210/5211
  */
 static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
-		struct ath5k_desc *desc)
+		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
 {
 	struct ath5k_hw_rx_status *rx_status;
 
@@ -3909,28 +3913,29 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
 	/*
 	 * Frame receive status
 	 */
-	desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
+	rs->rs_datalen = rx_status->rx_status_0 &
 		AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
-	desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
 		AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
-	desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
 		AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
-	desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
+	rs->rs_antenna = rx_status->rx_status_0 &
 		AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
-	desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
+	rs->rs_more = rx_status->rx_status_0 &
 		AR5K_5210_RX_DESC_STATUS0_MORE;
-	desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+	/* TODO: this timestamp is 13 bit, later on we assume 15 bit */
+	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
 		AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
-	desc->ds_us.rx.rs_status = 0;
+	rs->rs_status = 0;
 
 	/*
 	 * Key table status
 	 */
 	if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
-		desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+		rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
 			AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
 	else
-		desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
+		rs->rs_keyix = AR5K_RXKEYIX_INVALID;
 
 	/*
 	 * Receive/descriptor errors
@@ -3939,23 +3944,22 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
 			AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
 		if (rx_status->rx_status_1 &
 				AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
-			desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
+			rs->rs_status |= AR5K_RXERR_CRC;
 
 		if (rx_status->rx_status_1 &
 				AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
-			desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
+			rs->rs_status |= AR5K_RXERR_FIFO;
 
 		if (rx_status->rx_status_1 &
 				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
-			desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
-			desc->ds_us.rx.rs_phyerr =
-				AR5K_REG_MS(rx_status->rx_status_1,
-					AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
+			rs->rs_status |= AR5K_RXERR_PHY;
+			rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
+					   AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
 		}
 
 		if (rx_status->rx_status_1 &
 				AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
-			desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
+			rs->rs_status |= AR5K_RXERR_DECRYPT;
 	}
 
 	return 0;
@@ -3965,7 +3969,7 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
  * Proccess the rx status descriptor on 5212
  */
 static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
-		struct ath5k_desc *desc)
+		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
 {
 	struct ath5k_hw_rx_status *rx_status;
 	struct ath5k_hw_rx_error *rx_err;
@@ -3984,28 +3988,28 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
 	/*
 	 * Frame receive status
 	 */
-	desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
+	rs->rs_datalen = rx_status->rx_status_0 &
 		AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
-	desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
 		AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
-	desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
 		AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
-	desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
+	rs->rs_antenna = rx_status->rx_status_0 &
 		AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
-	desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
+	rs->rs_more = rx_status->rx_status_0 &
 		AR5K_5212_RX_DESC_STATUS0_MORE;
-	desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
 		AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
-	desc->ds_us.rx.rs_status = 0;
+	rs->rs_status = 0;
 
 	/*
 	 * Key table status
 	 */
 	if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
-		desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+		rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
 				AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
 	else
-		desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
+		rs->rs_keyix = AR5K_RXKEYIX_INVALID;
 
 	/*
 	 * Receive/descriptor errors
@@ -4014,23 +4018,22 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
 			AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
 		if (rx_status->rx_status_1 &
 				AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
-			desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
+			rs->rs_status |= AR5K_RXERR_CRC;
 
 		if (rx_status->rx_status_1 &
 				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
-			desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
-			desc->ds_us.rx.rs_phyerr =
-				AR5K_REG_MS(rx_err->rx_error_1,
-					AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
+			rs->rs_status |= AR5K_RXERR_PHY;
+			rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1,
+					   AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
 		}
 
 		if (rx_status->rx_status_1 &
 				AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
-			desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
+			rs->rs_status |= AR5K_RXERR_DECRYPT;
 
 		if (rx_status->rx_status_1 &
 				AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
-			desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
+			rs->rs_status |= AR5K_RXERR_MIC;
 	}
 
 	return 0;


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/4] ath5k: add notes about rx timestamp
  2008-03-05  9:34 [PATCH 0/4] ath5k descriptor cleanup + ibss beacon fix Bruno Randolf
  2008-03-05  9:35 ` [PATCH 1/4] ath5k: struct ath5k_desc cleanups Bruno Randolf
  2008-03-05  9:35 ` [PATCH 2/4] ath5k: move rx and tx status structures out of hardware descriptor Bruno Randolf
@ 2008-03-05  9:36 ` Bruno Randolf
  2008-03-05  9:36 ` [PATCH 4/4] ath5k: work around wrong beacon rx timestamp in IBSS mode Bruno Randolf
  3 siblings, 0 replies; 6+ messages in thread
From: Bruno Randolf @ 2008-03-05  9:36 UTC (permalink / raw)
  To: ath5k-devel; +Cc: mcgrof, jirislaby, mickflemm, linux-wireless, linville

add comments about the fact that we don't know when exactly the atheros
hardware takes the RX timestamp.

drivers/net/wireless/ath5k/base.c:      Changes-licensed-under: 3-Clause-BSD

Signed-off-by: Bruno Randolf <bruno@thinktube.com>
---

 drivers/net/wireless/ath5k/base.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)


diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 777bc4a..03e05fe 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1841,6 +1841,17 @@ accept:
 		 * 15bit only. that means TSF extension has to be done within
 		 * 32768usec (about 32ms). it might be necessary to move this to
 		 * the interrupt handler, like it is done in madwifi.
+		 *
+		 * Unfortunately we don't know when the hardware takes the rx
+		 * timestamp (beginning of phy frame, data frame, end of rx?).
+		 * The only thing we know is that it is hardware specific...
+		 * On AR5213 it seems the rx timestamp is at the end of the
+		 * frame, but i'm not sure.
+		 *
+		 * NOTE: mac80211 defines mactime at the beginning of the first
+		 * data symbol. Since we don't have any time references it's
+		 * impossible to comply to that. This affects IBSS merge only
+		 * right now, so it's not too bad...
 		 */
 		rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
 		rxs.flag |= RX_FLAG_TSFT;


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/4] ath5k: work around wrong beacon rx timestamp in IBSS mode
  2008-03-05  9:34 [PATCH 0/4] ath5k descriptor cleanup + ibss beacon fix Bruno Randolf
                   ` (2 preceding siblings ...)
  2008-03-05  9:36 ` [PATCH 3/4] ath5k: add notes about rx timestamp Bruno Randolf
@ 2008-03-05  9:36 ` Bruno Randolf
  3 siblings, 0 replies; 6+ messages in thread
From: Bruno Randolf @ 2008-03-05  9:36 UTC (permalink / raw)
  To: ath5k-devel; +Cc: mcgrof, jirislaby, mickflemm, linux-wireless, linville

atheros hardware has a problem with the rx timestamp of some IBSS beacons when
they caused a TSF update (they have the same BSSID).

the rx timestamp is wrong especially if the beacon frames get bigger than 78
byte (at least on AR5213 and AR5414 hardware). in that case ath5k_extend_tsf()
will assume a rs_tstamp overflow and give us a timestamp too far in the past
which will cause mac80211 to merge IBSS on every beacon (which is not necessary
since the BSSID already matches). but in this case we know that the HW must
have synced to the beacons TSF and the rx timestamp must be later than that so
we can adjust mactime accordingly.

also rename the function to ath5k_check_ibss_tsf() and change comments, since
"hw merge" is better described as a TSF update.

drivers/net/wireless/ath5k/base.c:      Changes-licensed-under: 3-Clause-BSD

Signed-off-by: Bruno Randolf <bruno@thinktube.com>
---

 drivers/net/wireless/ath5k/base.c |   59 ++++++++++++++++++++++++++++---------
 1 files changed, 45 insertions(+), 14 deletions(-)


diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 03e05fe..5139217 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1712,8 +1712,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
 
 
 static void
-ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
+ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
+		     struct ieee80211_rx_status *rxs)
 {
+	u64 tsf, bc_tstamp;
 	u32 hw_tu;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
 
@@ -1724,16 +1726,45 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
 	    le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
 	    memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
 		/*
-		 * Received an IBSS beacon with the same BSSID. Hardware might
-		 * have updated the TSF, check if we need to update timers.
+		 * Received an IBSS beacon with the same BSSID. Hardware *must*
+		 * have updated the local TSF. We have to work around various
+		 * hardware bugs, though...
 		 */
-		hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
-		if (hw_tu >= sc->nexttbtt) {
-			ath5k_beacon_update_timers(sc,
-				le64_to_cpu(mgmt->u.beacon.timestamp));
+		tsf = ath5k_hw_get_tsf64(sc->ah);
+		bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+		hw_tu = TSF_TO_TU(tsf);
+
+		ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+			"beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
+			bc_tstamp, rxs->mactime,
+			(rxs->mactime - bc_tstamp), tsf);
+
+		/*
+		 * Sometimes the HW will give us a wrong tstamp in the rx
+		 * status, causing the timestamp extension to go wrong.
+		 * (This seems to happen especially with beacon frames bigger
+		 * than 78 byte (incl. FCS))
+		 * But we know that the receive timestamp must be later than the
+		 * timestamp of the beacon since HW must have synced to that.
+		 *
+		 * NOTE: here we assume mactime to be after the frame was
+		 * received, not like mac80211 which defines it at the start.
+		 */
+		if (bc_tstamp > rxs->mactime) {
 			ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-				"detected HW merge from received beacon\n");
+				"fixing mactime from %llx to %llx\n",
+				rxs->mactime, tsf);
+			rxs->mactime = tsf;
 		}
+
+		/*
+		 * Local TSF might have moved higher than our beacon timers,
+		 * in that case we have to update them to continue sending
+		 * beacons. This also takes care of synchronizing beacon sending
+		 * times with other stations.
+		 */
+		if (hw_tu >= sc->nexttbtt)
+			ath5k_beacon_update_timers(sc, bc_tstamp);
 	}
 }
 
@@ -1882,7 +1913,7 @@ accept:
 
 		/* check beacons in IBSS mode */
 		if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
-			ath5k_check_ibss_hw_merge(sc, skb);
+			ath5k_check_ibss_tsf(sc, skb, &rxs);
 
 		__ieee80211_rx(sc->hw, skb, &rxs);
 		sc->led_rxrate = rs.rs_rate;
@@ -2115,7 +2146,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
  * beacon timer registers.
  *
  * This is called in a variety of situations, e.g. when a beacon is received,
- * when a HW merge has been detected, but also when an new IBSS is created or
+ * when a TSF update has been detected, but also when an new IBSS is created or
  * when we otherwise know we have to update the timers, but we keep it in this
  * function to have it all together in one place.
  */
@@ -2215,7 +2246,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
  * another AP to associate with.
  *
  * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
- * interrupts to detect HW merges only.
+ * interrupts to detect TSF updates only.
  *
  * AP mode is missing.
  */
@@ -2235,7 +2266,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
 		 * hardware send the beacons automatically. We have to load it
 		 * only once here.
 		 * We use the SWBA interrupt only to keep track of the beacon
-		 * timers in order to detect HW merges (automatic TSF updates).
+		 * timers in order to detect automatic TSF updates.
 		 */
 		ath5k_beaconq_config(sc);
 
@@ -2448,8 +2479,8 @@ ath5k_intr(int irq, void *dev_id)
 				*
 				* In IBSS mode we use this interrupt just to
 				* keep track of the next TBTT (target beacon
-				* transmission time) in order to detect hardware
-				* merges (TSF updates).
+				* transmission time) in order to detect wether
+				* automatic TSF updates happened.
 				*/
 				if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
 					 /* XXX: only if VEOL suppported */


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH] ath5k: struct ath5k_desc cleanups
  2008-03-05  9:35 ` [PATCH 1/4] ath5k: struct ath5k_desc cleanups Bruno Randolf
@ 2008-03-05  9:57   ` Bruno Randolf
  0 siblings, 0 replies; 6+ messages in thread
From: Bruno Randolf @ 2008-03-05  9:57 UTC (permalink / raw)
  To: ath5k-devel; +Cc: mcgrof, jirislaby, mickflemm, linux-wireless, linville

* make struct ath5k_desc clearer by directly including unions of structures,
  which correspond to the hardware descriptors of different HW versions (5210
  and 5212). before they were casted at onto ath5k_desc at different points
  (e.g.  ds_hw[2]).

* rename some structures and variable names to make their use clearer, e.g.
  struct ath5k_hw_4w_tx_desc to ath5k_hw_4w_tx_ctl.

* substitute "old" with "5210" and "new" with "5212" (eg. rename
  ath5k_hw_proc_new_rx_status() to ath5k_hw_proc_5212_rx_status()) because old
  and new are relative and we might have a newer structure at some point.

* unify structs ath5k_hw_old_rx_status and ath5k_hw_new_rx_status into one
  ath5k_hw_rx_status, because they only differ in the flags and masks.

drivers/net/wireless/ath5k/ath5k.h:     Changes-licensed-under: ISC
drivers/net/wireless/ath5k/debug.c:     Changes-licensed-under: GPL
drivers/net/wireless/ath5k/hw.c:        Changes-licensed-under: ISC
drivers/net/wireless/ath5k/hw.h:        Changes-licensed-under: ISC

Signed-off-by: Bruno Randolf <bruno@thinktube.com>
---

 drivers/net/wireless/ath5k/ath5k.h |   23 ++--
 drivers/net/wireless/ath5k/debug.c |   12 +-
 drivers/net/wireless/ath5k/hw.c    |  212 +++++++++++++++++-------------------
 drivers/net/wireless/ath5k/hw.h    |  150 +++++++++++++++----------
 4 files changed, 210 insertions(+), 187 deletions(-)


diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index 18223d9..e2f889b 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -268,12 +268,13 @@ enum ath5k_driver_mode {
 #define SHPREAMBLE_FLAG(_ix) \
 	(HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
 
+
 /****************\
   TX DEFINITIONS
 \****************/
 
 /*
- * Tx Descriptor
+ * TX Status
  */
 struct ath5k_tx_status {
 	u16	ts_seqnum;
@@ -421,7 +422,7 @@ enum ath5k_dmasize {
 \****************/
 
 /*
- * Rx Descriptor
+ * RX Status
  */
 struct ath5k_rx_status {
 	u16	rs_datalen;
@@ -452,8 +453,6 @@ struct ath5k_mib_stats {
 };
 
 
-
-
 /**************************\
  BEACON TIMERS DEFINITIONS
 \**************************/
@@ -495,20 +494,22 @@ struct ath5k_beacon_state {
 #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
 
 
-
 /********************\
   COMMON DEFINITIONS
 \********************/
 
 /*
- * Atheros descriptor
+ * Atheros hardware descriptor
  */
 struct ath5k_desc {
-	u32	ds_link;
-	u32	ds_data;
-	u32	ds_ctl0;
-	u32	ds_ctl1;
-	u32	ds_hw[4];
+	u32	ds_link;	/* physical address of the next descriptor */
+	u32	ds_data;	/* physical address of data buffer (skb) */
+
+	union {
+		struct ath5k_hw_5210_tx_desc	ds_tx5210;
+		struct ath5k_hw_5212_tx_desc	ds_tx5212;
+		struct ath5k_hw_all_rx_desc	ds_rx;
+	} ud;
 
 	union {
 		struct ath5k_rx_status rx;
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
index 05bf4fb..9301494 100644
--- a/drivers/net/wireless/ath5k/debug.c
+++ b/drivers/net/wireless/ath5k/debug.c
@@ -500,11 +500,13 @@ static inline void
 ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
 {
 	struct ath5k_desc *ds = bf->desc;
+	struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
 
 	printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
 		ds, (unsigned long long)bf->daddr,
-		ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
-		ds->ds_hw[0], ds->ds_hw[1],
+		ds->ds_link, ds->ds_data,
+		rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
+		rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
 		!done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
 }
 
@@ -554,14 +556,16 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc,
 			struct ath5k_buf *bf, int done)
 {
 	struct ath5k_desc *ds = bf->desc;
+	struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
 
 	if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
 		return;
 
 	printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
 		"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
-		ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
-		ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
+		ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
+		td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
+		td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
 		!done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
 }
 
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
index eec2b80..bcd6041 100644
--- a/drivers/net/wireless/ath5k/hw.c
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -54,8 +54,8 @@ static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
 	unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
 	unsigned int, unsigned int);
 static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *);
-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *);
 static int ath5k_hw_get_capabilities(struct ath5k_hw *);
 
 static int ath5k_eeprom_init(struct ath5k_hw *);
@@ -174,9 +174,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
 	}
 
 	if (ah->ah_version == AR5K_AR5212)
-		ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status;
+		ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
 	else if (ah->ah_version <= AR5K_AR5211)
-		ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status;
+		ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
 
 	/* Bring device out of sleep and reset it's units */
 	ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
@@ -3456,10 +3456,10 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	unsigned int rtscts_rate, unsigned int rtscts_duration)
 {
 	u32 frame_type;
-	struct ath5k_hw_2w_tx_desc *tx_desc;
+	struct ath5k_hw_2w_tx_ctl *tx_ctl;
 	unsigned int frame_len;
 
-	tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
+	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
 
 	/*
 	 * Validate input
@@ -3478,12 +3478,8 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 		return -EINVAL;
 	}
 
-	/* Clear status descriptor */
-	memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status));
-
-	/* Initialize control descriptor */
-	tx_desc->tx_control_0 = 0;
-	tx_desc->tx_control_1 = 0;
+	/* Clear descriptor */
+	memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
 
 	/* Setup control descriptor */
 
@@ -3495,7 +3491,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
 		return -EINVAL;
 
-	tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+	tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
 
 	/* Verify and set buffer length */
 
@@ -3506,7 +3502,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
 		return -EINVAL;
 
-	tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+	tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
 
 	/*
 	 * Verify and set header length
@@ -3515,7 +3511,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	if (ah->ah_version == AR5K_AR5210) {
 		if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
 			return -EINVAL;
-		tx_desc->tx_control_0 |=
+		tx_ctl->tx_control_0 |=
 			AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
 	}
 
@@ -3531,19 +3527,19 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 			frame_type = type /*<< 2 ?*/;
 		}
 
-		tx_desc->tx_control_0 |=
+		tx_ctl->tx_control_0 |=
 			AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
 			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
 	} else {
-		tx_desc->tx_control_0 |=
+		tx_ctl->tx_control_0 |=
 			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
 			AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
-		tx_desc->tx_control_1 |=
+		tx_ctl->tx_control_1 |=
 			AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
 	}
 #define _TX_FLAGS(_c, _flag)						\
 	if (flags & AR5K_TXDESC_##_flag)				\
-		tx_desc->tx_control_##_c |=				\
+		tx_ctl->tx_control_##_c |=				\
 			AR5K_2W_TX_DESC_CTL##_c##_##_flag
 
 	_TX_FLAGS(0, CLRDMASK);
@@ -3558,9 +3554,9 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	 * WEP crap
 	 */
 	if (key_index != AR5K_TXKEYIX_INVALID) {
-		tx_desc->tx_control_0 |=
+		tx_ctl->tx_control_0 |=
 			AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-		tx_desc->tx_control_1 |=
+		tx_ctl->tx_control_1 |=
 			AR5K_REG_SM(key_index,
 			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
 	}
@@ -3570,7 +3566,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	 */
 	if ((ah->ah_version == AR5K_AR5210) &&
 			(flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
-		tx_desc->tx_control_1 |= rtscts_duration &
+		tx_ctl->tx_control_1 |= rtscts_duration &
 				AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
 
 	return 0;
@@ -3586,13 +3582,11 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
 	unsigned int rtscts_duration)
 {
-	struct ath5k_hw_4w_tx_desc *tx_desc;
-	struct ath5k_hw_tx_status *tx_status;
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
 	unsigned int frame_len;
 
 	ATH5K_TRACE(ah->ah_sc);
-	tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
-	tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
+	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
 
 	/*
 	 * Validate input
@@ -3611,14 +3605,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 		return -EINVAL;
 	}
 
-	/* Clear status descriptor */
-	memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status));
-
-	/* Initialize control descriptor */
-	tx_desc->tx_control_0 = 0;
-	tx_desc->tx_control_1 = 0;
-	tx_desc->tx_control_2 = 0;
-	tx_desc->tx_control_3 = 0;
+	/* Clear descriptor */
+	memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
 
 	/* Setup control descriptor */
 
@@ -3630,7 +3618,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
 		return -EINVAL;
 
-	tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+	tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
 
 	/* Verify and set buffer length */
 
@@ -3641,20 +3629,20 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
 		return -EINVAL;
 
-	tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+	tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
 
-	tx_desc->tx_control_0 |=
+	tx_ctl->tx_control_0 |=
 		AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
 		AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
-	tx_desc->tx_control_1 |= AR5K_REG_SM(type,
+	tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
 					AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
-	tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+	tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
 					AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
-	tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+	tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
 
 #define _TX_FLAGS(_c, _flag)			\
 	if (flags & AR5K_TXDESC_##_flag)	\
-		tx_desc->tx_control_##_c |=	\
+		tx_ctl->tx_control_##_c |=	\
 			AR5K_4W_TX_DESC_CTL##_c##_##_flag
 
 	_TX_FLAGS(0, CLRDMASK);
@@ -3670,8 +3658,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 	 * WEP crap
 	 */
 	if (key_index != AR5K_TXKEYIX_INVALID) {
-		tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-		tx_desc->tx_control_1 |= AR5K_REG_SM(key_index,
+		tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+		tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
 				AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
 	}
 
@@ -3682,9 +3670,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
 		if ((flags & AR5K_TXDESC_RTSENA) &&
 				(flags & AR5K_TXDESC_CTSENA))
 			return -EINVAL;
-		tx_desc->tx_control_2 |= rtscts_duration &
+		tx_ctl->tx_control_2 |= rtscts_duration &
 				AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
-		tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+		tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
 				AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
 	}
 
@@ -3699,7 +3687,7 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
 	unsigned int tx_rate3, u_int tx_tries3)
 {
-	struct ath5k_hw_4w_tx_desc *tx_desc;
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
 
 	/*
 	 * Rates can be 0 as long as the retry count is 0 too.
@@ -3716,14 +3704,14 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 	}
 
 	if (ah->ah_version == AR5K_AR5212) {
-		tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+		tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
 
 #define _XTX_TRIES(_n)							\
 	if (tx_tries##_n) {						\
-		tx_desc->tx_control_2 |=				\
+		tx_ctl->tx_control_2 |=				\
 		    AR5K_REG_SM(tx_tries##_n,				\
 		    AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n);		\
-		tx_desc->tx_control_3 |=				\
+		tx_ctl->tx_control_3 |=				\
 		    AR5K_REG_SM(tx_rate##_n,				\
 		    AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n);		\
 	}
@@ -3746,11 +3734,13 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
 		struct ath5k_desc *desc)
 {
+	struct ath5k_hw_2w_tx_ctl *tx_ctl;
 	struct ath5k_hw_tx_status *tx_status;
-	struct ath5k_hw_2w_tx_desc *tx_desc;
 
-	tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
-	tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0];
+	ATH5K_TRACE(ah->ah_sc);
+
+	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+	tx_status = &desc->ud.ds_tx5210.tx_stat;
 
 	/* No frame has been send or error */
 	if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
@@ -3772,7 +3762,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
 		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
 	desc->ds_us.tx.ts_antenna = 1;
 	desc->ds_us.tx.ts_status = 0;
-	desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0,
+	desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
 		AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
 
 	if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
@@ -3796,12 +3786,13 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
 static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 		struct ath5k_desc *desc)
 {
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
 	struct ath5k_hw_tx_status *tx_status;
-	struct ath5k_hw_4w_tx_desc *tx_desc;
 
 	ATH5K_TRACE(ah->ah_sc);
-	tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
-	tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
+
+	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+	tx_status = &desc->ud.ds_tx5212.tx_stat;
 
 	/* No frame has been send or error */
 	if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
@@ -3827,25 +3818,25 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 	switch (AR5K_REG_MS(tx_status->tx_status_1,
 			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
 	case 0:
-		desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
+		desc->ds_us.tx.ts_rate = tx_ctl->tx_control_3 &
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
 		break;
 	case 1:
-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
-		desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+		desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
 		break;
 	case 2:
-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
-		desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+		desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
 		break;
 	case 3:
-		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+		desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
-		desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+		desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
 		break;
 	}
@@ -3875,31 +3866,27 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
 int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 			u32 size, unsigned int flags)
 {
-	struct ath5k_rx_desc *rx_desc;
+	struct ath5k_hw_rx_ctl *rx_ctl;
 
 	ATH5K_TRACE(ah->ah_sc);
-	rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0;
+	rx_ctl = &desc->ud.ds_rx.rx_ctl;
 
 	/*
-	 *Clear ds_hw
+	 * Clear the descriptor
 	 * If we don't clean the status descriptor,
 	 * while scanning we get too many results,
 	 * most of them virtual, after some secs
 	 * of scanning system hangs. M.F.
 	*/
-	memset(desc->ds_hw, 0, sizeof(desc->ds_hw));
-
-	/*Initialize rx descriptor*/
-	rx_desc->rx_control_0 = 0;
-	rx_desc->rx_control_1 = 0;
+	memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
 
 	/* Setup descriptor */
-	rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
-	if (unlikely(rx_desc->rx_control_1 != size))
+	rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+	if (unlikely(rx_ctl->rx_control_1 != size))
 		return -EINVAL;
 
 	if (flags & AR5K_RXDESC_INTREQ)
-		rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+		rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
 
 	return 0;
 }
@@ -3907,15 +3894,15 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
 /*
  * Proccess the rx status descriptor on 5210/5211
  */
-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
 		struct ath5k_desc *desc)
 {
-	struct ath5k_hw_old_rx_status *rx_status;
+	struct ath5k_hw_rx_status *rx_status;
 
-	rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0];
+	rx_status = &desc->ud.ds_rx.u.rx_stat;
 
 	/* No frame received / not ready */
-	if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE)
+	if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE)
 				== 0))
 		return -EINPROGRESS;
 
@@ -3923,50 +3910,51 @@ static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
 	 * Frame receive status
 	 */
 	desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
-		AR5K_OLD_RX_DESC_STATUS0_DATA_LEN;
+		AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
 	desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
 	desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE);
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
 	desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
-		AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
 	desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
-		AR5K_OLD_RX_DESC_STATUS0_MORE;
+		AR5K_5210_RX_DESC_STATUS0_MORE;
 	desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-		AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+		AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
 	desc->ds_us.rx.rs_status = 0;
 
 	/*
 	 * Key table status
 	 */
-	if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID)
+	if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
 		desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-			AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX);
+			AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
 	else
 		desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
 
 	/*
 	 * Receive/descriptor errors
 	 */
-	if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK)
-			== 0) {
-		if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR)
+	if ((rx_status->rx_status_1 &
+			AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
+		if (rx_status->rx_status_1 &
+				AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
 
 		if (rx_status->rx_status_1 &
-				AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN)
+				AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
 
 		if (rx_status->rx_status_1 &
-				AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) {
+				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
 			desc->ds_us.rx.rs_phyerr =
 				AR5K_REG_MS(rx_status->rx_status_1,
-					AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR);
+					AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
 		}
 
 		if (rx_status->rx_status_1 &
-				AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+				AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
 	}
 
@@ -3976,20 +3964,20 @@ static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
 /*
  * Proccess the rx status descriptor on 5212
  */
-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
 		struct ath5k_desc *desc)
 {
-	struct ath5k_hw_new_rx_status *rx_status;
+	struct ath5k_hw_rx_status *rx_status;
 	struct ath5k_hw_rx_error *rx_err;
 
 	ATH5K_TRACE(ah->ah_sc);
-	rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0];
+	rx_status = &desc->ud.ds_rx.u.rx_stat;
 
 	/* Overlay on error */
-	rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0];
+	rx_err = &desc->ud.ds_rx.u.rx_err;
 
 	/* No frame received / not ready */
-	if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE)
+	if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE)
 				== 0))
 		return -EINPROGRESS;
 
@@ -3997,25 +3985,25 @@ static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
 	 * Frame receive status
 	 */
 	desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
-		AR5K_NEW_RX_DESC_STATUS0_DATA_LEN;
+		AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
 	desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
 	desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-		AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE);
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
 	desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
-		AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
 	desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
-		AR5K_NEW_RX_DESC_STATUS0_MORE;
+		AR5K_5212_RX_DESC_STATUS0_MORE;
 	desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-		AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+		AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
 	desc->ds_us.rx.rs_status = 0;
 
 	/*
 	 * Key table status
 	 */
-	if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID)
+	if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
 		desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-				AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX);
+				AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
 	else
 		desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
 
@@ -4023,12 +4011,13 @@ static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
 	 * Receive/descriptor errors
 	 */
 	if ((rx_status->rx_status_1 &
-			AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
-		if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR)
+			AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
+		if (rx_status->rx_status_1 &
+				AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
 
 		if (rx_status->rx_status_1 &
-				AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) {
+				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
 			desc->ds_us.rx.rs_phyerr =
 				AR5K_REG_MS(rx_err->rx_error_1,
@@ -4036,10 +4025,11 @@ static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
 		}
 
 		if (rx_status->rx_status_1 &
-				AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+				AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
 
-		if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR)
+		if (rx_status->rx_status_1 &
+				AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
 			desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
 	}
 
diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/hw.h
index d9a7c09..64fca8d 100644
--- a/drivers/net/wireless/ath5k/hw.h
+++ b/drivers/net/wireless/ath5k/hw.h
@@ -173,7 +173,10 @@ struct ath5k_eeprom_info {
  * (rX: reserved fields possibily used by future versions of the ar5k chipset)
  */
 
-struct ath5k_rx_desc {
+/*
+ * common hardware RX control descriptor
+ */
+struct ath5k_hw_rx_ctl {
 	u32	rx_control_0; /* RX control word 0 */
 
 #define AR5K_DESC_RX_CTL0			0x00000000
@@ -185,69 +188,63 @@ struct ath5k_rx_desc {
 } __packed;
 
 /*
- * 5210/5211 rx status descriptor
+ * common hardware RX status descriptor
+ * 5210/11 and 5212 differ only in the flags defined below
  */
-struct ath5k_hw_old_rx_status {
+struct ath5k_hw_rx_status {
 	u32	rx_status_0; /* RX status word 0 */
-
-#define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN		0x00000fff
-#define AR5K_OLD_RX_DESC_STATUS0_MORE			0x00001000
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE		0x00078000
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S		15
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL		0x07f80000
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	19
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA	0x38000000
-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	27
-
 	u32	rx_status_1; /* RX status word 1 */
-
-#define AR5K_OLD_RX_DESC_STATUS1_DONE			0x00000001
-#define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
-#define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR		0x00000004
-#define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN		0x00000008
-#define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010
-#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR		0x000000e0
-#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S		5
-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX		0x00007e00
-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S		9
-#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000
-#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
-#define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS		0x10000000
 } __packed;
 
+/* 5210/5211 */
+#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN		0x00000fff
+#define AR5K_5210_RX_DESC_STATUS0_MORE			0x00001000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE		0x00078000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S	15
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x07f80000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	19
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA	0x38000000
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	27
+#define AR5K_5210_RX_DESC_STATUS1_DONE			0x00000001
+#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
+#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR		0x00000004
+#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN		0x00000008
+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR		0x000000e0
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S		5
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S		9
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
+#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS	0x10000000
+
+/* 5212 */
+#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN		0x00000fff
+#define AR5K_5212_RX_DESC_STATUS0_MORE			0x00001000
+#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR	0x00002000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE		0x000f8000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S	15
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x0ff00000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	20
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA	0xf0000000
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	28
+#define AR5K_5212_RX_DESC_STATUS1_DONE			0x00000001
+#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
+#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR		0x00000004
+#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000008
+#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR		0x00000010
+#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR		0x00000020
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX		0x0000fe00
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S		9
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x7fff0000
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	16
+#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS	0x80000000
+
 /*
- * 5212 rx status descriptor
+ * common hardware RX error descriptor
  */
-struct ath5k_hw_new_rx_status {
-	u32	rx_status_0; /* RX status word 0 */
-
-#define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN		0x00000fff
-#define AR5K_NEW_RX_DESC_STATUS0_MORE			0x00001000
-#define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR	0x00002000
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE		0x000f8000
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S		15
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL		0x0ff00000
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	20
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA	0xf0000000
-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	28
-
-	u32	rx_status_1; /* RX status word 1 */
-
-#define AR5K_NEW_RX_DESC_STATUS1_DONE			0x00000001
-#define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
-#define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR		0x00000004
-#define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000008
-#define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR		0x00000010
-#define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR		0x00000020
-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX		0x0000fe00
-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S		9
-#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x7fff0000
-#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	16
-#define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS		0x80000000
-} __packed;
-
 struct ath5k_hw_rx_error {
 	u32	rx_error_0; /* RX error word 0 */
 
@@ -268,7 +265,10 @@ struct ath5k_hw_rx_error {
 #define AR5K_DESC_RX_PHY_ERROR_SERVICE		0xc0
 #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR	0xe0
 
-struct ath5k_hw_2w_tx_desc {
+/*
+ * 5210/5211 hardware 2-word TX control descriptor
+ */
+struct ath5k_hw_2w_tx_ctl {
 	u32	tx_control_0; /* TX control word 0 */
 
 #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
@@ -314,9 +314,9 @@ struct ath5k_hw_2w_tx_desc {
 #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS     0x10
 
 /*
- * 5212 4-word tx control descriptor
+ * 5212 hardware 4-word TX control descriptor
  */
-struct ath5k_hw_4w_tx_desc {
+struct ath5k_hw_4w_tx_ctl {
 	u32	tx_control_0; /* TX control word 0 */
 
 #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
@@ -374,7 +374,7 @@ struct ath5k_hw_4w_tx_desc {
 } __packed;
 
 /*
- * Common tx status descriptor
+ * Common TX status descriptor
  */
 struct ath5k_hw_tx_status {
 	u32	tx_status_0; /* TX status word 0 */
@@ -415,6 +415,34 @@ struct ath5k_hw_tx_status {
 
 
 /*
+ * 5210/5211 hardware TX descriptor
+ */
+struct ath5k_hw_5210_tx_desc {
+	struct ath5k_hw_2w_tx_ctl	tx_ctl;
+	struct ath5k_hw_tx_status	tx_stat;
+} __packed;
+
+/*
+ * 5212 hardware TX descriptor
+ */
+struct ath5k_hw_5212_tx_desc {
+	struct ath5k_hw_4w_tx_ctl	tx_ctl;
+	struct ath5k_hw_tx_status	tx_stat;
+} __packed;
+
+/*
+ * common hardware RX descriptor
+ */
+struct ath5k_hw_all_rx_desc {
+	struct ath5k_hw_rx_ctl			rx_ctl;
+	union {
+		struct ath5k_hw_rx_status	rx_stat;
+		struct ath5k_hw_rx_error	rx_err;
+	} u;
+} __packed;
+
+
+/*
  * AR5K REGISTER ACCESS
  */
 


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2008-03-05  9:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-05  9:34 [PATCH 0/4] ath5k descriptor cleanup + ibss beacon fix Bruno Randolf
2008-03-05  9:35 ` [PATCH 1/4] ath5k: struct ath5k_desc cleanups Bruno Randolf
2008-03-05  9:57   ` [PATCH] " Bruno Randolf
2008-03-05  9:35 ` [PATCH 2/4] ath5k: move rx and tx status structures out of hardware descriptor Bruno Randolf
2008-03-05  9:36 ` [PATCH 3/4] ath5k: add notes about rx timestamp Bruno Randolf
2008-03-05  9:36 ` [PATCH 4/4] ath5k: work around wrong beacon rx timestamp in IBSS mode Bruno Randolf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).