Deleted Added
full compact
if_iwm.c (330206) if_iwm.c (330208)
1/* $OpenBSD: if_iwm.c,v 1.42 2015/05/30 02:49:23 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2014 genua mbh <info@genua.de>
5 * Copyright (c) 2014 Fixup Software Ltd.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above

--- 89 unchanged lines hidden (view full) ---

98 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
99 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
100 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
101 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
102 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
103 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
104 */
105#include <sys/cdefs.h>
1/* $OpenBSD: if_iwm.c,v 1.42 2015/05/30 02:49:23 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2014 genua mbh <info@genua.de>
5 * Copyright (c) 2014 Fixup Software Ltd.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above

--- 89 unchanged lines hidden (view full) ---

98 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
99 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
100 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
101 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
102 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
103 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
104 */
105#include <sys/cdefs.h>
106__FBSDID("$FreeBSD: stable/11/sys/dev/iwm/if_iwm.c 330206 2018-03-01 06:38:42Z eadler $");
106__FBSDID("$FreeBSD: stable/11/sys/dev/iwm/if_iwm.c 330208 2018-03-01 06:39:44Z eadler $");
107
108#include "opt_wlan.h"
109
110#include <sys/param.h>
111#include <sys/bus.h>
112#include <sys/conf.h>
113#include <sys/endian.h>
114#include <sys/firmware.h>

--- 48 unchanged lines hidden (view full) ---

163#include <dev/iwm/if_iwm_time_event.h>
164#include <dev/iwm/if_iwm_power.h>
165#include <dev/iwm/if_iwm_scan.h>
166
167#include <dev/iwm/if_iwm_pcie_trans.h>
168#include <dev/iwm/if_iwm_led.h>
169#include <dev/iwm/if_iwm_fw.h>
170
107
108#include "opt_wlan.h"
109
110#include <sys/param.h>
111#include <sys/bus.h>
112#include <sys/conf.h>
113#include <sys/endian.h>
114#include <sys/firmware.h>

--- 48 unchanged lines hidden (view full) ---

163#include <dev/iwm/if_iwm_time_event.h>
164#include <dev/iwm/if_iwm_power.h>
165#include <dev/iwm/if_iwm_scan.h>
166
167#include <dev/iwm/if_iwm_pcie_trans.h>
168#include <dev/iwm/if_iwm_led.h>
169#include <dev/iwm/if_iwm_fw.h>
170
171/* From DragonflyBSD */
172#define mtodoff(m, t, off) ((t)((m)->m_data + (off)))
173
171const uint8_t iwm_nvm_channels[] = {
172 /* 2.4 GHz */
173 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
174 /* 5 GHz */
175 36, 40, 44, 48, 52, 56, 60, 64,
176 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
177 149, 153, 157, 161, 165
178};

--- 135 unchanged lines hidden (view full) ---

314static int iwm_send_phy_cfg_cmd(struct iwm_softc *);
315static int iwm_mvm_load_ucode_wait_alive(struct iwm_softc *,
316 enum iwm_ucode_type);
317static int iwm_run_init_mvm_ucode(struct iwm_softc *, int);
318static int iwm_rx_addbuf(struct iwm_softc *, int, int);
319static int iwm_mvm_get_signal_strength(struct iwm_softc *,
320 struct iwm_rx_phy_info *);
321static void iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *,
174const uint8_t iwm_nvm_channels[] = {
175 /* 2.4 GHz */
176 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
177 /* 5 GHz */
178 36, 40, 44, 48, 52, 56, 60, 64,
179 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
180 149, 153, 157, 161, 165
181};

--- 135 unchanged lines hidden (view full) ---

317static int iwm_send_phy_cfg_cmd(struct iwm_softc *);
318static int iwm_mvm_load_ucode_wait_alive(struct iwm_softc *,
319 enum iwm_ucode_type);
320static int iwm_run_init_mvm_ucode(struct iwm_softc *, int);
321static int iwm_rx_addbuf(struct iwm_softc *, int, int);
322static int iwm_mvm_get_signal_strength(struct iwm_softc *,
323 struct iwm_rx_phy_info *);
324static void iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *,
322 struct iwm_rx_packet *,
323 struct iwm_rx_data *);
325 struct iwm_rx_packet *);
324static int iwm_get_noise(struct iwm_softc *sc,
325 const struct iwm_mvm_statistics_rx_non_phy *);
326static int iwm_get_noise(struct iwm_softc *sc,
327 const struct iwm_mvm_statistics_rx_non_phy *);
326static void iwm_mvm_rx_rx_mpdu(struct iwm_softc *, struct mbuf *);
328static boolean_t iwm_mvm_rx_rx_mpdu(struct iwm_softc *, struct mbuf *,
329 uint32_t, boolean_t);
327static int iwm_mvm_rx_tx_cmd_single(struct iwm_softc *,
328 struct iwm_rx_packet *,
329 struct iwm_node *);
330static int iwm_mvm_rx_tx_cmd_single(struct iwm_softc *,
331 struct iwm_rx_packet *,
332 struct iwm_node *);
330static void iwm_mvm_rx_tx_cmd(struct iwm_softc *, struct iwm_rx_packet *,
331 struct iwm_rx_data *);
333static void iwm_mvm_rx_tx_cmd(struct iwm_softc *, struct iwm_rx_packet *);
332static void iwm_cmd_done(struct iwm_softc *, struct iwm_rx_packet *);
333#if 0
334static void iwm_update_sched(struct iwm_softc *, int, int, uint8_t,
335 uint16_t);
336#endif
337static const struct iwm_rate *
338 iwm_tx_fill_cmd(struct iwm_softc *, struct iwm_node *,
339 struct mbuf *, struct iwm_tx_cmd *);

--- 39 unchanged lines hidden (view full) ---

379static void iwm_watchdog(void *);
380static void iwm_parent(struct ieee80211com *);
381#ifdef IWM_DEBUG
382static const char *
383 iwm_desc_lookup(uint32_t);
384static void iwm_nic_error(struct iwm_softc *);
385static void iwm_nic_umac_error(struct iwm_softc *);
386#endif
334static void iwm_cmd_done(struct iwm_softc *, struct iwm_rx_packet *);
335#if 0
336static void iwm_update_sched(struct iwm_softc *, int, int, uint8_t,
337 uint16_t);
338#endif
339static const struct iwm_rate *
340 iwm_tx_fill_cmd(struct iwm_softc *, struct iwm_node *,
341 struct mbuf *, struct iwm_tx_cmd *);

--- 39 unchanged lines hidden (view full) ---

381static void iwm_watchdog(void *);
382static void iwm_parent(struct ieee80211com *);
383#ifdef IWM_DEBUG
384static const char *
385 iwm_desc_lookup(uint32_t);
386static void iwm_nic_error(struct iwm_softc *);
387static void iwm_nic_umac_error(struct iwm_softc *);
388#endif
389static void iwm_handle_rxb(struct iwm_softc *, struct mbuf *);
387static void iwm_notif_intr(struct iwm_softc *);
388static void iwm_intr(void *);
389static int iwm_attach(device_t);
390static int iwm_is_valid_ether_addr(uint8_t *);
391static void iwm_preinit(void *);
392static int iwm_detach_local(struct iwm_softc *sc, int);
393static void iwm_init_task(void *);
394static void iwm_radiotap_attach(struct iwm_softc *);

--- 1031 unchanged lines hidden (view full) ---

1426 /* Set physical address of RX ring (256-byte aligned). */
1427 IWM_WRITE(sc,
1428 IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG, sc->rxq.desc_dma.paddr >> 8);
1429
1430 /* Set physical address of RX status (16-byte aligned). */
1431 IWM_WRITE(sc,
1432 IWM_FH_RSCSR_CHNL0_STTS_WPTR_REG, sc->rxq.stat_dma.paddr >> 4);
1433
390static void iwm_notif_intr(struct iwm_softc *);
391static void iwm_intr(void *);
392static int iwm_attach(device_t);
393static int iwm_is_valid_ether_addr(uint8_t *);
394static void iwm_preinit(void *);
395static int iwm_detach_local(struct iwm_softc *sc, int);
396static void iwm_init_task(void *);
397static void iwm_radiotap_attach(struct iwm_softc *);

--- 1031 unchanged lines hidden (view full) ---

1429 /* Set physical address of RX ring (256-byte aligned). */
1430 IWM_WRITE(sc,
1431 IWM_FH_RSCSR_CHNL0_RBDCB_BASE_REG, sc->rxq.desc_dma.paddr >> 8);
1432
1433 /* Set physical address of RX status (16-byte aligned). */
1434 IWM_WRITE(sc,
1435 IWM_FH_RSCSR_CHNL0_STTS_WPTR_REG, sc->rxq.stat_dma.paddr >> 4);
1436
1434 /* Enable RX. */
1437 /* Enable Rx DMA
1438 * XXX 5000 HW isn't supported by the iwm(4) driver.
1439 * IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
1440 * the credit mechanism in 5000 HW RX FIFO
1441 * Direct rx interrupts to hosts
1442 * Rx buffer size 4 or 8k or 12k
1443 * RB timeout 0x10
1444 * 256 RBDs
1445 */
1435 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG,
1436 IWM_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
1437 IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | /* HW bug */
1438 IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
1446 IWM_WRITE(sc, IWM_FH_MEM_RCSR_CHNL0_CONFIG_REG,
1447 IWM_FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
1448 IWM_FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | /* HW bug */
1449 IWM_FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
1439 IWM_FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
1440 (IWM_RX_RB_TIMEOUT << IWM_FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
1441 IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
1450 IWM_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
1451 (IWM_RX_RB_TIMEOUT << IWM_FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) |
1442 IWM_RX_QUEUE_SIZE_LOG << IWM_FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS);
1443
1444 IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF);
1445
1446 /* W/A for interrupt coalescing bug in 7260 and 3160 */
1447 if (sc->cfg->host_interrupt_operation_mode)
1448 IWM_SETBITS(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_OPER_MODE);
1449

--- 1670 unchanged lines hidden (view full) ---

3120 IWM_DPRINTF(sc, IWM_DEBUG_RECV,
3121 "energy In A %d B %d C %d , and max %d\n",
3122 energy_a, energy_b, energy_c, max_energy);
3123
3124 return max_energy;
3125}
3126
3127static void
1452 IWM_RX_QUEUE_SIZE_LOG << IWM_FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS);
1453
1454 IWM_WRITE_1(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_TIMEOUT_DEF);
1455
1456 /* W/A for interrupt coalescing bug in 7260 and 3160 */
1457 if (sc->cfg->host_interrupt_operation_mode)
1458 IWM_SETBITS(sc, IWM_CSR_INT_COALESCING, IWM_HOST_INT_OPER_MODE);
1459

--- 1670 unchanged lines hidden (view full) ---

3130 IWM_DPRINTF(sc, IWM_DEBUG_RECV,
3131 "energy In A %d B %d C %d , and max %d\n",
3132 energy_a, energy_b, energy_c, max_energy);
3133
3134 return max_energy;
3135}
3136
3137static void
3128iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *sc,
3129 struct iwm_rx_packet *pkt, struct iwm_rx_data *data)
3138iwm_mvm_rx_rx_phy_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt)
3130{
3131 struct iwm_rx_phy_info *phy_info = (void *)pkt->data;
3132
3133 IWM_DPRINTF(sc, IWM_DEBUG_RECV, "received PHY stats\n");
3139{
3140 struct iwm_rx_phy_info *phy_info = (void *)pkt->data;
3141
3142 IWM_DPRINTF(sc, IWM_DEBUG_RECV, "received PHY stats\n");
3134 bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
3135
3136 memcpy(&sc->sc_last_phy_info, phy_info, sizeof(sc->sc_last_phy_info));
3137}
3138
3139/*
3140 * Retrieve the average noise (in dBm) among receivers.
3141 */
3142static int

--- 27 unchanged lines hidden (view full) ---

3170#endif
3171}
3172
3173/*
3174 * iwm_mvm_rx_rx_mpdu - IWM_REPLY_RX_MPDU_CMD handler
3175 *
3176 * Handles the actual data of the Rx packet from the fw
3177 */
3143
3144 memcpy(&sc->sc_last_phy_info, phy_info, sizeof(sc->sc_last_phy_info));
3145}
3146
3147/*
3148 * Retrieve the average noise (in dBm) among receivers.
3149 */
3150static int

--- 27 unchanged lines hidden (view full) ---

3178#endif
3179}
3180
3181/*
3182 * iwm_mvm_rx_rx_mpdu - IWM_REPLY_RX_MPDU_CMD handler
3183 *
3184 * Handles the actual data of the Rx packet from the fw
3185 */
3178static void
3179iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m)
3186static boolean_t
3187iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *m, uint32_t offset,
3188 boolean_t stolen)
3180{
3181 struct ieee80211com *ic = &sc->sc_ic;
3182 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3183 struct ieee80211_frame *wh;
3184 struct ieee80211_node *ni;
3185 struct ieee80211_rx_stats rxs;
3186 struct iwm_rx_phy_info *phy_info;
3187 struct iwm_rx_mpdu_res_start *rx_res;
3189{
3190 struct ieee80211com *ic = &sc->sc_ic;
3191 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3192 struct ieee80211_frame *wh;
3193 struct ieee80211_node *ni;
3194 struct ieee80211_rx_stats rxs;
3195 struct iwm_rx_phy_info *phy_info;
3196 struct iwm_rx_mpdu_res_start *rx_res;
3188 struct iwm_rx_packet *pkt = mtod(m, struct iwm_rx_packet *);
3197 struct iwm_rx_packet *pkt = mtodoff(m, struct iwm_rx_packet *, offset);
3189 uint32_t len;
3190 uint32_t rx_pkt_status;
3191 int rssi;
3192
3193 phy_info = &sc->sc_last_phy_info;
3194 rx_res = (struct iwm_rx_mpdu_res_start *)pkt->data;
3195 wh = (struct ieee80211_frame *)(pkt->data + sizeof(*rx_res));
3196 len = le16toh(rx_res->byte_count);

--- 14 unchanged lines hidden (view full) ---

3211 }
3212
3213 rssi = iwm_mvm_get_signal_strength(sc, phy_info);
3214
3215 /* Map it to relative value */
3216 rssi = rssi - sc->sc_noise;
3217
3218 /* replenish ring for the buffer we're going to feed to the sharks */
3198 uint32_t len;
3199 uint32_t rx_pkt_status;
3200 int rssi;
3201
3202 phy_info = &sc->sc_last_phy_info;
3203 rx_res = (struct iwm_rx_mpdu_res_start *)pkt->data;
3204 wh = (struct ieee80211_frame *)(pkt->data + sizeof(*rx_res));
3205 len = le16toh(rx_res->byte_count);

--- 14 unchanged lines hidden (view full) ---

3220 }
3221
3222 rssi = iwm_mvm_get_signal_strength(sc, phy_info);
3223
3224 /* Map it to relative value */
3225 rssi = rssi - sc->sc_noise;
3226
3227 /* replenish ring for the buffer we're going to feed to the sharks */
3219 if (iwm_rx_addbuf(sc, IWM_RBUF_SIZE, sc->rxq.cur) != 0) {
3228 if (!stolen && iwm_rx_addbuf(sc, IWM_RBUF_SIZE, sc->rxq.cur) != 0) {
3220 device_printf(sc->sc_dev, "%s: unable to add more buffers\n",
3221 __func__);
3222 goto fail;
3223 }
3224
3225 m->m_data = pkt->data + sizeof(*rx_res);
3226 m->m_pkthdr.len = m->m_len = len;
3227

--- 63 unchanged lines hidden (view full) ---

3291 ieee80211_input_mimo(ni, m, &rxs);
3292 ieee80211_free_node(ni);
3293 } else {
3294 IWM_DPRINTF(sc, IWM_DEBUG_RECV, "inputall m %p\n", m);
3295 ieee80211_input_mimo_all(ic, m, &rxs);
3296 }
3297 IWM_LOCK(sc);
3298
3229 device_printf(sc->sc_dev, "%s: unable to add more buffers\n",
3230 __func__);
3231 goto fail;
3232 }
3233
3234 m->m_data = pkt->data + sizeof(*rx_res);
3235 m->m_pkthdr.len = m->m_len = len;
3236

--- 63 unchanged lines hidden (view full) ---

3300 ieee80211_input_mimo(ni, m, &rxs);
3301 ieee80211_free_node(ni);
3302 } else {
3303 IWM_DPRINTF(sc, IWM_DEBUG_RECV, "inputall m %p\n", m);
3304 ieee80211_input_mimo_all(ic, m, &rxs);
3305 }
3306 IWM_LOCK(sc);
3307
3299 return;
3308 return TRUE;
3300
3301fail: counter_u64_add(ic->ic_ierrors, 1);
3309
3310fail: counter_u64_add(ic->ic_ierrors, 1);
3311 return FALSE;
3302}
3303
3304static int
3305iwm_mvm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
3306 struct iwm_node *in)
3307{
3308 struct iwm_mvm_tx_resp *tx_resp = (void *)pkt->data;
3309 struct ieee80211_node *ni = &in->in_ni;

--- 23 unchanged lines hidden (view full) ---

3333 } else {
3334 ieee80211_ratectl_tx_complete(vap, ni,
3335 IEEE80211_RATECTL_TX_SUCCESS, &failack, NULL);
3336 return (0);
3337 }
3338}
3339
3340static void
3312}
3313
3314static int
3315iwm_mvm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
3316 struct iwm_node *in)
3317{
3318 struct iwm_mvm_tx_resp *tx_resp = (void *)pkt->data;
3319 struct ieee80211_node *ni = &in->in_ni;

--- 23 unchanged lines hidden (view full) ---

3343 } else {
3344 ieee80211_ratectl_tx_complete(vap, ni,
3345 IEEE80211_RATECTL_TX_SUCCESS, &failack, NULL);
3346 return (0);
3347 }
3348}
3349
3350static void
3341iwm_mvm_rx_tx_cmd(struct iwm_softc *sc,
3342 struct iwm_rx_packet *pkt, struct iwm_rx_data *data)
3351iwm_mvm_rx_tx_cmd(struct iwm_softc *sc, struct iwm_rx_packet *pkt)
3343{
3344 struct iwm_cmd_header *cmd_hdr = &pkt->hdr;
3345 int idx = cmd_hdr->idx;
3346 int qid = cmd_hdr->qid;
3347 struct iwm_tx_ring *ring = &sc->txq[qid];
3348 struct iwm_tx_data *txd = &ring->data[idx];
3349 struct iwm_node *in = txd->in;
3350 struct mbuf *m = txd->m;
3351 int status;
3352
3353 KASSERT(txd->done == 0, ("txd not done"));
3354 KASSERT(txd->in != NULL, ("txd without node"));
3355 KASSERT(txd->m != NULL, ("txd without mbuf"));
3356
3352{
3353 struct iwm_cmd_header *cmd_hdr = &pkt->hdr;
3354 int idx = cmd_hdr->idx;
3355 int qid = cmd_hdr->qid;
3356 struct iwm_tx_ring *ring = &sc->txq[qid];
3357 struct iwm_tx_data *txd = &ring->data[idx];
3358 struct iwm_node *in = txd->in;
3359 struct mbuf *m = txd->m;
3360 int status;
3361
3362 KASSERT(txd->done == 0, ("txd not done"));
3363 KASSERT(txd->in != NULL, ("txd without node"));
3364 KASSERT(txd->m != NULL, ("txd without mbuf"));
3365
3357 bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
3358
3359 sc->sc_tx_timer = 0;
3360
3361 status = iwm_mvm_rx_tx_cmd_single(sc, pkt, in);
3362
3363 /* Unmap and free mbuf. */
3364 bus_dmamap_sync(ring->data_dmat, txd->map, BUS_DMASYNC_POSTWRITE);
3365 bus_dmamap_unload(ring->data_dmat, txd->map);
3366

--- 1986 unchanged lines hidden (view full) ---

5353 device_printf(sc->sc_dev, "%08X | timestamp\n", table.u_timestamp);
5354 device_printf(sc->sc_dev, "%08X | flow_handler\n", table.flow_handler);
5355
5356 if (sc->umac_error_event_table)
5357 iwm_nic_umac_error(sc);
5358}
5359#endif
5360
3366 sc->sc_tx_timer = 0;
3367
3368 status = iwm_mvm_rx_tx_cmd_single(sc, pkt, in);
3369
3370 /* Unmap and free mbuf. */
3371 bus_dmamap_sync(ring->data_dmat, txd->map, BUS_DMASYNC_POSTWRITE);
3372 bus_dmamap_unload(ring->data_dmat, txd->map);
3373

--- 1986 unchanged lines hidden (view full) ---

5360 device_printf(sc->sc_dev, "%08X | timestamp\n", table.u_timestamp);
5361 device_printf(sc->sc_dev, "%08X | flow_handler\n", table.flow_handler);
5362
5363 if (sc->umac_error_event_table)
5364 iwm_nic_umac_error(sc);
5365}
5366#endif
5367
5361#define ADVANCE_RXQ(sc) (sc->rxq.cur = (sc->rxq.cur + 1) % IWM_RX_RING_COUNT);
5362
5363/*
5364 * Process an IWM_CSR_INT_BIT_FH_RX or IWM_CSR_INT_BIT_SW_RX interrupt.
5365 * Basic structure from if_iwn
5366 */
5367static void
5368static void
5368iwm_notif_intr(struct iwm_softc *sc)
5369iwm_handle_rxb(struct iwm_softc *sc, struct mbuf *m)
5369{
5370 struct ieee80211com *ic = &sc->sc_ic;
5370{
5371 struct ieee80211com *ic = &sc->sc_ic;
5371 uint16_t hw;
5372 struct iwm_cmd_response *cresp;
5373 struct mbuf *m1;
5374 uint32_t offset = 0;
5375 uint32_t maxoff = IWM_RBUF_SIZE;
5376 uint32_t nextoff;
5377 boolean_t stolen = FALSE;
5372
5378
5373 bus_dmamap_sync(sc->rxq.stat_dma.tag, sc->rxq.stat_dma.map,
5374 BUS_DMASYNC_POSTREAD);
5379#define HAVEROOM(a) \
5380 ((a) + sizeof(uint32_t) + sizeof(struct iwm_cmd_header) < maxoff)
5375
5381
5376 hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff;
5382 while (HAVEROOM(offset)) {
5383 struct iwm_rx_packet *pkt = mtodoff(m, struct iwm_rx_packet *,
5384 offset);
5385 int qid, idx, code, len;
5377
5386
5378 /*
5379 * Process responses
5380 */
5381 while (sc->rxq.cur != hw) {
5382 struct iwm_rx_ring *ring = &sc->rxq;
5383 struct iwm_rx_data *data = &ring->data[ring->cur];
5384 struct iwm_rx_packet *pkt;
5385 struct iwm_cmd_response *cresp;
5386 int qid, idx, code;
5387
5388 bus_dmamap_sync(ring->data_dmat, data->map,
5389 BUS_DMASYNC_POSTREAD);
5390 pkt = mtod(data->m, struct iwm_rx_packet *);
5391
5392 qid = pkt->hdr.qid & ~0x80;
5387 qid = pkt->hdr.qid;
5393 idx = pkt->hdr.idx;
5394
5395 code = IWM_WIDE_ID(pkt->hdr.flags, pkt->hdr.code);
5388 idx = pkt->hdr.idx;
5389
5390 code = IWM_WIDE_ID(pkt->hdr.flags, pkt->hdr.code);
5396 IWM_DPRINTF(sc, IWM_DEBUG_INTR,
5397 "rx packet qid=%d idx=%d type=%x %d %d\n",
5398 pkt->hdr.qid & ~0x80, pkt->hdr.idx, code, ring->cur, hw);
5399
5400 /*
5401 * randomly get these from the firmware, no idea why.
5402 * they at least seem harmless, so just ignore them for now
5403 */
5391
5392 /*
5393 * randomly get these from the firmware, no idea why.
5394 * they at least seem harmless, so just ignore them for now
5395 */
5404 if (__predict_false((pkt->hdr.code == 0 && qid == 0 && idx == 0)
5405 || pkt->len_n_flags == htole32(0x55550000))) {
5406 ADVANCE_RXQ(sc);
5407 continue;
5396 if ((pkt->hdr.code == 0 && (qid & ~0x80) == 0 && idx == 0) ||
5397 pkt->len_n_flags == htole32(IWM_FH_RSCSR_FRAME_INVALID)) {
5398 break;
5408 }
5409
5399 }
5400
5401 IWM_DPRINTF(sc, IWM_DEBUG_INTR,
5402 "rx packet qid=%d idx=%d type=%x\n",
5403 qid & ~0x80, pkt->hdr.idx, code);
5404
5405 len = le32toh(pkt->len_n_flags) & IWM_FH_RSCSR_FRAME_SIZE_MSK;
5406 len += sizeof(uint32_t); /* account for status word */
5407 nextoff = offset + roundup2(len, IWM_FH_RSCSR_FRAME_ALIGN);
5408
5410 iwm_notification_wait_notify(sc->sc_notif_wait, code, pkt);
5411
5412 switch (code) {
5413 case IWM_REPLY_RX_PHY_CMD:
5409 iwm_notification_wait_notify(sc->sc_notif_wait, code, pkt);
5410
5411 switch (code) {
5412 case IWM_REPLY_RX_PHY_CMD:
5414 iwm_mvm_rx_rx_phy_cmd(sc, pkt, data);
5413 iwm_mvm_rx_rx_phy_cmd(sc, pkt);
5415 break;
5416
5414 break;
5415
5417 case IWM_REPLY_RX_MPDU_CMD:
5418 iwm_mvm_rx_rx_mpdu(sc, data->m);
5416 case IWM_REPLY_RX_MPDU_CMD: {
5417 /*
5418 * If this is the last frame in the RX buffer, we
5419 * can directly feed the mbuf to the sharks here.
5420 */
5421 struct iwm_rx_packet *nextpkt = mtodoff(m,
5422 struct iwm_rx_packet *, nextoff);
5423 if (!HAVEROOM(nextoff) ||
5424 (nextpkt->hdr.code == 0 &&
5425 (nextpkt->hdr.qid & ~0x80) == 0 &&
5426 nextpkt->hdr.idx == 0) ||
5427 (nextpkt->len_n_flags ==
5428 htole32(IWM_FH_RSCSR_FRAME_INVALID))) {
5429 if (iwm_mvm_rx_rx_mpdu(sc, m, offset, stolen)) {
5430 stolen = FALSE;
5431 /* Make sure we abort the loop */
5432 nextoff = maxoff;
5433 }
5434 break;
5435 }
5436
5437 /*
5438 * Use m_copym instead of m_split, because that
5439 * makes it easier to keep a valid rx buffer in
5440 * the ring, when iwm_mvm_rx_rx_mpdu() fails.
5441 *
5442 * We need to start m_copym() at offset 0, to get the
5443 * M_PKTHDR flag preserved.
5444 */
5445 m1 = m_copym(m, 0, M_COPYALL, M_NOWAIT);
5446 if (m1) {
5447 if (iwm_mvm_rx_rx_mpdu(sc, m1, offset, stolen))
5448 stolen = TRUE;
5449 else
5450 m_freem(m1);
5451 }
5419 break;
5452 break;
5453 }
5420
5421 case IWM_TX_CMD:
5454
5455 case IWM_TX_CMD:
5422 iwm_mvm_rx_tx_cmd(sc, pkt, data);
5456 iwm_mvm_rx_tx_cmd(sc, pkt);
5423 break;
5424
5425 case IWM_MISSED_BEACONS_NOTIFICATION: {
5426 struct iwm_missed_beacons_notif *resp;
5427 int missed;
5428
5429 /* XXX look at mac_id to determine interface ID */
5430 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);

--- 44 unchanged lines hidden (view full) ---

5475 stats = (void *)pkt->data;
5476 memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));
5477 sc->sc_noise = iwm_get_noise(sc, &stats->rx.general);
5478 break;
5479 }
5480
5481 case IWM_NVM_ACCESS_CMD:
5482 case IWM_MCC_UPDATE_CMD:
5457 break;
5458
5459 case IWM_MISSED_BEACONS_NOTIFICATION: {
5460 struct iwm_missed_beacons_notif *resp;
5461 int missed;
5462
5463 /* XXX look at mac_id to determine interface ID */
5464 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);

--- 44 unchanged lines hidden (view full) ---

5509 stats = (void *)pkt->data;
5510 memcpy(&sc->sc_stats, stats, sizeof(sc->sc_stats));
5511 sc->sc_noise = iwm_get_noise(sc, &stats->rx.general);
5512 break;
5513 }
5514
5515 case IWM_NVM_ACCESS_CMD:
5516 case IWM_MCC_UPDATE_CMD:
5483 if (sc->sc_wantresp == ((qid << 16) | idx)) {
5517 if (sc->sc_wantresp == (((qid & ~0x80) << 16) | idx)) {
5484 memcpy(sc->sc_cmd_resp,
5485 pkt, sizeof(sc->sc_cmd_resp));
5486 }
5487 break;
5488
5489 case IWM_MCC_CHUB_UPDATE_CMD: {
5490 struct iwm_mcc_chub_notif *notif;
5491 notif = (void *)pkt->data;

--- 43 unchanged lines hidden (view full) ---

5535 case IWM_TIME_QUOTA_CMD:
5536 case IWM_REMOVE_STA:
5537 case IWM_TXPATH_FLUSH:
5538 case IWM_LQ_CMD:
5539 case IWM_FW_PAGING_BLOCK_CMD:
5540 case IWM_BT_CONFIG:
5541 case IWM_REPLY_THERMAL_MNG_BACKOFF:
5542 cresp = (void *)pkt->data;
5518 memcpy(sc->sc_cmd_resp,
5519 pkt, sizeof(sc->sc_cmd_resp));
5520 }
5521 break;
5522
5523 case IWM_MCC_CHUB_UPDATE_CMD: {
5524 struct iwm_mcc_chub_notif *notif;
5525 notif = (void *)pkt->data;

--- 43 unchanged lines hidden (view full) ---

5569 case IWM_TIME_QUOTA_CMD:
5570 case IWM_REMOVE_STA:
5571 case IWM_TXPATH_FLUSH:
5572 case IWM_LQ_CMD:
5573 case IWM_FW_PAGING_BLOCK_CMD:
5574 case IWM_BT_CONFIG:
5575 case IWM_REPLY_THERMAL_MNG_BACKOFF:
5576 cresp = (void *)pkt->data;
5543 if (sc->sc_wantresp == ((qid << 16) | idx)) {
5577 if (sc->sc_wantresp == (((qid & ~0x80) << 16) | idx)) {
5544 memcpy(sc->sc_cmd_resp,
5545 pkt, sizeof(*pkt)+sizeof(*cresp));
5546 }
5547 break;
5548
5549 /* ignore */
5550 case 0x6c: /* IWM_PHY_DB_CMD, no idea why it's not in fw-api.h */
5551 break;

--- 77 unchanged lines hidden (view full) ---

5629 rsp->token, rsp->sta_id, rsp->tid,
5630 rsp->scd_queue);
5631 break;
5632 }
5633
5634 default:
5635 device_printf(sc->sc_dev,
5636 "frame %d/%d %x UNHANDLED (this should "
5578 memcpy(sc->sc_cmd_resp,
5579 pkt, sizeof(*pkt)+sizeof(*cresp));
5580 }
5581 break;
5582
5583 /* ignore */
5584 case 0x6c: /* IWM_PHY_DB_CMD, no idea why it's not in fw-api.h */
5585 break;

--- 77 unchanged lines hidden (view full) ---

5663 rsp->token, rsp->sta_id, rsp->tid,
5664 rsp->scd_queue);
5665 break;
5666 }
5667
5668 default:
5669 device_printf(sc->sc_dev,
5670 "frame %d/%d %x UNHANDLED (this should "
5637 "not happen)\n", qid, idx,
5671 "not happen)\n", qid & ~0x80, idx,
5638 pkt->len_n_flags);
5639 break;
5640 }
5641
5642 /*
5643 * Why test bit 0x80? The Linux driver:
5644 *
5645 * There is one exception: uCode sets bit 15 when it
5646 * originates the response/notification, i.e. when the
5647 * response/notification is not a direct response to a
5648 * command sent by the driver. For example, uCode issues
5649 * IWM_REPLY_RX when it sends a received frame to the driver;
5650 * it is not a direct response to any driver command.
5651 *
5652 * Ok, so since when is 7 == 15? Well, the Linux driver
5653 * uses a slightly different format for pkt->hdr, and "qid"
5654 * is actually the upper byte of a two-byte field.
5655 */
5672 pkt->len_n_flags);
5673 break;
5674 }
5675
5676 /*
5677 * Why test bit 0x80? The Linux driver:
5678 *
5679 * There is one exception: uCode sets bit 15 when it
5680 * originates the response/notification, i.e. when the
5681 * response/notification is not a direct response to a
5682 * command sent by the driver. For example, uCode issues
5683 * IWM_REPLY_RX when it sends a received frame to the driver;
5684 * it is not a direct response to any driver command.
5685 *
5686 * Ok, so since when is 7 == 15? Well, the Linux driver
5687 * uses a slightly different format for pkt->hdr, and "qid"
5688 * is actually the upper byte of a two-byte field.
5689 */
5656 if (!(pkt->hdr.qid & (1 << 7))) {
5690 if (!(qid & (1 << 7)))
5657 iwm_cmd_done(sc, pkt);
5691 iwm_cmd_done(sc, pkt);
5658 }
5659
5692
5660 ADVANCE_RXQ(sc);
5693 offset = nextoff;
5661 }
5694 }
5695 if (stolen)
5696 m_freem(m);
5697#undef HAVEROOM
5698}
5662
5699
5700/*
5701 * Process an IWM_CSR_INT_BIT_FH_RX or IWM_CSR_INT_BIT_SW_RX interrupt.
5702 * Basic structure from if_iwn
5703 */
5704static void
5705iwm_notif_intr(struct iwm_softc *sc)
5706{
5707 uint16_t hw;
5708
5709 bus_dmamap_sync(sc->rxq.stat_dma.tag, sc->rxq.stat_dma.map,
5710 BUS_DMASYNC_POSTREAD);
5711
5712 hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff;
5713
5663 /*
5714 /*
5664 * Tell the firmware what we have processed.
5715 * Process responses
5716 */
5717 while (sc->rxq.cur != hw) {
5718 struct iwm_rx_ring *ring = &sc->rxq;
5719 struct iwm_rx_data *data = &ring->data[ring->cur];
5720
5721 bus_dmamap_sync(ring->data_dmat, data->map,
5722 BUS_DMASYNC_POSTREAD);
5723
5724 IWM_DPRINTF(sc, IWM_DEBUG_INTR,
5725 "%s: hw = %d cur = %d\n", __func__, hw, ring->cur);
5726 iwm_handle_rxb(sc, data->m);
5727
5728 ring->cur = (ring->cur + 1) % IWM_RX_RING_COUNT;
5729 }
5730
5731 /*
5732 * Tell the firmware that it can reuse the ring entries that
5733 * we have just processed.
5665 * Seems like the hardware gets upset unless we align
5666 * the write by 8??
5667 */
5668 hw = (hw == 0) ? IWM_RX_RING_COUNT - 1 : hw - 1;
5734 * Seems like the hardware gets upset unless we align
5735 * the write by 8??
5736 */
5737 hw = (hw == 0) ? IWM_RX_RING_COUNT - 1 : hw - 1;
5669 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, hw & ~7);
5738 IWM_WRITE(sc, IWM_FH_RSCSR_CHNL0_WPTR, rounddown2(hw, 8));
5670}
5671
5672static void
5673iwm_intr(void *arg)
5674{
5675 struct iwm_softc *sc = arg;
5676 int handled = 0;
5677 int r1, r2, rv = 0;

--- 868 unchanged lines hidden ---
5739}
5740
5741static void
5742iwm_intr(void *arg)
5743{
5744 struct iwm_softc *sc = arg;
5745 int handled = 0;
5746 int r1, r2, rv = 0;

--- 868 unchanged lines hidden ---