Author: adrian
Date: Sat Feb 14 17:45:53 2015
New Revision: 278764
URL: https://svnweb.freebsd.org/changeset/base/278764

Log:
  More fixes to wpi(4), again not by me! Woo!
  
  - Use IEEE80211_F_DATAPAD;
  - (c->ic_flags & IEEE80211_CHAN_PASSIVE) -> IEEE80211_IS_CHAN_PASSIVE(c);
  - Convert ackfailcnt to int (there is dereference to *(int *) in 
ieee80211_ratectl_tx_complete());
  - Fix & move cleanup to the end in wpi_rx_done();
  - Add missed lock in wpi_update_beacon();
  - Try to fix powersave.
  
  PR:           kern/197143
  Submitted by:  Andriy Voskoboinyk <s3er...@gmail.com>

Modified:
  head/sys/dev/wpi/if_wpi.c
  head/sys/dev/wpi/if_wpireg.h

Modified: head/sys/dev/wpi/if_wpi.c
==============================================================================
--- head/sys/dev/wpi/if_wpi.c   Sat Feb 14 17:44:24 2015        (r278763)
+++ head/sys/dev/wpi/if_wpi.c   Sat Feb 14 17:45:53 2015        (r278764)
@@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$");
  *
  * A similar thing happens with the tx rings. The difference is the firmware
  * stop processing buffers once the queue is full and until confirmation
- * of a successful transmition (tx_intr) has occurred.
+ * of a successful transmition (tx_done) has occurred.
  *
  * The command ring operates in the same manner as the tx queues.
  *
@@ -447,6 +447,8 @@ wpi_attach(device_t dev)
        ic->ic_cryptocaps =
                  IEEE80211_CRYPTO_AES_CCM;
 
+       ic->ic_flags |= IEEE80211_F_DATAPAD;
+
        /*
         * Read in the eeprom and also setup the channels for
         * net80211. We don't set the rates as net80211 does this for us
@@ -1378,8 +1380,7 @@ wpi_read_eeprom_band(struct wpi_softc *s
                    "adding chan %d (%dMHz) flags=0x%x maxpwr=%d passive=%d,"
                    " offset %d\n", chan, c->ic_freq,
                    channels[i].flags, sc->maxpwr[chan],
-                   (c->ic_flags & IEEE80211_CHAN_PASSIVE) != 0,
-                   ic->ic_nchans);
+                   IEEE80211_IS_CHAN_PASSIVE(c), ic->ic_nchans);
        }
 }
 
@@ -1695,8 +1696,7 @@ wpi_rx_done(struct wpi_softc *sc, struct
 
        if (stat->len > WPI_STAT_MAXLEN) {
                device_printf(sc->sc_dev, "invalid RX statistic header\n");
-               if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-               return;
+               goto fail1;
        }
 
        bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
@@ -1714,23 +1714,20 @@ wpi_rx_done(struct wpi_softc *sc, struct
        if ((flags & WPI_RX_NOERROR) != WPI_RX_NOERROR) {
                DPRINTF(sc, WPI_DEBUG_RECV, "%s: RX flags error %x\n",
                    __func__, flags);
-               if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-               return;
+               goto fail1;
        }
        /* Discard frames that are too short. */
        if (len < sizeof (*wh)) {
                DPRINTF(sc, WPI_DEBUG_RECV, "%s: frame too short: %d\n",
                    __func__, len);
-               if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-               return;
+               goto fail1;
        }
 
        m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
        if (m1 == NULL) {
                DPRINTF(sc, WPI_DEBUG_ANY, "%s: no mbuf to restock ring\n",
                    __func__);
-               if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-               return;
+               goto fail1;
        }
        bus_dmamap_unload(ring->data_dmat, data->map);
 
@@ -1752,8 +1749,7 @@ wpi_rx_done(struct wpi_softc *sc, struct
                ring->desc[ring->cur] = htole32(paddr);
                bus_dmamap_sync(ring->data_dmat, ring->desc_dma.map,
                    BUS_DMASYNC_PREWRITE);
-               if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-               return;
+               goto fail1;
        }
 
        m = data->m;
@@ -1777,18 +1773,14 @@ wpi_rx_done(struct wpi_softc *sc, struct
        if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
            !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
            cip != NULL && cip->ic_cipher == IEEE80211_CIPHER_AES_CCM) {
-               if ((flags & WPI_RX_CIPHER_MASK) != WPI_RX_CIPHER_CCMP) {
-                       if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-                       m_freem(m);
-                       return;
-               }
+               if ((flags & WPI_RX_CIPHER_MASK) != WPI_RX_CIPHER_CCMP)
+                       goto fail2;
+
                /* Check whether decryption was successful or not. */
                if ((flags & WPI_RX_DECRYPT_MASK) != WPI_RX_DECRYPT_OK) {
                        DPRINTF(sc, WPI_DEBUG_RECV,
                            "CCMP decryption failed 0x%x\n", flags);
-                       if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-                       m_freem(m);
-                       return;
+                       goto fail2;
                }
                m->m_flags |= M_WEP;
        }
@@ -1817,6 +1809,13 @@ wpi_rx_done(struct wpi_softc *sc, struct
                (void)ieee80211_input_all(ic, m, stat->rssi, -WPI_RSSI_OFFSET);
 
        WPI_LOCK(sc);
+
+       return;
+
+fail2: ieee80211_free_node(ni);
+       m_freem(m);
+
+fail1: if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 }
 
 static void
@@ -1836,6 +1835,7 @@ wpi_tx_done(struct wpi_softc *sc, struct
        struct mbuf *m;
        struct ieee80211_node *ni;
        struct ieee80211vap *vap;
+       int ackfailcnt = stat->ackfailcnt;
        int status = le32toh(stat->status);
 
        KASSERT(data->ni != NULL, ("no node"));
@@ -1844,7 +1844,7 @@ wpi_tx_done(struct wpi_softc *sc, struct
 
        DPRINTF(sc, WPI_DEBUG_XMIT, "%s: "
            "qid %d idx %d retries %d btkillcnt %d rate %x duration %d "
-           "status %x\n", __func__, desc->qid, desc->idx, stat->ackfailcnt,
+           "status %x\n", __func__, desc->qid, desc->idx, ackfailcnt,
            stat->btkillcnt, stat->rate, le32toh(stat->duration), status);
 
        /* Unmap and free mbuf. */
@@ -1861,11 +1861,11 @@ wpi_tx_done(struct wpi_softc *sc, struct
        if ((status & 0xff) != 1) {
                if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
                ieee80211_ratectl_tx_complete(vap, ni,
-                   IEEE80211_RATECTL_TX_FAILURE, &stat->ackfailcnt, NULL);
+                   IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
        } else {
                if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
                ieee80211_ratectl_tx_complete(vap, ni,
-                   IEEE80211_RATECTL_TX_SUCCESS, &stat->ackfailcnt, NULL);
+                   IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
        }
 
        ieee80211_tx_complete(ni, m, (status & 0xff) != 1);
@@ -1931,10 +1931,7 @@ wpi_notif_intr(struct wpi_softc *sc)
        hw = le32toh(sc->shared->next);
        hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1;
 
-       if (sc->rxq.cur == hw)
-               return;
-
-       do {
+       while (sc->rxq.cur != hw) {
                sc->rxq.cur = (sc->rxq.cur + 1) % WPI_RX_RING_COUNT;
 
                struct wpi_rx_data *data = &sc->rxq.data[sc->rxq.cur];
@@ -2020,10 +2017,10 @@ wpi_notif_intr(struct wpi_softc *sc)
                             BUS_DMASYNC_POSTREAD);
 
                        uint32_t *status = (uint32_t *)(desc + 1);
-#ifdef WPI_DEBUG
+
                        DPRINTF(sc, WPI_DEBUG_STATE, "state changed to %x\n",
                            le32toh(*status));
-#endif
+
                        if (le32toh(*status) & 1) {
                                ieee80211_runtask(ic, &sc->sc_radiooff_task);
                                return;
@@ -2061,7 +2058,7 @@ wpi_notif_intr(struct wpi_softc *sc)
                        break;
                }
                }
-       } while (sc->rxq.cur != hw);
+       }
 
        /* Tell the firmware what we have processed. */
        wpi_update_rx_ring(sc);
@@ -2081,15 +2078,15 @@ wpi_wakeup_intr(struct wpi_softc *sc)
 
        /* Wakeup RX and TX rings. */
        if (sc->rxq.update) {
-               wpi_update_rx_ring(sc);
                sc->rxq.update = 0;
+               wpi_update_rx_ring(sc);
        }
        for (qid = 0; qid < WPI_NTXQUEUES; qid++) {
                struct wpi_tx_ring *ring = &sc->txq[qid];
 
                if (ring->update) {
-                       wpi_update_tx_ring(sc, ring);
                        ring->update = 0;
+                       wpi_update_tx_ring(sc, ring);
                }
        }
 
@@ -2227,6 +2224,8 @@ done:
 static int
 wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf)
 {
+       struct ifnet *ifp = sc->sc_ifp;
+       struct ieee80211com *ic = ifp->if_l2com;
        struct ieee80211_frame *wh;
        struct wpi_tx_cmd *cmd;
        struct wpi_tx_data *data;
@@ -2234,23 +2233,16 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
        struct wpi_tx_ring *ring;
        struct mbuf *m1;
        bus_dma_segment_t *seg, segs[WPI_MAX_SCATTER];
-       u_int hdrlen;
-       int error, i, nsegs, pad, totlen;
+       int error, i, hdrspace, nsegs, totlen;
 
        WPI_LOCK_ASSERT(sc);
 
        DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
 
        wh = mtod(buf->m, struct ieee80211_frame *);
-       hdrlen = ieee80211_anyhdrsize(wh);
+       hdrspace = ieee80211_anyhdrspace(ic, wh);
        totlen = buf->m->m_pkthdr.len;
 
-       if (hdrlen & 3) {
-               /* First segment length must be a multiple of 4. */
-               pad = 4 - (hdrlen & 3);
-       } else
-               pad = 0;
-
        ring = &sc->txq[buf->ac];
        desc = &ring->desc[ring->cur];
        data = &ring->data[ring->cur];
@@ -2265,8 +2257,8 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
        memcpy(cmd->data, buf->data, buf->size);
 
        /* Save and trim IEEE802.11 header. */
-       memcpy((uint8_t *)(cmd->data + buf->size), wh, hdrlen);
-       m_adj(buf->m, hdrlen);
+       memcpy((uint8_t *)(cmd->data + buf->size), wh, hdrspace);
+       m_adj(buf->m, hdrspace);
 
        error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, buf->m,
            segs, &nsegs, BUS_DMA_NOWAIT);
@@ -2304,10 +2296,10 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
            __func__, ring->qid, ring->cur, totlen, nsegs);
 
        /* Fill TX descriptor. */
-       desc->nsegs = WPI_PAD32(totlen + pad) << 4 | (1 + nsegs);
+       desc->nsegs = WPI_PAD32(totlen) << 4 | (1 + nsegs);
        /* First DMA segment is used by the TX command. */
        desc->segs[0].addr = htole32(data->cmd_paddr);
-       desc->segs[0].len  = htole32(4 + buf->size + hdrlen + pad);
+       desc->segs[0].len  = htole32(4 + buf->size + hdrspace);
        /* Other DMA segments are for data payload. */
        seg = &segs[0];
        for (i = 1; i <= nsegs; i++) {
@@ -2353,9 +2345,10 @@ wpi_tx_data(struct wpi_softc *sc, struct
        uint32_t flags;
        uint16_t qos;
        uint8_t tid, type;
-       int ac, error, rate, ismcast, totlen;
+       int ac, error, rate, ismcast, hdrlen, totlen;
 
        wh = mtod(m, struct ieee80211_frame *);
+       hdrlen = ieee80211_anyhdrsize(wh);
        type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
        ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
 
@@ -2399,12 +2392,12 @@ wpi_tx_data(struct wpi_softc *sc, struct
                /* 802.11 header may have moved. */
                wh = mtod(m, struct ieee80211_frame *);
        }
-       totlen = m->m_pkthdr.len;
+       totlen = m->m_pkthdr.len - (hdrlen & 3);
 
        if (ieee80211_radiotap_active_vap(vap)) {
                struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
 
-               tap->wt_flags = 0;
+               tap->wt_flags = IEEE80211_RADIOTAP_F_DATAPAD;
                tap->wt_rate = rate;
                if (k != NULL)
                        tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
@@ -2420,6 +2413,9 @@ wpi_tx_data(struct wpi_softc *sc, struct
                        flags |= WPI_TX_NEED_ACK;
        }
 
+       if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG)
+               flags |= WPI_TX_MORE_FRAG;      /* Cannot happen yet. */
+
        /* Check if frame must be protected using RTS/CTS or CTS-to-self. */
        if (!ismcast) {
                /* NB: Group frames are sent using CCK in 802.11b/g. */
@@ -2518,11 +2514,12 @@ wpi_tx_data_raw(struct wpi_softc *sc, st
        struct wpi_buf tx_data;
        uint32_t flags;
        uint8_t type;
-       int ac, rate, totlen;
+       int ac, rate, hdrlen, totlen;
 
        wh = mtod(m, struct ieee80211_frame *);
+       hdrlen = ieee80211_anyhdrsize(wh);
        type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
-       totlen = m->m_pkthdr.len;
+       totlen = m->m_pkthdr.len - (hdrlen & 3);
 
        ac = params->ibp_pri & 3;
 
@@ -2544,6 +2541,8 @@ wpi_tx_data_raw(struct wpi_softc *sc, st
 
                tap->wt_flags = 0;
                tap->wt_rate = rate;
+               if (params->ibp_flags & IEEE80211_BPF_DATAPAD)
+                       tap->wt_flags |= IEEE80211_RADIOTAP_F_DATAPAD;
 
                ieee80211_radiotap_tx(vap, m);
        }
@@ -3434,31 +3433,28 @@ wpi_config(struct wpi_softc *sc)
        if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
                sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ);
 
+       sc->rxon.filter = WPI_FILTER_MULTICAST;
        switch (ic->ic_opmode) {
        case IEEE80211_M_STA:
                sc->rxon.mode = WPI_MODE_STA;
-               sc->rxon.filter = htole32(WPI_FILTER_MULTICAST);
                break;
        case IEEE80211_M_IBSS:
                sc->rxon.mode = WPI_MODE_IBSS;
-               sc->rxon.filter = htole32(WPI_FILTER_BEACON |
-                   WPI_FILTER_MULTICAST);
+               sc->rxon.filter |= WPI_FILTER_BEACON;
                break;
        /* XXX workaround for passive channels selection */
        case IEEE80211_M_AHDEMO:
-               sc->rxon.filter = htole32(WPI_FILTER_MULTICAST);
-               /* FALLTHROUGH */
        case IEEE80211_M_HOSTAP:
                sc->rxon.mode = WPI_MODE_HOSTAP;
                break;
        case IEEE80211_M_MONITOR:
                sc->rxon.mode = WPI_MODE_MONITOR;
-               sc->rxon.filter = htole32(WPI_FILTER_MULTICAST);
                break;
        default:
                device_printf(sc->sc_dev, "unknown opmode %d\n", ic->ic_opmode);
                return EINVAL;
        }
+       sc->rxon.filter = htole32(sc->rxon.filter);
        wpi_set_promisc(sc);
        sc->rxon.cck_mask  = 0x0f;      /* not yet negotiated */
        sc->rxon.ofdm_mask = 0xff;      /* not yet negotiated */
@@ -3677,7 +3673,7 @@ wpi_scan(struct wpi_softc *sc, struct ie
        } else
                hdr->crc_threshold = WPI_SCAN_CRC_TH_NEVER;
 
-       if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE))
+       if (!IEEE80211_IS_CHAN_PASSIVE(c))
                chan->flags |= WPI_CHAN_ACTIVE;
 
        /*
@@ -3702,7 +3698,7 @@ wpi_scan(struct wpi_softc *sc, struct ie
                chan->rf_gain = 0x28;
 
        DPRINTF(sc, WPI_DEBUG_SCAN, "Scanning %u Passive: %d\n",
-            chan->chan, (c->ic_flags & IEEE80211_CHAN_PASSIVE) ? 1 : 0);
+            chan->chan, IEEE80211_IS_CHAN_PASSIVE(c));
 
        hdr->nchan++;
        chan++;
@@ -3838,11 +3834,13 @@ wpi_update_beacon(struct ieee80211vap *v
        struct wpi_softc *sc = ifp->if_softc;
        int error;
 
+       WPI_LOCK(sc);
        if ((error = wpi_setup_beacon(sc, ni)) != 0) {
                device_printf(sc->sc_dev,
                    "%s: could not update beacon frame, error %d", __func__,
                    error);
        }
+       WPI_UNLOCK(sc);
 }
 
 static int
@@ -3939,6 +3937,8 @@ wpi_run(struct wpi_softc *sc, struct iee
        /* Enable power-saving mode if requested by user. */
        if (vap->iv_flags & IEEE80211_F_PMGTON)
                (void)wpi_set_pslevel(sc, 0, 3, 1);
+       else
+               (void)wpi_set_pslevel(sc, 0, 0, 1);
 
        DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
 
@@ -4384,6 +4384,8 @@ wpi_apm_init(struct wpi_softc *sc)
        DELAY(20);
        /* Disable L1-Active. */
        wpi_prph_setbits(sc, WPI_APMG_PCI_STT, WPI_APMG_PCI_STT_L1A_DIS);
+       /* ??? */
+       wpi_prph_clrbits(sc, WPI_APMG_PS, 0x00000E00);
        wpi_nic_unlock(sc);
 
        return 0;

Modified: head/sys/dev/wpi/if_wpireg.h
==============================================================================
--- head/sys/dev/wpi/if_wpireg.h        Sat Feb 14 17:44:24 2015        
(r278763)
+++ head/sys/dev/wpi/if_wpireg.h        Sat Feb 14 17:45:53 2015        
(r278764)
@@ -470,6 +470,7 @@ struct wpi_cmd_data {
 #define WPI_TX_FULL_TXOP       (1 <<  7)
 #define WPI_TX_BT_DISABLE      (1 << 12)       /* bluetooth coexistence */
 #define WPI_TX_AUTO_SEQ                (1 << 13)
+#define WPI_TX_MORE_FRAG       (1 << 14)
 #define WPI_TX_INSERT_TSTAMP   (1 << 16)
 
        uint8_t         plcp;
@@ -964,11 +965,6 @@ static const char * const wpi_fw_errmsg[
        "FATAL_ERROR"
 };
 
-/* XXX description for some error codes (error data). */
-/* 0x00000074 - wrong totlen field */
-/* 0x000003B3 - powersave error */
-/* 0x00000447 - wrong channel selected */
-
 #define WPI_READ(sc, reg)                                              \
        bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to