Re: iwm ack rate mapping

2016-10-08 Thread Mark Kettenis
> Date: Fri, 7 Oct 2016 14:01:27 +0200
> From: Stefan Sperling 
> 
> Imre Vadasz pointed out that rate sets managed by net80211 are sorted
> by effective data rate speed, while the iwm_rates array sorts CCK rates
> (1 - 11 Mbit/s) before OFDM rates (6Mbit/s - 54Mbit/s).
> 
> rate set (11g): 1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 54
> iwm_rates:  1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 54
> 
> The rate set is sorted at runtime and its length differs between 11a/11b/11g.
> So let's add a mapping function and fill the ACK rate bitmap correctly
> without making assumptions about the rate set.

Looks good to me.

> Index: if_iwm.c
> ===
> RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
> retrieving revision 1.143
> diff -u -p -r1.143 if_iwm.c
> --- if_iwm.c  5 Oct 2016 18:13:25 -   1.143
> +++ if_iwm.c  7 Oct 2016 11:50:19 -
> @@ -398,6 +398,7 @@ int   iwm_fill_probe_req(struct iwm_softc 
>  int  iwm_lmac_scan(struct iwm_softc *);
>  int  iwm_config_umac_scan(struct iwm_softc *);
>  int  iwm_umac_scan(struct iwm_softc *);
> +uint8_t  iwm_ridx2rate(struct ieee80211_rateset *, int);
>  void iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, int *);
>  void iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *,
>   struct iwm_mac_ctx_cmd *, uint32_t, int);
> @@ -4881,6 +4882,21 @@ iwm_umac_scan(struct iwm_softc *sc)
>   return err;
>  }
>  
> +uint8_t
> +iwm_ridx2rate(struct ieee80211_rateset *rs, int ridx)
> +{
> + int i;
> + uint8_t rval;
> +
> + for (i = 0; i < rs->rs_nrates; i++) {
> + rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);
> + if (rval == iwm_rates[ridx].rate)
> + return rs->rs_rates[i];
> + }
> +
> + return 0;
> +}
> +
>  void
>  iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates,
>  int *ofdm_rates)
> @@ -4895,17 +4911,16 @@ iwm_ack_rates(struct iwm_softc *sc, stru
>  
>   if (ni->ni_chan == IEEE80211_CHAN_ANYC ||
>   IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
> - for (i = 0; i < MIN(IWM_FIRST_OFDM_RATE, rs->rs_nrates); i++) {
> - if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)
> + for (i = IWM_FIRST_CCK_RATE; i < IWM_FIRST_OFDM_RATE; i++) {
> + if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
>   continue;
>   cck |= (1 << i);
>   if (lowest_present_cck > i)
>   lowest_present_cck = i;
>   }
>   }
> - for (i = IWM_FIRST_OFDM_RATE;
> - i <= MIN(IWM_LAST_NON_HT_RATE, rs->rs_nrates - 1); i++) {
> - if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)
> + for (i = IWM_FIRST_OFDM_RATE; i <= IWM_LAST_NON_HT_RATE; i++) {
> + if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
>   continue;   
>   ofdm |= (1 << (i - IWM_FIRST_OFDM_RATE));
>   if (lowest_present_ofdm > i)
> 
> 



iwm ack rate mapping

2016-10-07 Thread Stefan Sperling
Imre Vadasz pointed out that rate sets managed by net80211 are sorted
by effective data rate speed, while the iwm_rates array sorts CCK rates
(1 - 11 Mbit/s) before OFDM rates (6Mbit/s - 54Mbit/s).

rate set (11g): 1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 54
iwm_rates:  1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 54

The rate set is sorted at runtime and its length differs between 11a/11b/11g.
So let's add a mapping function and fill the ACK rate bitmap correctly
without making assumptions about the rate set.

Index: if_iwm.c
===
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.143
diff -u -p -r1.143 if_iwm.c
--- if_iwm.c5 Oct 2016 18:13:25 -   1.143
+++ if_iwm.c7 Oct 2016 11:50:19 -
@@ -398,6 +398,7 @@ int iwm_fill_probe_req(struct iwm_softc 
 intiwm_lmac_scan(struct iwm_softc *);
 intiwm_config_umac_scan(struct iwm_softc *);
 intiwm_umac_scan(struct iwm_softc *);
+uint8_tiwm_ridx2rate(struct ieee80211_rateset *, int);
 void   iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, int *);
 void   iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *,
struct iwm_mac_ctx_cmd *, uint32_t, int);
@@ -4881,6 +4882,21 @@ iwm_umac_scan(struct iwm_softc *sc)
return err;
 }
 
+uint8_t
+iwm_ridx2rate(struct ieee80211_rateset *rs, int ridx)
+{
+   int i;
+   uint8_t rval;
+
+   for (i = 0; i < rs->rs_nrates; i++) {
+   rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);
+   if (rval == iwm_rates[ridx].rate)
+   return rs->rs_rates[i];
+   }
+
+   return 0;
+}
+
 void
 iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates,
 int *ofdm_rates)
@@ -4895,17 +4911,16 @@ iwm_ack_rates(struct iwm_softc *sc, stru
 
if (ni->ni_chan == IEEE80211_CHAN_ANYC ||
IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
-   for (i = 0; i < MIN(IWM_FIRST_OFDM_RATE, rs->rs_nrates); i++) {
-   if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)
+   for (i = IWM_FIRST_CCK_RATE; i < IWM_FIRST_OFDM_RATE; i++) {
+   if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
continue;
cck |= (1 << i);
if (lowest_present_cck > i)
lowest_present_cck = i;
}
}
-   for (i = IWM_FIRST_OFDM_RATE;
-   i <= MIN(IWM_LAST_NON_HT_RATE, rs->rs_nrates - 1); i++) {
-   if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)
+   for (i = IWM_FIRST_OFDM_RATE; i <= IWM_LAST_NON_HT_RATE; i++) {
+   if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0)
continue;   
ofdm |= (1 << (i - IWM_FIRST_OFDM_RATE));
if (lowest_present_ofdm > i)