diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index cf4272d92..74acba566 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -170,7 +170,7 @@ 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); @@ -180,17 +180,13 @@ 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; @@ -198,7 +194,7 @@ 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 index 000000000..b6bfa2405 --- /dev/null +++ b/package/mac80211/patches/460-ath5k_fix_tx_status_reporting.patch @@ -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 index 000000000..8d0a3e800 --- /dev/null +++ b/package/mac80211/patches/461-ath5k_fix_short_preamble_dur.patch @@ -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 index 000000000..7d3efcae5 --- /dev/null +++ b/package/mac80211/patches/462-ath5k_fix_sifs.patch @@ -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 index 000000000..01e55d35d --- /dev/null +++ b/package/mac80211/patches/463-ath5k_fix_slottime.patch @@ -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 index 000000000..77dfae8c7 --- /dev/null +++ b/package/mac80211/patches/464-ath5k_optimize_tx_desc_setup.patch @@ -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 index 000000000..265b6a755 --- /dev/null +++ b/package/mac80211/patches/465-ath5k_remove_ts_rate.patch @@ -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 index 000000000..04ba844a2 --- /dev/null +++ b/package/mac80211/patches/466-ath5k_optimize_tx_status.patch @@ -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 index 000000000..b0ccb5fe4 --- /dev/null +++ b/package/mac80211/patches/467-ath5k_optimize_rx_status.patch @@ -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 index 000000000..5e0b7432d --- /dev/null +++ b/package/mac80211/patches/468-ath5k_remove_ts_retry.patch @@ -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 index 000000000..875f21f4a --- /dev/null +++ b/package/mac80211/patches/469-ath5k_cleanup_debugfs.patch @@ -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 index 000000000..5273bb075 --- /dev/null +++ b/package/mac80211/patches/470-ath5k_decrease_irq_load.patch @@ -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 index 000000000..c394562a4 --- /dev/null +++ b/package/mac80211/patches/471-ath5k_detect_2ghz_radio.patch @@ -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 index 000000000..b3b0eab1f --- /dev/null +++ b/package/mac80211/patches/472-ath_unshare_bus_ops.patch @@ -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 index 000000000..83c951fdc --- /dev/null +++ b/package/mac80211/patches/473-ath5k_read_mac_addr.patch @@ -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 + #include + #include ++#include + #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 + #include ++#include + #include + #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 index 000000000..cac679a59 --- /dev/null +++ b/package/mac80211/patches/474-ath5k_fix_aes_crypto_support.patch @@ -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 index 000000000..535c61e43 --- /dev/null +++ b/package/mac80211/patches/475-ath5k_fix_ar5312_5ghz_cap.patch @@ -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); diff --git a/package/mac80211/patches/551-mac80211_fix_iftype_wds.patch b/package/mac80211/patches/551-mac80211_fix_iftype_wds.patch index 693cdd291..e779ad364 100644 --- a/package/mac80211/patches/551-mac80211_fix_iftype_wds.patch +++ b/package/mac80211/patches/551-mac80211_fix_iftype_wds.patch @@ -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: diff --git a/package/mac80211/patches/552-mac80211_enable_iftype_wds_aggregation.patch b/package/mac80211/patches/552-mac80211_enable_iftype_wds_aggregation.patch index 953ff59f4..e17194698 100644 --- a/package/mac80211/patches/552-mac80211_enable_iftype_wds_aggregation.patch +++ b/package/mac80211/patches/552-mac80211_enable_iftype_wds_aggregation.patch @@ -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: