On Fri, 2008-11-28 at 21:43 +0100, Christian Lamparter wrote: > On Friday 28 November 2008 21:09:35 Christian Lamparter wrote: > > Ahh... I knew it! > > > > Alright, I looks like I have to change the mac80211 stack for this. > > What I need is a callback form ap_sta_ps_end & (ap_sta_ps_start). > > > > It's because (p54_)set_tim - and therefore p54_sta_unlock as well - won't > > be executed if the station changes its power state very quickly/or if no package comes in > > So we have no change to notify the firmware about the stations new power state > > and then the firmware won't let us send anything to the station. > > > > here is my proposal for mac80211: > > --- > Updates: > - integrate sta_notify_ps into sta_notify. > - added trivial switch cases for mac80211_hwsim.c (or else gcc complains) Looks fine to me. > And BTW: can someone please check the spelling? And that too. > --- > diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c > index f43da1c..e2c50ed 100644 > --- a/drivers/net/wireless/mac80211_hwsim.c > +++ b/drivers/net/wireless/mac80211_hwsim.c > @@ -524,6 +524,10 @@ static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw, > case STA_NOTIFY_REMOVE: > hwsim_clear_sta_magic(sta); > break; > + case STA_NOTIFY_AWAKE: > + case STA_NOTIFY_SLEEP: > + /* TODO: make good use of these callbacks */ > + break; > } > } > > diff --git a/include/net/mac80211.h b/include/net/mac80211.h > index 6a1d4ea..7bd8edc 100644 > --- a/include/net/mac80211.h > +++ b/include/net/mac80211.h > @@ -768,14 +768,18 @@ struct ieee80211_sta { > /** > * enum sta_notify_cmd - sta notify command > * > - * Used with the sta_notify() callback in &struct ieee80211_ops, this > - * indicates addition and removal of a station to station table. > + * Used with the sta_notify() callback in &struct ieee80211_ops. > + * this command indicates addition and removal of a station to > + * station table, or if a station made a power state transition. > * > * @STA_NOTIFY_ADD: a station was added to the station table > * @STA_NOTIFY_REMOVE: a station being removed from the station table > + * @STA_NOTIFY_SLEEP: a station is now sleeping > + * @STA_NOTIFY_AWAKE: a sleeping station woke up > */ > enum sta_notify_cmd { > - STA_NOTIFY_ADD, STA_NOTIFY_REMOVE > + STA_NOTIFY_ADD, STA_NOTIFY_REMOVE, > + STA_NOTIFY_SLEEP, STA_NOTIFY_AWAKE, > }; > > /** > diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c > index 5a1a60f..2d311a1 100644 > --- a/net/mac80211/rx.c > +++ b/net/mac80211/rx.c > @@ -654,10 +654,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) > static void ap_sta_ps_start(struct sta_info *sta) > { > struct ieee80211_sub_if_data *sdata = sta->sdata; > + struct ieee80211_local *local = sdata->local; > DECLARE_MAC_BUF(mac); > > atomic_inc(&sdata->bss->num_sta_ps); > set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); > + if (local->ops->sta_notify) > + local->ops->sta_notify(local_to_hw(local), &sdata->vif, > + STA_NOTIFY_SLEEP, &sta->sta); > #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG > printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", > sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); > @@ -675,6 +679,9 @@ static int ap_sta_ps_end(struct sta_info *sta) > atomic_dec(&sdata->bss->num_sta_ps); > > clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); > + if (local->ops->sta_notify) > + local->ops->sta_notify(local_to_hw(local), &sdata->vif, > + STA_NOTIFY_AWAKE, &sta->sta); > > if (!skb_queue_empty(&sta->ps_tx_buf)) > sta_info_clear_tim_bit(sta); > --- > > p54 updates: > - update to new api > --- > diff -Nurp a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c > --- a/drivers/net/wireless/p54/p54common.c 2008-11-28 20:18:53.000000000 +0100 > +++ b/drivers/net/wireless/p54/p54common.c 2008-11-28 21:37:45.000000000 +0100 > @@ -653,6 +653,10 @@ static void p54_rx_frame_sent(struct iee > __skb_unlink(entry, &priv->tx_queue); > spin_unlock_irqrestore(&priv->tx_queue.lock, flags); > > + entry_hdr = (struct p54_hdr *) entry->data; > + entry_data = (struct p54_tx_data *) entry_hdr->data; > + priv->tx_stats[entry_data->hw_queue].len--; > + > if (unlikely(entry == priv->cached_beacon)) { > kfree_skb(entry); > priv->cached_beacon = NULL; > @@ -669,8 +673,6 @@ static void p54_rx_frame_sent(struct iee > BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, > status.ampdu_ack_len) != 23); > > - entry_hdr = (struct p54_hdr *) entry->data; > - entry_data = (struct p54_tx_data *) entry_hdr->data; > if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN)) > pad = entry_data->align[0]; > > @@ -688,7 +690,6 @@ static void p54_rx_frame_sent(struct iee > } > } > > - priv->tx_stats[entry_data->hw_queue].len--; > if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && > (!payload->status)) > info->flags |= IEEE80211_TX_STAT_ACK; > @@ -1005,6 +1006,26 @@ static int p54_sta_unlock(struct ieee802 > return 0; > } > > +static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, > + enum sta_notify_cmd notify_cmd, > + struct ieee80211_sta *sta) > +{ > + switch (notify_cmd) { > + case STA_NOTIFY_ADD: > + case STA_NOTIFY_REMOVE: > + case STA_NOTIFY_AWAKE: > + /* > + * Notify the firmware that we don't want or we don't > + * need to buffer frames for this station anymore. > + */ > + > + p54_sta_unlock(dev, sta->addr); > + break; > + default: > + break; > + } > +} > + > static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry) > { > struct p54_common *priv = dev->priv; > @@ -1070,7 +1091,7 @@ static int p54_tx_fill(struct ieee80211_ > if (info->control.sta) > *aid = info->control.sta->aid; > else > - *flags = P54_HDR_FLAG_DATA_OUT_NOCANCEL; > + *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; > } > return ret; > } > @@ -1083,7 +1104,7 @@ static int p54_tx(struct ieee80211_hw *d > struct p54_hdr *hdr; > struct p54_tx_data *txhdr; > size_t padding, len, tim_len = 0; > - int i, j, ridx; > + int i, j, ridx, ret; > u16 hdr_flags = 0, aid = 0; > u8 rate, queue; > u8 cts_rate = 0x20; > @@ -1093,30 +1114,18 @@ static int p54_tx(struct ieee80211_hw *d > > queue = skb_get_queue_mapping(skb); > > - if (p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid)) { > - current_queue = &priv->tx_stats[queue]; > - if (unlikely(current_queue->len > current_queue->limit)) > - return NETDEV_TX_BUSY; > - current_queue->len++; > - current_queue->count++; > - if (current_queue->len == current_queue->limit) > - ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); > - } > + ret = p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid); > + current_queue = &priv->tx_stats[queue]; > + if (unlikely((current_queue->len > current_queue->limit) && ret)) > + return NETDEV_TX_BUSY; > + current_queue->len++; > + current_queue->count++; > + if ((current_queue->len == current_queue->limit) && ret) > + ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); > > padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; > len = skb->len; > > - if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) { > - if (info->control.sta) > - if (p54_sta_unlock(dev, info->control.sta->addr)) { > - if (current_queue) { > - current_queue->len--; > - current_queue->count--; > - } > - return NETDEV_TX_BUSY; > - } > - } > - > txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding); > hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr)); > > @@ -1835,6 +1844,7 @@ static const struct ieee80211_ops p54_op > .add_interface = p54_add_interface, > .remove_interface = p54_remove_interface, > .set_tim = p54_set_tim, > + .sta_notify = p54_sta_notify, > .config = p54_config, > .config_interface = p54_config_interface, > .bss_info_changed = p54_bss_info_changed, > diff -Nurp a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h > --- a/drivers/net/wireless/p54/p54common.h 2008-11-28 20:18:53.000000000 +0100 > +++ b/drivers/net/wireless/p54/p54common.h 2008-11-28 20:27:59.000000000 +0100 > @@ -302,7 +302,7 @@ enum p54_frame_sent_status { > P54_TX_OK = 0, > P54_TX_FAILED, > P54_TX_PSM, > - P54_TX_PSM_CANCELLED > + P54_TX_PSM_CANCELLED = 4 > }; > > struct p54_frame_sent { >
Attachment:
signature.asc
Description: This is a digitally signed message part