X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fath%2Far9170%2Fmain.c;h=fed6695ec04e4c1046cb43304f27b2bd25c5e269;hp=f9d6db8d013ec9bea5545dea749f5ba4013d4786;hb=b409894f9d6961bd5feffb86ba1d8dbbebfb5b72;hpb=f02f465b1cdcdf7485f89ec019e6cceaf80cadd5 diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index f9d6db8d013e..fed6695ec04e 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -194,12 +194,15 @@ static inline u16 ar9170_get_seq(struct sk_buff *skb) return ar9170_get_seq_h((void *) txc->frame_data); } +static inline u16 ar9170_get_tid_h(struct ieee80211_hdr *hdr) +{ + return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; +} + static inline u16 ar9170_get_tid(struct sk_buff *skb) { struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - - return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; + return ar9170_get_tid_h((struct ieee80211_hdr *) txc->frame_data); } #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) @@ -213,10 +216,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; struct ieee80211_hdr *hdr = (void *) txc->frame_data; - printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d " + printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d " "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), - ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr), + ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), jiffies_to_msecs(arinfo->timeout - jiffies)); } @@ -232,7 +235,7 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); skb_queue_walk(queue, skb) { - printk(KERN_DEBUG "index:%d => \n", i++); + printk(KERN_DEBUG "index:%d =>\n", i++); ar9170_print_txheader(ar, skb); } if (i != skb_queue_len(queue)) @@ -277,7 +280,7 @@ static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) unsigned long flags; spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); - printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n", + printk(KERN_DEBUG "%s: A-MPDU tx_status queue =>\n", wiphy_name(ar->hw->wiphy)); __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); @@ -304,7 +307,7 @@ static void ar9170_recycle_expired(struct ar9170 *ar, if (time_is_before_jiffies(arinfo->timeout)) { #ifdef AR9170_QUEUE_DEBUG printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => " - "recycle \n", wiphy_name(ar->hw->wiphy), + "recycle\n", wiphy_name(ar->hw->wiphy), jiffies, arinfo->timeout); ar9170_print_txheader(ar, skb); #endif /* AR9170_QUEUE_DEBUG */ @@ -430,7 +433,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) spin_lock_irqsave(&ar->tx_stats_lock, flags); ar->tx_stats[queue].len--; - if (skb_queue_empty(&ar->tx_pending[queue])) { + if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { #ifdef AR9170_QUEUE_STOP_DEBUG printk(KERN_DEBUG "%s: wake queue %d\n", wiphy_name(ar->hw->wiphy), queue); @@ -440,22 +443,17 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) } spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { - ar9170_tx_ampdu_callback(ar, skb); - } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { - arinfo->timeout = jiffies + - msecs_to_jiffies(AR9170_TX_TIMEOUT); - - skb_queue_tail(&ar->tx_status[queue], skb); - } else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) { + if (info->flags & IEEE80211_TX_CTL_NO_ACK) { ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); } else { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: unsupported frame flags!\n", - wiphy_name(ar->hw->wiphy)); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - dev_kfree_skb_any(skb); + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + ar9170_tx_ampdu_callback(ar, skb); + } else { + arinfo->timeout = jiffies + + msecs_to_jiffies(AR9170_TX_TIMEOUT); + + skb_queue_tail(&ar->tx_status[queue], skb); + } } if (!ar->tx_stats[queue].len && @@ -690,7 +688,8 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) /* firmware debug */ case 0xca: - printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4); + printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, + (char *)buf + 4); break; case 0xcb: len -= 4; @@ -1407,17 +1406,6 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - if (unlikely(!info->control.sta)) - goto err_out; - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); - arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; - - goto out; - } - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); /* * WARNING: * Putting the QoS queue bits into an unexplored territory is @@ -1431,12 +1419,17 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) txc->phy_control |= cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); - arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK; - } else { - arinfo->flags = AR9170_TX_FLAG_NO_ACK; + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + if (unlikely(!info->control.sta)) + goto err_out; + + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); + } else { + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); + } } -out: return 0; err_out: @@ -1671,8 +1664,7 @@ static bool ar9170_tx_ampdu(struct ar9170 *ar) * tell the FW/HW that this is the last frame, * that way it will wait for the immediate block ack. */ - if (likely(skb_peek_tail(&agg))) - ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); + ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); #ifdef AR9170_TXAGG_DEBUG printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", @@ -1716,12 +1708,27 @@ static void ar9170_tx(struct ar9170 *ar) for (i = 0; i < __AR9170_NUM_TXQ; i++) { spin_lock_irqsave(&ar->tx_stats_lock, flags); + frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, + skb_queue_len(&ar->tx_pending[i])); + + if (remaining_space < frames) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: tx quota reached queue:%d, " + "remaining slots:%d, needed:%d\n", + wiphy_name(ar->hw->wiphy), i, remaining_space, + frames); +#endif /* AR9170_QUEUE_DEBUG */ + frames = remaining_space; + } + + ar->tx_stats[i].len += frames; + ar->tx_stats[i].count += frames; if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { #ifdef AR9170_QUEUE_DEBUG printk(KERN_DEBUG "%s: queue %d full\n", wiphy_name(ar->hw->wiphy), i); - printk(KERN_DEBUG "%s: stuck frames: ===> \n", + printk(KERN_DEBUG "%s: stuck frames: ===>\n", wiphy_name(ar->hw->wiphy)); ar9170_dump_txqueue(ar, &ar->tx_pending[i]); ar9170_dump_txqueue(ar, &ar->tx_status[i]); @@ -1733,25 +1740,8 @@ static void ar9170_tx(struct ar9170 *ar) __ar9170_dump_txstats(ar); #endif /* AR9170_QUEUE_STOP_DEBUG */ ieee80211_stop_queue(ar->hw, i); - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - continue; } - frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, - skb_queue_len(&ar->tx_pending[i])); - - if (remaining_space < frames) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: tx quota reached queue:%d, " - "remaining slots:%d, needed:%d\n", - wiphy_name(ar->hw->wiphy), i, remaining_space, - frames); -#endif /* AR9170_QUEUE_DEBUG */ - frames = remaining_space; - } - - ar->tx_stats[i].len += frames; - ar->tx_stats[i].count += frames; spin_unlock_irqrestore(&ar->tx_stats_lock, flags); if (!frames) @@ -1773,7 +1763,7 @@ static void ar9170_tx(struct ar9170 *ar) arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_TX_TIMEOUT); - if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) + if (info->flags & IEEE80211_TX_CTL_AMPDU) atomic_inc(&ar->tx_ampdu_pending); #ifdef AR9170_QUEUE_DEBUG @@ -1784,7 +1774,7 @@ static void ar9170_tx(struct ar9170 *ar) err = ar->tx(ar, skb); if (unlikely(err)) { - if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) + if (info->flags & IEEE80211_TX_CTL_AMPDU) atomic_dec(&ar->tx_ampdu_pending); frames_failed++; @@ -1950,7 +1940,7 @@ err_free: } static int ar9170_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ar9170 *ar = hw->priv; struct ath_common *common = &ar->common; @@ -1963,8 +1953,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, goto unlock; } - ar->vif = conf->vif; - memcpy(common->macaddr, conf->mac_addr, ETH_ALEN); + ar->vif = vif; + memcpy(common->macaddr, vif->addr, ETH_ALEN); if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { ar->rx_software_decryption = true; @@ -1984,7 +1974,7 @@ unlock: } static void ar9170_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ar9170 *ar = hw->priv; @@ -2340,55 +2330,55 @@ out: return err; } -static void ar9170_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) +static int ar9170_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct ar9170 *ar = hw->priv; struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; unsigned int i; - switch (cmd) { - case STA_NOTIFY_ADD: - memset(sta_info, 0, sizeof(*sta_info)); + memset(sta_info, 0, sizeof(*sta_info)); - if (!sta->ht_cap.ht_supported) - break; + if (!sta->ht_cap.ht_supported) + return 0; - if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) - ar->global_ampdu_density = sta->ht_cap.ampdu_density; + if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) + ar->global_ampdu_density = sta->ht_cap.ampdu_density; - if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) - ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; + if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) + ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; - for (i = 0; i < AR9170_NUM_TID; i++) { - sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; - sta_info->agg[i].active = false; - sta_info->agg[i].ssn = 0; - sta_info->agg[i].retry = 0; - sta_info->agg[i].tid = i; - INIT_LIST_HEAD(&sta_info->agg[i].list); - skb_queue_head_init(&sta_info->agg[i].queue); - } + for (i = 0; i < AR9170_NUM_TID; i++) { + sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; + sta_info->agg[i].active = false; + sta_info->agg[i].ssn = 0; + sta_info->agg[i].tid = i; + INIT_LIST_HEAD(&sta_info->agg[i].list); + skb_queue_head_init(&sta_info->agg[i].queue); + } - sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); - break; + sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); - case STA_NOTIFY_REMOVE: - if (!sta->ht_cap.ht_supported) - break; + return 0; +} - for (i = 0; i < AR9170_NUM_TID; i++) { - sta_info->agg[i].state = AR9170_TID_STATE_INVALID; - skb_queue_purge(&sta_info->agg[i].queue); - } +static int ar9170_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; + unsigned int i; - break; + if (!sta->ht_cap.ht_supported) + return 0; - default: - break; + for (i = 0; i < AR9170_NUM_TID; i++) { + sta_info->agg[i].state = AR9170_TID_STATE_INVALID; + skb_queue_purge(&sta_info->agg[i].queue); } + + return 0; } static int ar9170_get_stats(struct ieee80211_hw *hw, @@ -2408,18 +2398,6 @@ static int ar9170_get_stats(struct ieee80211_hw *hw, return 0; } -static int ar9170_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *tx_stats) -{ - struct ar9170 *ar = hw->priv; - - spin_lock_bh(&ar->tx_stats_lock); - memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues); - spin_unlock_bh(&ar->tx_stats_lock); - - return 0; -} - static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *param) { @@ -2519,9 +2497,9 @@ static const struct ieee80211_ops ar9170_ops = { .bss_info_changed = ar9170_op_bss_info_changed, .get_tsf = ar9170_op_get_tsf, .set_key = ar9170_set_key, - .sta_notify = ar9170_sta_notify, + .sta_add = ar9170_sta_add, + .sta_remove = ar9170_sta_remove, .get_stats = ar9170_get_stats, - .get_tx_stats = ar9170_get_tx_stats, .ampdu_action = ar9170_ampdu_action, }; @@ -2538,7 +2516,7 @@ void *ar9170_alloc(size_t priv_size) * tends to split the streams into seperate rx descriptors. */ - skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL); + skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); if (!skb) goto err_nomem; @@ -2724,7 +2702,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", wiphy_name(ar->hw->wiphy)); - return err; + ar->registered = true; + return 0; err_unreg: ieee80211_unregister_hw(ar->hw); @@ -2735,11 +2714,14 @@ err_out: void ar9170_unregister(struct ar9170 *ar) { + if (ar->registered) { #ifdef CONFIG_AR9170_LEDS - ar9170_unregister_leds(ar); + ar9170_unregister_leds(ar); #endif /* CONFIG_AR9170_LEDS */ - kfree_skb(ar->rx_failover); ieee80211_unregister_hw(ar->hw); + } + + kfree_skb(ar->rx_failover); mutex_destroy(&ar->mutex); }