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;

Reply via email to