/* FIX: what would be proper limits for MTU?
* This interface uses 802.3 frames. */
if (new_mtu < 256 ||
- new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
- printk(KERN_WARNING "%s: invalid MTU %d\n",
- dev->name, new_mtu);
+ new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
return -EINVAL;
}
{
struct ieee80211_sub_if_data *sdata, *nsdata;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct sta_info *sta;
struct ieee80211_if_init_conf conf;
+ u32 changed = 0;
int res;
bool need_hw_reconfig = 0;
- struct sta_info *sta;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
goto err_stop;
ieee80211_if_config(dev);
- ieee80211_reset_erp_info(dev);
+ changed |= ieee80211_reset_erp_info(dev);
+ ieee80211_bss_info_change_notify(sdata, changed);
ieee80211_enable_keys(sdata);
if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
local->sta_hw_scanning = 0;
}
- flush_workqueue(local->hw.workqueue);
-
sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
kfree(sdata->u.sta.extra_ie);
sdata->u.sta.extra_ie = NULL;
ieee80211_led_radio(local, 0);
+ flush_workqueue(local->hw.workqueue);
+
tasklet_disable(&local->tx_pending_tasklet);
tasklet_disable(&local->tasklet);
}
int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
{
struct ieee80211_local *local = hw_to_local(hw);
+ struct netdev_queue *txq;
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata;
u16 start_seq_num = 0;
sta = sta_info_get(local, ra);
if (!sta) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Could not find the station\n");
+#endif
ret = -ENOENT;
goto exit;
}
sta->ampdu_mlme.tid_tx[tid] =
kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
if (!sta->ampdu_mlme.tid_tx[tid]) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
tid);
+#endif
ret = -ENOMEM;
goto err_unlock_sta;
}
/* ensure that TX flow won't interrupt us
* until the end of the call to requeue function */
- spin_lock_bh(&local->mdev->queue_lock);
+ txq = &local->mdev->tx_queue;
+ spin_lock_bh(&txq->lock);
/* create a new queue for this aggregation */
ret = ieee80211_ht_agg_queue_add(local, sta, tid);
/* Will put all the packets in the new SW queue */
ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
- spin_unlock_bh(&local->mdev->queue_lock);
+ spin_unlock_bh(&txq->lock);
spin_unlock_bh(&sta->lock);
/* send an addBA request */
sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
jiffies + ADDBA_RESP_INTERVAL;
add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
+#endif
goto exit;
err_unlock_queue:
kfree(sta->ampdu_mlme.tid_tx[tid]);
sta->ampdu_mlme.tid_tx[tid] = NULL;
- spin_unlock_bh(&local->mdev->queue_lock);
+ spin_unlock_bh(&txq->lock);
ret = -EBUSY;
err_unlock_sta:
spin_unlock_bh(&sta->lock);
DECLARE_MAC_BUF(mac);
if (tid >= STA_TID_NUM) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
tid, STA_TID_NUM);
+#endif
return;
}
sta = sta_info_get(local, ra);
if (!sta) {
rcu_read_unlock();
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Could not find station: %s\n",
print_mac(mac, ra));
+#endif
return;
}
spin_lock_bh(&sta->lock);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
*state);
+#endif
spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
*state |= HT_ADDBA_DRV_READY_MSK;
if (*state == HT_AGG_STATE_OPERATIONAL) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
+#endif
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
}
spin_unlock_bh(&sta->lock);
void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
{
struct ieee80211_local *local = hw_to_local(hw);
+ struct netdev_queue *txq;
struct sta_info *sta;
u8 *state;
int agg_queue;
DECLARE_MAC_BUF(mac);
if (tid >= STA_TID_NUM) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
tid, STA_TID_NUM);
+#endif
return;
}
rcu_read_lock();
sta = sta_info_get(local, ra);
if (!sta) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Could not find station: %s\n",
print_mac(mac, ra));
+#endif
rcu_read_unlock();
return;
}
* ieee80211_stop_tx_ba_session will let only
* one stop call to pass through per sta/tid */
if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
+#endif
rcu_read_unlock();
return;
}
/* avoid ordering issues: we are the only one that can modify
* the content of the qdiscs */
- spin_lock_bh(&local->mdev->queue_lock);
+ txq = &local->mdev->tx_queue;
+ spin_lock_bh(&txq->lock);
/* remove the queue for this aggregation */
ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
- spin_unlock_bh(&local->mdev->queue_lock);
+ spin_unlock_bh(&txq->lock);
/* we just requeued the all the frames that were in the removed
* queue, and since we might miss a softirq we do netif_schedule.
struct sk_buff *skb = dev_alloc_skb(0);
if (unlikely(!skb)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_WARNING "%s: Not enough memory, "
"dropping start BA session", skb->dev->name);
+#endif
return;
}
ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
struct sk_buff *skb = dev_alloc_skb(0);
if (unlikely(!skb)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
if (net_ratelimit())
printk(KERN_WARNING "%s: Not enough memory, "
"dropping stop BA session", skb->dev->name);
+#endif
return;
}
ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
changed);
}
-void ieee80211_reset_erp_info(struct net_device *dev)
+u32 ieee80211_reset_erp_info(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
sdata->bss_conf.use_cts_prot = 0;
sdata->bss_conf.use_short_preamble = 0;
- ieee80211_bss_info_change_notify(sdata,
- BSS_CHANGED_ERP_CTS_PROT |
- BSS_CHANGED_ERP_PREAMBLE);
+ return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE;
}
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
ra_tid->ra, ra_tid->tid);
dev_kfree_skb(skb);
break ;
- default: /* should never get here! */
- printk(KERN_ERR "%s: Unknown message type (%d)\n",
- wiphy_name(local->hw.wiphy), skb->pkt_type);
+ default:
+ WARN_ON(1);
dev_kfree_skb(skb);
break;
}
return;
}
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: dropped TX filtered frame, "
"queue_len=%d PS=%d @%lu\n",
wiphy_name(local->hw.wiphy),
skb_queue_len(&sta->tx_filtered),
!!test_sta_flags(sta, WLAN_STA_PS), jiffies);
+#endif
dev_kfree_skb(skb);
}
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u16 frag, type;
+ __le16 fc;
struct ieee80211_tx_status_rtap_hdr *rthdr;
struct ieee80211_sub_if_data *sdata;
struct net_device *prev_dev = NULL;
+ struct sta_info *sta;
rcu_read_lock();
if (info->status.excessive_retries) {
- struct sta_info *sta;
sta = sta_info_get(local, hdr->addr1);
if (sta) {
if (test_sta_flags(sta, WLAN_STA_PS)) {
}
}
+ fc = hdr->frame_control;
+
+ if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
+ (ieee80211_is_data_qos(fc))) {
+ u16 tid, ssn;
+ u8 *qc;
+ sta = sta_info_get(local, hdr->addr1);
+ if (sta) {
+ qc = ieee80211_get_qos_ctl(hdr);
+ tid = qc[0] & 0xf;
+ ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10)
+ & IEEE80211_SCTL_SEQ);
+ ieee80211_send_bar(sta->sdata->dev, hdr->addr1,
+ tid, ssn);
+ }
+ }
+
if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
- struct sta_info *sta;
sta = sta_info_get(local, hdr->addr1);
if (sta) {
ieee80211_handle_filtered_frame(local, sta, skb);
list_add_tail(&sdata->list, &local->interfaces);
name = wiphy_dev(local->hw.wiphy)->driver->name;
- local->hw.workqueue = create_singlethread_workqueue(name);
+ local->hw.workqueue = create_freezeable_workqueue(name);
if (!local->hw.workqueue) {
result = -ENOMEM;
goto fail_workqueue;