iwm tx rate fixes

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

iwm tx rate fixes

Stefan Sperling-5
iwm(4) should always send multicast frames at the lowest rate.
We probably got lucky and frames were still sent at a compatible rate
via the LQ retry table. But it is better to have an "IS_MULTICAST" check
like other drivers do.

On 5GHz, iwm(4) passes the wrong rate to BPF. This is a cosmetic issue.
E.g. "tcpdump -n -i iwm0 -y IEEE802_11 -v" will show "1 Mbit/s" for
multicast frames, which is wrong (should be 6Mbit/s on 5Ghz).

In iwm_setrates(), don't bother looping over CCK rates if we're on a 5 GHz
channel. CCK rates aren't valid on 5GHz channels. We didn't add them, so
this is not a bug, but we might as well exit the loop early.

Index: if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.88
diff -u -p -r1.88 if_iwm.c
--- if_iwm.c 19 Jun 2016 12:05:25 -0000 1.88
+++ if_iwm.c 20 Jun 2016 07:44:58 -0000
@@ -4376,7 +4376,8 @@ iwm_tx_fill_cmd(struct iwm_softc *sc, st
  tx->rts_retry_limit = IWM_RTS_DFAULT_RETRY_LIMIT;
  tx->data_retry_limit = IWM_DEFAULT_TX_RETRY;
 
- if (type != IEEE80211_FC0_TYPE_DATA) {
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
+    type != IEEE80211_FC0_TYPE_DATA) {
  /* for non-data, use the lowest supported rate */
  ridx = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ?
     IWM_RIDX_OFDM : IWM_RIDX_CCK;
@@ -4393,7 +4394,8 @@ iwm_tx_fill_cmd(struct iwm_softc *sc, st
  ridx = iwm_mcs2ridx[ni->ni_txmcs];
  return &iwm_rates[ridx];
  }
- ridx = 0;
+ ridx = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ?
+    IWM_RIDX_OFDM : IWM_RIDX_CCK;
  for (i = 0; i < nrates; i++) {
  if (iwm_rates[i].rate == (ni->ni_txrate &
     IEEE80211_RATE_VAL)) {
@@ -6124,7 +6126,7 @@ iwm_setrates(struct iwm_node *in)
  struct iwm_softc *sc = IC2IFP(ic)->if_softc;
  struct iwm_lq_cmd *lq = &in->in_lq;
  struct ieee80211_rateset *rs = &ni->ni_rates;
- int i, ridx, j, tab = 0;
+ int i, ridx, ridx_min, j, tab = 0;
  struct iwm_host_cmd cmd = {
  .id = IWM_LQ_CMD,
  .len = { sizeof(in->in_lq), },
@@ -6148,7 +6150,9 @@ iwm_setrates(struct iwm_node *in)
  * legacy/HT are assumed to be marked with an 'invalid' PLCP value.
  */
  j = 0;
- for (ridx = IWM_RIDX_MAX; ridx >= 0; ridx--) {
+ ridx_min = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ?
+    IWM_RIDX_OFDM : IWM_RIDX_CCK;
+ for (ridx = IWM_RIDX_MAX; ridx >= ridx_min; ridx--) {
  if (j >= nitems(lq->rs_table))
  break;
  tab = 0;