mac80211: merge latest changes from trunk, fixes #9227
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Tue, 12 Apr 2011 17:19:06 +0000 (17:19 +0000)
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Tue, 12 Apr 2011 17:19:06 +0000 (17:19 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@26610 3c298f89-4303-0410-b956-a3cf2f4a3e73

19 files changed:
package/mac80211/patches/300-pending_work.patch
package/mac80211/patches/460-ath5k_fix_tx_status_reporting.patch [new file with mode: 0644]
package/mac80211/patches/461-ath5k_fix_short_preamble_dur.patch [new file with mode: 0644]
package/mac80211/patches/462-ath5k_fix_sifs.patch [new file with mode: 0644]
package/mac80211/patches/463-ath5k_fix_slottime.patch [new file with mode: 0644]
package/mac80211/patches/464-ath5k_optimize_tx_desc_setup.patch [new file with mode: 0644]
package/mac80211/patches/465-ath5k_remove_ts_rate.patch [new file with mode: 0644]
package/mac80211/patches/466-ath5k_optimize_tx_status.patch [new file with mode: 0644]
package/mac80211/patches/467-ath5k_optimize_rx_status.patch [new file with mode: 0644]
package/mac80211/patches/468-ath5k_remove_ts_retry.patch [new file with mode: 0644]
package/mac80211/patches/469-ath5k_cleanup_debugfs.patch [new file with mode: 0644]
package/mac80211/patches/470-ath5k_decrease_irq_load.patch [new file with mode: 0644]
package/mac80211/patches/471-ath5k_detect_2ghz_radio.patch [new file with mode: 0644]
package/mac80211/patches/472-ath_unshare_bus_ops.patch [new file with mode: 0644]
package/mac80211/patches/473-ath5k_read_mac_addr.patch [new file with mode: 0644]
package/mac80211/patches/474-ath5k_fix_aes_crypto_support.patch [new file with mode: 0644]
package/mac80211/patches/475-ath5k_fix_ar5312_5ghz_cap.patch [new file with mode: 0644]
package/mac80211/patches/551-mac80211_fix_iftype_wds.patch
package/mac80211/patches/552-mac80211_enable_iftype_wds_aggregation.patch

index cf4272d..74acba5 100644 (file)
        if (ieee80211_has_a4(hdr->frame_control) &&
            sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
                return -1;
-@@ -1611,12 +1612,16 @@ __ieee80211_data_to_8023(struct ieee8021
+@@ -1611,11 +1612,13 @@ __ieee80211_data_to_8023(struct ieee8021
                return -1;
  
        ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
  
        ehdr = (struct ethhdr *) rx->skb->data;
 -      if (ehdr->h_proto != rx->sdata->control_port_protocol)
--              return -1;
-+      if (ehdr->h_proto == rx->sdata->control_port_protocol) {
++      if (ehdr->h_proto == rx->sdata->control_port_protocol)
 +              *port_control = true;
-+
-+              if (check_port_control)
-+                      return -1;
-+      }
++      else if (check_port_control)
+               return -1;
  
        return 0;
- }
-@@ -1916,6 +1921,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_
+@@ -1916,6 +1919,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_
        struct net_device *dev = sdata->dev;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        __le16 fc = hdr->frame_control;
        int err;
  
        if (unlikely(!ieee80211_is_data(hdr->frame_control)))
-@@ -1932,13 +1938,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_
+@@ -1932,13 +1936,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_
            sdata->vif.type == NL80211_IFTYPE_AP)
                return RX_DROP_MONITOR;
  
diff --git a/package/mac80211/patches/460-ath5k_fix_tx_status_reporting.patch b/package/mac80211/patches/460-ath5k_fix_tx_status_reporting.patch
new file mode 100644 (file)
index 0000000..b6bfa24
--- /dev/null
@@ -0,0 +1,37 @@
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -1580,21 +1580,14 @@ ath5k_tx_frame_completed(struct ath5k_so
+       info = IEEE80211_SKB_CB(skb);
+       ieee80211_tx_info_clear_status(info);
+-      for (i = 0; i < 4; i++) {
++      for (i = 0; i <= ts->ts_final_idx; i++) {
+               struct ieee80211_tx_rate *r =
+                       &info->status.rates[i];
+-              if (ts->ts_rate[i]) {
+-                      r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]);
+-                      r->count = ts->ts_retry[i];
+-              } else {
+-                      r->idx = -1;
+-                      r->count = 0;
+-              }
++              r->count = ts->ts_retry[i];
+       }
+-      /* count the successful attempt as well */
+-      info->status.rates[ts->ts_final_idx].count++;
++      info->status.rates[ts->ts_final_idx + 1].idx = -1;
+       if (unlikely(ts->ts_status)) {
+               sc->stats.ack_fail++;
+@@ -1609,6 +1602,9 @@ ath5k_tx_frame_completed(struct ath5k_so
+       } else {
+               info->flags |= IEEE80211_TX_STAT_ACK;
+               info->status.ack_signal = ts->ts_rssi;
++
++              /* count the successful attempt as well */
++              info->status.rates[ts->ts_final_idx].count++;
+       }
+       /*
diff --git a/package/mac80211/patches/461-ath5k_fix_short_preamble_dur.patch b/package/mac80211/patches/461-ath5k_fix_short_preamble_dur.patch
new file mode 100644 (file)
index 0000000..8d0a3e8
--- /dev/null
@@ -0,0 +1,82 @@
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1233,7 +1233,7 @@ int ath5k_eeprom_read_mac(struct ath5k_h
+ /* Protocol Control Unit Functions */
+ /* Helpers */
+ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
+-              int len, struct ieee80211_rate *rate);
++              int len, struct ieee80211_rate *rate, bool shortpre);
+ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
+ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
+ extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
+--- a/drivers/net/wireless/ath/ath5k/pcu.c
++++ b/drivers/net/wireless/ath/ath5k/pcu.c
+@@ -75,7 +75,7 @@ static const unsigned int ack_rates_high
+  * bwmodes.
+  */
+ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
+-              int len, struct ieee80211_rate *rate)
++              int len, struct ieee80211_rate *rate, bool shortpre)
+ {
+       struct ath5k_softc *sc = ah->ah_sc;
+       int sifs, preamble, plcp_bits, sym_time;
+@@ -84,9 +84,15 @@ int ath5k_hw_get_frame_duration(struct a
+       /* Fallback */
+       if (!ah->ah_bwmode) {
+-              dur = ieee80211_generic_frame_duration(sc->hw,
+-                                              NULL, len, rate);
+-              return le16_to_cpu(dur);
++              __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw,
++                                      NULL, len, rate);
++
++              /* subtract difference between long and short preamble */
++              dur = le16_to_cpu(raw_dur);
++              if (shortpre)
++                      dur -= 96;
++
++              return dur;
+       }
+       bitrate = rate->bitrate;
+@@ -263,27 +269,14 @@ static inline void ath5k_hw_write_rate_d
+                * actual rate for this rate. See mac80211 tx.c
+                * ieee80211_duration() for a brief description of
+                * what rate we should choose to TX ACKs. */
+-              tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
++              tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
+               ath5k_hw_reg_write(ah, tx_time, reg);
+               if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
+                       continue;
+-              /*
+-               * We're not distinguishing short preamble here,
+-               * This is true, all we'll get is a longer value here
+-               * which is not necessarilly bad. We could use
+-               * export ieee80211_frame_duration() but that needs to be
+-               * fixed first to be properly used by mac802111 drivers:
+-               *
+-               *  - remove erp stuff and let the routine figure ofdm
+-               *    erp rates
+-               *  - remove passing argument ieee80211_local as
+-               *    drivers don't have access to it
+-               *  - move drivers using ieee80211_generic_frame_duration()
+-               *    to this
+-               */
++              tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true);
+               ath5k_hw_reg_write(ah, tx_time,
+                       reg + (AR5K_SET_SHORT_PREAMBLE << 2));
+       }
+--- a/drivers/net/wireless/ath/ath5k/qcu.c
++++ b/drivers/net/wireless/ath/ath5k/qcu.c
+@@ -550,7 +550,7 @@ int ath5k_hw_set_ifs_intervals(struct at
+       else
+               rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
+-      ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
++      ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
+       /* ack_tx_time includes an SIFS already */
+       eifs = ack_tx_time + sifs + 2 * slot_time;
diff --git a/package/mac80211/patches/462-ath5k_fix_sifs.patch b/package/mac80211/patches/462-ath5k_fix_sifs.patch
new file mode 100644 (file)
index 0000000..7d3efca
--- /dev/null
@@ -0,0 +1,23 @@
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -224,8 +224,7 @@
+ /* SIFS */
+ #define       AR5K_INIT_SIFS_TURBO                    6
+-/* XXX: 8 from initvals 10 from standard */
+-#define       AR5K_INIT_SIFS_DEFAULT_BG               8
++#define       AR5K_INIT_SIFS_DEFAULT_BG               10
+ #define       AR5K_INIT_SIFS_DEFAULT_A                16
+ #define       AR5K_INIT_SIFS_HALF_RATE                32
+ #define AR5K_INIT_SIFS_QUARTER_RATE           64
+--- a/drivers/net/wireless/ath/ath5k/qcu.c
++++ b/drivers/net/wireless/ath/ath5k/qcu.c
+@@ -519,7 +519,7 @@ int ath5k_hw_set_ifs_intervals(struct at
+               return -EINVAL;
+       sifs = ath5k_hw_get_default_sifs(ah);
+-      sifs_clock = ath5k_hw_htoclock(ah, sifs);
++      sifs_clock = ath5k_hw_htoclock(ah, sifs - 2);
+       /* EIFS
+        * Txtime of ack at lowest rate + SIFS + DIFS
diff --git a/package/mac80211/patches/463-ath5k_fix_slottime.patch b/package/mac80211/patches/463-ath5k_fix_slottime.patch
new file mode 100644 (file)
index 0000000..01e55d3
--- /dev/null
@@ -0,0 +1,42 @@
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1057,6 +1057,7 @@ struct ath5k_hw {
+       u8                      ah_coverage_class;
+       bool                    ah_ack_bitrate_high;
+       u8                      ah_bwmode;
++      bool                    ah_short_slot;
+       /* Antenna Control */
+       u32                     ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
+--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+@@ -282,6 +282,15 @@ ath5k_bss_info_changed(struct ieee80211_
+       if (changes & BSS_CHANGED_BEACON_INT)
+               sc->bintval = bss_conf->beacon_int;
++      if (changes & BSS_CHANGED_ERP_SLOT) {
++              int slot_time;
++
++              ah->ah_short_slot = bss_conf->use_short_slot;
++              slot_time = ath5k_hw_get_default_slottime(ah) +
++                          3 * ah->ah_coverage_class;
++              ath5k_hw_set_ifs_intervals(ah, slot_time);
++      }
++
+       if (changes & BSS_CHANGED_ASSOC) {
+               avf->assoc = bss_conf->assoc;
+               if (bss_conf->assoc)
+--- a/drivers/net/wireless/ath/ath5k/pcu.c
++++ b/drivers/net/wireless/ath/ath5k/pcu.c
+@@ -151,9 +151,9 @@ unsigned int ath5k_hw_get_default_slotti
+               slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE;
+               break;
+       case AR5K_BWMODE_DEFAULT:
+-              slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
+       default:
+-              if (channel->hw_value & CHANNEL_CCK)
++              slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
++              if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot)
+                       slot_time = AR5K_INIT_SLOT_TIME_B;
+               break;
+       }
diff --git a/package/mac80211/patches/464-ath5k_optimize_tx_desc_setup.patch b/package/mac80211/patches/464-ath5k_optimize_tx_desc_setup.patch
new file mode 100644 (file)
index 0000000..77dfae8
--- /dev/null
@@ -0,0 +1,89 @@
+--- a/drivers/net/wireless/ath/ath5k/desc.c
++++ b/drivers/net/wireless/ath/ath5k/desc.c
+@@ -184,6 +184,7 @@ static int ath5k_hw_setup_4word_tx_desc(
+ {
+       struct ath5k_hw_4w_tx_ctl *tx_ctl;
+       unsigned int frame_len;
++      u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0;
+       tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+@@ -209,7 +210,8 @@ static int ath5k_hw_setup_4word_tx_desc(
+               tx_power = AR5K_TUNE_MAX_TXPOWER;
+       /* Clear descriptor */
+-      memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
++      memset(&desc->ud.ds_tx5212.tx_stat, 0,
++             sizeof(desc->ud.ds_tx5212.tx_stat));
+       /* Setup control descriptor */
+@@ -221,7 +223,7 @@ static int ath5k_hw_setup_4word_tx_desc(
+       if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
+               return -EINVAL;
+-      tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
++      txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+       /* Verify and set buffer length */
+@@ -232,21 +234,17 @@ static int ath5k_hw_setup_4word_tx_desc(
+       if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
+               return -EINVAL;
+-      tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
++      txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+-      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_ctl->tx_control_1 |= AR5K_REG_SM(type,
+-                                      AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
+-      tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0,
+-                                      AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
+-      tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
++      txctl0 |= 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);
++      txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
++      txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
++      txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+ #define _TX_FLAGS(_c, _flag)                                  \
+       if (flags & AR5K_TXDESC_##_flag) {                      \
+-              tx_ctl->tx_control_##_c |=                      \
+-                      AR5K_4W_TX_DESC_CTL##_c##_##_flag;      \
++              txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
+       }
+       _TX_FLAGS(0, CLRDMASK);
+@@ -262,8 +260,8 @@ static int ath5k_hw_setup_4word_tx_desc(
+        * WEP crap
+        */
+       if (key_index != AR5K_TXKEYIX_INVALID) {
+-              tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+-              tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
++              txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
++              txctl1 |= AR5K_REG_SM(key_index,
+                               AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX);
+       }
+@@ -274,12 +272,16 @@ static int ath5k_hw_setup_4word_tx_desc(
+               if ((flags & AR5K_TXDESC_RTSENA) &&
+                               (flags & AR5K_TXDESC_CTSENA))
+                       return -EINVAL;
+-              tx_ctl->tx_control_2 |= rtscts_duration &
+-                              AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
+-              tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
++              txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
++              txctl3 |= AR5K_REG_SM(rtscts_rate,
+                               AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
+       }
++      tx_ctl->tx_control_0 = txctl0;
++      tx_ctl->tx_control_1 = txctl1;
++      tx_ctl->tx_control_2 = txctl2;
++      tx_ctl->tx_control_3 = txctl3;
++
+       return 0;
+ }
diff --git a/package/mac80211/patches/465-ath5k_remove_ts_rate.patch b/package/mac80211/patches/465-ath5k_remove_ts_rate.patch
new file mode 100644 (file)
index 0000000..265b6a7
--- /dev/null
@@ -0,0 +1,54 @@
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -452,7 +452,6 @@ struct ath5k_tx_status {
+       u16     ts_seqnum;
+       u16     ts_tstamp;
+       u8      ts_status;
+-      u8      ts_rate[4];
+       u8      ts_retry[4];
+       u8      ts_final_idx;
+       s8      ts_rssi;
+--- a/drivers/net/wireless/ath/ath5k/desc.c
++++ b/drivers/net/wireless/ath/ath5k/desc.c
+@@ -375,8 +375,6 @@ static int ath5k_hw_proc_2word_tx_status
+               AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+       ts->ts_antenna = 1;
+       ts->ts_status = 0;
+-      ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
+-              AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+       ts->ts_retry[0] = ts->ts_longretry;
+       ts->ts_final_idx = 0;
+@@ -439,32 +437,21 @@ static int ath5k_hw_proc_4word_tx_status
+       ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
+       switch (ts->ts_final_idx) {
+       case 3:
+-              ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
+-                      AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
+-
+               ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
+                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
+               ts->ts_longretry += ts->ts_retry[2];
+               /* fall through */
+       case 2:
+-              ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
+-                      AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
+-
+               ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
+                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+               ts->ts_longretry += ts->ts_retry[1];
+               /* fall through */
+       case 1:
+-              ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
+-                      AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
+-
+               ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
+                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+               ts->ts_longretry += ts->ts_retry[0];
+               /* fall through */
+       case 0:
+-              ts->ts_rate[0] = tx_ctl->tx_control_3 &
+-                      AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+               break;
+       }
diff --git a/package/mac80211/patches/466-ath5k_optimize_tx_status.patch b/package/mac80211/patches/466-ath5k_optimize_tx_status.patch
new file mode 100644 (file)
index 0000000..04ba844
--- /dev/null
@@ -0,0 +1,90 @@
+--- a/drivers/net/wireless/ath/ath5k/desc.c
++++ b/drivers/net/wireless/ath/ath5k/desc.c
+@@ -401,32 +401,38 @@ static int ath5k_hw_proc_4word_tx_status
+ {
+       struct ath5k_hw_4w_tx_ctl *tx_ctl;
+       struct ath5k_hw_tx_status *tx_status;
++      u32 txstat0, txstat1, txctl2;
+       tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+       tx_status = &desc->ud.ds_tx5212.tx_stat;
++      txstat1 = ACCESS_ONCE(tx_status->tx_status_1);
++
+       /* No frame has been send or error */
+-      if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE)))
++      if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE)))
+               return -EINPROGRESS;
++      txstat0 = ACCESS_ONCE(tx_status->tx_status_0);
++      txctl2 = ACCESS_ONCE(tx_ctl->tx_control_2);
++
+       /*
+        * Get descriptor status
+        */
+-      ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
++      ts->ts_tstamp = AR5K_REG_MS(txstat0,
+               AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+-      ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
++      ts->ts_shortretry = AR5K_REG_MS(txstat0,
+               AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+-      ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
++      ts->ts_longretry = AR5K_REG_MS(txstat0,
+               AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+-      ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
++      ts->ts_seqnum = AR5K_REG_MS(txstat1,
+               AR5K_DESC_TX_STATUS1_SEQ_NUM);
+-      ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
++      ts->ts_rssi = AR5K_REG_MS(txstat1,
+               AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+-      ts->ts_antenna = (tx_status->tx_status_1 &
++      ts->ts_antenna = (txstat1 &
+               AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1;
+       ts->ts_status = 0;
+-      ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
++      ts->ts_final_idx = AR5K_REG_MS(txstat1,
+                       AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212);
+       /* The longretry counter has the number of un-acked retries
+@@ -437,17 +443,17 @@ static int ath5k_hw_proc_4word_tx_status
+       ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
+       switch (ts->ts_final_idx) {
+       case 3:
+-              ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
++              ts->ts_retry[2] = AR5K_REG_MS(txctl2,
+                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
+               ts->ts_longretry += ts->ts_retry[2];
+               /* fall through */
+       case 2:
+-              ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
++              ts->ts_retry[1] = AR5K_REG_MS(txctl2,
+                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+               ts->ts_longretry += ts->ts_retry[1];
+               /* fall through */
+       case 1:
+-              ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
++              ts->ts_retry[0] = AR5K_REG_MS(txctl2,
+                       AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+               ts->ts_longretry += ts->ts_retry[0];
+               /* fall through */
+@@ -456,15 +462,14 @@ static int ath5k_hw_proc_4word_tx_status
+       }
+       /* TX error */
+-      if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+-              if (tx_status->tx_status_0 &
+-                              AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
++      if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
++              if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+                       ts->ts_status |= AR5K_TXERR_XRETRY;
+-              if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
++              if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+                       ts->ts_status |= AR5K_TXERR_FIFO;
+-              if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
++              if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED)
+                       ts->ts_status |= AR5K_TXERR_FILT;
+       }
diff --git a/package/mac80211/patches/467-ath5k_optimize_rx_status.patch b/package/mac80211/patches/467-ath5k_optimize_rx_status.patch
new file mode 100644 (file)
index 0000000..b0ccb5f
--- /dev/null
@@ -0,0 +1,86 @@
+--- a/drivers/net/wireless/ath/ath5k/desc.c
++++ b/drivers/net/wireless/ath/ath5k/desc.c
+@@ -603,37 +603,37 @@ static int ath5k_hw_proc_5212_rx_status(
+                                       struct ath5k_rx_status *rs)
+ {
+       struct ath5k_hw_rx_status *rx_status;
++      u32 rxstat0, rxstat1;
+       rx_status = &desc->ud.ds_rx.rx_stat;
++      rxstat1 = ACCESS_ONCE(rx_status->rx_status_1);
+       /* No frame received / not ready */
+-      if (unlikely(!(rx_status->rx_status_1 &
+-                              AR5K_5212_RX_DESC_STATUS1_DONE)))
++      if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE)))
+               return -EINPROGRESS;
+       memset(rs, 0, sizeof(struct ath5k_rx_status));
++      rxstat0 = ACCESS_ONCE(rx_status->rx_status_0);
+       /*
+        * Frame receive status
+        */
+-      rs->rs_datalen = rx_status->rx_status_0 &
+-              AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
+-      rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
++      rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
++      rs->rs_rssi = AR5K_REG_MS(rxstat0,
+               AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+-      rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
++      rs->rs_rate = AR5K_REG_MS(rxstat0,
+               AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
+-      rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
++      rs->rs_antenna = AR5K_REG_MS(rxstat0,
+               AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
+-      rs->rs_more = !!(rx_status->rx_status_0 &
+-              AR5K_5212_RX_DESC_STATUS0_MORE);
+-      rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
++      rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE);
++      rs->rs_tstamp = AR5K_REG_MS(rxstat1,
+               AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+       /*
+        * Key table status
+        */
+-      if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
+-              rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
++      if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
++              rs->rs_keyix = AR5K_REG_MS(rxstat1,
+                                          AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
+       else
+               rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+@@ -641,27 +641,22 @@ static int ath5k_hw_proc_5212_rx_status(
+       /*
+        * Receive/descriptor errors
+        */
+-      if (!(rx_status->rx_status_1 &
+-          AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
+-              if (rx_status->rx_status_1 &
+-                              AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
++      if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
++              if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
+                       rs->rs_status |= AR5K_RXERR_CRC;
+-              if (rx_status->rx_status_1 &
+-                              AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
++              if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
+                       rs->rs_status |= AR5K_RXERR_PHY;
+-                      rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
++                      rs->rs_phyerr = AR5K_REG_MS(rxstat1,
+                               AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE);
+                       if (!ah->ah_capabilities.cap_has_phyerr_counters)
+                               ath5k_ani_phy_error_report(ah, rs->rs_phyerr);
+               }
+-              if (rx_status->rx_status_1 &
+-                              AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
++              if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+                       rs->rs_status |= AR5K_RXERR_DECRYPT;
+-              if (rx_status->rx_status_1 &
+-                              AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
++              if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
+                       rs->rs_status |= AR5K_RXERR_MIC;
+       }
+       return 0;
diff --git a/package/mac80211/patches/468-ath5k_remove_ts_retry.patch b/package/mac80211/patches/468-ath5k_remove_ts_retry.patch
new file mode 100644 (file)
index 0000000..5e0b743
--- /dev/null
@@ -0,0 +1,125 @@
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -452,11 +452,10 @@ struct ath5k_tx_status {
+       u16     ts_seqnum;
+       u16     ts_tstamp;
+       u8      ts_status;
+-      u8      ts_retry[4];
+       u8      ts_final_idx;
++      u8      ts_final_retry;
+       s8      ts_rssi;
+       u8      ts_shortretry;
+-      u8      ts_longretry;
+       u8      ts_virtcol;
+       u8      ts_antenna;
+ };
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -1573,20 +1573,27 @@ ath5k_tx_frame_completed(struct ath5k_so
+                        struct ath5k_txq *txq, struct ath5k_tx_status *ts)
+ {
+       struct ieee80211_tx_info *info;
++      u8 tries[3];
+       int i;
+       sc->stats.tx_all_count++;
+       sc->stats.tx_bytes_count += skb->len;
+       info = IEEE80211_SKB_CB(skb);
++      tries[0] = info->status.rates[0].count;
++      tries[1] = info->status.rates[1].count;
++      tries[2] = info->status.rates[2].count;
++
+       ieee80211_tx_info_clear_status(info);
+-      for (i = 0; i <= ts->ts_final_idx; i++) {
++
++      for (i = 0; i < ts->ts_final_idx; i++) {
+               struct ieee80211_tx_rate *r =
+                       &info->status.rates[i];
+-              r->count = ts->ts_retry[i];
++              r->count = tries[i];
+       }
++      info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry;
+       info->status.rates[ts->ts_final_idx + 1].idx = -1;
+       if (unlikely(ts->ts_status)) {
+--- a/drivers/net/wireless/ath/ath5k/desc.c
++++ b/drivers/net/wireless/ath/ath5k/desc.c
+@@ -366,7 +366,7 @@ static int ath5k_hw_proc_2word_tx_status
+               AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+       ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+               AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+-      ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
++      ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0,
+               AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+       /*TODO: ts->ts_virtcol + test*/
+       ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+@@ -375,7 +375,6 @@ static int ath5k_hw_proc_2word_tx_status
+               AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+       ts->ts_antenna = 1;
+       ts->ts_status = 0;
+-      ts->ts_retry[0] = ts->ts_longretry;
+       ts->ts_final_idx = 0;
+       if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+@@ -401,7 +400,7 @@ static int ath5k_hw_proc_4word_tx_status
+ {
+       struct ath5k_hw_4w_tx_ctl *tx_ctl;
+       struct ath5k_hw_tx_status *tx_status;
+-      u32 txstat0, txstat1, txctl2;
++      u32 txstat0, txstat1;
+       tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+       tx_status = &desc->ud.ds_tx5212.tx_stat;
+@@ -413,7 +412,6 @@ static int ath5k_hw_proc_4word_tx_status
+               return -EINPROGRESS;
+       txstat0 = ACCESS_ONCE(tx_status->tx_status_0);
+-      txctl2 = ACCESS_ONCE(tx_ctl->tx_control_2);
+       /*
+        * Get descriptor status
+@@ -422,7 +420,7 @@ static int ath5k_hw_proc_4word_tx_status
+               AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+       ts->ts_shortretry = AR5K_REG_MS(txstat0,
+               AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+-      ts->ts_longretry = AR5K_REG_MS(txstat0,
++      ts->ts_final_retry = AR5K_REG_MS(txstat0,
+               AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+       ts->ts_seqnum = AR5K_REG_MS(txstat1,
+               AR5K_DESC_TX_STATUS1_SEQ_NUM);
+@@ -435,32 +433,6 @@ static int ath5k_hw_proc_4word_tx_status
+       ts->ts_final_idx = AR5K_REG_MS(txstat1,
+                       AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212);
+-      /* The longretry counter has the number of un-acked retries
+-       * for the final rate. To get the total number of retries
+-       * we have to add the retry counters for the other rates
+-       * as well
+-       */
+-      ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
+-      switch (ts->ts_final_idx) {
+-      case 3:
+-              ts->ts_retry[2] = AR5K_REG_MS(txctl2,
+-                      AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
+-              ts->ts_longretry += ts->ts_retry[2];
+-              /* fall through */
+-      case 2:
+-              ts->ts_retry[1] = AR5K_REG_MS(txctl2,
+-                      AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+-              ts->ts_longretry += ts->ts_retry[1];
+-              /* fall through */
+-      case 1:
+-              ts->ts_retry[0] = AR5K_REG_MS(txctl2,
+-                      AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+-              ts->ts_longretry += ts->ts_retry[0];
+-              /* fall through */
+-      case 0:
+-              break;
+-      }
+-
+       /* TX error */
+       if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
+               if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
diff --git a/package/mac80211/patches/469-ath5k_cleanup_debugfs.patch b/package/mac80211/patches/469-ath5k_cleanup_debugfs.patch
new file mode 100644 (file)
index 0000000..875f21f
--- /dev/null
@@ -0,0 +1,143 @@
+--- a/drivers/net/wireless/ath/ath5k/debug.c
++++ b/drivers/net/wireless/ath/ath5k/debug.c
+@@ -888,64 +888,37 @@ static const struct file_operations fops
+ void
+ ath5k_debug_init_device(struct ath5k_softc *sc)
+ {
++      struct dentry *phydir;
++
+       sc->debug.level = ath5k_debug;
+-      sc->debug.debugfs_phydir = debugfs_create_dir("ath5k",
+-                              sc->hw->wiphy->debugfsdir);
++      phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir);
++      if (!phydir)
++          return;
+-      sc->debug.debugfs_debug = debugfs_create_file("debug",
+-                              S_IWUSR | S_IRUSR,
+-                              sc->debug.debugfs_phydir, sc, &fops_debug);
+-
+-      sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR,
+-                              sc->debug.debugfs_phydir, sc, &fops_registers);
+-
+-      sc->debug.debugfs_beacon = debugfs_create_file("beacon",
+-                              S_IWUSR | S_IRUSR,
+-                              sc->debug.debugfs_phydir, sc, &fops_beacon);
+-
+-      sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR,
+-                              sc->debug.debugfs_phydir, sc, &fops_reset);
+-
+-      sc->debug.debugfs_antenna = debugfs_create_file("antenna",
+-                              S_IWUSR | S_IRUSR,
+-                              sc->debug.debugfs_phydir, sc, &fops_antenna);
+-
+-      sc->debug.debugfs_misc = debugfs_create_file("misc",
+-                              S_IRUSR,
+-                              sc->debug.debugfs_phydir, sc, &fops_misc);
+-
+-      sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors",
+-                              S_IWUSR | S_IRUSR,
+-                              sc->debug.debugfs_phydir, sc,
+-                              &fops_frameerrors);
+-
+-      sc->debug.debugfs_ani = debugfs_create_file("ani",
+-                              S_IWUSR | S_IRUSR,
+-                              sc->debug.debugfs_phydir, sc,
+-                              &fops_ani);
+-
+-      sc->debug.debugfs_queue = debugfs_create_file("queue",
+-                              S_IWUSR | S_IRUSR,
+-                              sc->debug.debugfs_phydir, sc,
+-                              &fops_queue);
+-}
++      debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc,
++                          &fops_debug);
+-void
+-ath5k_debug_finish_device(struct ath5k_softc *sc)
+-{
+-      debugfs_remove(sc->debug.debugfs_debug);
+-      debugfs_remove(sc->debug.debugfs_registers);
+-      debugfs_remove(sc->debug.debugfs_beacon);
+-      debugfs_remove(sc->debug.debugfs_reset);
+-      debugfs_remove(sc->debug.debugfs_antenna);
+-      debugfs_remove(sc->debug.debugfs_misc);
+-      debugfs_remove(sc->debug.debugfs_frameerrors);
+-      debugfs_remove(sc->debug.debugfs_ani);
+-      debugfs_remove(sc->debug.debugfs_queue);
+-      debugfs_remove(sc->debug.debugfs_phydir);
+-}
++      debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers);
++
++      debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc,
++                          &fops_beacon);
++      debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset);
++
++      debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc,
++                          &fops_antenna);
++
++      debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc);
++
++      debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc,
++                          &fops_frameerrors);
++
++      debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani);
++
++      debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc,
++                          &fops_queue);
++}
+ /* functions used in other places */
+--- a/drivers/net/wireless/ath/ath5k/debug.h
++++ b/drivers/net/wireless/ath/ath5k/debug.h
+@@ -68,17 +68,6 @@ struct ath5k_buf;
+ struct ath5k_dbg_info {
+       unsigned int            level;          /* debug level */
+-      /* debugfs entries */
+-      struct dentry           *debugfs_phydir;
+-      struct dentry           *debugfs_debug;
+-      struct dentry           *debugfs_registers;
+-      struct dentry           *debugfs_beacon;
+-      struct dentry           *debugfs_reset;
+-      struct dentry           *debugfs_antenna;
+-      struct dentry           *debugfs_misc;
+-      struct dentry           *debugfs_frameerrors;
+-      struct dentry           *debugfs_ani;
+-      struct dentry           *debugfs_queue;
+ };
+ /**
+@@ -141,9 +130,6 @@ void
+ ath5k_debug_init_device(struct ath5k_softc *sc);
+ void
+-ath5k_debug_finish_device(struct ath5k_softc *sc);
+-
+-void
+ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
+ void
+@@ -167,9 +153,6 @@ static inline void
+ ath5k_debug_init_device(struct ath5k_softc *sc) {}
+ static inline void
+-ath5k_debug_finish_device(struct ath5k_softc *sc) {}
+-
+-static inline void
+ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
+ static inline void
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -2901,7 +2901,6 @@ ath5k_deinit_softc(struct ath5k_softc *s
+        * XXX: ??? detach ath5k_hw ???
+        * Other than that, it's straightforward...
+        */
+-      ath5k_debug_finish_device(sc);
+       ieee80211_unregister_hw(hw);
+       ath5k_desc_free(sc);
+       ath5k_txq_release(sc);
diff --git a/package/mac80211/patches/470-ath5k_decrease_irq_load.patch b/package/mac80211/patches/470-ath5k_decrease_irq_load.patch
new file mode 100644 (file)
index 0000000..5273bb0
--- /dev/null
@@ -0,0 +1,140 @@
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -872,6 +872,19 @@ enum ath5k_int {
+       AR5K_INT_QTRIG  =       0x40000000, /* Non common */
+       AR5K_INT_GLOBAL =       0x80000000,
++      AR5K_INT_TX_ALL = AR5K_INT_TXOK
++              | AR5K_INT_TXDESC
++              | AR5K_INT_TXERR
++              | AR5K_INT_TXEOL
++              | AR5K_INT_TXURN,
++
++      AR5K_INT_RX_ALL = AR5K_INT_RXOK
++              | AR5K_INT_RXDESC
++              | AR5K_INT_RXERR
++              | AR5K_INT_RXNOFRM
++              | AR5K_INT_RXEOL
++              | AR5K_INT_RXORN,
++
+       AR5K_INT_COMMON  = AR5K_INT_RXOK
+               | AR5K_INT_RXDESC
+               | AR5K_INT_RXERR
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -1444,6 +1444,21 @@ ath5k_receive_frame_ok(struct ath5k_soft
+ }
+ static void
++ath5k_set_current_imask(struct ath5k_softc *sc)
++{
++      enum ath5k_int imask = sc->imask;
++      unsigned long flags;
++
++      spin_lock_irqsave(&sc->irqlock, flags);
++      if (sc->rx_pending)
++              imask &= ~AR5K_INT_RX_ALL;
++      if (sc->tx_pending)
++              imask &= ~AR5K_INT_TX_ALL;
++      ath5k_hw_set_imr(sc->ah, imask);
++      spin_unlock_irqrestore(&sc->irqlock, flags);
++}
++
++static void
+ ath5k_tasklet_rx(unsigned long data)
+ {
+       struct ath5k_rx_status rs = {};
+@@ -1506,6 +1521,8 @@ next:
+       } while (ath5k_rxbuf_setup(sc, bf) == 0);
+ unlock:
+       spin_unlock(&sc->rxbuflock);
++      sc->rx_pending = false;
++      ath5k_set_current_imask(sc);
+ }
+@@ -1693,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data)
+       for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
+               if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
+                       ath5k_tx_processq(sc, &sc->txqs[i]);
++
++      sc->tx_pending = false;
++      ath5k_set_current_imask(sc);
+ }
+@@ -2122,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k
+        * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
+ }
++static void
++ath5k_schedule_rx(struct ath5k_softc *sc)
++{
++      sc->rx_pending = true;
++      tasklet_schedule(&sc->rxtq);
++}
++
++static void
++ath5k_schedule_tx(struct ath5k_softc *sc)
++{
++      sc->tx_pending = true;
++      tasklet_schedule(&sc->txtq);
++}
++
+ irqreturn_t
+ ath5k_intr(int irq, void *dev_id)
+ {
+@@ -2164,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id)
+                               ieee80211_queue_work(sc->hw, &sc->reset_work);
+                       }
+                       else
+-                              tasklet_schedule(&sc->rxtq);
++                              ath5k_schedule_rx(sc);
+               } else {
+                       if (status & AR5K_INT_SWBA) {
+                               tasklet_hi_schedule(&sc->beacontq);
+@@ -2182,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id)
+                               ath5k_hw_update_tx_triglevel(ah, true);
+                       }
+                       if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
+-                              tasklet_schedule(&sc->rxtq);
++                              ath5k_schedule_rx(sc);
+                       if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
+                                       | AR5K_INT_TXERR | AR5K_INT_TXEOL))
+-                              tasklet_schedule(&sc->txtq);
++                              ath5k_schedule_tx(sc);
+                       if (status & AR5K_INT_BMISS) {
+                               /* TODO */
+                       }
+@@ -2204,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id)
+       } while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
++      if (sc->rx_pending || sc->tx_pending)
++              ath5k_set_current_imask(sc);
++
+       if (unlikely(!counter))
+               ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
+@@ -2575,6 +2612,8 @@ done:
+ static void stop_tasklets(struct ath5k_softc *sc)
+ {
++      sc->rx_pending = false;
++      sc->tx_pending = false;
+       tasklet_kill(&sc->rxtq);
+       tasklet_kill(&sc->txtq);
+       tasklet_kill(&sc->calib);
+--- a/drivers/net/wireless/ath/ath5k/base.h
++++ b/drivers/net/wireless/ath/ath5k/base.h
+@@ -207,6 +207,10 @@ struct ath5k_softc {
+       enum ath5k_int          imask;          /* interrupt mask copy */
++      spinlock_t              irqlock;
++      bool                    rx_pending;     /* rx tasklet pending */
++      bool                    tx_pending;     /* tx tasklet pending */
++
+       u8                      lladdr[ETH_ALEN];
+       u8                      bssidmask[ETH_ALEN];
diff --git a/package/mac80211/patches/471-ath5k_detect_2ghz_radio.patch b/package/mac80211/patches/471-ath5k_detect_2ghz_radio.patch
new file mode 100644 (file)
index 0000000..c394562
--- /dev/null
@@ -0,0 +1,12 @@
+--- a/drivers/net/wireless/ath/ath5k/caps.c
++++ b/drivers/net/wireless/ath/ath5k/caps.c
+@@ -94,6 +94,9 @@ int ath5k_hw_set_capabilities(struct ath
+               }
+       }
++      if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112)
++              __clear_bit(AR5K_MODE_11A, caps->cap_mode);
++
+       /* Set number of supported TX queues */
+       if (ah->ah_version == AR5K_AR5210)
+               caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU;
diff --git a/package/mac80211/patches/472-ath_unshare_bus_ops.patch b/package/mac80211/patches/472-ath_unshare_bus_ops.patch
new file mode 100644 (file)
index 0000000..b3b0eab
--- /dev/null
@@ -0,0 +1,50 @@
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -123,14 +123,7 @@ struct ath_ops {
+ };
+ struct ath_common;
+-
+-struct ath_bus_ops {
+-      enum ath_bus_type ath_bus_type;
+-      void (*read_cachesize)(struct ath_common *common, int *csz);
+-      bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
+-      void (*bt_coex_prep)(struct ath_common *common);
+-      void (*extn_synch_en)(struct ath_common *common);
+-};
++struct ath_bus_ops;
+ struct ath_common {
+       void *ah;
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -847,6 +847,14 @@ struct ath_hw {
+       u32 ent_mode;
+ };
++struct ath_bus_ops {
++      enum ath_bus_type ath_bus_type;
++      void (*read_cachesize)(struct ath_common *common, int *csz);
++      bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
++      void (*bt_coex_prep)(struct ath_common *common);
++      void (*extn_synch_en)(struct ath_common *common);
++};
++
+ static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
+ {
+       return &ah->common;
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1155,6 +1155,12 @@ struct ath5k_hw {
+               struct ath5k_rx_status *);
+ };
++struct ath_bus_ops {
++      enum ath_bus_type ath_bus_type;
++      void (*read_cachesize)(struct ath_common *common, int *csz);
++      bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
++};
++
+ /*
+  * Prototypes
+  */
diff --git a/package/mac80211/patches/473-ath5k_read_mac_addr.patch b/package/mac80211/patches/473-ath5k_read_mac_addr.patch
new file mode 100644 (file)
index 0000000..83c951f
--- /dev/null
@@ -0,0 +1,179 @@
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1159,6 +1159,7 @@ struct ath_bus_ops {
+       enum ath_bus_type ath_bus_type;
+       void (*read_cachesize)(struct ath_common *common, int *csz);
+       bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
++      int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac);
+ };
+ /*
+@@ -1244,7 +1245,6 @@ int ath5k_hw_dma_stop(struct ath5k_hw *a
+ /* EEPROM access functions */
+ int ath5k_eeprom_init(struct ath5k_hw *ah);
+ void ath5k_eeprom_detach(struct ath5k_hw *ah);
+-int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
+ /* Protocol Control Unit Functions */
+--- a/drivers/net/wireless/ath/ath5k/eeprom.c
++++ b/drivers/net/wireless/ath/ath5k/eeprom.c
+@@ -1723,46 +1723,6 @@ ath5k_eeprom_read_spur_chans(struct ath5
+       return ret;
+ }
+-/*
+- * Read the MAC address from eeprom or platform_data
+- */
+-int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+-{
+-      u8 mac_d[ETH_ALEN] = {};
+-      u32 total, offset;
+-      u16 data;
+-      int octet;
+-      struct ath5k_platform_data *pdata = NULL;
+-
+-      if (ah->ah_sc->pdev)
+-              pdata = ah->ah_sc->pdev->dev.platform_data;
+-
+-      if (pdata && pdata->macaddr)
+-      {
+-              memcpy(mac, pdata->macaddr, ETH_ALEN);
+-              return 0;
+-      }
+-
+-      AR5K_EEPROM_READ(0x20, data);
+-
+-      for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+-              AR5K_EEPROM_READ(offset, data);
+-
+-              total += data;
+-              mac_d[octet + 1] = data & 0xff;
+-              mac_d[octet] = data >> 8;
+-              octet += 2;
+-      }
+-
+-      if (!total || total == 3 * 0xffff)
+-              return -EINVAL;
+-
+-      memcpy(mac, mac_d, ETH_ALEN);
+-
+-      return 0;
+-}
+-
+-
+ /***********************\
+ * Init/Detach functions *
+ \***********************/
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -18,6 +18,7 @@
+ #include <linux/pci.h>
+ #include <linux/pci-aspm.h>
+ #include <linux/ath5k_platform.h>
++#include <linux/etherdevice.h>
+ #include "../ath.h"
+ #include "ath5k.h"
+ #include "debug.h"
+@@ -122,11 +123,52 @@ int ath5k_hw_read_srev(struct ath5k_hw *
+       return 0;
+ }
++/*
++ * Read the MAC address from eeprom or platform_data
++ */
++static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
++{
++      u8 mac_d[ETH_ALEN] = {};
++      u32 total, offset;
++      u16 data;
++      int octet;
++      struct ath5k_platform_data *pdata = NULL;
++
++      if (ah->ah_sc->pdev)
++              pdata = ah->ah_sc->pdev->dev.platform_data;
++
++      if (pdata && pdata->macaddr)
++      {
++              memcpy(mac, pdata->macaddr, ETH_ALEN);
++              return 0;
++      }
++
++      AR5K_EEPROM_READ(0x20, data);
++
++      for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
++              AR5K_EEPROM_READ(offset, data);
++
++              total += data;
++              mac_d[octet + 1] = data & 0xff;
++              mac_d[octet] = data >> 8;
++              octet += 2;
++      }
++
++      if (!total || total == 3 * 0xffff)
++              return -EINVAL;
++
++      memcpy(mac, mac_d, ETH_ALEN);
++
++      return 0;
++}
++
++
+ /* Common ath_bus_opts structure */
+ static const struct ath_bus_ops ath_pci_bus_ops = {
+       .ath_bus_type = ATH_PCI,
+       .read_cachesize = ath5k_pci_read_cachesize,
+       .eeprom_read = ath5k_pci_eeprom_read,
++      .eeprom_read_mac = ath5k_pci_eeprom_read_mac,
+ };
+ /********************\
+--- a/drivers/net/wireless/ath/ath5k/ahb.c
++++ b/drivers/net/wireless/ath/ath5k/ahb.c
+@@ -18,6 +18,7 @@
+ #include <linux/nl80211.h>
+ #include <linux/platform_device.h>
++#include <linux/etherdevice.h>
+ #include <ar231x_platform.h>
+ #include "ath5k.h"
+ #include "debug.h"
+@@ -62,10 +63,27 @@ int ath5k_hw_read_srev(struct ath5k_hw *
+       return 0;
+ }
++static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
++{
++      struct ath5k_softc *sc = ah->ah_sc;
++      struct platform_device *pdev = to_platform_device(sc->dev);
++      struct ar231x_board_config *bcfg = pdev->dev.platform_data;
++      u8 *cfg_mac;
++
++      if (to_platform_device(sc->dev)->id == 0)
++              cfg_mac = bcfg->config->wlan0_mac;
++      else
++              cfg_mac = bcfg->config->wlan1_mac;
++
++      memcpy(mac, cfg_mac, ETH_ALEN);
++      return 0;
++}
++
+ static const struct ath_bus_ops ath_ahb_bus_ops = {
+       .ath_bus_type = ATH_AHB,
+       .read_cachesize = ath5k_ahb_read_cachesize,
+       .eeprom_read = ath5k_ahb_eeprom_read,
++      .eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
+ };
+ /*Initialization*/
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -2880,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw)
+       INIT_WORK(&sc->reset_work, ath5k_reset_work);
+       INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);
+-      ret = ath5k_eeprom_read_mac(ah, mac);
++      ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac);
+       if (ret) {
+               ATH5K_ERR(sc, "unable to read address from EEPROM\n");
+               goto err_queues;
diff --git a/package/mac80211/patches/474-ath5k_fix_aes_crypto_support.patch b/package/mac80211/patches/474-ath5k_fix_aes_crypto_support.patch
new file mode 100644 (file)
index 0000000..cac679a
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath5k/attach.c
++++ b/drivers/net/wireless/ath/ath5k/attach.c
+@@ -318,7 +318,7 @@ int ath5k_hw_init(struct ath5k_softc *sc
+                         AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
+       if (srev >= AR5K_SREV_AR5212_V4 &&
+-          (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 &&
++          (ee->ee_version < AR5K_EEPROM_VERSION_5_0 ||
+           !AR5K_EEPROM_AES_DIS(ee->ee_misc5)))
+               common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM;
diff --git a/package/mac80211/patches/475-ath5k_fix_ar5312_5ghz_cap.patch b/package/mac80211/patches/475-ath5k_fix_ar5312_5ghz_cap.patch
new file mode 100644 (file)
index 0000000..535c61e
--- /dev/null
@@ -0,0 +1,50 @@
+--- a/drivers/net/wireless/ath/ath5k/base.h
++++ b/drivers/net/wireless/ath/ath5k/base.h
+@@ -193,12 +193,13 @@ struct ath5k_softc {
+       dma_addr_t              desc_daddr;     /* DMA (physical) address */
+       size_t                  desc_len;       /* size of TX/RX descriptors */
+-      DECLARE_BITMAP(status, 5);
++      DECLARE_BITMAP(status, 6);
+ #define ATH_STAT_INVALID      0               /* disable hardware accesses */
+ #define ATH_STAT_MRRETRY      1               /* multi-rate retry support */
+ #define ATH_STAT_PROMISC      2
+ #define ATH_STAT_LEDSOFT      3               /* enable LED gpio status */
+ #define ATH_STAT_STARTED      4               /* opened & irqs enabled */
++#define ATH_STAT_2G_DISABLED  5               /* multiband radio without 2G */
+       unsigned int            filter_flags;   /* HW flags, AR5K_RX_FILTER_* */
+       struct ieee80211_channel *curchan;      /* current h/w channel */
+--- a/drivers/net/wireless/ath/ath5k/ahb.c
++++ b/drivers/net/wireless/ath/ath5k/ahb.c
+@@ -160,6 +160,16 @@ static int ath_ahb_probe(struct platform
+               else
+                       reg |= AR5K_AR5312_ENABLE_WLAN1;
+               __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
++
++              /*
++               * On a dual-band AR5312, the multiband radio is only
++               * used as pass-through. Disable 2 GHz support in the
++               * driver for it
++               */
++              if (to_platform_device(sc->dev)->id == 0 &&
++                  (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) ==
++                   (BD_WLAN1|BD_WLAN0))
++                      __set_bit(ATH_STAT_2G_DISABLED, sc->status);
+       }
+       ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
+--- a/drivers/net/wireless/ath/ath5k/attach.c
++++ b/drivers/net/wireless/ath/ath5k/attach.c
+@@ -313,6 +313,11 @@ int ath5k_hw_init(struct ath5k_softc *sc
+               goto err;
+       }
++      if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) {
++              __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode);
++              __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode);
++      }
++
+       /* Crypto settings */
+       common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?
+                         AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);
index 693cdd2..e779ad3 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/mac80211/rx.c
 +++ b/net/mac80211/rx.c
-@@ -2330,13 +2330,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+@@ -2328,13 +2328,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
  
        if (!ieee80211_vif_is_mesh(&sdata->vif) &&
            sdata->vif.type != NL80211_IFTYPE_ADHOC &&
@@ -17,7 +17,7 @@
                break;
        case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
        case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
-@@ -2716,7 +2717,10 @@ static int prepare_for_handlers(struct i
+@@ -2714,7 +2715,10 @@ static int prepare_for_handlers(struct i
                }
                break;
        case NL80211_IFTYPE_WDS:
index 953ff59..e171946 100644 (file)
@@ -33,7 +33,7 @@
                                          IEEE80211_STYPE_ACTION);
 --- a/net/mac80211/rx.c
 +++ b/net/mac80211/rx.c
-@@ -2132,7 +2132,8 @@ ieee80211_rx_h_action(struct ieee80211_r
+@@ -2130,7 +2130,8 @@ ieee80211_rx_h_action(struct ieee80211_r
                 */
                if (sdata->vif.type != NL80211_IFTYPE_STATION &&
                    sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
@@ -43,7 +43,7 @@
                        break;
  
                /* verify action_code is present */
-@@ -2717,13 +2718,16 @@ static int prepare_for_handlers(struct i
+@@ -2715,13 +2716,16 @@ static int prepare_for_handlers(struct i
                }
                break;
        case NL80211_IFTYPE_WDS: