summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/qcu.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-23 11:47:02 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-23 11:47:02 -0700
commit5f05647dd81c11a6a165ccc8f0c1370b16f3bcb0 (patch)
tree7851ef1c93aa1aba7ef327ca4b75fd35e6d10f29 /drivers/net/wireless/ath/ath5k/qcu.c
parent02f36038c568111ad4fc433f6fa760ff5e38fab4 (diff)
parentec37a48d1d16c30b655ac5280209edf52a6775d4 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1699 commits) bnx2/bnx2x: Unsupported Ethtool operations should return -EINVAL. vlan: Calling vlan_hwaccel_do_receive() is always valid. tproxy: use the interface primary IP address as a default value for --on-ip tproxy: added IPv6 support to the socket match cxgb3: function namespace cleanup tproxy: added IPv6 support to the TPROXY target tproxy: added IPv6 socket lookup function to nf_tproxy_core be2net: Changes to use only priority codes allowed by f/w tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled tproxy: added tproxy sockopt interface in the IPV6 layer tproxy: added udp6_lib_lookup function tproxy: added const specifiers to udp lookup functions tproxy: split off ipv6 defragmentation to a separate module l2tp: small cleanup nf_nat: restrict ICMP translation for embedded header can: mcp251x: fix generation of error frames can: mcp251x: fix endless loop in interrupt handler if CANINTF_MERRF is set can-raw: add msg_flags to distinguish local traffic 9p: client code cleanup rds: make local functions/variables static ... Fix up conflicts in net/core/dev.c, drivers/net/pcmcia/smc91c92_cs.c and drivers/net/wireless/ath/ath9k/debug.c as per David
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/qcu.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c99
1 files changed, 51 insertions, 48 deletions
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 4186ff4c6e9..84c717ded1c 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -36,24 +36,58 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
}
/*
+ * Make sure cw is a power of 2 minus 1 and smaller than 1024
+ */
+static u16 ath5k_cw_validate(u16 cw_req)
+{
+ u32 cw = 1;
+ cw_req = min(cw_req, (u16)1023);
+
+ while (cw < cw_req)
+ cw = (cw << 1) | 1;
+
+ return cw;
+}
+
+/*
* Set properties for a transmit queue
*/
int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
- const struct ath5k_txq_info *queue_info)
+ const struct ath5k_txq_info *qinfo)
{
+ struct ath5k_txq_info *qi;
+
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
- if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ qi = &ah->ah_txq[queue];
+
+ if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE)
return -EIO;
- memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
+ /* copy and validate values */
+ qi->tqi_type = qinfo->tqi_type;
+ qi->tqi_subtype = qinfo->tqi_subtype;
+ qi->tqi_flags = qinfo->tqi_flags;
+ /*
+ * According to the docs: Although the AIFS field is 8 bit wide,
+ * the maximum supported value is 0xFC. Setting it higher than that
+ * will cause the DCU to hang.
+ */
+ qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC);
+ qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min);
+ qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max);
+ qi->tqi_cbr_period = qinfo->tqi_cbr_period;
+ qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit;
+ qi->tqi_burst_time = qinfo->tqi_burst_time;
+ qi->tqi_ready_time = qinfo->tqi_ready_time;
/*XXX: Is this supported on 5210 ?*/
- if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
- ((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
- (queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
- queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
- ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
+ /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/
+ if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA &&
+ ((qinfo->tqi_subtype == AR5K_WME_AC_VI) ||
+ (qinfo->tqi_subtype == AR5K_WME_AC_VO))) ||
+ qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD)
+ qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
return 0;
}
@@ -186,7 +220,7 @@ void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
*/
int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
{
- u32 cw_min, cw_max, retry_lg, retry_sh;
+ u32 retry_lg, retry_sh;
struct ath5k_txq_info *tq = &ah->ah_txq[queue];
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
@@ -217,14 +251,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
/* Set IFS0 */
if (ah->ah_turbo) {
ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
- (ah->ah_aifs + tq->tqi_aifs) *
- AR5K_INIT_SLOT_TIME_TURBO) <<
+ tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) <<
AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
AR5K_IFS0);
} else {
ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
- (ah->ah_aifs + tq->tqi_aifs) *
- AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
+ tq->tqi_aifs * AR5K_INIT_SLOT_TIME) <<
+ AR5K_IFS0_DIFS_S) |
AR5K_INIT_SIFS, AR5K_IFS0);
}
@@ -248,35 +281,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
}
/*
- * Calculate cwmin/max by channel mode
- */
- cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
- cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
- ah->ah_aifs = AR5K_TUNE_AIFS;
- /*XR is only supported on 5212*/
- if (IS_CHAN_XR(ah->ah_current_channel) &&
- ah->ah_version == AR5K_AR5212) {
- cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
- cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
- ah->ah_aifs = AR5K_TUNE_AIFS_XR;
- /*B mode is not supported on 5210*/
- } else if (IS_CHAN_B(ah->ah_current_channel) &&
- ah->ah_version != AR5K_AR5210) {
- cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
- cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
- ah->ah_aifs = AR5K_TUNE_AIFS_11B;
- }
-
- cw_min = 1;
- while (cw_min < ah->ah_cw_min)
- cw_min = (cw_min << 1) | 1;
-
- cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
- ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
- cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
- ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
-
- /*
* Calculate and set retry limits
*/
if (ah->ah_software_retry) {
@@ -292,7 +296,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
/*No QCU/DCU [5210]*/
if (ah->ah_version == AR5K_AR5210) {
ath5k_hw_reg_write(ah,
- (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
+ (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
AR5K_NODCU_RETRY_LMT_SLG_RETRY)
| AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
@@ -314,14 +318,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
/*===Rest is also for QCU/DCU only [5211+]===*/
/*
- * Set initial content window (cw_min/cw_max)
+ * Set contention window (cw_min/cw_max)
* and arbitrated interframe space (aifs)...
*/
ath5k_hw_reg_write(ah,
- AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
- AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
- AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
- AR5K_DCU_LCL_IFS_AIFS),
+ AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+ AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+ AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
AR5K_QUEUE_DFS_LOCAL_IFS(queue));
/*