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 --- |