diff -Naur a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h --- a/drivers/net/wireless/ath/ath9k/ath9k.h 2011-05-27 20:04:49.000000000 +0100 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h 2011-06-02 19:59:28.043327000 +0100 @@ -137,7 +137,7 @@ #define ATH_AGGR_ENCRYPTDELIM 10 /* minimum h/w qdepth to be sustained to maximize aggregation */ #define ATH_AGGR_MIN_QDEPTH 2 -#define ATH_AMPDU_SUBFRAME_DEFAULT 32 +#define ATH_AMPDU_SUBFRAME_DEFAULT sc->debug.subframe_size #define IEEE80211_SEQ_SEQ_SHIFT 4 #define IEEE80211_SEQ_MAX 4096 @@ -537,7 +537,7 @@ #define DEFAULT_CACHELINE 32 #define ATH_REGCLASSIDS_MAX 10 #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ -#define ATH_MAX_SW_RETRIES 10 +#define ATH_MAX_SW_RETRIES sc->debug.retry_limit #define ATH_CHAN_MAX 255 #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ diff -Naur a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c --- a/drivers/net/wireless/ath/ath9k/debug.c 2011-05-27 20:04:49.000000000 +0100 +++ b/drivers/net/wireless/ath/ath9k/debug.c 2011-06-02 19:54:09.260320000 +0100 @@ -1045,6 +1048,162 @@ .llseek = default_llseek, }; +static ssize_t read_file_ampdu_len(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[32]; + unsigned int len; + + len = sprintf(buf, "%u\n", sc->debug.ampdu_len); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_ampdu_len(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + unsigned long ampdu_len; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, &du_len)) + return -EINVAL; + + sc->debug.ampdu_len = ampdu_len; + return count; +} + +static const struct file_operations fops_ampdu_len = { + .read = read_file_ampdu_len, + .write = write_file_ampdu_len, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_retry_limit(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[16]; + unsigned int len; + + len = sprintf(buf, "%u\n", sc->debug.retry_limit); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_retry_limit(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + unsigned long retry_limit; + char buf[16]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, &retry_limit)) + return -EINVAL; + + sc->debug.retry_limit = retry_limit; + return count; +} + +static const struct file_operations fops_retry_limit = { + .read = read_file_retry_limit, + .write = write_file_retry_limit, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_subframe_size(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[16]; + unsigned int len; + + len = sprintf(buf, "%u\n", sc->debug.subframe_size); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_subframe_size(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + unsigned long subframe_size; + char buf[16]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, &subframe_size)) + return -EINVAL; + + sc->debug.subframe_size = subframe_size; + return count; +} + +static const struct file_operations fops_subframe_size = { + .read = read_file_subframe_size, + .write = write_file_subframe_size, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t read_file_auto_ampdu(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + char buf[8]; + unsigned int len; + + len = sprintf(buf, "%u\n", sc->debug.auto_ampdu); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_auto_ampdu(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + unsigned long auto_ampdu; + char buf[8]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, &auto_ampdu)) + return -EINVAL; + + sc->debug.auto_ampdu = auto_ampdu; + return count; +} + +static const struct file_operations fops_auto_ampdu = { + .read = read_file_auto_ampdu, + .write = write_file_auto_ampdu, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static ssize_t read_file_regval(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1162,6 +1407,15 @@ sc->debug.debugfs_phy, sc, &fops_tx_chainmask); debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_regidx); + + debugfs_create_file("ampdu_len", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_ampdu_len); + debugfs_create_file("retry_limit", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_retry_limit); + debugfs_create_file("subframe_size", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_subframe_size); + debugfs_create_file("auto_ampdu[0:OFF,1:ON]", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_auto_ampdu); debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_regval); debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, @@ -1177,5 +1302,8 @@ sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); sc->debug.regidx = 0; + sc->debug.auto_ampdu = 1; + sc->debug.ampdu_len = ATH_AMPDU_LIMIT_MAX; + sc->debug.retry_limit = 10; return 0; } diff -Naur a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h --- a/drivers/net/wireless/ath/ath9k/debug.h 2011-05-27 20:04:49.000000000 +0100 +++ b/drivers/net/wireless/ath/ath9k/debug.h 2011-06-02 19:55:33.332337000 +0100 @@ -179,6 +180,10 @@ struct ath9k_debug { struct dentry *debugfs_phy; u32 regidx; + u32 ampdu_len; + u16 retry_limit; + u16 subframe_size; + u8 auto_ampdu; struct ath_stats stats; }; diff -Naur a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c --- a/drivers/net/wireless/ath/ath9k/xmit.c 2011-05-27 20:04:49.000000000 +0100 +++ b/drivers/net/wireless/ath/ath9k/xmit.c 2011-06-02 19:58:19.647347000 +0100 @@ -616,8 +616,12 @@ if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) modeidx++; - frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx]; - max_4ms_framelen = min(max_4ms_framelen, frmlen); + frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx]; + + if (sc->debug.auto_ampdu==1) + max_4ms_framelen = min(max_4ms_framelen, frmlen); + else + max_4ms_framelen = sc->debug.ampdu_len; } } @@ -641,7 +645,7 @@ * The IE, however can hold up to 65536, which shows up here * as zero. Ignore 65536 since we are constrained by hw. */ - if (tid->an->maxampdu) + if (sc->debug.auto_ampdu==1 && tid->an->maxampdu) aggr_limit = min(aggr_limit, tid->an->maxampdu); return aggr_limit;