On Thu, Jun 19, 2008 at 12:56 PM, Johannes Berg <johannes@xxxxxxxxxxxxxxxx> wrote: > On Thu, 2008-06-19 at 12:20 +0300, Tomas Winkler wrote: >> Johannes >> Your patch bellow has broken the fragmentation. Can you please have a >> look at this. > >> /* Setup duration field for the first fragment of the frame. Duration >> * for remaining fragments will be updated when they are being sent >> * to low-level driver in ieee80211_tx(). */ >> dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1), >> (tx->flags & IEEE80211_TX_FRAGMENTED) ? >> tx->extra_frag[0]->len : 0); -- >> NULL pointer > > Oops, you're right, I missed the part where it accesses the fragments, > the bulk of the function does txinfo updates which I didn't want to > apply to all fragments. > > There is another bug too, this must come after encryption since > encryption can add to the length of the frame. What do you think about > the patch below? Untested so far because I have to go and wanted to get > it out to you. > Now it crashes in the driver...maybe the txinfo to cb changes. Looking into it. Tomas > johannes > > --- > net/mac80211/tx.c | 66 ++++++++++++++++++++++++++++-------------------------- > 1 file changed, 35 insertions(+), 31 deletions(-) > > --- everything.orig/net/mac80211/tx.c 2008-06-19 11:25:12.000000000 +0200 > +++ everything/net/mac80211/tx.c 2008-06-19 11:53:08.000000000 +0200 > @@ -87,8 +87,8 @@ static inline void ieee80211_dump_frame( > } > #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ > > -static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, > - int next_frag_len) > +static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, > + int next_frag_len) > { > int rate, mrate, erp, dur, i; > struct ieee80211_rate *txrate; > @@ -140,7 +140,7 @@ static u16 ieee80211_duration(struct iee > > /* data/mgmt */ > if (0 /* FIX: data/mgmt during CFP */) > - return 32768; > + return cpu_to_le16(32768); > > if (group_addr) /* Group address as the destination - no ACK */ > return 0; > @@ -210,7 +210,7 @@ static u16 ieee80211_duration(struct iee > tx->sdata->bss_conf.use_short_preamble); > } > > - return dur; > + return cpu_to_le16(dur); > } > > static int inline is_ieee80211_device(struct net_device *dev, > @@ -544,7 +544,6 @@ ieee80211_tx_h_misc(struct ieee80211_tx_ > { > struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; > u16 fc = le16_to_cpu(hdr->frame_control); > - u16 dur; > struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); > struct ieee80211_supported_band *sband; > > @@ -602,14 +601,6 @@ ieee80211_tx_h_misc(struct ieee80211_tx_ > info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; > } > > - /* Setup duration field for the first fragment of the frame. Duration > - * for remaining fragments will be updated when they are being sent > - * to low-level driver in ieee80211_tx(). */ > - dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1), > - (tx->flags & IEEE80211_TX_FRAGMENTED) ? > - tx->extra_frag[0]->len : 0); > - hdr->duration_id = cpu_to_le16(dur); > - > if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || > (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { > struct ieee80211_rate *rate; > @@ -755,6 +746,36 @@ ieee80211_tx_h_encrypt(struct ieee80211_ > } > > static ieee80211_tx_result > +ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) > +{ > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; > + int next_len, i; > + int group_addr = is_multicast_ether_addr(hdr->addr1); > + > + if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) { > + hdr->duration_id = ieee80211_duration(tx, group_addr, 0); > + return TX_CONTINUE; > + } > + > + hdr->duration_id = ieee80211_duration(tx, group_addr, > + tx->extra_frag[0]->len); > + > + for (i = 0; i < tx->num_extra_frag; i++) { > + if (i + 1 < tx->num_extra_frag) { > + next_len = tx->extra_frag[i + 1]->len; > + } else { > + next_len = 0; > + tx->rate_idx = tx->last_frag_rate_idx; > + } > + > + hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; > + hdr->duration_id = ieee80211_duration(tx, 0, next_len); > + } > + > + return TX_CONTINUE; > +} > + > +static ieee80211_tx_result > ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) > { > int i; > @@ -788,6 +809,7 @@ static ieee80211_tx_handler ieee80211_tx > ieee80211_tx_h_fragment, > /* handlers after fragment must be aware of tx info fragmentation! */ > ieee80211_tx_h_encrypt, > + ieee80211_tx_h_calculate_duration, > ieee80211_tx_h_stats, > NULL > }; > @@ -1139,24 +1161,6 @@ static int ieee80211_tx(struct net_devic > return 0; > } > > - if (tx.extra_frag) { > - for (i = 0; i < tx.num_extra_frag; i++) { > - int next_len, dur; > - struct ieee80211_hdr *hdr = > - (struct ieee80211_hdr *) > - tx.extra_frag[i]->data; > - > - if (i + 1 < tx.num_extra_frag) { > - next_len = tx.extra_frag[i + 1]->len; > - } else { > - next_len = 0; > - tx.rate_idx = tx.last_frag_rate_idx; > - } > - dur = ieee80211_duration(&tx, 0, next_len); > - hdr->duration_id = cpu_to_le16(dur); > - } > - } > - > retry: > ret = __ieee80211_tx(local, skb, &tx); > if (ret) { > > > -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html