wireless-drivers-next patches for 4.19
This time a bigger pull request as we have two new Mediatek drivers MT76x2u (CONFIG_MT76x2U) and MT76x0U (CONFIG_MT76x0U). Also iwlwifi got support for the new IEEE 802.11ax standard, the successor for 802.11ac. And naturally smaller new features and bugfixes all over. Major changes: wcn36xx * fix WEP in client mode wil6210 * add support for Talyn-MB (Talyn ver 2.0) device * add support for enhanced DMA firmware feature iwlwifi * implement 802.11ax D2.0 * support for the new 22560 device family * new PCI IDs for 22000 and 22560 qtnfmac * implement cfg80211 power management callback * enable multiple SSIDs scan support * qtnfmac: implement basic WoWLAN support mt7601u * fall back to software encryption for hw unsupported ciphers * enable 802.11 Management Frame Protection (MFP) mt76 * support setting RTS threshold * add USB support * add support for MT76x2u devices * add support for MT76x0U devices mwifiex * allow user space to set all other IEs except WMM IE rsi * add firmware support for AP+BT dual mode -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJbZyxDAAoJEG4XJFUm622bq2AH/2yJAeOKb7Z25ezsvldaEDd3 cYS4TjLevXacDU5NdINtm1IRMct1ZldwUjrjgR2I/eLaSHhxyIdV4hb05etSN8qZ yo86aa1gs+8rSEn/GVO8UjX8Bh4NM/tff+yzMKWiWJGe9DtBvswSUPxBOU91vS8K WcCpvWh9SpmAPyZEDWsZnTK7AUc+X2T+Soit+pJmLm9P3RxkvMqQxG82eMGVnooO 5aNe0T9zYLB4aB8unCJqPSYSLVDJ55vnC8tFIjcEhNCF/745gyMD/CrcQ4zCxdN/ KF6WEDc/XePF5qrHvkzWA7HiR0Xs9pDt3KugkU0enZV+cba0kKaBq230sZ++1KM= =BwxN -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-for-davem-2018-08-05' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== wireless-drivers-next patches for 4.19 This time a bigger pull request as we have two new Mediatek drivers MT76x2u (CONFIG_MT76x2U) and MT76x0U (CONFIG_MT76x0U). Also iwlwifi got support for the new IEEE 802.11ax standard, the successor for 802.11ac. And naturally smaller new features and bugfixes all over. Major changes: wcn36xx * fix WEP in client mode wil6210 * add support for Talyn-MB (Talyn ver 2.0) device * add support for enhanced DMA firmware feature iwlwifi * implement 802.11ax D2.0 * support for the new 22560 device family * new PCI IDs for 22000 and 22560 qtnfmac * implement cfg80211 power management callback * enable multiple SSIDs scan support * qtnfmac: implement basic WoWLAN support mt7601u * fall back to software encryption for hw unsupported ciphers * enable 802.11 Management Frame Protection (MFP) mt76 * support setting RTS threshold * add USB support * add support for MT76x2u devices * add support for MT76x0U devices mwifiex * allow user space to set all other IEs except WMM IE rsi * add firmware support for AP+BT dual mode ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b9a7f2ee56
211 changed files with 22061 additions and 3867 deletions
|
@ -274,7 +274,7 @@ ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc,
|
|||
struct ath10k *ar = htc->ar;
|
||||
int bundle_cnt = len / sizeof(*report);
|
||||
|
||||
if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE)) {
|
||||
if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_RX_BUNDLE)) {
|
||||
ath10k_warn(ar, "Invalid lookahead bundle count: %d\n",
|
||||
bundle_cnt);
|
||||
return -EINVAL;
|
||||
|
@ -655,7 +655,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
|
|||
sizeof(msg->hdr) + sizeof(msg->ready_ext)) {
|
||||
htc->max_msgs_per_htc_bundle =
|
||||
min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle,
|
||||
HTC_HOST_MAX_MSG_PER_BUNDLE);
|
||||
HTC_HOST_MAX_MSG_PER_RX_BUNDLE);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC,
|
||||
"Extended ready message. RX bundle size: %d\n",
|
||||
htc->max_msgs_per_htc_bundle);
|
||||
|
|
|
@ -50,7 +50,8 @@ struct ath10k;
|
|||
* 4-byte aligned.
|
||||
*/
|
||||
|
||||
#define HTC_HOST_MAX_MSG_PER_BUNDLE 8
|
||||
#define HTC_HOST_MAX_MSG_PER_RX_BUNDLE 8
|
||||
#define HTC_HOST_MAX_MSG_PER_TX_BUNDLE 16
|
||||
|
||||
enum ath10k_htc_tx_flags {
|
||||
ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
|
||||
|
@ -58,6 +59,7 @@ enum ath10k_htc_tx_flags {
|
|||
};
|
||||
|
||||
enum ath10k_htc_rx_flags {
|
||||
ATH10K_HTC_FLAGS_RECV_1MORE_BLOCK = 0x01,
|
||||
ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02,
|
||||
ATH10K_HTC_FLAG_BUNDLE_MASK = 0xF0
|
||||
};
|
||||
|
|
|
@ -268,11 +268,12 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
|
|||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
ret = ath10k_htt_rx_ring_fill_n(htt, (htt->rx_ring.fill_level -
|
||||
htt->rx_ring.fill_cnt));
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
|
||||
if (ret)
|
||||
ath10k_htt_rx_ring_free(htt);
|
||||
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -284,7 +285,9 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt)
|
|||
skb_queue_purge(&htt->rx_in_ord_compl_q);
|
||||
skb_queue_purge(&htt->tx_fetch_ind_q);
|
||||
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
ath10k_htt_rx_ring_free(htt);
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
|
||||
dma_free_coherent(htt->ar->dev,
|
||||
ath10k_htt_get_rx_ring_size(htt),
|
||||
|
@ -1089,7 +1092,7 @@ static void ath10k_htt_rx_h_queue_msdu(struct ath10k *ar,
|
|||
status = IEEE80211_SKB_RXCB(skb);
|
||||
*status = *rx_status;
|
||||
|
||||
__skb_queue_tail(&ar->htt.rx_msdus_q, skb);
|
||||
skb_queue_tail(&ar->htt.rx_msdus_q, skb);
|
||||
}
|
||||
|
||||
static void ath10k_process_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
|
@ -2810,7 +2813,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: {
|
||||
__skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
|
||||
skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
|
||||
return false;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND:
|
||||
|
@ -2874,7 +2877,7 @@ static int ath10k_htt_rx_deliver_msdu(struct ath10k *ar, int quota, int budget)
|
|||
if (skb_queue_empty(&ar->htt.rx_msdus_q))
|
||||
break;
|
||||
|
||||
skb = __skb_dequeue(&ar->htt.rx_msdus_q);
|
||||
skb = skb_dequeue(&ar->htt.rx_msdus_q);
|
||||
if (!skb)
|
||||
break;
|
||||
ath10k_process_rx(ar, skb);
|
||||
|
@ -2905,7 +2908,7 @@ int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
while ((skb = __skb_dequeue(&htt->rx_in_ord_compl_q))) {
|
||||
while ((skb = skb_dequeue(&htt->rx_in_ord_compl_q))) {
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
ret = ath10k_htt_rx_in_ord_ind(ar, skb);
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
|
|
|
@ -1056,7 +1056,7 @@ static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth)
|
|||
if (!is_eth && ieee80211_is_mgmt(hdr->frame_control))
|
||||
return HTT_DATA_TX_EXT_TID_MGMT;
|
||||
else if (cb->flags & ATH10K_SKB_F_QOS)
|
||||
return skb->priority % IEEE80211_QOS_CTL_TID_MASK;
|
||||
return skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
else
|
||||
return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
|
||||
}
|
||||
|
|
|
@ -4026,7 +4026,7 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar)
|
|||
drv_priv);
|
||||
|
||||
/* Prevent aggressive sta/tid taking over tx queue */
|
||||
max = 16;
|
||||
max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE;
|
||||
ret = 0;
|
||||
while (ath10k_mac_tx_can_push(hw, txq) && max--) {
|
||||
ret = ath10k_mac_tx_push_txq(hw, txq);
|
||||
|
@ -4047,6 +4047,7 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar)
|
|||
rcu_read_unlock();
|
||||
spin_unlock_bh(&ar->txqs_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_mac_tx_push_pending);
|
||||
|
||||
/************/
|
||||
/* Scanning */
|
||||
|
@ -4287,7 +4288,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
|
|||
struct ieee80211_txq *f_txq;
|
||||
struct ath10k_txq *f_artxq;
|
||||
int ret = 0;
|
||||
int max = 16;
|
||||
int max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE;
|
||||
|
||||
spin_lock_bh(&ar->txqs_lock);
|
||||
if (list_empty(&artxq->list))
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "debug.h"
|
||||
#include "hif.h"
|
||||
#include "htc.h"
|
||||
#include "mac.h"
|
||||
#include "targaddrs.h"
|
||||
#include "trace.h"
|
||||
#include "sdio.h"
|
||||
|
@ -396,6 +397,7 @@ static int ath10k_sdio_mbox_rx_process_packet(struct ath10k *ar,
|
|||
int ret;
|
||||
|
||||
payload_len = le16_to_cpu(htc_hdr->len);
|
||||
skb->len = payload_len + sizeof(struct ath10k_htc_hdr);
|
||||
|
||||
if (trailer_present) {
|
||||
trailer = skb->data + sizeof(*htc_hdr) +
|
||||
|
@ -434,12 +436,14 @@ static int ath10k_sdio_mbox_rx_process_packets(struct ath10k *ar,
|
|||
enum ath10k_htc_ep_id id;
|
||||
int ret, i, *n_lookahead_local;
|
||||
u32 *lookaheads_local;
|
||||
int lookahead_idx = 0;
|
||||
|
||||
for (i = 0; i < ar_sdio->n_rx_pkts; i++) {
|
||||
lookaheads_local = lookaheads;
|
||||
n_lookahead_local = n_lookahead;
|
||||
|
||||
id = ((struct ath10k_htc_hdr *)&lookaheads[i])->eid;
|
||||
id = ((struct ath10k_htc_hdr *)
|
||||
&lookaheads[lookahead_idx++])->eid;
|
||||
|
||||
if (id >= ATH10K_HTC_EP_COUNT) {
|
||||
ath10k_warn(ar, "invalid endpoint in look-ahead: %d\n",
|
||||
|
@ -462,6 +466,7 @@ static int ath10k_sdio_mbox_rx_process_packets(struct ath10k *ar,
|
|||
/* Only read lookahead's from RX trailers
|
||||
* for the last packet in a bundle.
|
||||
*/
|
||||
lookahead_idx--;
|
||||
lookaheads_local = NULL;
|
||||
n_lookahead_local = NULL;
|
||||
}
|
||||
|
@ -505,11 +510,11 @@ static int ath10k_sdio_mbox_alloc_pkt_bundle(struct ath10k *ar,
|
|||
|
||||
*bndl_cnt = FIELD_GET(ATH10K_HTC_FLAG_BUNDLE_MASK, htc_hdr->flags);
|
||||
|
||||
if (*bndl_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE) {
|
||||
if (*bndl_cnt > HTC_HOST_MAX_MSG_PER_RX_BUNDLE) {
|
||||
ath10k_warn(ar,
|
||||
"HTC bundle length %u exceeds maximum %u\n",
|
||||
le16_to_cpu(htc_hdr->len),
|
||||
HTC_HOST_MAX_MSG_PER_BUNDLE);
|
||||
HTC_HOST_MAX_MSG_PER_RX_BUNDLE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -600,6 +605,9 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
|
|||
* ATH10K_HTC_FLAG_BUNDLE_MASK flag set, all bundled
|
||||
* packet skb's have been allocated in the previous step.
|
||||
*/
|
||||
if (htc_hdr->flags & ATH10K_HTC_FLAGS_RECV_1MORE_BLOCK)
|
||||
full_len += ATH10K_HIF_MBOX_BLOCK_SIZE;
|
||||
|
||||
ret = ath10k_sdio_mbox_alloc_rx_pkt(&ar_sdio->rx_pkts[i],
|
||||
act_len,
|
||||
full_len,
|
||||
|
@ -1342,6 +1350,8 @@ static void ath10k_sdio_irq_handler(struct sdio_func *func)
|
|||
break;
|
||||
} while (time_before(jiffies, timeout) && !done);
|
||||
|
||||
ath10k_mac_tx_push_pending(ar);
|
||||
|
||||
sdio_claim_host(ar_sdio->func);
|
||||
|
||||
if (ret && ret != -ECANCELED)
|
||||
|
|
|
@ -96,14 +96,14 @@
|
|||
* way:
|
||||
*
|
||||
* Let's assume that each packet in a bundle of the maximum bundle size
|
||||
* (HTC_HOST_MAX_MSG_PER_BUNDLE) has the HTC header bundle count set
|
||||
* to the maximum value (HTC_HOST_MAX_MSG_PER_BUNDLE).
|
||||
* (HTC_HOST_MAX_MSG_PER_RX_BUNDLE) has the HTC header bundle count set
|
||||
* to the maximum value (HTC_HOST_MAX_MSG_PER_RX_BUNDLE).
|
||||
*
|
||||
* in this case the driver must allocate
|
||||
* (HTC_HOST_MAX_MSG_PER_BUNDLE * HTC_HOST_MAX_MSG_PER_BUNDLE) skb's.
|
||||
* (HTC_HOST_MAX_MSG_PER_RX_BUNDLE * HTC_HOST_MAX_MSG_PER_RX_BUNDLE) skb's.
|
||||
*/
|
||||
#define ATH10K_SDIO_MAX_RX_MSGS \
|
||||
(HTC_HOST_MAX_MSG_PER_BUNDLE * HTC_HOST_MAX_MSG_PER_BUNDLE)
|
||||
(HTC_HOST_MAX_MSG_PER_RX_BUNDLE * HTC_HOST_MAX_MSG_PER_RX_BUNDLE)
|
||||
|
||||
#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL 0x00000868u
|
||||
#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
|
||||
|
|
|
@ -1076,6 +1076,8 @@ static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
|
|||
arg->phy_capab = ev->phy_capability;
|
||||
arg->num_rf_chains = ev->num_rf_chains;
|
||||
arg->eeprom_rd = reg->eeprom_rd;
|
||||
arg->low_5ghz_chan = reg->low_5ghz_chan;
|
||||
arg->high_5ghz_chan = reg->high_5ghz_chan;
|
||||
arg->num_mem_reqs = ev->num_mem_reqs;
|
||||
arg->service_map = svc_bmap;
|
||||
arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
|
||||
|
@ -1614,10 +1616,10 @@ ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
|
|||
bssid_len = arg->n_bssids * sizeof(struct wmi_mac_addr);
|
||||
ie_len = roundup(arg->ie_len, 4);
|
||||
len = (sizeof(*tlv) + sizeof(*cmd)) +
|
||||
(arg->n_channels ? sizeof(*tlv) + chan_len : 0) +
|
||||
(arg->n_ssids ? sizeof(*tlv) + ssid_len : 0) +
|
||||
(arg->n_bssids ? sizeof(*tlv) + bssid_len : 0) +
|
||||
(arg->ie_len ? sizeof(*tlv) + ie_len : 0);
|
||||
sizeof(*tlv) + chan_len +
|
||||
sizeof(*tlv) + ssid_len +
|
||||
sizeof(*tlv) + bssid_len +
|
||||
sizeof(*tlv) + ie_len;
|
||||
|
||||
skb = ath10k_wmi_alloc_skb(ar, len);
|
||||
if (!skb)
|
||||
|
|
|
@ -342,7 +342,7 @@ struct ath_chanctx {
|
|||
|
||||
struct ath_beacon_config beacon;
|
||||
struct ath9k_hw_cal_data caldata;
|
||||
struct timespec tsf_ts;
|
||||
struct timespec64 tsf_ts;
|
||||
u64 tsf_val;
|
||||
u32 last_beacon;
|
||||
|
||||
|
@ -1021,7 +1021,7 @@ struct ath_softc {
|
|||
struct ath_offchannel offchannel;
|
||||
struct ath_chanctx *next_chan;
|
||||
struct completion go_beacon;
|
||||
struct timespec last_event_time;
|
||||
struct timespec64 last_event_time;
|
||||
#endif
|
||||
|
||||
unsigned long driver_data;
|
||||
|
|
|
@ -233,9 +233,9 @@ static const char *chanctx_state_string(enum ath_chanctx_state state)
|
|||
static u32 chanctx_event_delta(struct ath_softc *sc)
|
||||
{
|
||||
u64 ms;
|
||||
struct timespec ts, *old;
|
||||
struct timespec64 ts, *old;
|
||||
|
||||
getrawmonotonic(&ts);
|
||||
ktime_get_raw_ts64(&ts);
|
||||
old = &sc->last_event_time;
|
||||
ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
||||
ms -= old->tv_sec * 1000 + old->tv_nsec / 1000000;
|
||||
|
@ -334,7 +334,7 @@ ath_chanctx_get_next(struct ath_softc *sc, struct ath_chanctx *ctx)
|
|||
static void ath_chanctx_adjust_tbtt_delta(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_chanctx *prev, *cur;
|
||||
struct timespec ts;
|
||||
struct timespec64 ts;
|
||||
u32 cur_tsf, prev_tsf, beacon_int;
|
||||
s32 offset;
|
||||
|
||||
|
@ -346,7 +346,7 @@ static void ath_chanctx_adjust_tbtt_delta(struct ath_softc *sc)
|
|||
if (!prev->switch_after_beacon)
|
||||
return;
|
||||
|
||||
getrawmonotonic(&ts);
|
||||
ktime_get_raw_ts64(&ts);
|
||||
cur_tsf = (u32) cur->tsf_val +
|
||||
ath9k_hw_get_tsf_offset(&cur->tsf_ts, &ts);
|
||||
|
||||
|
@ -1230,7 +1230,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
|
|||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_chanctx *old_ctx;
|
||||
struct timespec ts;
|
||||
struct timespec64 ts;
|
||||
bool measure_time = false;
|
||||
bool send_ps = false;
|
||||
bool queues_stopped = false;
|
||||
|
@ -1260,7 +1260,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
|
|||
spin_unlock_bh(&sc->chan_lock);
|
||||
|
||||
if (sc->next_chan == &sc->offchannel.chan) {
|
||||
getrawmonotonic(&ts);
|
||||
ktime_get_raw_ts64(&ts);
|
||||
measure_time = true;
|
||||
}
|
||||
|
||||
|
@ -1277,7 +1277,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
|
|||
spin_lock_bh(&sc->chan_lock);
|
||||
|
||||
if (sc->cur_chan != &sc->offchannel.chan) {
|
||||
getrawmonotonic(&sc->cur_chan->tsf_ts);
|
||||
ktime_get_raw_ts64(&sc->cur_chan->tsf_ts);
|
||||
sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,6 +138,7 @@ static void hif_usb_mgmt_cb(struct urb *urb)
|
|||
{
|
||||
struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
|
||||
struct hif_device_usb *hif_dev;
|
||||
unsigned long flags;
|
||||
bool txok = true;
|
||||
|
||||
if (!cmd || !cmd->skb || !cmd->hif_dev)
|
||||
|
@ -158,14 +159,14 @@ static void hif_usb_mgmt_cb(struct urb *urb)
|
|||
* If the URBs are being flushed, no need to complete
|
||||
* this packet.
|
||||
*/
|
||||
spin_lock(&hif_dev->tx.tx_lock);
|
||||
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
|
||||
if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
|
||||
spin_unlock(&hif_dev->tx.tx_lock);
|
||||
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
||||
dev_kfree_skb_any(cmd->skb);
|
||||
kfree(cmd);
|
||||
return;
|
||||
}
|
||||
spin_unlock(&hif_dev->tx.tx_lock);
|
||||
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1107,25 +1107,26 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
|
|||
struct ath_hw *ah = priv->ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&priv->rx.rxbuflock);
|
||||
spin_lock_irqsave(&priv->rx.rxbuflock, flags);
|
||||
list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
|
||||
if (!tmp_buf->in_process) {
|
||||
rxbuf = tmp_buf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&priv->rx.rxbuflock);
|
||||
spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
|
||||
|
||||
if (rxbuf == NULL) {
|
||||
ath_dbg(common, ANY, "No free RX buffer\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_lock(&priv->rx.rxbuflock);
|
||||
spin_lock_irqsave(&priv->rx.rxbuflock, flags);
|
||||
rxbuf->skb = skb;
|
||||
rxbuf->in_process = true;
|
||||
spin_unlock(&priv->rx.rxbuflock);
|
||||
spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
|
||||
|
||||
tasklet_schedule(&priv->rx_tasklet);
|
||||
return;
|
||||
|
|
|
@ -1835,13 +1835,13 @@ fail:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
u32 ath9k_hw_get_tsf_offset(struct timespec *last, struct timespec *cur)
|
||||
u32 ath9k_hw_get_tsf_offset(struct timespec64 *last, struct timespec64 *cur)
|
||||
{
|
||||
struct timespec ts;
|
||||
struct timespec64 ts;
|
||||
s64 usec;
|
||||
|
||||
if (!cur) {
|
||||
getrawmonotonic(&ts);
|
||||
ktime_get_raw_ts64(&ts);
|
||||
cur = &ts;
|
||||
}
|
||||
|
||||
|
@ -1859,7 +1859,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
u32 saveLedState;
|
||||
u32 saveDefAntenna;
|
||||
u32 macStaId1;
|
||||
struct timespec tsf_ts;
|
||||
struct timespec64 tsf_ts;
|
||||
u32 tsf_offset;
|
||||
u64 tsf = 0;
|
||||
int r;
|
||||
|
@ -1905,7 +1905,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
|
||||
|
||||
/* Save TSF before chip reset, a cold reset clears it */
|
||||
getrawmonotonic(&tsf_ts);
|
||||
ktime_get_raw_ts64(&tsf_ts);
|
||||
tsf = ath9k_hw_gettsf64(ah);
|
||||
|
||||
saveLedState = REG_READ(ah, AR_CFG_LED) &
|
||||
|
|
|
@ -1060,7 +1060,7 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah);
|
|||
u64 ath9k_hw_gettsf64(struct ath_hw *ah);
|
||||
void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
|
||||
void ath9k_hw_reset_tsf(struct ath_hw *ah);
|
||||
u32 ath9k_hw_get_tsf_offset(struct timespec *last, struct timespec *cur);
|
||||
u32 ath9k_hw_get_tsf_offset(struct timespec64 *last, struct timespec64 *cur);
|
||||
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set);
|
||||
void ath9k_hw_init_global_settings(struct ath_hw *ah);
|
||||
u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
|
||||
|
|
|
@ -1865,7 +1865,7 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw,
|
|||
mutex_lock(&sc->mutex);
|
||||
ath9k_ps_wakeup(sc);
|
||||
tsf -= le64_to_cpu(avp->tsf_adjust);
|
||||
getrawmonotonic(&avp->chanctx->tsf_ts);
|
||||
ktime_get_raw_ts64(&avp->chanctx->tsf_ts);
|
||||
if (sc->cur_chan == avp->chanctx)
|
||||
ath9k_hw_settsf64(sc->sc_ah, tsf);
|
||||
avp->chanctx->tsf_val = tsf;
|
||||
|
@ -1881,7 +1881,7 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
mutex_lock(&sc->mutex);
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
getrawmonotonic(&avp->chanctx->tsf_ts);
|
||||
ktime_get_raw_ts64(&avp->chanctx->tsf_ts);
|
||||
if (sc->cur_chan == avp->chanctx)
|
||||
ath9k_hw_reset_tsf(sc->sc_ah);
|
||||
avp->chanctx->tsf_val = 0;
|
||||
|
|
|
@ -209,6 +209,7 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
|
|||
{
|
||||
struct wmi *wmi = priv;
|
||||
struct wmi_cmd_hdr *hdr;
|
||||
unsigned long flags;
|
||||
u16 cmd_id;
|
||||
|
||||
if (unlikely(wmi->stopped))
|
||||
|
@ -218,20 +219,20 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
|
|||
cmd_id = be16_to_cpu(hdr->command_id);
|
||||
|
||||
if (cmd_id & 0x1000) {
|
||||
spin_lock(&wmi->wmi_lock);
|
||||
spin_lock_irqsave(&wmi->wmi_lock, flags);
|
||||
__skb_queue_tail(&wmi->wmi_event_queue, skb);
|
||||
spin_unlock(&wmi->wmi_lock);
|
||||
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
|
||||
tasklet_schedule(&wmi->wmi_event_tasklet);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if there has been a timeout. */
|
||||
spin_lock(&wmi->wmi_lock);
|
||||
spin_lock_irqsave(&wmi->wmi_lock, flags);
|
||||
if (be16_to_cpu(hdr->seq_no) != wmi->last_seq_id) {
|
||||
spin_unlock(&wmi->wmi_lock);
|
||||
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
|
||||
goto free_skb;
|
||||
}
|
||||
spin_unlock(&wmi->wmi_lock);
|
||||
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
|
||||
|
||||
/* WMI command response */
|
||||
ath9k_wmi_rsp_callback(wmi, skb);
|
||||
|
|
|
@ -493,7 +493,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
|
||||
struct wcn36xx_sta *sta_priv = sta ? wcn36xx_sta_to_priv(sta) : NULL;
|
||||
int ret = 0;
|
||||
u8 key[WLAN_MAX_KEY_LEN];
|
||||
|
||||
|
@ -512,7 +512,7 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
|
||||
vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP104;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
|
||||
|
@ -567,15 +567,19 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
key_conf->keyidx,
|
||||
key_conf->keylen,
|
||||
key);
|
||||
|
||||
if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
|
||||
(WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
|
||||
sta_priv->is_data_encrypted = true;
|
||||
wcn36xx_smd_set_stakey(wcn,
|
||||
vif_priv->encrypt_type,
|
||||
key_conf->keyidx,
|
||||
key_conf->keylen,
|
||||
key,
|
||||
get_sta_index(vif, sta_priv));
|
||||
list_for_each_entry(sta_priv,
|
||||
&vif_priv->sta_list, list) {
|
||||
sta_priv->is_data_encrypted = true;
|
||||
wcn36xx_smd_set_stakey(wcn,
|
||||
vif_priv->encrypt_type,
|
||||
key_conf->keyidx,
|
||||
key_conf->keylen,
|
||||
key,
|
||||
get_sta_index(vif, sta_priv));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -984,6 +988,7 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,
|
|||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
|
||||
INIT_LIST_HEAD(&vif_priv->sta_list);
|
||||
list_add(&vif_priv->list, &wcn->vif_list);
|
||||
wcn36xx_smd_add_sta_self(wcn, vif);
|
||||
|
||||
|
@ -1005,6 +1010,8 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
|
||||
spin_lock_init(&sta_priv->ampdu_lock);
|
||||
sta_priv->vif = vif_priv;
|
||||
list_add(&sta_priv->list, &vif_priv->sta_list);
|
||||
|
||||
/*
|
||||
* For STA mode HW will be configured on BSS_CHANGED_ASSOC because
|
||||
* at this stage AID is not available yet.
|
||||
|
@ -1032,6 +1039,7 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&wcn->conf_mutex);
|
||||
|
||||
list_del(&sta_priv->list);
|
||||
wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
|
||||
sta_priv->vif = NULL;
|
||||
|
||||
|
@ -1153,8 +1161,6 @@ static const struct ieee80211_ops wcn36xx_ops = {
|
|||
|
||||
static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
static const u32 cipher_suites[] = {
|
||||
WLAN_CIPHER_SUITE_WEP40,
|
||||
WLAN_CIPHER_SUITE_WEP104,
|
||||
|
@ -1201,7 +1207,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
|
|||
wiphy_ext_feature_set(wcn->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_CQM_RSSI_LIST);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
|
||||
|
|
|
@ -250,7 +250,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
|
|||
|
||||
static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
unsigned long start;
|
||||
struct wcn36xx_hal_msg_header *hdr =
|
||||
(struct wcn36xx_hal_msg_header *)wcn->hal_buf;
|
||||
|
@ -446,7 +446,7 @@ static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
|
|||
int wcn36xx_smd_start(struct wcn36xx *wcn)
|
||||
{
|
||||
struct wcn36xx_hal_mac_start_req_msg msg_body, *body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
|
@ -493,7 +493,7 @@ out:
|
|||
int wcn36xx_smd_stop(struct wcn36xx *wcn)
|
||||
{
|
||||
struct wcn36xx_hal_mac_stop_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
|
||||
|
@ -520,7 +520,7 @@ out:
|
|||
int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode)
|
||||
{
|
||||
struct wcn36xx_hal_init_scan_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
|
||||
|
@ -549,7 +549,7 @@ out:
|
|||
int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel)
|
||||
{
|
||||
struct wcn36xx_hal_start_scan_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
|
||||
|
@ -579,7 +579,7 @@ out:
|
|||
int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel)
|
||||
{
|
||||
struct wcn36xx_hal_end_scan_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
|
||||
|
@ -610,7 +610,7 @@ int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
|
|||
enum wcn36xx_hal_sys_mode mode)
|
||||
{
|
||||
struct wcn36xx_hal_finish_scan_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
|
||||
|
@ -732,7 +732,7 @@ out:
|
|||
static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
|
||||
{
|
||||
struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
ret = wcn36xx_smd_rsp_status_check(buf, len);
|
||||
if (ret)
|
||||
|
@ -747,7 +747,7 @@ int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
|
|||
struct ieee80211_vif *vif, int ch)
|
||||
{
|
||||
struct wcn36xx_hal_switch_channel_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
|
||||
|
@ -860,7 +860,7 @@ int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn,
|
|||
u8 *channels, size_t channel_count)
|
||||
{
|
||||
struct wcn36xx_hal_update_scan_params_req_ex msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
|
||||
|
@ -931,7 +931,7 @@ static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
|
|||
int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wcn36xx_hal_add_sta_self_req msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
|
||||
|
@ -965,7 +965,7 @@ out:
|
|||
int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
|
||||
{
|
||||
struct wcn36xx_hal_del_sta_self_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
|
||||
|
@ -993,7 +993,7 @@ out:
|
|||
int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
|
||||
{
|
||||
struct wcn36xx_hal_delete_sta_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
|
||||
|
@ -1040,7 +1040,7 @@ static int wcn36xx_smd_join_rsp(void *buf, size_t len)
|
|||
int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
|
||||
{
|
||||
struct wcn36xx_hal_join_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
|
||||
|
@ -1089,7 +1089,7 @@ int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
|
|||
enum wcn36xx_hal_link_state state)
|
||||
{
|
||||
struct wcn36xx_hal_set_link_state_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
|
||||
|
@ -1215,7 +1215,7 @@ int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
|
|||
{
|
||||
struct wcn36xx_hal_config_sta_req_msg msg;
|
||||
struct wcn36xx_hal_config_sta_params *sta_params;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
|
||||
|
@ -1414,7 +1414,7 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
|
|||
struct wcn36xx_hal_config_bss_params *bss;
|
||||
struct wcn36xx_hal_config_sta_params *sta_params;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ);
|
||||
|
@ -1579,7 +1579,7 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
|
|||
u16 p2p_off)
|
||||
{
|
||||
struct wcn36xx_hal_send_beacon_req_msg msg_body;
|
||||
int ret = 0, pad, pvm_len;
|
||||
int ret, pad, pvm_len;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
|
||||
|
@ -1653,7 +1653,7 @@ int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
|
|||
struct sk_buff *skb)
|
||||
{
|
||||
struct wcn36xx_hal_send_probe_resp_req_msg msg;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
|
||||
|
@ -1700,7 +1700,7 @@ int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
|
|||
u8 sta_index)
|
||||
{
|
||||
struct wcn36xx_hal_set_sta_key_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
|
||||
|
@ -1708,12 +1708,20 @@ int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
|
|||
msg_body.set_sta_key_params.sta_index = sta_index;
|
||||
msg_body.set_sta_key_params.enc_type = enc_type;
|
||||
|
||||
msg_body.set_sta_key_params.key[0].id = keyidx;
|
||||
msg_body.set_sta_key_params.key[0].unicast = 1;
|
||||
msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
|
||||
msg_body.set_sta_key_params.key[0].pae_role = 0;
|
||||
msg_body.set_sta_key_params.key[0].length = keylen;
|
||||
memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
|
||||
if (enc_type == WCN36XX_HAL_ED_WEP104 ||
|
||||
enc_type == WCN36XX_HAL_ED_WEP40) {
|
||||
/* Use bss key for wep (static) */
|
||||
msg_body.set_sta_key_params.def_wep_idx = keyidx;
|
||||
msg_body.set_sta_key_params.wep_type = 0;
|
||||
} else {
|
||||
msg_body.set_sta_key_params.key[0].id = keyidx;
|
||||
msg_body.set_sta_key_params.key[0].unicast = 1;
|
||||
msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
|
||||
msg_body.set_sta_key_params.key[0].pae_role = 0;
|
||||
msg_body.set_sta_key_params.key[0].length = keylen;
|
||||
memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
|
||||
}
|
||||
|
||||
msg_body.set_sta_key_params.single_tid_rc = 1;
|
||||
|
||||
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
|
||||
|
@ -1741,7 +1749,7 @@ int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
|
|||
u8 *key)
|
||||
{
|
||||
struct wcn36xx_hal_set_bss_key_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
|
||||
|
@ -1778,7 +1786,7 @@ int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
|
|||
u8 sta_index)
|
||||
{
|
||||
struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
|
||||
|
@ -1810,7 +1818,7 @@ int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
|
|||
u8 keyidx)
|
||||
{
|
||||
struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
|
||||
|
@ -1839,7 +1847,7 @@ int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
|
|||
{
|
||||
struct wcn36xx_hal_enter_bmps_req_msg msg_body;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
|
||||
|
@ -1869,7 +1877,7 @@ int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
|
|||
{
|
||||
struct wcn36xx_hal_exit_bmps_req_msg msg_body;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
|
||||
|
@ -1895,7 +1903,7 @@ out:
|
|||
int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
|
||||
{
|
||||
struct wcn36xx_hal_set_power_params_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
|
||||
|
@ -1930,7 +1938,7 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
|
|||
{
|
||||
struct wcn36xx_hal_keep_alive_req_msg msg_body;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
|
||||
|
@ -1968,7 +1976,7 @@ int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
|
|||
u32 arg3, u32 arg4, u32 arg5)
|
||||
{
|
||||
struct wcn36xx_hal_dump_cmd_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
|
||||
|
@ -2013,7 +2021,6 @@ void set_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
|
|||
int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
|
||||
{
|
||||
int arr_idx, bit_idx;
|
||||
int ret = 0;
|
||||
|
||||
if (cap < 0 || cap > 127) {
|
||||
wcn36xx_warn("error cap idx %d\n", cap);
|
||||
|
@ -2022,8 +2029,8 @@ int get_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
|
|||
|
||||
arr_idx = cap / 32;
|
||||
bit_idx = cap % 32;
|
||||
ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0;
|
||||
return ret;
|
||||
|
||||
return (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0;
|
||||
}
|
||||
|
||||
void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
|
||||
|
@ -2043,7 +2050,7 @@ void clear_feat_caps(u32 *bitmap, enum place_holder_in_cap_bitmap cap)
|
|||
int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
|
||||
{
|
||||
struct wcn36xx_hal_feat_caps_msg msg_body, *rsp;
|
||||
int ret = 0, i;
|
||||
int ret, i;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
|
||||
|
@ -2079,7 +2086,7 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
|
|||
u8 sta_index)
|
||||
{
|
||||
struct wcn36xx_hal_add_ba_session_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
|
||||
|
@ -2117,7 +2124,7 @@ out:
|
|||
int wcn36xx_smd_add_ba(struct wcn36xx *wcn)
|
||||
{
|
||||
struct wcn36xx_hal_add_ba_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
|
||||
|
@ -2145,7 +2152,7 @@ out:
|
|||
int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index)
|
||||
{
|
||||
struct wcn36xx_hal_del_ba_req_msg msg_body;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
|
||||
|
@ -2185,7 +2192,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
|
|||
{
|
||||
struct wcn36xx_hal_trigger_ba_req_msg msg_body;
|
||||
struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
|
||||
|
@ -2364,7 +2371,7 @@ int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
|
|||
{
|
||||
struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
|
||||
size_t len;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
|
||||
|
@ -2399,7 +2406,7 @@ int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn,
|
|||
{
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg *msg_body = NULL;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
|
||||
|
|
|
@ -129,6 +129,8 @@ struct wcn36xx_vif {
|
|||
u8 self_sta_index;
|
||||
u8 self_dpu_desc_index;
|
||||
u8 self_ucast_dpu_sign;
|
||||
|
||||
struct list_head sta_list;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -154,6 +156,7 @@ struct wcn36xx_vif {
|
|||
* |______________|_____________|_______________|
|
||||
*/
|
||||
struct wcn36xx_sta {
|
||||
struct list_head list;
|
||||
struct wcn36xx_vif *vif;
|
||||
u16 aid;
|
||||
u16 tid;
|
||||
|
|
|
@ -9,6 +9,7 @@ wil6210-$(CONFIG_WIL6210_DEBUGFS) += debugfs.o
|
|||
wil6210-y += wmi.o
|
||||
wil6210-y += interrupt.o
|
||||
wil6210-y += txrx.o
|
||||
wil6210-y += txrx_edma.o
|
||||
wil6210-y += debug.o
|
||||
wil6210-y += rx_reorder.o
|
||||
wil6210-y += fw.o
|
||||
|
|
|
@ -1726,7 +1726,7 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy,
|
|||
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
|
||||
int authorize;
|
||||
int cid, i;
|
||||
struct vring_tx_data *txdata = NULL;
|
||||
struct wil_ring_tx_data *txdata = NULL;
|
||||
|
||||
wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x mid %d\n",
|
||||
mac, params->sta_flags_mask, params->sta_flags_set,
|
||||
|
@ -1746,20 +1746,20 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy,
|
|||
return -ENOLINK;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++)
|
||||
if (wil->vring2cid_tid[i][0] == cid) {
|
||||
txdata = &wil->vring_tx_data[i];
|
||||
for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++)
|
||||
if (wil->ring2cid_tid[i][0] == cid) {
|
||||
txdata = &wil->ring_tx_data[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!txdata) {
|
||||
wil_err(wil, "vring data not found\n");
|
||||
wil_err(wil, "ring data not found\n");
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED);
|
||||
txdata->dot1x_open = authorize ? 1 : 0;
|
||||
wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i,
|
||||
wil_dbg_misc(wil, "cid %d ring %d authorize %d\n", cid, i,
|
||||
txdata->dot1x_open);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -29,7 +29,10 @@
|
|||
/* Nasty hack. Better have per device instances */
|
||||
static u32 mem_addr;
|
||||
static u32 dbg_txdesc_index;
|
||||
static u32 dbg_vring_index; /* 24+ for Rx, 0..23 for Tx */
|
||||
static u32 dbg_ring_index; /* 24+ for Rx, 0..23 for Tx */
|
||||
static u32 dbg_status_msg_index;
|
||||
/* 0..wil->num_rx_status_rings-1 for Rx, wil->tx_sring_idx for Tx */
|
||||
static u32 dbg_sring_index;
|
||||
|
||||
enum dbg_off_type {
|
||||
doff_u32 = 0,
|
||||
|
@ -47,20 +50,53 @@ struct dbg_off {
|
|||
enum dbg_off_type type;
|
||||
};
|
||||
|
||||
static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
|
||||
const char *name, struct vring *vring,
|
||||
char _s, char _h)
|
||||
static void wil_print_desc_edma(struct seq_file *s, struct wil6210_priv *wil,
|
||||
struct wil_ring *ring,
|
||||
char _s, char _h, int idx)
|
||||
{
|
||||
void __iomem *x = wmi_addr(wil, vring->hwtail);
|
||||
u8 num_of_descs;
|
||||
bool has_skb = false;
|
||||
|
||||
if (ring->is_rx) {
|
||||
struct wil_rx_enhanced_desc *rx_d =
|
||||
(struct wil_rx_enhanced_desc *)
|
||||
&ring->va[idx].rx.enhanced;
|
||||
u16 buff_id = le16_to_cpu(rx_d->mac.buff_id);
|
||||
|
||||
has_skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;
|
||||
seq_printf(s, "%c", (has_skb) ? _h : _s);
|
||||
} else {
|
||||
struct wil_tx_enhanced_desc *d =
|
||||
(struct wil_tx_enhanced_desc *)
|
||||
&ring->va[idx].tx.enhanced;
|
||||
|
||||
num_of_descs = (u8)d->mac.d[2];
|
||||
has_skb = ring->ctx[idx].skb;
|
||||
if (num_of_descs >= 1)
|
||||
seq_printf(s, "%c", ring->ctx[idx].skb ? _h : _s);
|
||||
else
|
||||
/* num_of_descs == 0, it's a frag in a list of descs */
|
||||
seq_printf(s, "%c", has_skb ? 'h' : _s);
|
||||
}
|
||||
}
|
||||
|
||||
static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil,
|
||||
const char *name, struct wil_ring *ring,
|
||||
char _s, char _h)
|
||||
{
|
||||
void __iomem *x = wmi_addr(wil, ring->hwtail);
|
||||
u32 v;
|
||||
|
||||
seq_printf(s, "VRING %s = {\n", name);
|
||||
seq_printf(s, " pa = %pad\n", &vring->pa);
|
||||
seq_printf(s, " va = 0x%p\n", vring->va);
|
||||
seq_printf(s, " size = %d\n", vring->size);
|
||||
seq_printf(s, " swtail = %d\n", vring->swtail);
|
||||
seq_printf(s, " swhead = %d\n", vring->swhead);
|
||||
seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail);
|
||||
seq_printf(s, "RING %s = {\n", name);
|
||||
seq_printf(s, " pa = %pad\n", &ring->pa);
|
||||
seq_printf(s, " va = 0x%p\n", ring->va);
|
||||
seq_printf(s, " size = %d\n", ring->size);
|
||||
if (wil->use_enhanced_dma_hw && ring->is_rx)
|
||||
seq_printf(s, " swtail = %u\n", *ring->edma_rx_swtail.va);
|
||||
else
|
||||
seq_printf(s, " swtail = %d\n", ring->swtail);
|
||||
seq_printf(s, " swhead = %d\n", ring->swhead);
|
||||
seq_printf(s, " hwtail = [0x%08x] -> ", ring->hwtail);
|
||||
if (x) {
|
||||
v = readl(x);
|
||||
seq_printf(s, "0x%08x = %d\n", v, v);
|
||||
|
@ -68,41 +104,45 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
|
|||
seq_puts(s, "???\n");
|
||||
}
|
||||
|
||||
if (vring->va && (vring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) {
|
||||
if (ring->va && (ring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) {
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < vring->size; i++) {
|
||||
volatile struct vring_tx_desc *d = &vring->va[i].tx;
|
||||
|
||||
if ((i % 128) == 0 && (i != 0))
|
||||
for (i = 0; i < ring->size; i++) {
|
||||
if ((i % 128) == 0 && i != 0)
|
||||
seq_puts(s, "\n");
|
||||
seq_printf(s, "%c", (d->dma.status & BIT(0)) ?
|
||||
_s : (vring->ctx[i].skb ? _h : 'h'));
|
||||
if (wil->use_enhanced_dma_hw) {
|
||||
wil_print_desc_edma(s, wil, ring, _s, _h, i);
|
||||
} else {
|
||||
volatile struct vring_tx_desc *d =
|
||||
&ring->va[i].tx.legacy;
|
||||
seq_printf(s, "%c", (d->dma.status & BIT(0)) ?
|
||||
_s : (ring->ctx[i].skb ? _h : 'h'));
|
||||
}
|
||||
}
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
seq_puts(s, "}\n");
|
||||
}
|
||||
|
||||
static int wil_vring_debugfs_show(struct seq_file *s, void *data)
|
||||
static int wil_ring_debugfs_show(struct seq_file *s, void *data)
|
||||
{
|
||||
uint i;
|
||||
struct wil6210_priv *wil = s->private;
|
||||
|
||||
wil_print_vring(s, wil, "rx", &wil->vring_rx, 'S', '_');
|
||||
wil_print_ring(s, wil, "rx", &wil->ring_rx, 'S', '_');
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
|
||||
struct vring *vring = &wil->vring_tx[i];
|
||||
struct vring_tx_data *txdata = &wil->vring_tx_data[i];
|
||||
for (i = 0; i < ARRAY_SIZE(wil->ring_tx); i++) {
|
||||
struct wil_ring *ring = &wil->ring_tx[i];
|
||||
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i];
|
||||
|
||||
if (vring->va) {
|
||||
int cid = wil->vring2cid_tid[i][0];
|
||||
int tid = wil->vring2cid_tid[i][1];
|
||||
u32 swhead = vring->swhead;
|
||||
u32 swtail = vring->swtail;
|
||||
int used = (vring->size + swhead - swtail)
|
||||
% vring->size;
|
||||
int avail = vring->size - used - 1;
|
||||
if (ring->va) {
|
||||
int cid = wil->ring2cid_tid[i][0];
|
||||
int tid = wil->ring2cid_tid[i][1];
|
||||
u32 swhead = ring->swhead;
|
||||
u32 swtail = ring->swtail;
|
||||
int used = (ring->size + swhead - swtail)
|
||||
% ring->size;
|
||||
int avail = ring->size - used - 1;
|
||||
char name[10];
|
||||
char sidle[10];
|
||||
/* performance monitoring */
|
||||
|
@ -137,20 +177,88 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data)
|
|||
txdata->dot1x_open ? "+" : "-",
|
||||
used, avail, sidle);
|
||||
|
||||
wil_print_vring(s, wil, name, vring, '_', 'H');
|
||||
wil_print_ring(s, wil, name, ring, '_', 'H');
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_vring_seq_open(struct inode *inode, struct file *file)
|
||||
static int wil_ring_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_vring_debugfs_show, inode->i_private);
|
||||
return single_open(file, wil_ring_debugfs_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_vring = {
|
||||
.open = wil_vring_seq_open,
|
||||
static const struct file_operations fops_ring = {
|
||||
.open = wil_ring_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static void wil_print_sring(struct seq_file *s, struct wil6210_priv *wil,
|
||||
struct wil_status_ring *sring)
|
||||
{
|
||||
void __iomem *x = wmi_addr(wil, sring->hwtail);
|
||||
int sring_idx = sring - wil->srings;
|
||||
u32 v;
|
||||
|
||||
seq_printf(s, "Status Ring %s [ %d ] = {\n",
|
||||
sring->is_rx ? "RX" : "TX", sring_idx);
|
||||
seq_printf(s, " pa = %pad\n", &sring->pa);
|
||||
seq_printf(s, " va = 0x%pK\n", sring->va);
|
||||
seq_printf(s, " size = %d\n", sring->size);
|
||||
seq_printf(s, " elem_size = %zu\n", sring->elem_size);
|
||||
seq_printf(s, " swhead = %d\n", sring->swhead);
|
||||
seq_printf(s, " hwtail = [0x%08x] -> ", sring->hwtail);
|
||||
if (x) {
|
||||
v = readl_relaxed(x);
|
||||
seq_printf(s, "0x%08x = %d\n", v, v);
|
||||
} else {
|
||||
seq_puts(s, "???\n");
|
||||
}
|
||||
seq_printf(s, " desc_rdy_pol = %d\n", sring->desc_rdy_pol);
|
||||
|
||||
if (sring->va && (sring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) {
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < sring->size; i++) {
|
||||
u32 *sdword_0 =
|
||||
(u32 *)(sring->va + (sring->elem_size * i));
|
||||
|
||||
if ((i % 128) == 0 && i != 0)
|
||||
seq_puts(s, "\n");
|
||||
if (i == sring->swhead)
|
||||
seq_printf(s, "%c", (*sdword_0 & BIT(31)) ?
|
||||
'X' : 'x');
|
||||
else
|
||||
seq_printf(s, "%c", (*sdword_0 & BIT(31)) ?
|
||||
'1' : '0');
|
||||
}
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
seq_puts(s, "}\n");
|
||||
}
|
||||
|
||||
static int wil_srings_debugfs_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < WIL6210_MAX_STATUS_RINGS; i++)
|
||||
if (wil->srings[i].va)
|
||||
wil_print_sring(s, wil, &wil->srings[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_srings_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_srings_debugfs_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_srings = {
|
||||
.open = wil_srings_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
@ -162,8 +270,8 @@ static void wil_seq_hexdump(struct seq_file *s, void *p, int len,
|
|||
seq_hex_dump(s, prefix, DUMP_PREFIX_NONE, 16, 1, p, len, false);
|
||||
}
|
||||
|
||||
static void wil_print_ring(struct seq_file *s, const char *prefix,
|
||||
void __iomem *off)
|
||||
static void wil_print_mbox_ring(struct seq_file *s, const char *prefix,
|
||||
void __iomem *off)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
struct wil6210_mbox_ring r;
|
||||
|
@ -249,9 +357,9 @@ static int wil_mbox_debugfs_show(struct seq_file *s, void *data)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wil_print_ring(s, "tx", wil->csr + HOST_MBOX +
|
||||
wil_print_mbox_ring(s, "tx", wil->csr + HOST_MBOX +
|
||||
offsetof(struct wil6210_mbox_ctl, tx));
|
||||
wil_print_ring(s, "rx", wil->csr + HOST_MBOX +
|
||||
wil_print_mbox_ring(s, "rx", wil->csr + HOST_MBOX +
|
||||
offsetof(struct wil6210_mbox_ctl, rx));
|
||||
|
||||
wil_pm_runtime_put(wil);
|
||||
|
@ -719,13 +827,13 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf,
|
|||
|
||||
if ((strcmp(cmd, "add") == 0) ||
|
||||
(strcmp(cmd, "del_tx") == 0)) {
|
||||
struct vring_tx_data *txdata;
|
||||
struct wil_ring_tx_data *txdata;
|
||||
|
||||
if (p1 < 0 || p1 >= WIL6210_MAX_TX_RINGS) {
|
||||
wil_err(wil, "BACK: invalid ring id %d\n", p1);
|
||||
return -EINVAL;
|
||||
}
|
||||
txdata = &wil->vring_tx_data[p1];
|
||||
txdata = &wil->ring_tx_data[p1];
|
||||
if (strcmp(cmd, "add") == 0) {
|
||||
if (rc < 3) {
|
||||
wil_err(wil, "BACK: add require at least 2 params\n");
|
||||
|
@ -972,55 +1080,94 @@ static void wil_seq_print_skb(struct seq_file *s, struct sk_buff *skb)
|
|||
static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
struct vring *vring;
|
||||
bool tx = (dbg_vring_index < WIL6210_MAX_TX_RINGS);
|
||||
struct wil_ring *ring;
|
||||
bool tx;
|
||||
int ring_idx = dbg_ring_index;
|
||||
int txdesc_idx = dbg_txdesc_index;
|
||||
volatile struct vring_tx_desc *d;
|
||||
volatile u32 *u;
|
||||
struct sk_buff *skb;
|
||||
|
||||
vring = tx ? &wil->vring_tx[dbg_vring_index] : &wil->vring_rx;
|
||||
if (wil->use_enhanced_dma_hw) {
|
||||
/* RX ring index == 0 */
|
||||
if (ring_idx >= WIL6210_MAX_TX_RINGS) {
|
||||
seq_printf(s, "invalid ring index %d\n", ring_idx);
|
||||
return 0;
|
||||
}
|
||||
tx = ring_idx > 0; /* desc ring 0 is reserved for RX */
|
||||
} else {
|
||||
/* RX ring index == WIL6210_MAX_TX_RINGS */
|
||||
if (ring_idx > WIL6210_MAX_TX_RINGS) {
|
||||
seq_printf(s, "invalid ring index %d\n", ring_idx);
|
||||
return 0;
|
||||
}
|
||||
tx = (ring_idx < WIL6210_MAX_TX_RINGS);
|
||||
}
|
||||
|
||||
if (!vring->va) {
|
||||
ring = tx ? &wil->ring_tx[ring_idx] : &wil->ring_rx;
|
||||
|
||||
if (!ring->va) {
|
||||
if (tx)
|
||||
seq_printf(s, "No Tx[%2d] VRING\n", dbg_vring_index);
|
||||
seq_printf(s, "No Tx[%2d] RING\n", ring_idx);
|
||||
else
|
||||
seq_puts(s, "No Rx VRING\n");
|
||||
seq_puts(s, "No Rx RING\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dbg_txdesc_index < vring->size) {
|
||||
/* use struct vring_tx_desc for Rx as well,
|
||||
* only field used, .dma.length, is the same
|
||||
*/
|
||||
volatile struct vring_tx_desc *d =
|
||||
&vring->va[dbg_txdesc_index].tx;
|
||||
volatile u32 *u = (volatile u32 *)d;
|
||||
struct sk_buff *skb = vring->ctx[dbg_txdesc_index].skb;
|
||||
|
||||
if (tx)
|
||||
seq_printf(s, "Tx[%2d][%3d] = {\n", dbg_vring_index,
|
||||
dbg_txdesc_index);
|
||||
else
|
||||
seq_printf(s, "Rx[%3d] = {\n", dbg_txdesc_index);
|
||||
seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
u[0], u[1], u[2], u[3]);
|
||||
seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
u[4], u[5], u[6], u[7]);
|
||||
seq_printf(s, " SKB = 0x%p\n", skb);
|
||||
|
||||
if (skb) {
|
||||
skb_get(skb);
|
||||
wil_seq_print_skb(s, skb);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
seq_puts(s, "}\n");
|
||||
} else {
|
||||
if (txdesc_idx >= ring->size) {
|
||||
if (tx)
|
||||
seq_printf(s, "[%2d] TxDesc index (%d) >= size (%d)\n",
|
||||
dbg_vring_index, dbg_txdesc_index,
|
||||
vring->size);
|
||||
ring_idx, txdesc_idx, ring->size);
|
||||
else
|
||||
seq_printf(s, "RxDesc index (%d) >= size (%d)\n",
|
||||
dbg_txdesc_index, vring->size);
|
||||
txdesc_idx, ring->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* use struct vring_tx_desc for Rx as well,
|
||||
* only field used, .dma.length, is the same
|
||||
*/
|
||||
d = &ring->va[txdesc_idx].tx.legacy;
|
||||
u = (volatile u32 *)d;
|
||||
skb = NULL;
|
||||
|
||||
if (wil->use_enhanced_dma_hw) {
|
||||
if (tx) {
|
||||
skb = ring->ctx[txdesc_idx].skb;
|
||||
} else {
|
||||
struct wil_rx_enhanced_desc *rx_d =
|
||||
(struct wil_rx_enhanced_desc *)
|
||||
&ring->va[txdesc_idx].rx.enhanced;
|
||||
u16 buff_id = le16_to_cpu(rx_d->mac.buff_id);
|
||||
|
||||
if (!wil_val_in_range(buff_id, 0,
|
||||
wil->rx_buff_mgmt.size)) {
|
||||
seq_printf(s, "invalid buff_id %d\n", buff_id);
|
||||
return 0;
|
||||
}
|
||||
skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;
|
||||
}
|
||||
} else {
|
||||
skb = ring->ctx[txdesc_idx].skb;
|
||||
}
|
||||
if (tx)
|
||||
seq_printf(s, "Tx[%2d][%3d] = {\n", ring_idx,
|
||||
txdesc_idx);
|
||||
else
|
||||
seq_printf(s, "Rx[%3d] = {\n", txdesc_idx);
|
||||
seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
u[0], u[1], u[2], u[3]);
|
||||
seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
u[4], u[5], u[6], u[7]);
|
||||
seq_printf(s, " SKB = 0x%p\n", skb);
|
||||
|
||||
if (skb) {
|
||||
skb_get(skb);
|
||||
wil_seq_print_skb(s, skb);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
seq_puts(s, "}\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1036,6 +1183,115 @@ static const struct file_operations fops_txdesc = {
|
|||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
/*---------Tx/Rx status message------------*/
|
||||
static int wil_status_msg_debugfs_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
int sring_idx = dbg_sring_index;
|
||||
struct wil_status_ring *sring;
|
||||
bool tx = sring_idx == wil->tx_sring_idx ? 1 : 0;
|
||||
u32 status_msg_idx = dbg_status_msg_index;
|
||||
u32 *u;
|
||||
|
||||
if (sring_idx >= WIL6210_MAX_STATUS_RINGS) {
|
||||
seq_printf(s, "invalid status ring index %d\n", sring_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sring = &wil->srings[sring_idx];
|
||||
|
||||
if (!sring->va) {
|
||||
seq_printf(s, "No %cX status ring\n", tx ? 'T' : 'R');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (status_msg_idx >= sring->size) {
|
||||
seq_printf(s, "%cxDesc index (%d) >= size (%d)\n",
|
||||
tx ? 'T' : 'R', status_msg_idx, sring->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u = sring->va + (sring->elem_size * status_msg_idx);
|
||||
|
||||
seq_printf(s, "%cx[%d][%3d] = {\n",
|
||||
tx ? 'T' : 'R', sring_idx, status_msg_idx);
|
||||
|
||||
seq_printf(s, " 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
u[0], u[1], u[2], u[3]);
|
||||
if (!tx && !wil->use_compressed_rx_status)
|
||||
seq_printf(s, " 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
u[4], u[5], u[6], u[7]);
|
||||
|
||||
seq_puts(s, "}\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_status_msg_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_status_msg_debugfs_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_status_msg = {
|
||||
.open = wil_status_msg_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
static int wil_print_rx_buff(struct seq_file *s, struct list_head *lh)
|
||||
{
|
||||
struct wil_rx_buff *it;
|
||||
int i = 0;
|
||||
|
||||
list_for_each_entry(it, lh, list) {
|
||||
if ((i % 16) == 0 && i != 0)
|
||||
seq_puts(s, "\n ");
|
||||
seq_printf(s, "[%4d] ", it->id);
|
||||
i++;
|
||||
}
|
||||
seq_printf(s, "\nNumber of buffers: %u\n", i);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int wil_rx_buff_mgmt_debugfs_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
struct wil_rx_buff_mgmt *rbm = &wil->rx_buff_mgmt;
|
||||
int num_active;
|
||||
int num_free;
|
||||
|
||||
seq_printf(s, " size = %zu\n", rbm->size);
|
||||
seq_printf(s, " free_list_empty_cnt = %lu\n",
|
||||
rbm->free_list_empty_cnt);
|
||||
|
||||
/* Print active list */
|
||||
seq_puts(s, " Active list:\n");
|
||||
num_active = wil_print_rx_buff(s, &rbm->active);
|
||||
seq_puts(s, "\n Free list:\n");
|
||||
num_free = wil_print_rx_buff(s, &rbm->free);
|
||||
|
||||
seq_printf(s, " Total number of buffers: %u\n",
|
||||
num_active + num_free);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_rx_buff_mgmt_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_rx_buff_mgmt_debugfs_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_rx_buff_mgmt = {
|
||||
.open = wil_rx_buff_mgmt_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
/*---------beamforming------------*/
|
||||
static char *wil_bfstatus_str(u32 status)
|
||||
{
|
||||
|
@ -1478,6 +1734,13 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
|
|||
p->stats.rx_large_frame,
|
||||
p->stats.rx_replay);
|
||||
|
||||
if (wil->use_enhanced_dma_hw)
|
||||
seq_printf(s,
|
||||
"mic error %lu, key error %lu, amsdu error %lu\n",
|
||||
p->stats.rx_mic_error,
|
||||
p->stats.rx_key_error,
|
||||
p->stats.rx_amsdu_error);
|
||||
|
||||
seq_puts(s, "Rx/MCS:");
|
||||
for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs);
|
||||
mcs++)
|
||||
|
@ -1760,6 +2023,60 @@ static const struct file_operations fops_suspend_stats = {
|
|||
.open = simple_open,
|
||||
};
|
||||
|
||||
/*---------compressed_rx_status---------*/
|
||||
static ssize_t wil_compressed_rx_status_write(struct file *file,
|
||||
const char __user *buf,
|
||||
size_t len, loff_t *ppos)
|
||||
{
|
||||
struct seq_file *s = file->private_data;
|
||||
struct wil6210_priv *wil = s->private;
|
||||
int compressed_rx_status;
|
||||
int rc;
|
||||
|
||||
rc = kstrtoint_from_user(buf, len, 0, &compressed_rx_status);
|
||||
if (rc) {
|
||||
wil_err(wil, "Invalid argument\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (wil_has_active_ifaces(wil, true, false)) {
|
||||
wil_err(wil, "cannot change edma config after iface is up\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
wil_info(wil, "%sable compressed_rx_status\n",
|
||||
compressed_rx_status ? "En" : "Dis");
|
||||
|
||||
wil->use_compressed_rx_status = compressed_rx_status;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
wil_compressed_rx_status_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
|
||||
seq_printf(s, "%d\n", wil->use_compressed_rx_status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wil_compressed_rx_status_seq_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, wil_compressed_rx_status_show,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_compressed_rx_status = {
|
||||
.open = wil_compressed_rx_status_seq_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.write = wil_compressed_rx_status_write,
|
||||
.llseek = seq_lseek,
|
||||
};
|
||||
|
||||
/*----------------*/
|
||||
static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
|
||||
struct dentry *dbg)
|
||||
|
@ -1790,7 +2107,7 @@ static const struct {
|
|||
const struct file_operations *fops;
|
||||
} dbg_files[] = {
|
||||
{"mbox", 0444, &fops_mbox},
|
||||
{"vrings", 0444, &fops_vring},
|
||||
{"rings", 0444, &fops_ring},
|
||||
{"stations", 0444, &fops_sta},
|
||||
{"mids", 0444, &fops_mids},
|
||||
{"desc", 0444, &fops_txdesc},
|
||||
|
@ -1813,6 +2130,10 @@ static const struct {
|
|||
{"fw_capabilities", 0444, &fops_fw_capabilities},
|
||||
{"fw_version", 0444, &fops_fw_version},
|
||||
{"suspend_stats", 0644, &fops_suspend_stats},
|
||||
{"compressed_rx_status", 0644, &fops_compressed_rx_status},
|
||||
{"srings", 0444, &fops_srings},
|
||||
{"status_msg", 0444, &fops_status_msg},
|
||||
{"rx_buff_mgmt", 0444, &fops_rx_buff_mgmt},
|
||||
};
|
||||
|
||||
static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
|
||||
|
@ -1858,7 +2179,12 @@ static const struct dbg_off dbg_wil_off[] = {
|
|||
WIL_FIELD(chip_revision, 0444, doff_u8),
|
||||
WIL_FIELD(abft_len, 0644, doff_u8),
|
||||
WIL_FIELD(wakeup_trigger, 0644, doff_u8),
|
||||
WIL_FIELD(vring_idle_trsh, 0644, doff_u32),
|
||||
WIL_FIELD(ring_idle_trsh, 0644, doff_u32),
|
||||
WIL_FIELD(num_rx_status_rings, 0644, doff_u8),
|
||||
WIL_FIELD(rx_status_ring_order, 0644, doff_u32),
|
||||
WIL_FIELD(tx_status_ring_order, 0644, doff_u32),
|
||||
WIL_FIELD(rx_buff_id_count, 0644, doff_u32),
|
||||
WIL_FIELD(amsdu_en, 0644, doff_u8),
|
||||
{},
|
||||
};
|
||||
|
||||
|
@ -1872,9 +2198,11 @@ static const struct dbg_off dbg_wil_regs[] = {
|
|||
/* static parameters */
|
||||
static const struct dbg_off dbg_statics[] = {
|
||||
{"desc_index", 0644, (ulong)&dbg_txdesc_index, doff_u32},
|
||||
{"vring_index", 0644, (ulong)&dbg_vring_index, doff_u32},
|
||||
{"ring_index", 0644, (ulong)&dbg_ring_index, doff_u32},
|
||||
{"mem_addr", 0644, (ulong)&mem_addr, doff_u32},
|
||||
{"led_polarity", 0644, (ulong)&led_polarity, doff_u8},
|
||||
{"status_index", 0644, (ulong)&dbg_status_msg_index, doff_u32},
|
||||
{"sring_index", 0644, (ulong)&dbg_sring_index, doff_u32},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wil_configure_interrupt_moderation(wil);
|
||||
wil->txrx_ops.configure_interrupt_moderation(wil);
|
||||
|
||||
wil_pm_runtime_put(wil);
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
(~(BIT_DMA_EP_RX_ICR_RX_HTRSH)))
|
||||
#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \
|
||||
BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
|
||||
#define WIL6210_IMC_TX_EDMA BIT_TX_STATUS_IRQ
|
||||
#define WIL6210_IMC_RX_EDMA BIT_RX_STATUS_IRQ
|
||||
#define WIL6210_IMC_MISC_NO_HALP (ISR_MISC_FW_READY | \
|
||||
ISR_MISC_MBOX_EVT | \
|
||||
ISR_MISC_FW_ERROR)
|
||||
|
@ -87,12 +89,24 @@ static void wil6210_mask_irq_tx(struct wil6210_priv *wil)
|
|||
WIL6210_IRQ_DISABLE);
|
||||
}
|
||||
|
||||
static void wil6210_mask_irq_tx_edma(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, IMS),
|
||||
WIL6210_IRQ_DISABLE);
|
||||
}
|
||||
|
||||
static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMS),
|
||||
WIL6210_IRQ_DISABLE);
|
||||
}
|
||||
|
||||
static void wil6210_mask_irq_rx_edma(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMS),
|
||||
WIL6210_IRQ_DISABLE);
|
||||
}
|
||||
|
||||
static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp)
|
||||
{
|
||||
wil_dbg_irq(wil, "mask_irq_misc: mask_halp(%s)\n",
|
||||
|
@ -125,6 +139,12 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
|
|||
WIL6210_IMC_TX);
|
||||
}
|
||||
|
||||
void wil6210_unmask_irq_tx_edma(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, IMC),
|
||||
WIL6210_IMC_TX_EDMA);
|
||||
}
|
||||
|
||||
void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
|
||||
{
|
||||
bool unmask_rx_htrsh = atomic_read(&wil->connected_vifs) > 0;
|
||||
|
@ -133,6 +153,12 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
|
|||
unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH);
|
||||
}
|
||||
|
||||
void wil6210_unmask_irq_rx_edma(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMC),
|
||||
WIL6210_IMC_RX_EDMA);
|
||||
}
|
||||
|
||||
static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp)
|
||||
{
|
||||
wil_dbg_irq(wil, "unmask_irq_misc: unmask_halp(%s)\n",
|
||||
|
@ -164,7 +190,9 @@ void wil_mask_irq(struct wil6210_priv *wil)
|
|||
wil_dbg_irq(wil, "mask_irq\n");
|
||||
|
||||
wil6210_mask_irq_tx(wil);
|
||||
wil6210_mask_irq_tx_edma(wil);
|
||||
wil6210_mask_irq_rx(wil);
|
||||
wil6210_mask_irq_rx_edma(wil);
|
||||
wil6210_mask_irq_misc(wil, true);
|
||||
wil6210_mask_irq_pseudo(wil);
|
||||
}
|
||||
|
@ -179,13 +207,43 @@ void wil_unmask_irq(struct wil6210_priv *wil)
|
|||
WIL_ICR_ICC_VALUE);
|
||||
wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC),
|
||||
WIL_ICR_ICC_MISC_VALUE);
|
||||
wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC),
|
||||
WIL_ICR_ICC_VALUE);
|
||||
wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, ICC),
|
||||
WIL_ICR_ICC_VALUE);
|
||||
|
||||
wil6210_unmask_irq_pseudo(wil);
|
||||
wil6210_unmask_irq_tx(wil);
|
||||
wil6210_unmask_irq_rx(wil);
|
||||
if (wil->use_enhanced_dma_hw) {
|
||||
wil6210_unmask_irq_tx_edma(wil);
|
||||
wil6210_unmask_irq_rx_edma(wil);
|
||||
} else {
|
||||
wil6210_unmask_irq_tx(wil);
|
||||
wil6210_unmask_irq_rx(wil);
|
||||
}
|
||||
wil6210_unmask_irq_misc(wil, true);
|
||||
}
|
||||
|
||||
void wil_configure_interrupt_moderation_edma(struct wil6210_priv *wil)
|
||||
{
|
||||
u32 moderation;
|
||||
|
||||
wil_s(wil, RGF_INT_GEN_IDLE_TIME_LIMIT, WIL_EDMA_IDLE_TIME_LIMIT_USEC);
|
||||
|
||||
wil_s(wil, RGF_INT_GEN_TIME_UNIT_LIMIT, WIL_EDMA_TIME_UNIT_CLK_CYCLES);
|
||||
|
||||
/* Update RX and TX moderation */
|
||||
moderation = wil->rx_max_burst_duration |
|
||||
(WIL_EDMA_AGG_WATERMARK << WIL_EDMA_AGG_WATERMARK_POS);
|
||||
wil_w(wil, RGF_INT_CTRL_INT_GEN_CFG_0, moderation);
|
||||
wil_w(wil, RGF_INT_CTRL_INT_GEN_CFG_1, moderation);
|
||||
|
||||
/* Treat special events as regular
|
||||
* (set bit 0 to 0x1 and clear bits 1-8)
|
||||
*/
|
||||
wil_c(wil, RGF_INT_COUNT_ON_SPECIAL_EVT, 0x1FE);
|
||||
wil_s(wil, RGF_INT_COUNT_ON_SPECIAL_EVT, 0x1);
|
||||
}
|
||||
|
||||
void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
|
||||
{
|
||||
struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
|
||||
|
@ -294,6 +352,97 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t wil6210_irq_rx_edma(int irq, void *cookie)
|
||||
{
|
||||
struct wil6210_priv *wil = cookie;
|
||||
u32 isr = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_INT_GEN_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
bool need_unmask = true;
|
||||
|
||||
trace_wil6210_irq_rx(isr);
|
||||
wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
|
||||
|
||||
if (unlikely(!isr)) {
|
||||
wil_err(wil, "spurious IRQ: RX\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
wil6210_mask_irq_rx_edma(wil);
|
||||
|
||||
if (likely(isr & BIT_RX_STATUS_IRQ)) {
|
||||
wil_dbg_irq(wil, "RX status ring\n");
|
||||
isr &= ~BIT_RX_STATUS_IRQ;
|
||||
if (likely(test_bit(wil_status_fwready, wil->status))) {
|
||||
if (likely(test_bit(wil_status_napi_en, wil->status))) {
|
||||
wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
|
||||
need_unmask = false;
|
||||
napi_schedule(&wil->napi_rx);
|
||||
} else {
|
||||
wil_err(wil,
|
||||
"Got Rx interrupt while stopping interface\n");
|
||||
}
|
||||
} else {
|
||||
wil_err(wil, "Got Rx interrupt while in reset\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(isr))
|
||||
wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr);
|
||||
|
||||
/* Rx IRQ will be enabled when NAPI processing finished */
|
||||
|
||||
atomic_inc(&wil->isr_count_rx);
|
||||
|
||||
if (unlikely(need_unmask))
|
||||
wil6210_unmask_irq_rx_edma(wil);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t wil6210_irq_tx_edma(int irq, void *cookie)
|
||||
{
|
||||
struct wil6210_priv *wil = cookie;
|
||||
u32 isr = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_INT_GEN_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
bool need_unmask = true;
|
||||
|
||||
trace_wil6210_irq_tx(isr);
|
||||
wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
|
||||
|
||||
if (unlikely(!isr)) {
|
||||
wil_err(wil, "spurious IRQ: TX\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
wil6210_mask_irq_tx_edma(wil);
|
||||
|
||||
if (likely(isr & BIT_TX_STATUS_IRQ)) {
|
||||
wil_dbg_irq(wil, "TX status ring\n");
|
||||
isr &= ~BIT_TX_STATUS_IRQ;
|
||||
if (likely(test_bit(wil_status_fwready, wil->status))) {
|
||||
wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
|
||||
need_unmask = false;
|
||||
napi_schedule(&wil->napi_tx);
|
||||
} else {
|
||||
wil_err(wil, "Got Tx status ring IRQ while in reset\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(isr))
|
||||
wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
|
||||
|
||||
/* Tx IRQ will be enabled when NAPI processing finished */
|
||||
|
||||
atomic_inc(&wil->isr_count_tx);
|
||||
|
||||
if (unlikely(need_unmask))
|
||||
wil6210_unmask_irq_tx_edma(wil);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
||||
{
|
||||
struct wil6210_priv *wil = cookie;
|
||||
|
@ -510,30 +659,53 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
|
|||
*/
|
||||
static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
|
||||
{
|
||||
u32 icm_rx, icr_rx, imv_rx;
|
||||
u32 icm_tx, icr_tx, imv_tx;
|
||||
u32 icm_misc, icr_misc, imv_misc;
|
||||
|
||||
if (!test_bit(wil_status_irqen, wil->status)) {
|
||||
u32 icm_rx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICM));
|
||||
u32 icr_rx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
u32 imv_rx = wil_r(wil, RGF_DMA_EP_RX_ICR +
|
||||
if (wil->use_enhanced_dma_hw) {
|
||||
icm_rx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_INT_GEN_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICM));
|
||||
icr_rx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_INT_GEN_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
imv_rx = wil_r(wil, RGF_INT_GEN_RX_ICR +
|
||||
offsetof(struct RGF_ICR, IMV));
|
||||
u32 icm_tx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICM));
|
||||
u32 icr_tx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
u32 imv_tx = wil_r(wil, RGF_DMA_EP_TX_ICR +
|
||||
icm_tx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_INT_GEN_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICM));
|
||||
icr_tx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_INT_GEN_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
imv_tx = wil_r(wil, RGF_INT_GEN_TX_ICR +
|
||||
offsetof(struct RGF_ICR, IMV));
|
||||
} else {
|
||||
icm_rx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICM));
|
||||
icr_rx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
imv_rx = wil_r(wil, RGF_DMA_EP_RX_ICR +
|
||||
offsetof(struct RGF_ICR, IMV));
|
||||
u32 icm_misc = wil_ioread32_and_clear(wil->csr +
|
||||
icm_tx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICM));
|
||||
icr_tx = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
imv_tx = wil_r(wil, RGF_DMA_EP_TX_ICR +
|
||||
offsetof(struct RGF_ICR, IMV));
|
||||
}
|
||||
icm_misc = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_MISC_ICR) +
|
||||
offsetof(struct RGF_ICR, ICM));
|
||||
u32 icr_misc = wil_ioread32_and_clear(wil->csr +
|
||||
icr_misc = wil_ioread32_and_clear(wil->csr +
|
||||
HOSTADDR(RGF_DMA_EP_MISC_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
u32 imv_misc = wil_r(wil, RGF_DMA_EP_MISC_ICR +
|
||||
imv_misc = wil_r(wil, RGF_DMA_EP_MISC_ICR +
|
||||
offsetof(struct RGF_ICR, IMV));
|
||||
|
||||
/* HALP interrupt can be unmasked when misc interrupts are
|
||||
|
@ -592,11 +764,11 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
|
|||
* voting for wake thread - need at least 1 vote
|
||||
*/
|
||||
if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) &&
|
||||
(wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
|
||||
(wil->txrx_ops.irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
|
||||
rc = IRQ_WAKE_THREAD;
|
||||
|
||||
if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) &&
|
||||
(wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD))
|
||||
(wil->txrx_ops.irq_tx(irq, cookie) == IRQ_WAKE_THREAD))
|
||||
rc = IRQ_WAKE_THREAD;
|
||||
|
||||
if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) &&
|
||||
|
@ -624,6 +796,10 @@ void wil6210_clear_irq(struct wil6210_priv *wil)
|
|||
offsetof(struct RGF_ICR, ICR));
|
||||
wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
|
||||
offsetof(struct RGF_ICR, ICR));
|
||||
wmb(); /* make sure write completed */
|
||||
|
@ -652,6 +828,13 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi)
|
|||
|
||||
wil_dbg_misc(wil, "init_irq: %s\n", use_msi ? "MSI" : "INTx");
|
||||
|
||||
if (wil->use_enhanced_dma_hw) {
|
||||
wil->txrx_ops.irq_tx = wil6210_irq_tx_edma;
|
||||
wil->txrx_ops.irq_rx = wil6210_irq_rx_edma;
|
||||
} else {
|
||||
wil->txrx_ops.irq_tx = wil6210_irq_tx;
|
||||
wil->txrx_ops.irq_rx = wil6210_irq_rx;
|
||||
}
|
||||
rc = request_threaded_irq(irq, wil6210_hardirq,
|
||||
wil6210_thread_irq,
|
||||
use_msi ? 0 : IRQF_SHARED,
|
||||
|
|
|
@ -21,11 +21,13 @@
|
|||
|
||||
#include "wil6210.h"
|
||||
#include "txrx.h"
|
||||
#include "txrx_edma.h"
|
||||
#include "wmi.h"
|
||||
#include "boot_loader.h"
|
||||
|
||||
#define WAIT_FOR_HALP_VOTE_MS 100
|
||||
#define WAIT_FOR_SCAN_ABORT_MS 1000
|
||||
#define WIL_DEFAULT_NUM_RX_STATUS_RINGS 1
|
||||
|
||||
bool debug_fw; /* = false; */
|
||||
module_param(debug_fw, bool, 0444);
|
||||
|
@ -110,9 +112,29 @@ MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order");
|
|||
module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, 0444);
|
||||
MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order");
|
||||
|
||||
#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
|
||||
enum {
|
||||
WIL_BOOT_ERR,
|
||||
WIL_BOOT_VANILLA,
|
||||
WIL_BOOT_PRODUCTION,
|
||||
WIL_BOOT_DEVELOPMENT,
|
||||
};
|
||||
|
||||
enum {
|
||||
WIL_SIG_STATUS_VANILLA = 0x0,
|
||||
WIL_SIG_STATUS_DEVELOPMENT = 0x1,
|
||||
WIL_SIG_STATUS_PRODUCTION = 0x2,
|
||||
WIL_SIG_STATUS_CORRUPTED_PRODUCTION = 0x3,
|
||||
};
|
||||
|
||||
#define RST_DELAY (20) /* msec, for loop in @wil_wait_device_ready */
|
||||
#define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
|
||||
|
||||
#define PMU_READY_DELAY_MS (4) /* ms, for sleep in @wil_wait_device_ready */
|
||||
|
||||
#define OTP_HW_DELAY (200) /* usec, loop in @wil_wait_device_ready_talyn_mb */
|
||||
/* round up to be above 2 ms total */
|
||||
#define OTP_HW_COUNT (1 + 2000 / OTP_HW_DELAY)
|
||||
|
||||
/*
|
||||
* Due to a hardware issue,
|
||||
* one has to read/write to/from NIC in 32-bit chunks;
|
||||
|
@ -160,6 +182,37 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
|
|||
}
|
||||
}
|
||||
|
||||
static void wil_ring_fini_tx(struct wil6210_priv *wil, int id)
|
||||
{
|
||||
struct wil_ring *ring = &wil->ring_tx[id];
|
||||
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id];
|
||||
|
||||
lockdep_assert_held(&wil->mutex);
|
||||
|
||||
if (!ring->va)
|
||||
return;
|
||||
|
||||
wil_dbg_misc(wil, "vring_fini_tx: id=%d\n", id);
|
||||
|
||||
spin_lock_bh(&txdata->lock);
|
||||
txdata->dot1x_open = false;
|
||||
txdata->mid = U8_MAX;
|
||||
txdata->enabled = 0; /* no Tx can be in progress or start anew */
|
||||
spin_unlock_bh(&txdata->lock);
|
||||
/* napi_synchronize waits for completion of the current NAPI but will
|
||||
* not prevent the next NAPI run.
|
||||
* Add a memory barrier to guarantee that txdata->enabled is zeroed
|
||||
* before napi_synchronize so that the next scheduled NAPI will not
|
||||
* handle this vring
|
||||
*/
|
||||
wmb();
|
||||
/* make sure NAPI won't touch this vring */
|
||||
if (test_bit(wil_status_napi_en, wil->status))
|
||||
napi_synchronize(&wil->napi_tx);
|
||||
|
||||
wil->txrx_ops.ring_fini_tx(wil, ring);
|
||||
}
|
||||
|
||||
static void wil_disconnect_cid(struct wil6210_vif *vif, int cid,
|
||||
u16 reason_code, bool from_event)
|
||||
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
||||
|
@ -219,9 +272,9 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
memset(sta->tid_crypto_rx, 0, sizeof(sta->tid_crypto_rx));
|
||||
memset(&sta->group_crypto_rx, 0, sizeof(sta->group_crypto_rx));
|
||||
/* release vrings */
|
||||
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
|
||||
if (wil->vring2cid_tid[i][0] == cid)
|
||||
wil_vring_fini_tx(wil, i);
|
||||
for (i = 0; i < ARRAY_SIZE(wil->ring_tx); i++) {
|
||||
if (wil->ring2cid_tid[i][0] == cid)
|
||||
wil_ring_fini_tx(wil, i);
|
||||
}
|
||||
/* statistics */
|
||||
memset(&sta->stats, 0, sizeof(sta->stats));
|
||||
|
@ -453,18 +506,19 @@ static void wil_fw_error_worker(struct work_struct *work)
|
|||
mutex_unlock(&wil->mutex);
|
||||
}
|
||||
|
||||
static int wil_find_free_vring(struct wil6210_priv *wil)
|
||||
static int wil_find_free_ring(struct wil6210_priv *wil)
|
||||
{
|
||||
int i;
|
||||
int min_ring_id = wil_get_min_tx_ring_id(wil);
|
||||
|
||||
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
|
||||
if (!wil->vring_tx[i].va)
|
||||
for (i = min_ring_id; i < WIL6210_MAX_TX_RINGS; i++) {
|
||||
if (!wil->ring_tx[i].va)
|
||||
return i;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int wil_tx_init(struct wil6210_vif *vif, int cid)
|
||||
int wil_ring_init_tx(struct wil6210_vif *vif, int cid)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
int rc = -EINVAL, ringid;
|
||||
|
@ -473,16 +527,17 @@ int wil_tx_init(struct wil6210_vif *vif, int cid)
|
|||
wil_err(wil, "No connection pending\n");
|
||||
goto out;
|
||||
}
|
||||
ringid = wil_find_free_vring(wil);
|
||||
ringid = wil_find_free_ring(wil);
|
||||
if (ringid < 0) {
|
||||
wil_err(wil, "No free vring found\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
wil_dbg_wmi(wil, "Configure for connection CID %d MID %d vring %d\n",
|
||||
wil_dbg_wmi(wil, "Configure for connection CID %d MID %d ring %d\n",
|
||||
cid, vif->mid, ringid);
|
||||
|
||||
rc = wil_vring_init_tx(vif, ringid, 1 << tx_ring_order, cid, 0);
|
||||
rc = wil->txrx_ops.ring_init_tx(vif, ringid, 1 << tx_ring_order,
|
||||
cid, 0);
|
||||
if (rc)
|
||||
wil_err(wil, "init TX for CID %d MID %d vring %d failed\n",
|
||||
cid, vif->mid, ringid);
|
||||
|
@ -494,19 +549,19 @@ out:
|
|||
int wil_bcast_init(struct wil6210_vif *vif)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
int ri = vif->bcast_vring, rc;
|
||||
int ri = vif->bcast_ring, rc;
|
||||
|
||||
if ((ri >= 0) && wil->vring_tx[ri].va)
|
||||
if (ri >= 0 && wil->ring_tx[ri].va)
|
||||
return 0;
|
||||
|
||||
ri = wil_find_free_vring(wil);
|
||||
ri = wil_find_free_ring(wil);
|
||||
if (ri < 0)
|
||||
return ri;
|
||||
|
||||
vif->bcast_vring = ri;
|
||||
rc = wil_vring_init_bcast(vif, ri, 1 << bcast_ring_order);
|
||||
vif->bcast_ring = ri;
|
||||
rc = wil->txrx_ops.ring_init_bcast(vif, ri, 1 << bcast_ring_order);
|
||||
if (rc)
|
||||
vif->bcast_vring = -1;
|
||||
vif->bcast_ring = -1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -514,13 +569,13 @@ int wil_bcast_init(struct wil6210_vif *vif)
|
|||
void wil_bcast_fini(struct wil6210_vif *vif)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
int ri = vif->bcast_vring;
|
||||
int ri = vif->bcast_ring;
|
||||
|
||||
if (ri < 0)
|
||||
return;
|
||||
|
||||
vif->bcast_vring = -1;
|
||||
wil_vring_fini_tx(wil, ri);
|
||||
vif->bcast_ring = -1;
|
||||
wil_ring_fini_tx(wil, ri);
|
||||
}
|
||||
|
||||
void wil_bcast_fini_all(struct wil6210_priv *wil)
|
||||
|
@ -548,7 +603,7 @@ int wil_priv_init(struct wil6210_priv *wil)
|
|||
}
|
||||
|
||||
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++)
|
||||
spin_lock_init(&wil->vring_tx_data[i].lock);
|
||||
spin_lock_init(&wil->ring_tx_data[i].lock);
|
||||
|
||||
mutex_init(&wil->mutex);
|
||||
mutex_init(&wil->vif_mutex);
|
||||
|
@ -589,11 +644,30 @@ int wil_priv_init(struct wil6210_priv *wil)
|
|||
wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST |
|
||||
WMI_WAKEUP_TRIGGER_BCAST;
|
||||
memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
|
||||
wil->vring_idle_trsh = 16;
|
||||
wil->ring_idle_trsh = 16;
|
||||
|
||||
wil->reply_mid = U8_MAX;
|
||||
wil->max_vifs = 1;
|
||||
|
||||
/* edma configuration can be updated via debugfs before allocation */
|
||||
wil->num_rx_status_rings = WIL_DEFAULT_NUM_RX_STATUS_RINGS;
|
||||
wil->use_compressed_rx_status = true;
|
||||
wil->use_rx_hw_reordering = true;
|
||||
wil->tx_status_ring_order = WIL_TX_SRING_SIZE_ORDER_DEFAULT;
|
||||
|
||||
/* Rx status ring size should be bigger than the number of RX buffers
|
||||
* in order to prevent backpressure on the status ring, which may
|
||||
* cause HW freeze.
|
||||
*/
|
||||
wil->rx_status_ring_order = WIL_RX_SRING_SIZE_ORDER_DEFAULT;
|
||||
/* Number of RX buffer IDs should be bigger than the RX descriptor
|
||||
* ring size as in HW reorder flow, the HW can consume additional
|
||||
* buffers before releasing the previous ones.
|
||||
*/
|
||||
wil->rx_buff_id_count = WIL_RX_BUFF_ARR_SIZE_DEFAULT;
|
||||
|
||||
wil->amsdu_en = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
out_wmi_wq:
|
||||
|
@ -736,14 +810,24 @@ static void wil_bl_prepare_halt(struct wil6210_priv *wil)
|
|||
|
||||
static inline void wil_halt_cpu(struct wil6210_priv *wil)
|
||||
{
|
||||
wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST);
|
||||
wil_w(wil, RGF_USER_MAC_CPU_0, BIT_USER_MAC_CPU_MAN_RST);
|
||||
if (wil->hw_version >= HW_VER_TALYN_MB) {
|
||||
wil_w(wil, RGF_USER_USER_CPU_0_TALYN_MB,
|
||||
BIT_USER_USER_CPU_MAN_RST);
|
||||
wil_w(wil, RGF_USER_MAC_CPU_0_TALYN_MB,
|
||||
BIT_USER_MAC_CPU_MAN_RST);
|
||||
} else {
|
||||
wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST);
|
||||
wil_w(wil, RGF_USER_MAC_CPU_0, BIT_USER_MAC_CPU_MAN_RST);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void wil_release_cpu(struct wil6210_priv *wil)
|
||||
{
|
||||
/* Start CPU */
|
||||
wil_w(wil, RGF_USER_USER_CPU_0, 1);
|
||||
if (wil->hw_version >= HW_VER_TALYN_MB)
|
||||
wil_w(wil, RGF_USER_USER_CPU_0_TALYN_MB, 1);
|
||||
else
|
||||
wil_w(wil, RGF_USER_USER_CPU_0, 1);
|
||||
}
|
||||
|
||||
static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode)
|
||||
|
@ -767,11 +851,146 @@ static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode)
|
|||
}
|
||||
}
|
||||
|
||||
static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
|
||||
static int wil_wait_device_ready(struct wil6210_priv *wil, int no_flash)
|
||||
{
|
||||
int delay = 0;
|
||||
u32 x, x1 = 0;
|
||||
|
||||
/* wait until device ready. */
|
||||
if (no_flash) {
|
||||
msleep(PMU_READY_DELAY_MS);
|
||||
|
||||
wil_dbg_misc(wil, "Reset completed\n");
|
||||
} else {
|
||||
do {
|
||||
msleep(RST_DELAY);
|
||||
x = wil_r(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v0,
|
||||
boot_loader_ready));
|
||||
if (x1 != x) {
|
||||
wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n",
|
||||
x1, x);
|
||||
x1 = x;
|
||||
}
|
||||
if (delay++ > RST_COUNT) {
|
||||
wil_err(wil, "Reset not completed, bl.ready 0x%08x\n",
|
||||
x);
|
||||
return -ETIME;
|
||||
}
|
||||
} while (x != BL_READY);
|
||||
|
||||
wil_dbg_misc(wil, "Reset completed in %d ms\n",
|
||||
delay * RST_DELAY);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_wait_device_ready_talyn_mb(struct wil6210_priv *wil)
|
||||
{
|
||||
u32 otp_hw;
|
||||
u8 signature_status;
|
||||
bool otp_signature_err;
|
||||
bool hw_section_done;
|
||||
u32 otp_qc_secured;
|
||||
int delay = 0;
|
||||
|
||||
/* Wait for OTP signature test to complete */
|
||||
usleep_range(2000, 2200);
|
||||
|
||||
wil->boot_config = WIL_BOOT_ERR;
|
||||
|
||||
/* Poll until OTP signature status is valid.
|
||||
* In vanilla and development modes, when signature test is complete
|
||||
* HW sets BIT_OTP_SIGNATURE_ERR_TALYN_MB.
|
||||
* In production mode BIT_OTP_SIGNATURE_ERR_TALYN_MB remains 0, poll
|
||||
* for signature status change to 2 or 3.
|
||||
*/
|
||||
do {
|
||||
otp_hw = wil_r(wil, RGF_USER_OTP_HW_RD_MACHINE_1);
|
||||
signature_status = WIL_GET_BITS(otp_hw, 8, 9);
|
||||
otp_signature_err = otp_hw & BIT_OTP_SIGNATURE_ERR_TALYN_MB;
|
||||
|
||||
if (otp_signature_err &&
|
||||
signature_status == WIL_SIG_STATUS_VANILLA) {
|
||||
wil->boot_config = WIL_BOOT_VANILLA;
|
||||
break;
|
||||
}
|
||||
if (otp_signature_err &&
|
||||
signature_status == WIL_SIG_STATUS_DEVELOPMENT) {
|
||||
wil->boot_config = WIL_BOOT_DEVELOPMENT;
|
||||
break;
|
||||
}
|
||||
if (!otp_signature_err &&
|
||||
signature_status == WIL_SIG_STATUS_PRODUCTION) {
|
||||
wil->boot_config = WIL_BOOT_PRODUCTION;
|
||||
break;
|
||||
}
|
||||
if (!otp_signature_err &&
|
||||
signature_status ==
|
||||
WIL_SIG_STATUS_CORRUPTED_PRODUCTION) {
|
||||
/* Unrecognized OTP signature found. Possibly a
|
||||
* corrupted production signature, access control
|
||||
* is applied as in production mode, therefore
|
||||
* do not fail
|
||||
*/
|
||||
wil->boot_config = WIL_BOOT_PRODUCTION;
|
||||
break;
|
||||
}
|
||||
if (delay++ > OTP_HW_COUNT)
|
||||
break;
|
||||
|
||||
usleep_range(OTP_HW_DELAY, OTP_HW_DELAY + 10);
|
||||
} while (!otp_signature_err && signature_status == 0);
|
||||
|
||||
if (wil->boot_config == WIL_BOOT_ERR) {
|
||||
wil_err(wil,
|
||||
"invalid boot config, signature_status %d otp_signature_err %d\n",
|
||||
signature_status, otp_signature_err);
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
wil_dbg_misc(wil,
|
||||
"signature test done in %d usec, otp_hw 0x%x, boot_config %d\n",
|
||||
delay * OTP_HW_DELAY, otp_hw, wil->boot_config);
|
||||
|
||||
if (wil->boot_config == WIL_BOOT_VANILLA)
|
||||
/* Assuming not SPI boot (currently not supported) */
|
||||
goto out;
|
||||
|
||||
hw_section_done = otp_hw & BIT_OTP_HW_SECTION_DONE_TALYN_MB;
|
||||
delay = 0;
|
||||
|
||||
while (!hw_section_done) {
|
||||
msleep(RST_DELAY);
|
||||
|
||||
otp_hw = wil_r(wil, RGF_USER_OTP_HW_RD_MACHINE_1);
|
||||
hw_section_done = otp_hw & BIT_OTP_HW_SECTION_DONE_TALYN_MB;
|
||||
|
||||
if (delay++ > RST_COUNT) {
|
||||
wil_err(wil, "TO waiting for hw_section_done\n");
|
||||
return -ETIME;
|
||||
}
|
||||
}
|
||||
|
||||
wil_dbg_misc(wil, "HW section done in %d ms\n", delay * RST_DELAY);
|
||||
|
||||
otp_qc_secured = wil_r(wil, RGF_OTP_QC_SECURED);
|
||||
wil->secured_boot = otp_qc_secured & BIT_BOOT_FROM_ROM ? 1 : 0;
|
||||
wil_dbg_misc(wil, "secured boot is %sabled\n",
|
||||
wil->secured_boot ? "en" : "dis");
|
||||
|
||||
out:
|
||||
wil_dbg_misc(wil, "Reset completed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
|
||||
{
|
||||
u32 x;
|
||||
int rc;
|
||||
|
||||
wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->hw_name);
|
||||
|
||||
/* Clear MAC link up */
|
||||
|
@ -811,10 +1030,17 @@ static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
|
|||
wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
|
||||
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x000000f0);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00);
|
||||
if (wil->hw_version >= HW_VER_TALYN_MB) {
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x7e000000);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003f);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0xc00000f0);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xffe7fe00);
|
||||
} else {
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xfe000000);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003f);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x000000f0);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xffe7fe00);
|
||||
}
|
||||
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0);
|
||||
|
@ -830,34 +1056,12 @@ static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
|
|||
|
||||
wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
|
||||
|
||||
/* wait until device ready. typical time is 20..80 msec */
|
||||
if (no_flash)
|
||||
do {
|
||||
msleep(RST_DELAY);
|
||||
x = wil_r(wil, USER_EXT_USER_PMU_3);
|
||||
if (delay++ > RST_COUNT) {
|
||||
wil_err(wil, "Reset not completed, PMU_3 0x%08x\n",
|
||||
x);
|
||||
return -ETIME;
|
||||
}
|
||||
} while ((x & BIT_PMU_DEVICE_RDY) == 0);
|
||||
if (wil->hw_version == HW_VER_TALYN_MB)
|
||||
rc = wil_wait_device_ready_talyn_mb(wil);
|
||||
else
|
||||
do {
|
||||
msleep(RST_DELAY);
|
||||
x = wil_r(wil, RGF_USER_BL +
|
||||
offsetof(struct bl_dedicated_registers_v0,
|
||||
boot_loader_ready));
|
||||
if (x1 != x) {
|
||||
wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n",
|
||||
x1, x);
|
||||
x1 = x;
|
||||
}
|
||||
if (delay++ > RST_COUNT) {
|
||||
wil_err(wil, "Reset not completed, bl.ready 0x%08x\n",
|
||||
x);
|
||||
return -ETIME;
|
||||
}
|
||||
} while (x != BL_READY);
|
||||
rc = wil_wait_device_ready(wil, no_flash);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
|
||||
|
||||
|
@ -865,7 +1069,7 @@ static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
|
|||
wil_s(wil, RGF_DMA_OFUL_NID_0, BIT_DMA_OFUL_NID_0_RX_EXT_TR_EN |
|
||||
BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC);
|
||||
|
||||
if (no_flash) {
|
||||
if (wil->hw_version < HW_VER_TALYN_MB && no_flash) {
|
||||
/* Reset OTP HW vectors to fit 40MHz */
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME1, 0x60001);
|
||||
wil_w(wil, RGF_USER_XPM_IFC_RD_TIME2, 0x20027);
|
||||
|
@ -880,7 +1084,6 @@ static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
|
|||
wil_w(wil, RGF_USER_XPM_RD_DOUT_SAMPLE_TIME, 0x57);
|
||||
}
|
||||
|
||||
wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1042,8 +1245,14 @@ static int wil_get_otp_info(struct wil6210_priv *wil)
|
|||
struct net_device *ndev = wil->main_ndev;
|
||||
struct wiphy *wiphy = wil_to_wiphy(wil);
|
||||
u8 mac[8];
|
||||
int mac_addr;
|
||||
|
||||
wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(RGF_OTP_MAC),
|
||||
if (wil->hw_version >= HW_VER_TALYN_MB)
|
||||
mac_addr = RGF_OTP_MAC_TALYN_MB;
|
||||
else
|
||||
mac_addr = RGF_OTP_MAC;
|
||||
|
||||
wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(mac_addr),
|
||||
sizeof(mac));
|
||||
if (!is_valid_ether_addr(mac)) {
|
||||
wil_err(wil, "Invalid MAC %pM\n", mac);
|
||||
|
@ -1147,8 +1356,13 @@ static void wil_pre_fw_config(struct wil6210_priv *wil)
|
|||
/* it is W1C, clear by writing back same value */
|
||||
wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0);
|
||||
wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
|
||||
/* clear PAL_UNIT_ICR (potential D0->D3 leftover) */
|
||||
wil_s(wil, RGF_PAL_UNIT_ICR + offsetof(struct RGF_ICR, ICR), 0);
|
||||
/* clear PAL_UNIT_ICR (potential D0->D3 leftover)
|
||||
* In Talyn-MB host cannot access this register due to
|
||||
* access control, hence PAL_UNIT_ICR is cleared by the FW
|
||||
*/
|
||||
if (wil->hw_version < HW_VER_TALYN_MB)
|
||||
wil_s(wil, RGF_PAL_UNIT_ICR + offsetof(struct RGF_ICR, ICR),
|
||||
0);
|
||||
|
||||
if (wil->fw_calib_result > 0) {
|
||||
__le32 val = cpu_to_le32(wil->fw_calib_result |
|
||||
|
@ -1284,7 +1498,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
rc = wil_target_reset(wil, no_flash);
|
||||
wil6210_clear_irq(wil);
|
||||
wil_enable_irq(wil);
|
||||
wil_rx_fini(wil);
|
||||
wil->txrx_ops.rx_fini(wil);
|
||||
wil->txrx_ops.tx_fini(wil);
|
||||
if (rc) {
|
||||
if (!no_flash)
|
||||
wil_bl_crash_info(wil, true);
|
||||
|
@ -1337,7 +1552,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
clear_bit(wil_status_resetting, wil->status);
|
||||
|
||||
if (load_fw) {
|
||||
wil_configure_interrupt_moderation(wil);
|
||||
wil_unmask_irq(wil);
|
||||
|
||||
/* we just started MAC, wait for FW ready */
|
||||
|
@ -1352,6 +1566,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
|
|||
return rc;
|
||||
}
|
||||
|
||||
wil->txrx_ops.configure_interrupt_moderation(wil);
|
||||
|
||||
rc = wil_restore_vifs(wil);
|
||||
if (rc) {
|
||||
wil_err(wil, "failed to restore vifs, rc %d\n", rc);
|
||||
|
@ -1406,8 +1622,12 @@ int __wil_up(struct wil6210_priv *wil)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Rx VRING. After MAC and beacon */
|
||||
rc = wil_rx_init(wil, 1 << rx_ring_order);
|
||||
/* Rx RING. After MAC and beacon */
|
||||
rc = wil->txrx_ops.rx_init(wil, 1 << rx_ring_order);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = wil->txrx_ops.tx_init(wil);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -1568,3 +1788,11 @@ void wil_halp_unvote(struct wil6210_priv *wil)
|
|||
|
||||
mutex_unlock(&wil->halp.lock);
|
||||
}
|
||||
|
||||
void wil_init_txrx_ops(struct wil6210_priv *wil)
|
||||
{
|
||||
if (wil->use_enhanced_dma_hw)
|
||||
wil_init_txrx_ops_edma(wil);
|
||||
else
|
||||
wil_init_txrx_ops_legacy_dma(wil);
|
||||
}
|
||||
|
|
|
@ -120,6 +120,27 @@ static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
|
|||
return done;
|
||||
}
|
||||
|
||||
static int wil6210_netdev_poll_rx_edma(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
|
||||
napi_rx);
|
||||
int quota = budget;
|
||||
int done;
|
||||
|
||||
wil_rx_handle_edma(wil, "a);
|
||||
done = budget - quota;
|
||||
|
||||
if (done < budget) {
|
||||
napi_complete_done(napi, done);
|
||||
wil6210_unmask_irq_rx_edma(wil);
|
||||
wil_dbg_txrx(wil, "NAPI RX complete\n");
|
||||
}
|
||||
|
||||
wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
|
||||
|
@ -129,11 +150,11 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
|
|||
|
||||
/* always process ALL Tx complete, regardless budget - it is fast */
|
||||
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
|
||||
struct vring *vring = &wil->vring_tx[i];
|
||||
struct vring_tx_data *txdata = &wil->vring_tx_data[i];
|
||||
struct wil_ring *ring = &wil->ring_tx[i];
|
||||
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i];
|
||||
struct wil6210_vif *vif;
|
||||
|
||||
if (!vring->va || !txdata->enabled ||
|
||||
if (!ring->va || !txdata->enabled ||
|
||||
txdata->mid >= wil->max_vifs)
|
||||
continue;
|
||||
|
||||
|
@ -157,6 +178,30 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
|
|||
return min(tx_done, budget);
|
||||
}
|
||||
|
||||
static int wil6210_netdev_poll_tx_edma(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
|
||||
napi_tx);
|
||||
int tx_done;
|
||||
/* There is only one status TX ring */
|
||||
struct wil_status_ring *sring = &wil->srings[wil->tx_sring_idx];
|
||||
|
||||
if (!sring->va)
|
||||
return 0;
|
||||
|
||||
tx_done = wil_tx_sring_handler(wil, sring);
|
||||
|
||||
if (tx_done < budget) {
|
||||
napi_complete(napi);
|
||||
wil6210_unmask_irq_tx_edma(wil);
|
||||
wil_dbg_txrx(wil, "NAPI TX complete\n");
|
||||
}
|
||||
|
||||
wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done);
|
||||
|
||||
return min(tx_done, budget);
|
||||
}
|
||||
|
||||
static void wil_dev_setup(struct net_device *dev)
|
||||
{
|
||||
ether_setup(dev);
|
||||
|
@ -228,7 +273,7 @@ static void wil_p2p_discovery_timer_fn(struct timer_list *t)
|
|||
|
||||
static void wil_vif_init(struct wil6210_vif *vif)
|
||||
{
|
||||
vif->bcast_vring = -1;
|
||||
vif->bcast_ring = -1;
|
||||
|
||||
mutex_init(&vif->probe_client_mutex);
|
||||
|
||||
|
@ -418,11 +463,21 @@ int wil_if_add(struct wil6210_priv *wil)
|
|||
}
|
||||
|
||||
init_dummy_netdev(&wil->napi_ndev);
|
||||
netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx,
|
||||
WIL6210_NAPI_BUDGET);
|
||||
netif_tx_napi_add(&wil->napi_ndev,
|
||||
&wil->napi_tx, wil6210_netdev_poll_tx,
|
||||
WIL6210_NAPI_BUDGET);
|
||||
if (wil->use_enhanced_dma_hw) {
|
||||
netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
|
||||
wil6210_netdev_poll_rx_edma,
|
||||
WIL6210_NAPI_BUDGET);
|
||||
netif_tx_napi_add(&wil->napi_ndev,
|
||||
&wil->napi_tx, wil6210_netdev_poll_tx_edma,
|
||||
WIL6210_NAPI_BUDGET);
|
||||
} else {
|
||||
netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
|
||||
wil6210_netdev_poll_rx,
|
||||
WIL6210_NAPI_BUDGET);
|
||||
netif_tx_napi_add(&wil->napi_ndev,
|
||||
&wil->napi_tx, wil6210_netdev_poll_tx,
|
||||
WIL6210_NAPI_BUDGET);
|
||||
}
|
||||
|
||||
wil_update_net_queues_bh(wil, vif, NULL, true);
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ int wil_set_capabilities(struct wil6210_priv *wil)
|
|||
wil->rgf_ucode_assert_code_addr = SPARROW_RGF_UCODE_ASSERT_CODE;
|
||||
break;
|
||||
case JTAG_DEV_ID_TALYN:
|
||||
wil->hw_name = "Talyn";
|
||||
wil->hw_name = "Talyn-MA";
|
||||
wil->hw_version = HW_VER_TALYN;
|
||||
memcpy(fw_mapping, talyn_fw_mapping, sizeof(talyn_fw_mapping));
|
||||
wil->rgf_fw_assert_code_addr = TALYN_RGF_FW_ASSERT_CODE;
|
||||
|
@ -94,6 +94,17 @@ int wil_set_capabilities(struct wil6210_priv *wil)
|
|||
BIT_NO_FLASH_INDICATION)
|
||||
set_bit(hw_capa_no_flash, wil->hw_capa);
|
||||
break;
|
||||
case JTAG_DEV_ID_TALYN_MB:
|
||||
wil->hw_name = "Talyn-MB";
|
||||
wil->hw_version = HW_VER_TALYN_MB;
|
||||
memcpy(fw_mapping, talyn_mb_fw_mapping,
|
||||
sizeof(talyn_mb_fw_mapping));
|
||||
wil->rgf_fw_assert_code_addr = TALYN_RGF_FW_ASSERT_CODE;
|
||||
wil->rgf_ucode_assert_code_addr = TALYN_RGF_UCODE_ASSERT_CODE;
|
||||
set_bit(hw_capa_no_flash, wil->hw_capa);
|
||||
wil->use_enhanced_dma_hw = true;
|
||||
wil->use_rx_hw_reordering = true;
|
||||
break;
|
||||
default:
|
||||
wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n",
|
||||
jtag_id, chip_revision);
|
||||
|
@ -102,6 +113,8 @@ int wil_set_capabilities(struct wil6210_priv *wil)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
wil_init_txrx_ops(wil);
|
||||
|
||||
iccm_section = wil_find_fw_mapping("fw_code");
|
||||
if (!iccm_section) {
|
||||
wil_err(wil, "fw_code section not found in fw_mapping\n");
|
||||
|
@ -257,8 +270,8 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
.fw_recovery = wil_platform_rop_fw_recovery,
|
||||
};
|
||||
u32 bar_size = pci_resource_len(pdev, 0);
|
||||
int dma_addr_size[] = {48, 40, 32}; /* keep descending order */
|
||||
int i;
|
||||
int dma_addr_size[] = {64, 48, 40, 32}; /* keep descending order */
|
||||
int i, start_idx;
|
||||
|
||||
/* check HW */
|
||||
dev_info(&pdev->dev, WIL_NAME
|
||||
|
@ -293,24 +306,6 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
goto if_free;
|
||||
}
|
||||
/* rollback to err_plat */
|
||||
|
||||
/* device supports >32bit addresses */
|
||||
for (i = 0; i < ARRAY_SIZE(dma_addr_size); i++) {
|
||||
rc = dma_set_mask_and_coherent(dev,
|
||||
DMA_BIT_MASK(dma_addr_size[i]));
|
||||
if (rc) {
|
||||
dev_err(dev, "dma_set_mask_and_coherent(%d) failed: %d\n",
|
||||
dma_addr_size[i], rc);
|
||||
continue;
|
||||
}
|
||||
dev_info(dev, "using dma mask %d", dma_addr_size[i]);
|
||||
wil->dma_addr_size = dma_addr_size[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (wil->dma_addr_size == 0)
|
||||
goto err_plat;
|
||||
|
||||
rc = pci_enable_device(pdev);
|
||||
if (rc && pdev->msi_enabled == 0) {
|
||||
wil_err(wil,
|
||||
|
@ -350,6 +345,28 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
wil_err(wil, "wil_set_capabilities failed, rc %d\n", rc);
|
||||
goto err_iounmap;
|
||||
}
|
||||
|
||||
/* device supports >32bit addresses.
|
||||
* for legacy DMA start from 48 bit.
|
||||
*/
|
||||
start_idx = wil->use_enhanced_dma_hw ? 0 : 1;
|
||||
|
||||
for (i = start_idx; i < ARRAY_SIZE(dma_addr_size); i++) {
|
||||
rc = dma_set_mask_and_coherent(dev,
|
||||
DMA_BIT_MASK(dma_addr_size[i]));
|
||||
if (rc) {
|
||||
dev_err(dev, "dma_set_mask_and_coherent(%d) failed: %d\n",
|
||||
dma_addr_size[i], rc);
|
||||
continue;
|
||||
}
|
||||
dev_info(dev, "using dma mask %d", dma_addr_size[i]);
|
||||
wil->dma_addr_size = dma_addr_size[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (wil->dma_addr_size == 0)
|
||||
goto err_iounmap;
|
||||
|
||||
wil6210_clear_irq(wil);
|
||||
|
||||
/* FW should raise IRQ when ready */
|
||||
|
|
|
@ -211,7 +211,7 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
|
|||
goto reject_suspend;
|
||||
}
|
||||
|
||||
if (!wil_is_rx_idle(wil)) {
|
||||
if (!wil->txrx_ops.is_rx_idle(wil)) {
|
||||
wil_dbg_pm(wil, "Pending RX data, reject suspend\n");
|
||||
wil->suspend_stats.rejected_by_host++;
|
||||
goto reject_suspend;
|
||||
|
@ -235,9 +235,9 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
|
|||
start = jiffies;
|
||||
data_comp_to = jiffies + msecs_to_jiffies(WIL_DATA_COMPLETION_TO_MS);
|
||||
if (test_bit(wil_status_napi_en, wil->status)) {
|
||||
while (!wil_is_rx_idle(wil)) {
|
||||
while (!wil->txrx_ops.is_rx_idle(wil)) {
|
||||
if (time_after(jiffies, data_comp_to)) {
|
||||
if (wil_is_rx_idle(wil))
|
||||
if (wil->txrx_ops.is_rx_idle(wil))
|
||||
break;
|
||||
wil_err(wil,
|
||||
"TO waiting for idle RX, suspend failed\n");
|
||||
|
|
|
@ -95,17 +95,17 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
{
|
||||
struct wil6210_vif *vif;
|
||||
struct net_device *ndev;
|
||||
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
|
||||
int tid = wil_rxdesc_tid(d);
|
||||
int cid = wil_rxdesc_cid(d);
|
||||
int mid = wil_rxdesc_mid(d);
|
||||
u16 seq = wil_rxdesc_seq(d);
|
||||
int mcast = wil_rxdesc_mcast(d);
|
||||
struct wil_sta_info *sta = &wil->sta[cid];
|
||||
int tid, cid, mid, mcast;
|
||||
u16 seq;
|
||||
struct wil_sta_info *sta;
|
||||
struct wil_tid_ampdu_rx *r;
|
||||
u16 hseq;
|
||||
int index;
|
||||
|
||||
wil->txrx_ops.get_reorder_params(wil, skb, &tid, &cid, &mid, &seq,
|
||||
&mcast);
|
||||
sta = &wil->sta[cid];
|
||||
|
||||
wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x mcast %01x\n",
|
||||
mid, cid, tid, seq, mcast);
|
||||
|
||||
|
@ -315,7 +315,10 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
* bits 6..15: buffer size
|
||||
*/
|
||||
u16 req_agg_wsize = WIL_GET_BITS(param_set, 6, 15);
|
||||
bool agg_amsdu = !!(param_set & BIT(0));
|
||||
bool agg_amsdu = wil->use_enhanced_dma_hw &&
|
||||
wil->use_rx_hw_reordering &&
|
||||
test_bit(WMI_FW_CAPABILITY_AMSDU, wil->fw_capabilities) &&
|
||||
wil->amsdu_en && (param_set & BIT(0));
|
||||
int ba_policy = param_set & BIT(1);
|
||||
u16 status = WLAN_STATUS_SUCCESS;
|
||||
u16 ssn = seq_ctrl >> 4;
|
||||
|
@ -360,8 +363,9 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
}
|
||||
}
|
||||
|
||||
rc = wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token, status,
|
||||
agg_amsdu, agg_wsize, agg_timeout);
|
||||
rc = wil->txrx_ops.wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token,
|
||||
status, agg_amsdu, agg_wsize,
|
||||
agg_timeout);
|
||||
if (rc || (status != WLAN_STATUS_SUCCESS)) {
|
||||
wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc,
|
||||
status);
|
||||
|
@ -384,7 +388,7 @@ int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize)
|
|||
{
|
||||
u8 agg_wsize = wil_agg_size(wil, wsize);
|
||||
u16 agg_timeout = 0;
|
||||
struct vring_tx_data *txdata = &wil->vring_tx_data[ringid];
|
||||
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ringid];
|
||||
int rc = 0;
|
||||
|
||||
if (txdata->addba_in_progress) {
|
||||
|
|
|
@ -187,6 +187,40 @@ TRACE_EVENT(wil6210_rx,
|
|||
__entry->seq, __entry->type, __entry->subtype)
|
||||
);
|
||||
|
||||
TRACE_EVENT(wil6210_rx_status,
|
||||
TP_PROTO(struct wil6210_priv *wil, u8 use_compressed, u16 buff_id,
|
||||
void *msg),
|
||||
TP_ARGS(wil, use_compressed, buff_id, msg),
|
||||
TP_STRUCT__entry(__field(u8, use_compressed)
|
||||
__field(u16, buff_id)
|
||||
__field(unsigned int, len)
|
||||
__field(u8, mid)
|
||||
__field(u8, cid)
|
||||
__field(u8, tid)
|
||||
__field(u8, type)
|
||||
__field(u8, subtype)
|
||||
__field(u16, seq)
|
||||
__field(u8, mcs)
|
||||
),
|
||||
TP_fast_assign(__entry->use_compressed = use_compressed;
|
||||
__entry->buff_id = buff_id;
|
||||
__entry->len = wil_rx_status_get_length(msg);
|
||||
__entry->mid = wil_rx_status_get_mid(msg);
|
||||
__entry->cid = wil_rx_status_get_cid(msg);
|
||||
__entry->tid = wil_rx_status_get_tid(msg);
|
||||
__entry->type = wil_rx_status_get_frame_type(wil,
|
||||
msg);
|
||||
__entry->subtype = wil_rx_status_get_fc1(wil, msg);
|
||||
__entry->seq = wil_rx_status_get_seq(wil, msg);
|
||||
__entry->mcs = wil_rx_status_get_mcs(msg);
|
||||
),
|
||||
TP_printk(
|
||||
"compressed %d buff_id %d len %d mid %d cid %d tid %d mcs %d seq 0x%03x type 0x%1x subtype 0x%1x",
|
||||
__entry->use_compressed, __entry->buff_id, __entry->len,
|
||||
__entry->mid, __entry->cid, __entry->tid, __entry->mcs,
|
||||
__entry->seq, __entry->type, __entry->subtype)
|
||||
);
|
||||
|
||||
TRACE_EVENT(wil6210_tx,
|
||||
TP_PROTO(u8 vring, u16 index, unsigned int len, u8 frags),
|
||||
TP_ARGS(vring, index, len, frags),
|
||||
|
@ -226,6 +260,31 @@ TRACE_EVENT(wil6210_tx_done,
|
|||
__entry->err)
|
||||
);
|
||||
|
||||
TRACE_EVENT(wil6210_tx_status,
|
||||
TP_PROTO(struct wil_ring_tx_status *msg, u16 index,
|
||||
unsigned int len),
|
||||
TP_ARGS(msg, index, len),
|
||||
TP_STRUCT__entry(__field(u16, index)
|
||||
__field(unsigned int, len)
|
||||
__field(u8, num_descs)
|
||||
__field(u8, ring_id)
|
||||
__field(u8, status)
|
||||
__field(u8, mcs)
|
||||
|
||||
),
|
||||
TP_fast_assign(__entry->index = index;
|
||||
__entry->len = len;
|
||||
__entry->num_descs = msg->num_descriptors;
|
||||
__entry->ring_id = msg->ring_id;
|
||||
__entry->status = msg->status;
|
||||
__entry->mcs = wil_tx_status_get_mcs(msg);
|
||||
),
|
||||
TP_printk(
|
||||
"ring_id %d swtail 0x%x len %d num_descs %d status 0x%x mcs %d",
|
||||
__entry->ring_id, __entry->index, __entry->len,
|
||||
__entry->num_descs, __entry->status, __entry->mcs)
|
||||
);
|
||||
|
||||
#endif /* WIL6210_TRACE_H || TRACE_HEADER_MULTI_READ*/
|
||||
|
||||
#if defined(CONFIG_WIL6210_TRACING) && !defined(__CHECKER__)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,6 +18,9 @@
|
|||
#ifndef WIL6210_TXRX_H
|
||||
#define WIL6210_TXRX_H
|
||||
|
||||
#include "wil6210.h"
|
||||
#include "txrx_edma.h"
|
||||
|
||||
#define BUF_SW_OWNED (1)
|
||||
#define BUF_HW_OWNED (0)
|
||||
|
||||
|
@ -29,19 +32,13 @@
|
|||
|
||||
/* Tx/Rx path */
|
||||
|
||||
/* Common representation of physical address in Vring */
|
||||
struct vring_dma_addr {
|
||||
__le32 addr_low;
|
||||
__le16 addr_high;
|
||||
} __packed;
|
||||
|
||||
static inline dma_addr_t wil_desc_addr(struct vring_dma_addr *addr)
|
||||
static inline dma_addr_t wil_desc_addr(struct wil_ring_dma_addr *addr)
|
||||
{
|
||||
return le32_to_cpu(addr->addr_low) |
|
||||
((u64)le16_to_cpu(addr->addr_high) << 32);
|
||||
}
|
||||
|
||||
static inline void wil_desc_addr_set(struct vring_dma_addr *addr,
|
||||
static inline void wil_desc_addr_set(struct wil_ring_dma_addr *addr,
|
||||
dma_addr_t pa)
|
||||
{
|
||||
addr->addr_low = cpu_to_le32(lower_32_bits(pa));
|
||||
|
@ -294,7 +291,7 @@ struct vring_tx_mac {
|
|||
*/
|
||||
struct vring_tx_dma {
|
||||
u32 d0;
|
||||
struct vring_dma_addr addr;
|
||||
struct wil_ring_dma_addr addr;
|
||||
u8 ip_length;
|
||||
u8 b11; /* 0..6: mac_length; 7:ip_version */
|
||||
u8 error; /* 0..2: err; 3..7: reserved; */
|
||||
|
@ -428,7 +425,7 @@ struct vring_rx_mac {
|
|||
|
||||
struct vring_rx_dma {
|
||||
u32 d0;
|
||||
struct vring_dma_addr addr;
|
||||
struct wil_ring_dma_addr addr;
|
||||
u8 ip_length;
|
||||
u8 b11;
|
||||
u8 error;
|
||||
|
@ -441,14 +438,24 @@ struct vring_tx_desc {
|
|||
struct vring_tx_dma dma;
|
||||
} __packed;
|
||||
|
||||
union wil_tx_desc {
|
||||
struct vring_tx_desc legacy;
|
||||
struct wil_tx_enhanced_desc enhanced;
|
||||
} __packed;
|
||||
|
||||
struct vring_rx_desc {
|
||||
struct vring_rx_mac mac;
|
||||
struct vring_rx_dma dma;
|
||||
} __packed;
|
||||
|
||||
union vring_desc {
|
||||
struct vring_tx_desc tx;
|
||||
struct vring_rx_desc rx;
|
||||
union wil_rx_desc {
|
||||
struct vring_rx_desc legacy;
|
||||
struct wil_rx_enhanced_desc enhanced;
|
||||
} __packed;
|
||||
|
||||
union wil_ring_desc {
|
||||
union wil_tx_desc tx;
|
||||
union wil_rx_desc rx;
|
||||
} __packed;
|
||||
|
||||
static inline int wil_rxdesc_tid(struct vring_rx_desc *d)
|
||||
|
@ -528,6 +535,76 @@ static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb)
|
|||
return (void *)skb->cb;
|
||||
}
|
||||
|
||||
static inline int wil_ring_is_empty(struct wil_ring *ring)
|
||||
{
|
||||
return ring->swhead == ring->swtail;
|
||||
}
|
||||
|
||||
static inline u32 wil_ring_next_tail(struct wil_ring *ring)
|
||||
{
|
||||
return (ring->swtail + 1) % ring->size;
|
||||
}
|
||||
|
||||
static inline void wil_ring_advance_head(struct wil_ring *ring, int n)
|
||||
{
|
||||
ring->swhead = (ring->swhead + n) % ring->size;
|
||||
}
|
||||
|
||||
static inline int wil_ring_is_full(struct wil_ring *ring)
|
||||
{
|
||||
return wil_ring_next_tail(ring) == ring->swhead;
|
||||
}
|
||||
|
||||
static inline bool wil_need_txstat(struct sk_buff *skb)
|
||||
{
|
||||
struct ethhdr *eth = (void *)skb->data;
|
||||
|
||||
return is_unicast_ether_addr(eth->h_dest) && skb->sk &&
|
||||
(skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS);
|
||||
}
|
||||
|
||||
static inline void wil_consume_skb(struct sk_buff *skb, bool acked)
|
||||
{
|
||||
if (unlikely(wil_need_txstat(skb)))
|
||||
skb_complete_wifi_ack(skb, acked);
|
||||
else
|
||||
acked ? dev_consume_skb_any(skb) : dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
/* Used space in Tx ring */
|
||||
static inline int wil_ring_used_tx(struct wil_ring *ring)
|
||||
{
|
||||
u32 swhead = ring->swhead;
|
||||
u32 swtail = ring->swtail;
|
||||
|
||||
return (ring->size + swhead - swtail) % ring->size;
|
||||
}
|
||||
|
||||
/* Available space in Tx ring */
|
||||
static inline int wil_ring_avail_tx(struct wil_ring *ring)
|
||||
{
|
||||
return ring->size - wil_ring_used_tx(ring) - 1;
|
||||
}
|
||||
|
||||
static inline int wil_get_min_tx_ring_id(struct wil6210_priv *wil)
|
||||
{
|
||||
/* In Enhanced DMA ring 0 is reserved for RX */
|
||||
return wil->use_enhanced_dma_hw ? 1 : 0;
|
||||
}
|
||||
|
||||
/* similar to ieee80211_ version, but FC contain only 1-st byte */
|
||||
static inline int wil_is_back_req(u8 fc)
|
||||
{
|
||||
return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
|
||||
(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ);
|
||||
}
|
||||
|
||||
/* wil_val_in_range - check if value in [min,max) */
|
||||
static inline bool wil_val_in_range(int val, int min, int max)
|
||||
{
|
||||
return val >= min && val < max;
|
||||
}
|
||||
|
||||
void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev);
|
||||
void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb);
|
||||
void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif,
|
||||
|
@ -536,5 +613,7 @@ struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil,
|
|||
int size, u16 ssn);
|
||||
void wil_tid_ampdu_rx_free(struct wil6210_priv *wil,
|
||||
struct wil_tid_ampdu_rx *r);
|
||||
void wil_tx_data_init(struct wil_ring_tx_data *txdata);
|
||||
void wil_init_txrx_ops_legacy_dma(struct wil6210_priv *wil);
|
||||
|
||||
#endif /* WIL6210_TXRX_H */
|
||||
|
|
1598
drivers/net/wireless/ath/wil6210/txrx_edma.c
Normal file
1598
drivers/net/wireless/ath/wil6210/txrx_edma.c
Normal file
File diff suppressed because it is too large
Load diff
562
drivers/net/wireless/ath/wil6210/txrx_edma.h
Normal file
562
drivers/net/wireless/ath/wil6210/txrx_edma.h
Normal file
|
@ -0,0 +1,562 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2016,2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef WIL6210_TXRX_EDMA_H
|
||||
#define WIL6210_TXRX_EDMA_H
|
||||
|
||||
#include "wil6210.h"
|
||||
|
||||
/* limit status ring size in range [ring size..max ring size] */
|
||||
#define WIL_SRING_SIZE_ORDER_MIN (WIL_RING_SIZE_ORDER_MIN)
|
||||
#define WIL_SRING_SIZE_ORDER_MAX (WIL_RING_SIZE_ORDER_MAX)
|
||||
/* RX sring order should be bigger than RX ring order */
|
||||
#define WIL_RX_SRING_SIZE_ORDER_DEFAULT (11)
|
||||
#define WIL_TX_SRING_SIZE_ORDER_DEFAULT (12)
|
||||
#define WIL_RX_BUFF_ARR_SIZE_DEFAULT (1536)
|
||||
|
||||
#define WIL_DEFAULT_RX_STATUS_RING_ID 0
|
||||
#define WIL_RX_DESC_RING_ID 0
|
||||
#define WIL_RX_STATUS_IRQ_IDX 0
|
||||
#define WIL_TX_STATUS_IRQ_IDX 1
|
||||
|
||||
#define WIL_EDMA_AGG_WATERMARK (0xffff)
|
||||
#define WIL_EDMA_AGG_WATERMARK_POS (16)
|
||||
|
||||
#define WIL_EDMA_IDLE_TIME_LIMIT_USEC (50)
|
||||
#define WIL_EDMA_TIME_UNIT_CLK_CYCLES (330) /* fits 1 usec */
|
||||
|
||||
/* Error field */
|
||||
#define WIL_RX_EDMA_ERROR_MIC (1)
|
||||
#define WIL_RX_EDMA_ERROR_KEY (2) /* Key missing */
|
||||
#define WIL_RX_EDMA_ERROR_REPLAY (3)
|
||||
#define WIL_RX_EDMA_ERROR_AMSDU (4)
|
||||
#define WIL_RX_EDMA_ERROR_FCS (7)
|
||||
|
||||
#define WIL_RX_EDMA_ERROR_L3_ERR (BIT(0) | BIT(1))
|
||||
#define WIL_RX_EDMA_ERROR_L4_ERR (BIT(0) | BIT(1))
|
||||
|
||||
#define WIL_RX_EDMA_DLPF_LU_MISS_BIT BIT(11)
|
||||
#define WIL_RX_EDMA_DLPF_LU_MISS_CID_TID_MASK 0x7
|
||||
#define WIL_RX_EDMA_DLPF_LU_HIT_CID_TID_MASK 0xf
|
||||
|
||||
#define WIL_RX_EDMA_DLPF_LU_MISS_CID_POS 2
|
||||
#define WIL_RX_EDMA_DLPF_LU_HIT_CID_POS 4
|
||||
|
||||
#define WIL_RX_EDMA_DLPF_LU_MISS_TID_POS 5
|
||||
|
||||
#define WIL_RX_EDMA_MID_VALID_BIT BIT(22)
|
||||
|
||||
#define WIL_EDMA_DESC_TX_MAC_CFG_0_QID_POS 16
|
||||
#define WIL_EDMA_DESC_TX_MAC_CFG_0_QID_LEN 6
|
||||
|
||||
#define WIL_EDMA_DESC_TX_CFG_EOP_POS 0
|
||||
#define WIL_EDMA_DESC_TX_CFG_EOP_LEN 1
|
||||
|
||||
#define WIL_EDMA_DESC_TX_CFG_TSO_DESC_TYPE_POS 3
|
||||
#define WIL_EDMA_DESC_TX_CFG_TSO_DESC_TYPE_LEN 2
|
||||
|
||||
#define WIL_EDMA_DESC_TX_CFG_SEG_EN_POS 5
|
||||
#define WIL_EDMA_DESC_TX_CFG_SEG_EN_LEN 1
|
||||
|
||||
#define WIL_EDMA_DESC_TX_CFG_INSERT_IP_CHKSUM_POS 6
|
||||
#define WIL_EDMA_DESC_TX_CFG_INSERT_IP_CHKSUM_LEN 1
|
||||
|
||||
#define WIL_EDMA_DESC_TX_CFG_INSERT_TCP_CHKSUM_POS 7
|
||||
#define WIL_EDMA_DESC_TX_CFG_INSERT_TCP_CHKSUM_LEN 1
|
||||
|
||||
#define WIL_EDMA_DESC_TX_CFG_L4_TYPE_POS 15
|
||||
#define WIL_EDMA_DESC_TX_CFG_L4_TYPE_LEN 1
|
||||
|
||||
#define WIL_EDMA_DESC_TX_CFG_PSEUDO_HEADER_CALC_EN_POS 5
|
||||
#define WIL_EDMA_DESC_TX_CFG_PSEUDO_HEADER_CALC_EN_LEN 1
|
||||
|
||||
/* Enhanced Rx descriptor - MAC part
|
||||
* [dword 0] : Reserved
|
||||
* [dword 1] : Reserved
|
||||
* [dword 2] : Reserved
|
||||
* [dword 3]
|
||||
* bit 0..15 : Buffer ID
|
||||
* bit 16..31 : Reserved
|
||||
*/
|
||||
struct wil_ring_rx_enhanced_mac {
|
||||
u32 d[3];
|
||||
__le16 buff_id;
|
||||
u16 reserved;
|
||||
} __packed;
|
||||
|
||||
/* Enhanced Rx descriptor - DMA part
|
||||
* [dword 0] - Reserved
|
||||
* [dword 1]
|
||||
* bit 0..31 : addr_low:32 The payload buffer address, bits 0-31
|
||||
* [dword 2]
|
||||
* bit 0..15 : addr_high_low:16 The payload buffer address, bits 32-47
|
||||
* bit 16..31 : Reserved
|
||||
* [dword 3]
|
||||
* bit 0..15 : addr_high_high:16 The payload buffer address, bits 48-63
|
||||
* bit 16..31 : length
|
||||
*/
|
||||
struct wil_ring_rx_enhanced_dma {
|
||||
u32 d0;
|
||||
struct wil_ring_dma_addr addr;
|
||||
u16 w5;
|
||||
__le16 addr_high_high;
|
||||
__le16 length;
|
||||
} __packed;
|
||||
|
||||
struct wil_rx_enhanced_desc {
|
||||
struct wil_ring_rx_enhanced_mac mac;
|
||||
struct wil_ring_rx_enhanced_dma dma;
|
||||
} __packed;
|
||||
|
||||
/* Enhanced Tx descriptor - DMA part
|
||||
* [dword 0]
|
||||
* Same as legacy
|
||||
* [dword 1]
|
||||
* bit 0..31 : addr_low:32 The payload buffer address, bits 0-31
|
||||
* [dword 2]
|
||||
* bit 0..15 : addr_high_low:16 The payload buffer address, bits 32-47
|
||||
* bit 16..23 : ip_length:8 The IP header length for the TX IP checksum
|
||||
* offload feature
|
||||
* bit 24..30 : mac_length:7
|
||||
* bit 31 : ip_version:1 1 - IPv4, 0 - IPv6
|
||||
* [dword 3]
|
||||
* bit 0..15 : addr_high_high:16 The payload buffer address, bits 48-63
|
||||
* bit 16..31 : length
|
||||
*/
|
||||
struct wil_ring_tx_enhanced_dma {
|
||||
u8 l4_hdr_len;
|
||||
u8 cmd;
|
||||
u16 w1;
|
||||
struct wil_ring_dma_addr addr;
|
||||
u8 ip_length;
|
||||
u8 b11; /* 0..6: mac_length; 7:ip_version */
|
||||
__le16 addr_high_high;
|
||||
__le16 length;
|
||||
} __packed;
|
||||
|
||||
/* Enhanced Tx descriptor - MAC part
|
||||
* [dword 0]
|
||||
* bit 0.. 9 : lifetime_expiry_value:10
|
||||
* bit 10 : interrupt_en:1
|
||||
* bit 11 : status_en:1
|
||||
* bit 12..13 : txss_override:2
|
||||
* bit 14 : timestamp_insertion:1
|
||||
* bit 15 : duration_preserve:1
|
||||
* bit 16..21 : reserved0:6
|
||||
* bit 22..26 : mcs_index:5
|
||||
* bit 27 : mcs_en:1
|
||||
* bit 28..30 : reserved1:3
|
||||
* bit 31 : sn_preserved:1
|
||||
* [dword 1]
|
||||
* bit 0.. 3 : pkt_mode:4
|
||||
* bit 4 : pkt_mode_en:1
|
||||
* bit 5..14 : reserved0:10
|
||||
* bit 15 : ack_policy_en:1
|
||||
* bit 16..19 : dst_index:4
|
||||
* bit 20 : dst_index_en:1
|
||||
* bit 21..22 : ack_policy:2
|
||||
* bit 23 : lifetime_en:1
|
||||
* bit 24..30 : max_retry:7
|
||||
* bit 31 : max_retry_en:1
|
||||
* [dword 2]
|
||||
* bit 0.. 7 : num_of_descriptors:8
|
||||
* bit 8..17 : reserved:10
|
||||
* bit 18..19 : l2_translation_type:2 00 - bypass, 01 - 802.3, 10 - 802.11
|
||||
* bit 20 : snap_hdr_insertion_en:1
|
||||
* bit 21 : vlan_removal_en:1
|
||||
* bit 22..23 : reserved0:2
|
||||
* bit 24 : Dest ID extension:1
|
||||
* bit 25..31 : reserved0:7
|
||||
* [dword 3]
|
||||
* bit 0..15 : tso_mss:16
|
||||
* bit 16..31 : descriptor_scratchpad:16 - mailbox between driver and ucode
|
||||
*/
|
||||
struct wil_ring_tx_enhanced_mac {
|
||||
u32 d[3];
|
||||
__le16 tso_mss;
|
||||
u16 scratchpad;
|
||||
} __packed;
|
||||
|
||||
struct wil_tx_enhanced_desc {
|
||||
struct wil_ring_tx_enhanced_mac mac;
|
||||
struct wil_ring_tx_enhanced_dma dma;
|
||||
} __packed;
|
||||
|
||||
#define TX_STATUS_DESC_READY_POS 7
|
||||
|
||||
/* Enhanced TX status message
|
||||
* [dword 0]
|
||||
* bit 0.. 7 : Number of Descriptor:8 - The number of descriptors that
|
||||
* are used to form the packets. It is needed for WB when
|
||||
* releasing the packet
|
||||
* bit 8..15 : tx_ring_id:8 The transmission ring ID that is related to
|
||||
* the message
|
||||
* bit 16..23 : Status:8 - The TX status Code
|
||||
* 0x0 - A successful transmission
|
||||
* 0x1 - Retry expired
|
||||
* 0x2 - Lifetime Expired
|
||||
* 0x3 - Released
|
||||
* 0x4-0xFF - Reserved
|
||||
* bit 24..30 : Reserved:7
|
||||
* bit 31 : Descriptor Ready bit:1 - It is initiated to
|
||||
* zero by the driver when the ring is created. It is set by the HW
|
||||
* to one for each completed status message. Each wrap around,
|
||||
* the DR bit value is flipped.
|
||||
* [dword 1]
|
||||
* bit 0..31 : timestamp:32 - Set when MPDU is transmitted.
|
||||
* [dword 2]
|
||||
* bit 0.. 4 : MCS:5 - The transmitted MCS value
|
||||
* bit 5 : Reserved:1
|
||||
* bit 6.. 7 : CB mode:2 - 0-DMG 1-EDMG 2-Wide
|
||||
* bit 8..12 : QID:5 - The QID that was used for the transmission
|
||||
* bit 13..15 : Reserved:3
|
||||
* bit 16..20 : Num of MSDUs:5 - Number of MSDUs in the aggregation
|
||||
* bit 21..22 : Reserved:2
|
||||
* bit 23 : Retry:1 - An indication that the transmission was retried
|
||||
* bit 24..31 : TX-Sector:8 - the antenna sector that was used for
|
||||
* transmission
|
||||
* [dword 3]
|
||||
* bit 0..11 : Sequence number:12 - The Sequence Number that was used
|
||||
* for the MPDU transmission
|
||||
* bit 12..31 : Reserved:20
|
||||
*/
|
||||
struct wil_ring_tx_status {
|
||||
u8 num_descriptors;
|
||||
u8 ring_id;
|
||||
u8 status;
|
||||
u8 desc_ready; /* Only the last bit should be set */
|
||||
u32 timestamp;
|
||||
u32 d2;
|
||||
u16 seq_number; /* Only the first 12 bits */
|
||||
u16 w7;
|
||||
} __packed;
|
||||
|
||||
/* Enhanced Rx status message - compressed part
|
||||
* [dword 0]
|
||||
* bit 0.. 2 : L2 Rx Status:3 - The L2 packet reception Status
|
||||
* 0-Success, 1-MIC Error, 2-Key Error, 3-Replay Error,
|
||||
* 4-A-MSDU Error, 5-Reserved, 6-Reserved, 7-FCS Error
|
||||
* bit 3.. 4 : L3 Rx Status:2 - Bit0 - L3I - L3 identified and checksum
|
||||
* calculated, Bit1- L3Err - IPv4 Checksum Error
|
||||
* bit 5.. 6 : L4 Rx Status:2 - Bit0 - L4I - L4 identified and checksum
|
||||
* calculated, Bit1- L4Err - TCP/UDP Checksum Error
|
||||
* bit 7 : Reserved:1
|
||||
* bit 8..19 : Flow ID:12 - MSDU flow ID
|
||||
* bit 20..21 : MID:2 - The MAC ID
|
||||
* bit 22 : MID_V:1 - The MAC ID field is valid
|
||||
* bit 23 : L3T:1 - IP types: 0-IPv6, 1-IPv4
|
||||
* bit 24 : L4T:1 - Layer 4 Type: 0-UDP, 1-TCP
|
||||
* bit 25 : BC:1 - The received MPDU is broadcast
|
||||
* bit 26 : MC:1 - The received MPDU is multicast
|
||||
* bit 27 : Raw:1 - The MPDU received with no translation
|
||||
* bit 28 : Sec:1 - The FC control (b14) - Frame Protected
|
||||
* bit 29 : Error:1 - An error is set when (L2 status != 0) ||
|
||||
* (L3 status == 3) || (L4 status == 3)
|
||||
* bit 30 : EOP:1 - End of MSDU signaling. It is set to mark the end
|
||||
* of the transfer, otherwise the status indicates buffer
|
||||
* only completion.
|
||||
* bit 31 : Descriptor Ready bit:1 - It is initiated to
|
||||
* zero by the driver when the ring is created. It is set
|
||||
* by the HW to one for each completed status message.
|
||||
* Each wrap around, the DR bit value is flipped.
|
||||
* [dword 1]
|
||||
* bit 0.. 5 : MAC Len:6 - The number of bytes that are used for L2 header
|
||||
* bit 6..11 : IPLEN:6 - The number of DW that are used for L3 header
|
||||
* bit 12..15 : I4Len:4 - The number of DW that are used for L4 header
|
||||
* bit 16..21 : MCS:6 - The received MCS field from the PLCP Header
|
||||
* bit 22..23 : CB mode:2 - The CB Mode: 0-DMG, 1-EDMG, 2-Wide
|
||||
* bit 24..27 : Data Offset:4 - The data offset, a code that describe the
|
||||
* payload shift from the beginning of the buffer:
|
||||
* 0 - 0 Bytes, 3 - 2 Bytes
|
||||
* bit 28 : A-MSDU Present:1 - The QoS (b7) A-MSDU present field
|
||||
* bit 29 : A-MSDU Type:1 The QoS (b8) A-MSDU Type field
|
||||
* bit 30 : A-MPDU:1 - Packet is part of aggregated MPDU
|
||||
* bit 31 : Key ID:1 - The extracted Key ID from the encryption header
|
||||
* [dword 2]
|
||||
* bit 0..15 : Buffer ID:16 - The Buffer Identifier
|
||||
* bit 16..31 : Length:16 - It indicates the valid bytes that are stored
|
||||
* in the current descriptor buffer. For multiple buffer
|
||||
* descriptor, SW need to sum the total descriptor length
|
||||
* in all buffers to produce the packet length
|
||||
* [dword 3]
|
||||
* bit 0..31 : timestamp:32 - The MPDU Timestamp.
|
||||
*/
|
||||
struct wil_rx_status_compressed {
|
||||
u32 d0;
|
||||
u32 d1;
|
||||
__le16 buff_id;
|
||||
__le16 length;
|
||||
u32 timestamp;
|
||||
} __packed;
|
||||
|
||||
/* Enhanced Rx status message - extension part
|
||||
* [dword 0]
|
||||
* bit 0.. 4 : QID:5 - The Queue Identifier that the packet is received
|
||||
* from
|
||||
* bit 5.. 7 : Reserved:3
|
||||
* bit 8..11 : TID:4 - The QoS (b3-0) TID Field
|
||||
* bit 12..15 Source index:4 - The Source index that was found
|
||||
during Parsing the TA. This field is used to define the
|
||||
source of the packet
|
||||
* bit 16..18 : Destination index:3 - The Destination index that
|
||||
was found during Parsing the RA.
|
||||
* bit 19..20 : DS Type:2 - The FC Control (b9-8) - From / To DS
|
||||
* bit 21..22 : MIC ICR:2 - this signal tells the DMA to assert an
|
||||
interrupt after it writes the packet
|
||||
* bit 23 : ESOP:1 - The QoS (b4) ESOP field
|
||||
* bit 24 : RDG:1
|
||||
* bit 25..31 : Reserved:7
|
||||
* [dword 1]
|
||||
* bit 0.. 1 : Frame Type:2 - The FC Control (b3-2) - MPDU Type
|
||||
(management, data, control and extension)
|
||||
* bit 2.. 5 : Syb type:4 - The FC Control (b7-4) - Frame Subtype
|
||||
* bit 6..11 : Ext sub type:6 - The FC Control (b11-8) - Frame Extended
|
||||
* Subtype
|
||||
* bit 12..13 : ACK Policy:2 - The QoS (b6-5) ACK Policy fields
|
||||
* bit 14 : DECRYPT_BYP:1 - The MPDU is bypass by the decryption unit
|
||||
* bit 15..23 : Reserved:9
|
||||
* bit 24..31 : RSSI/SNR:8 - The RSSI / SNR measurement for the received
|
||||
* MPDU
|
||||
* [dword 2]
|
||||
* bit 0..11 : SN:12 - The received Sequence number field
|
||||
* bit 12..15 : Reserved:4
|
||||
* bit 16..31 : PN bits [15:0]:16
|
||||
* [dword 3]
|
||||
* bit 0..31 : PN bits [47:16]:32
|
||||
*/
|
||||
struct wil_rx_status_extension {
|
||||
u32 d0;
|
||||
u32 d1;
|
||||
__le16 seq_num; /* only lower 12 bits */
|
||||
u16 pn_15_0;
|
||||
u32 pn_47_16;
|
||||
} __packed;
|
||||
|
||||
struct wil_rx_status_extended {
|
||||
struct wil_rx_status_compressed comp;
|
||||
struct wil_rx_status_extension ext;
|
||||
} __packed;
|
||||
|
||||
static inline void *wil_skb_rxstatus(struct sk_buff *skb)
|
||||
{
|
||||
return (void *)skb->cb;
|
||||
}
|
||||
|
||||
static inline __le16 wil_rx_status_get_length(void *msg)
|
||||
{
|
||||
return ((struct wil_rx_status_compressed *)msg)->length;
|
||||
}
|
||||
|
||||
static inline u8 wil_rx_status_get_mcs(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d1,
|
||||
16, 21);
|
||||
}
|
||||
|
||||
static inline u16 wil_rx_status_get_flow_id(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
8, 19);
|
||||
}
|
||||
|
||||
static inline u8 wil_rx_status_get_mcast(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
26, 26);
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of DLPF miss the parsing of flow Id should be as follows:
|
||||
* dest_id:2
|
||||
* src_id :3 - cid
|
||||
* tid:3
|
||||
* Otherwise:
|
||||
* tid:4
|
||||
* cid:4
|
||||
*/
|
||||
|
||||
static inline u8 wil_rx_status_get_cid(void *msg)
|
||||
{
|
||||
u16 val = wil_rx_status_get_flow_id(msg);
|
||||
|
||||
if (val & WIL_RX_EDMA_DLPF_LU_MISS_BIT)
|
||||
/* CID is in bits 2..4 */
|
||||
return (val >> WIL_RX_EDMA_DLPF_LU_MISS_CID_POS) &
|
||||
WIL_RX_EDMA_DLPF_LU_MISS_CID_TID_MASK;
|
||||
else
|
||||
/* CID is in bits 4..7 */
|
||||
return (val >> WIL_RX_EDMA_DLPF_LU_HIT_CID_POS) &
|
||||
WIL_RX_EDMA_DLPF_LU_HIT_CID_TID_MASK;
|
||||
}
|
||||
|
||||
static inline u8 wil_rx_status_get_tid(void *msg)
|
||||
{
|
||||
u16 val = wil_rx_status_get_flow_id(msg);
|
||||
|
||||
if (val & WIL_RX_EDMA_DLPF_LU_MISS_BIT)
|
||||
/* TID is in bits 5..7 */
|
||||
return (val >> WIL_RX_EDMA_DLPF_LU_MISS_TID_POS) &
|
||||
WIL_RX_EDMA_DLPF_LU_MISS_CID_TID_MASK;
|
||||
else
|
||||
/* TID is in bits 0..3 */
|
||||
return val & WIL_RX_EDMA_DLPF_LU_MISS_CID_TID_MASK;
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_desc_rdy_bit(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
31, 31);
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_eop(void *msg) /* EoP = End of Packet */
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
30, 30);
|
||||
}
|
||||
|
||||
static inline __le16 wil_rx_status_get_buff_id(void *msg)
|
||||
{
|
||||
return ((struct wil_rx_status_compressed *)msg)->buff_id;
|
||||
}
|
||||
|
||||
static inline u8 wil_rx_status_get_data_offset(void *msg)
|
||||
{
|
||||
u8 val = WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d1,
|
||||
24, 27);
|
||||
|
||||
switch (val) {
|
||||
case 0: return 0;
|
||||
case 3: return 2;
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_frame_type(struct wil6210_priv *wil,
|
||||
void *msg)
|
||||
{
|
||||
if (wil->use_compressed_rx_status)
|
||||
return IEEE80211_FTYPE_DATA;
|
||||
|
||||
return WIL_GET_BITS(((struct wil_rx_status_extended *)msg)->ext.d1,
|
||||
0, 1) << 2;
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_fc1(struct wil6210_priv *wil, void *msg)
|
||||
{
|
||||
if (wil->use_compressed_rx_status)
|
||||
return 0;
|
||||
|
||||
return WIL_GET_BITS(((struct wil_rx_status_extended *)msg)->ext.d1,
|
||||
0, 5) << 2;
|
||||
}
|
||||
|
||||
static inline __le16 wil_rx_status_get_seq(struct wil6210_priv *wil, void *msg)
|
||||
{
|
||||
if (wil->use_compressed_rx_status)
|
||||
return 0;
|
||||
|
||||
return ((struct wil_rx_status_extended *)msg)->ext.seq_num;
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_mid(void *msg)
|
||||
{
|
||||
if (!(((struct wil_rx_status_compressed *)msg)->d0 &
|
||||
WIL_RX_EDMA_MID_VALID_BIT))
|
||||
return 0; /* use the default MID */
|
||||
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
20, 21);
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_error(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
29, 29);
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_l2_rx_status(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
0, 2);
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_l3_rx_status(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
3, 4);
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_l4_rx_status(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
5, 6);
|
||||
}
|
||||
|
||||
static inline int wil_rx_status_get_security(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
|
||||
28, 28);
|
||||
}
|
||||
|
||||
static inline u8 wil_rx_status_get_key_id(void *msg)
|
||||
{
|
||||
return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d1,
|
||||
31, 31);
|
||||
}
|
||||
|
||||
static inline u8 wil_tx_status_get_mcs(struct wil_ring_tx_status *msg)
|
||||
{
|
||||
return WIL_GET_BITS(msg->d2, 0, 4);
|
||||
}
|
||||
|
||||
static inline u32 wil_ring_next_head(struct wil_ring *ring)
|
||||
{
|
||||
return (ring->swhead + 1) % ring->size;
|
||||
}
|
||||
|
||||
static inline void wil_desc_set_addr_edma(struct wil_ring_dma_addr *addr,
|
||||
__le16 *addr_high_high,
|
||||
dma_addr_t pa)
|
||||
{
|
||||
addr->addr_low = cpu_to_le32(lower_32_bits(pa));
|
||||
addr->addr_high = cpu_to_le16((u16)upper_32_bits(pa));
|
||||
*addr_high_high = cpu_to_le16((u16)(upper_32_bits(pa) >> 16));
|
||||
}
|
||||
|
||||
static inline
|
||||
dma_addr_t wil_tx_desc_get_addr_edma(struct wil_ring_tx_enhanced_dma *dma)
|
||||
{
|
||||
return le32_to_cpu(dma->addr.addr_low) |
|
||||
((u64)le16_to_cpu(dma->addr.addr_high) << 32) |
|
||||
((u64)le16_to_cpu(dma->addr_high_high) << 48);
|
||||
}
|
||||
|
||||
static inline
|
||||
dma_addr_t wil_rx_desc_get_addr_edma(struct wil_ring_rx_enhanced_dma *dma)
|
||||
{
|
||||
return le32_to_cpu(dma->addr.addr_low) |
|
||||
((u64)le16_to_cpu(dma->addr.addr_high) << 32) |
|
||||
((u64)le16_to_cpu(dma->addr_high_high) << 48);
|
||||
}
|
||||
|
||||
void wil_configure_interrupt_moderation_edma(struct wil6210_priv *wil);
|
||||
int wil_tx_sring_handler(struct wil6210_priv *wil,
|
||||
struct wil_status_ring *sring);
|
||||
void wil_rx_handle_edma(struct wil6210_priv *wil, int *quota);
|
||||
void wil_init_txrx_ops_edma(struct wil6210_priv *wil);
|
||||
|
||||
#endif /* WIL6210_TXRX_EDMA_H */
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
#include <net/cfg80211.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include "wmi.h"
|
||||
#include "wil_platform.h"
|
||||
#include "fw.h"
|
||||
|
@ -37,6 +38,10 @@ extern bool rx_large_buf;
|
|||
extern bool debug_fw;
|
||||
extern bool disable_ap_sme;
|
||||
|
||||
struct wil6210_priv;
|
||||
struct wil6210_vif;
|
||||
union wil_tx_desc;
|
||||
|
||||
#define WIL_NAME "wil6210"
|
||||
|
||||
#define WIL_FW_NAME_DEFAULT "wil6210.fw"
|
||||
|
@ -80,6 +85,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
|
|||
#define WIL6210_NAPI_BUDGET (16) /* arbitrary */
|
||||
#define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */
|
||||
#define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */
|
||||
#define WIL6210_MAX_STATUS_RINGS (8)
|
||||
|
||||
/* Hardware offload block adds the following:
|
||||
* 26 bytes - 3-address QoS data header
|
||||
* 8 bytes - IV + EIV (for GCMP)
|
||||
|
@ -203,7 +210,9 @@ struct RGF_ICR {
|
|||
#define RGF_USER_SPARROW_M_4 (0x880c50) /* Sparrow */
|
||||
#define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF BIT(2)
|
||||
#define RGF_USER_OTP_HW_RD_MACHINE_1 (0x880ce0)
|
||||
#define BIT_NO_FLASH_INDICATION BIT(8)
|
||||
#define BIT_OTP_SIGNATURE_ERR_TALYN_MB BIT(0)
|
||||
#define BIT_OTP_HW_SECTION_DONE_TALYN_MB BIT(2)
|
||||
#define BIT_NO_FLASH_INDICATION BIT(8)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME1 (0x880cec)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME2 (0x880cf0)
|
||||
#define RGF_USER_XPM_IFC_RD_TIME3 (0x880cf4)
|
||||
|
@ -305,20 +314,49 @@ struct RGF_ICR {
|
|||
#define RGF_CAF_PLL_LOCK_STATUS (0x88afec)
|
||||
#define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0)
|
||||
|
||||
#define RGF_OTP_QC_SECURED (0x8a0038)
|
||||
#define BIT_BOOT_FROM_ROM BIT(31)
|
||||
|
||||
/* eDMA */
|
||||
#define RGF_INT_COUNT_ON_SPECIAL_EVT (0x8b62d8)
|
||||
|
||||
#define RGF_INT_CTRL_INT_GEN_CFG_0 (0x8bc000)
|
||||
#define RGF_INT_CTRL_INT_GEN_CFG_1 (0x8bc004)
|
||||
#define RGF_INT_GEN_TIME_UNIT_LIMIT (0x8bc0c8)
|
||||
|
||||
#define RGF_INT_GEN_CTRL (0x8bc0ec)
|
||||
#define BIT_CONTROL_0 BIT(0)
|
||||
|
||||
/* eDMA status interrupts */
|
||||
#define RGF_INT_GEN_RX_ICR (0x8bc0f4)
|
||||
#define BIT_RX_STATUS_IRQ BIT(WIL_RX_STATUS_IRQ_IDX)
|
||||
#define RGF_INT_GEN_TX_ICR (0x8bc110)
|
||||
#define BIT_TX_STATUS_IRQ BIT(WIL_TX_STATUS_IRQ_IDX)
|
||||
#define RGF_INT_CTRL_RX_INT_MASK (0x8bc12c)
|
||||
#define RGF_INT_CTRL_TX_INT_MASK (0x8bc130)
|
||||
|
||||
#define RGF_INT_GEN_IDLE_TIME_LIMIT (0x8bc134)
|
||||
|
||||
#define USER_EXT_USER_PMU_3 (0x88d00c)
|
||||
#define BIT_PMU_DEVICE_RDY BIT(0)
|
||||
|
||||
#define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */
|
||||
#define JTAG_DEV_ID_SPARROW (0x2632072f)
|
||||
#define JTAG_DEV_ID_TALYN (0x7e0e1)
|
||||
#define JTAG_DEV_ID_TALYN_MB (0x1007e0e1)
|
||||
|
||||
#define RGF_USER_REVISION_ID (0x88afe4)
|
||||
#define RGF_USER_REVISION_ID_MASK (3)
|
||||
#define REVISION_ID_SPARROW_B0 (0x0)
|
||||
#define REVISION_ID_SPARROW_D0 (0x3)
|
||||
|
||||
#define RGF_OTP_MAC_TALYN_MB (0x8a0304)
|
||||
#define RGF_OTP_MAC (0x8a0620)
|
||||
|
||||
/* Talyn-MB */
|
||||
#define RGF_USER_USER_CPU_0_TALYN_MB (0x8c0138)
|
||||
#define RGF_USER_MAC_CPU_0_TALYN_MB (0x8c0154)
|
||||
|
||||
/* crash codes for FW/Ucode stored here */
|
||||
|
||||
/* ASSERT RGFs */
|
||||
|
@ -332,6 +370,7 @@ enum {
|
|||
HW_VER_SPARROW_B0, /* REVISION_ID_SPARROW_B0 */
|
||||
HW_VER_SPARROW_D0, /* REVISION_ID_SPARROW_D0 */
|
||||
HW_VER_TALYN, /* JTAG_DEV_ID_TALYN */
|
||||
HW_VER_TALYN_MB /* JTAG_DEV_ID_TALYN_MB */
|
||||
};
|
||||
|
||||
/* popular locations */
|
||||
|
@ -349,7 +388,14 @@ enum {
|
|||
/* Hardware definitions end */
|
||||
#define SPARROW_FW_MAPPING_TABLE_SIZE 10
|
||||
#define TALYN_FW_MAPPING_TABLE_SIZE 13
|
||||
#define MAX_FW_MAPPING_TABLE_SIZE 13
|
||||
#define TALYN_MB_FW_MAPPING_TABLE_SIZE 19
|
||||
#define MAX_FW_MAPPING_TABLE_SIZE 19
|
||||
|
||||
/* Common representation of physical address in wil ring */
|
||||
struct wil_ring_dma_addr {
|
||||
__le32 addr_low;
|
||||
__le16 addr_high;
|
||||
} __packed;
|
||||
|
||||
struct fw_map {
|
||||
u32 from; /* linker address - from, inclusive */
|
||||
|
@ -357,12 +403,14 @@ struct fw_map {
|
|||
u32 host; /* PCI/Host address - BAR0 + 0x880000 */
|
||||
const char *name; /* for debugfs */
|
||||
bool fw; /* true if FW mapping, false if UCODE mapping */
|
||||
bool crash_dump; /* true if should be dumped during crash dump */
|
||||
};
|
||||
|
||||
/* array size should be in sync with actual definition in the wmi.c */
|
||||
extern const struct fw_map sparrow_fw_mapping[SPARROW_FW_MAPPING_TABLE_SIZE];
|
||||
extern const struct fw_map sparrow_d0_mac_rgf_ext;
|
||||
extern const struct fw_map talyn_fw_mapping[TALYN_FW_MAPPING_TABLE_SIZE];
|
||||
extern const struct fw_map talyn_mb_fw_mapping[TALYN_MB_FW_MAPPING_TABLE_SIZE];
|
||||
extern struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
|
||||
|
||||
/**
|
||||
|
@ -438,7 +486,7 @@ enum { /* for wil_ctx.mapped_as */
|
|||
};
|
||||
|
||||
/**
|
||||
* struct wil_ctx - software context for Vring descriptor
|
||||
* struct wil_ctx - software context for ring descriptor
|
||||
*/
|
||||
struct wil_ctx {
|
||||
struct sk_buff *skb;
|
||||
|
@ -446,22 +494,96 @@ struct wil_ctx {
|
|||
u8 mapped_as;
|
||||
};
|
||||
|
||||
union vring_desc;
|
||||
|
||||
struct vring {
|
||||
struct wil_desc_ring_rx_swtail { /* relevant for enhanced DMA only */
|
||||
u32 *va;
|
||||
dma_addr_t pa;
|
||||
volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */
|
||||
u16 size; /* number of vring_desc elements */
|
||||
};
|
||||
|
||||
/**
|
||||
* A general ring structure, used for RX and TX.
|
||||
* In legacy DMA it represents the vring,
|
||||
* In enahnced DMA it represents the descriptor ring (vrings are handled by FW)
|
||||
*/
|
||||
struct wil_ring {
|
||||
dma_addr_t pa;
|
||||
volatile union wil_ring_desc *va;
|
||||
u16 size; /* number of wil_ring_desc elements */
|
||||
u32 swtail;
|
||||
u32 swhead;
|
||||
u32 hwtail; /* write here to inform hw */
|
||||
struct wil_ctx *ctx; /* ctx[size] - software context */
|
||||
struct wil_desc_ring_rx_swtail edma_rx_swtail;
|
||||
bool is_rx;
|
||||
};
|
||||
|
||||
/**
|
||||
* Additional data for Tx Vring
|
||||
* Additional data for Rx ring.
|
||||
* Used for enhanced DMA RX chaining.
|
||||
*/
|
||||
struct vring_tx_data {
|
||||
struct wil_ring_rx_data {
|
||||
/* the skb being assembled */
|
||||
struct sk_buff *skb;
|
||||
/* true if we are skipping a bad fragmented packet */
|
||||
bool skipping;
|
||||
u16 buff_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Status ring structure, used for enhanced DMA completions for RX and TX.
|
||||
*/
|
||||
struct wil_status_ring {
|
||||
dma_addr_t pa;
|
||||
void *va; /* pointer to ring_[tr]x_status elements */
|
||||
u16 size; /* number of status elements */
|
||||
size_t elem_size; /* status element size in bytes */
|
||||
u32 swhead;
|
||||
u32 hwtail; /* write here to inform hw */
|
||||
bool is_rx;
|
||||
u8 desc_rdy_pol; /* Expected descriptor ready bit polarity */
|
||||
struct wil_ring_rx_data rx_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tx_rx_ops - different TX/RX ops for legacy and enhanced
|
||||
* DMA flow
|
||||
*/
|
||||
struct wil_txrx_ops {
|
||||
void (*configure_interrupt_moderation)(struct wil6210_priv *wil);
|
||||
/* TX ops */
|
||||
int (*ring_init_tx)(struct wil6210_vif *vif, int ring_id,
|
||||
int size, int cid, int tid);
|
||||
void (*ring_fini_tx)(struct wil6210_priv *wil, struct wil_ring *ring);
|
||||
int (*ring_init_bcast)(struct wil6210_vif *vif, int id, int size);
|
||||
int (*tx_init)(struct wil6210_priv *wil);
|
||||
void (*tx_fini)(struct wil6210_priv *wil);
|
||||
int (*tx_desc_map)(union wil_tx_desc *desc, dma_addr_t pa,
|
||||
u32 len, int ring_index);
|
||||
void (*tx_desc_unmap)(struct device *dev,
|
||||
union wil_tx_desc *desc,
|
||||
struct wil_ctx *ctx);
|
||||
int (*tx_ring_tso)(struct wil6210_priv *wil, struct wil6210_vif *vif,
|
||||
struct wil_ring *ring, struct sk_buff *skb);
|
||||
irqreturn_t (*irq_tx)(int irq, void *cookie);
|
||||
/* RX ops */
|
||||
int (*rx_init)(struct wil6210_priv *wil, u16 ring_size);
|
||||
void (*rx_fini)(struct wil6210_priv *wil);
|
||||
int (*wmi_addba_rx_resp)(struct wil6210_priv *wil, u8 mid, u8 cid,
|
||||
u8 tid, u8 token, u16 status, bool amsdu,
|
||||
u16 agg_wsize, u16 timeout);
|
||||
void (*get_reorder_params)(struct wil6210_priv *wil,
|
||||
struct sk_buff *skb, int *tid, int *cid,
|
||||
int *mid, u16 *seq, int *mcast);
|
||||
void (*get_netif_rx_params)(struct sk_buff *skb,
|
||||
int *cid, int *security);
|
||||
int (*rx_crypto_check)(struct wil6210_priv *wil, struct sk_buff *skb);
|
||||
bool (*is_rx_idle)(struct wil6210_priv *wil);
|
||||
irqreturn_t (*irq_rx)(int irq, void *cookie);
|
||||
};
|
||||
|
||||
/**
|
||||
* Additional data for Tx ring
|
||||
*/
|
||||
struct wil_ring_tx_data {
|
||||
bool dot1x_open;
|
||||
int enabled;
|
||||
cycles_t idle, last_idle, begin;
|
||||
|
@ -564,6 +686,9 @@ struct wil_net_stats {
|
|||
unsigned long rx_short_frame;
|
||||
unsigned long rx_large_frame;
|
||||
unsigned long rx_replay;
|
||||
unsigned long rx_mic_error; /* eDMA specific */
|
||||
unsigned long rx_key_error; /* eDMA specific */
|
||||
unsigned long rx_amsdu_error; /* eDMA specific */
|
||||
u16 last_mcs_rx;
|
||||
u64 rx_per_mcs[WIL_MCS_MAX + 1];
|
||||
};
|
||||
|
@ -681,7 +806,7 @@ struct wil6210_vif {
|
|||
u8 hidden_ssid; /* relevant in AP mode */
|
||||
u32 ap_isolate; /* no intra-BSS communication */
|
||||
bool pbss;
|
||||
int bcast_vring;
|
||||
int bcast_ring;
|
||||
struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */
|
||||
int locally_generated_disc; /* relevant in STA mode */
|
||||
struct timer_list connect_timer;
|
||||
|
@ -697,6 +822,31 @@ struct wil6210_vif {
|
|||
int net_queue_stopped; /* netif_tx_stop_all_queues invoked */
|
||||
};
|
||||
|
||||
/**
|
||||
* RX buffer allocated for enhanced DMA RX descriptors
|
||||
*/
|
||||
struct wil_rx_buff {
|
||||
struct sk_buff *skb;
|
||||
struct list_head list;
|
||||
int id;
|
||||
};
|
||||
|
||||
/**
|
||||
* During Rx completion processing, the driver extracts a buffer ID which
|
||||
* is used as an index to the rx_buff_mgmt.buff_arr array and then the SKB
|
||||
* is given to the network stack and the buffer is moved from the 'active'
|
||||
* list to the 'free' list.
|
||||
* During Rx refill, SKBs are attached to free buffers and moved to the
|
||||
* 'active' list.
|
||||
*/
|
||||
struct wil_rx_buff_mgmt {
|
||||
struct wil_rx_buff *buff_arr;
|
||||
size_t size; /* number of items in buff_arr */
|
||||
struct list_head active;
|
||||
struct list_head free;
|
||||
unsigned long free_list_empty_cnt; /* statistics */
|
||||
};
|
||||
|
||||
struct wil6210_priv {
|
||||
struct pci_dev *pdev;
|
||||
u32 bar_size;
|
||||
|
@ -761,14 +911,20 @@ struct wil6210_priv {
|
|||
struct net_device napi_ndev; /* dummy net_device serving all VIFs */
|
||||
|
||||
/* DMA related */
|
||||
struct vring vring_rx;
|
||||
struct wil_ring ring_rx;
|
||||
unsigned int rx_buf_len;
|
||||
struct vring vring_tx[WIL6210_MAX_TX_RINGS];
|
||||
struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS];
|
||||
u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */
|
||||
struct wil_ring ring_tx[WIL6210_MAX_TX_RINGS];
|
||||
struct wil_ring_tx_data ring_tx_data[WIL6210_MAX_TX_RINGS];
|
||||
struct wil_status_ring srings[WIL6210_MAX_STATUS_RINGS];
|
||||
u8 num_rx_status_rings;
|
||||
int tx_sring_idx;
|
||||
u8 ring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */
|
||||
struct wil_sta_info sta[WIL6210_MAX_CID];
|
||||
u32 vring_idle_trsh; /* HW fetches up to 16 descriptors at once */
|
||||
u32 ring_idle_trsh; /* HW fetches up to 16 descriptors at once */
|
||||
u32 dma_addr_size; /* indicates dma addr size */
|
||||
struct wil_rx_buff_mgmt rx_buff_mgmt;
|
||||
bool use_enhanced_dma_hw;
|
||||
struct wil_txrx_ops txrx_ops;
|
||||
|
||||
struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */
|
||||
/* statistics */
|
||||
|
@ -811,6 +967,16 @@ struct wil6210_priv {
|
|||
u32 rgf_fw_assert_code_addr;
|
||||
u32 rgf_ucode_assert_code_addr;
|
||||
u32 iccm_base;
|
||||
|
||||
/* relevant only for eDMA */
|
||||
bool use_compressed_rx_status;
|
||||
u32 rx_status_ring_order;
|
||||
u32 tx_status_ring_order;
|
||||
u32 rx_buff_id_count;
|
||||
bool amsdu_en;
|
||||
bool use_rx_hw_reordering;
|
||||
bool secured_boot;
|
||||
u8 boot_config;
|
||||
};
|
||||
|
||||
#define wil_to_wiphy(i) (i->wiphy)
|
||||
|
@ -990,7 +1156,7 @@ int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index,
|
|||
int key_usage);
|
||||
int wmi_echo(struct wil6210_priv *wil);
|
||||
int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie);
|
||||
int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring);
|
||||
int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring);
|
||||
int wmi_rxon(struct wil6210_priv *wil, bool on);
|
||||
int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r);
|
||||
int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac,
|
||||
|
@ -1083,30 +1249,28 @@ void wil_probe_client_flush(struct wil6210_vif *vif);
|
|||
void wil_probe_client_worker(struct work_struct *work);
|
||||
void wil_disconnect_worker(struct work_struct *work);
|
||||
|
||||
int wil_rx_init(struct wil6210_priv *wil, u16 size);
|
||||
void wil_rx_fini(struct wil6210_priv *wil);
|
||||
void wil_init_txrx_ops(struct wil6210_priv *wil);
|
||||
|
||||
/* TX API */
|
||||
int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
|
||||
int cid, int tid);
|
||||
void wil_vring_fini_tx(struct wil6210_priv *wil, int id);
|
||||
int wil_tx_init(struct wil6210_vif *vif, int cid);
|
||||
int wil_ring_init_tx(struct wil6210_vif *vif, int cid);
|
||||
int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size);
|
||||
int wil_bcast_init(struct wil6210_vif *vif);
|
||||
void wil_bcast_fini(struct wil6210_vif *vif);
|
||||
void wil_bcast_fini_all(struct wil6210_priv *wil);
|
||||
|
||||
void wil_update_net_queues(struct wil6210_priv *wil, struct wil6210_vif *vif,
|
||||
struct vring *vring, bool should_stop);
|
||||
struct wil_ring *ring, bool should_stop);
|
||||
void wil_update_net_queues_bh(struct wil6210_priv *wil, struct wil6210_vif *vif,
|
||||
struct vring *vring, bool check_stop);
|
||||
struct wil_ring *ring, bool check_stop);
|
||||
netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev);
|
||||
int wil_tx_complete(struct wil6210_vif *vif, int ringid);
|
||||
void wil6210_unmask_irq_tx(struct wil6210_priv *wil);
|
||||
void wil6210_unmask_irq_tx_edma(struct wil6210_priv *wil);
|
||||
|
||||
/* RX API */
|
||||
void wil_rx_handle(struct wil6210_priv *wil, int *quota);
|
||||
void wil6210_unmask_irq_rx(struct wil6210_priv *wil);
|
||||
void wil6210_unmask_irq_rx_edma(struct wil6210_priv *wil);
|
||||
|
||||
int wil_iftype_nl2wmi(enum nl80211_iftype type);
|
||||
|
||||
|
@ -1127,7 +1291,6 @@ bool wil_is_wmi_idle(struct wil6210_priv *wil);
|
|||
int wmi_resume(struct wil6210_priv *wil);
|
||||
int wmi_suspend(struct wil6210_priv *wil);
|
||||
bool wil_is_tx_idle(struct wil6210_priv *wil);
|
||||
bool wil_is_rx_idle(struct wil6210_priv *wil);
|
||||
|
||||
int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size);
|
||||
void wil_fw_core_dump(struct wil6210_priv *wil);
|
||||
|
@ -1142,4 +1305,19 @@ int wmi_start_sched_scan(struct wil6210_priv *wil,
|
|||
int wmi_stop_sched_scan(struct wil6210_priv *wil);
|
||||
int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len);
|
||||
|
||||
int reverse_memcmp(const void *cs, const void *ct, size_t count);
|
||||
|
||||
/* WMI for enhanced DMA */
|
||||
int wil_wmi_tx_sring_cfg(struct wil6210_priv *wil, int ring_id);
|
||||
int wil_wmi_cfg_def_rx_offload(struct wil6210_priv *wil,
|
||||
u16 max_rx_pl_per_desc);
|
||||
int wil_wmi_rx_sring_add(struct wil6210_priv *wil, u16 ring_id);
|
||||
int wil_wmi_rx_desc_ring_add(struct wil6210_priv *wil, int status_ring_id);
|
||||
int wil_wmi_tx_desc_ring_add(struct wil6210_vif *vif, int ring_id, int cid,
|
||||
int tid);
|
||||
int wil_wmi_bcast_desc_ring_add(struct wil6210_vif *vif, int ring_id);
|
||||
int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid,
|
||||
u8 tid, u8 token, u16 status, bool amsdu,
|
||||
u16 agg_wsize, u16 timeout);
|
||||
|
||||
#endif /* __WIL6210_H__ */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2015,2017 Qualcomm Atheros, Inc.
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -36,7 +37,7 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil,
|
|||
for (i = 1; i < ARRAY_SIZE(fw_mapping); i++) {
|
||||
map = &fw_mapping[i];
|
||||
|
||||
if (!map->fw)
|
||||
if (!map->crash_dump)
|
||||
continue;
|
||||
|
||||
if (map->host < host_min)
|
||||
|
@ -85,7 +86,7 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size)
|
|||
for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
|
||||
map = &fw_mapping[i];
|
||||
|
||||
if (!map->fw)
|
||||
if (!map->crash_dump)
|
||||
continue;
|
||||
|
||||
data = (void * __force)wil->csr + HOSTADDR(map->host);
|
||||
|
|
|
@ -89,28 +89,28 @@ MODULE_PARM_DESC(led_id,
|
|||
*/
|
||||
const struct fw_map sparrow_fw_mapping[] = {
|
||||
/* FW code RAM 256k */
|
||||
{0x000000, 0x040000, 0x8c0000, "fw_code", true},
|
||||
{0x000000, 0x040000, 0x8c0000, "fw_code", true, true},
|
||||
/* FW data RAM 32k */
|
||||
{0x800000, 0x808000, 0x900000, "fw_data", true},
|
||||
{0x800000, 0x808000, 0x900000, "fw_data", true, true},
|
||||
/* periph data 128k */
|
||||
{0x840000, 0x860000, 0x908000, "fw_peri", true},
|
||||
{0x840000, 0x860000, 0x908000, "fw_peri", true, true},
|
||||
/* various RGF 40k */
|
||||
{0x880000, 0x88a000, 0x880000, "rgf", true},
|
||||
{0x880000, 0x88a000, 0x880000, "rgf", true, true},
|
||||
/* AGC table 4k */
|
||||
{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true},
|
||||
{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
|
||||
/* Pcie_ext_rgf 4k */
|
||||
{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true},
|
||||
{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
|
||||
/* mac_ext_rgf 512b */
|
||||
{0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true},
|
||||
{0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext", true, true},
|
||||
/* upper area 548k */
|
||||
{0x8c0000, 0x949000, 0x8c0000, "upper", true},
|
||||
{0x8c0000, 0x949000, 0x8c0000, "upper", true, true},
|
||||
/* UCODE areas - accessible by debugfs blobs but not by
|
||||
* wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
|
||||
*/
|
||||
/* ucode code RAM 128k */
|
||||
{0x000000, 0x020000, 0x920000, "uc_code", false},
|
||||
{0x000000, 0x020000, 0x920000, "uc_code", false, false},
|
||||
/* ucode data RAM 16k */
|
||||
{0x800000, 0x804000, 0x940000, "uc_data", false},
|
||||
{0x800000, 0x804000, 0x940000, "uc_data", false, false},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -118,7 +118,7 @@ const struct fw_map sparrow_fw_mapping[] = {
|
|||
* it is a bit larger to support extra features
|
||||
*/
|
||||
const struct fw_map sparrow_d0_mac_rgf_ext = {
|
||||
0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true
|
||||
0x88c000, 0x88c500, 0x88c000, "mac_rgf_ext", true, true
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -134,34 +134,89 @@ const struct fw_map sparrow_d0_mac_rgf_ext = {
|
|||
*/
|
||||
const struct fw_map talyn_fw_mapping[] = {
|
||||
/* FW code RAM 1M */
|
||||
{0x000000, 0x100000, 0x900000, "fw_code", true},
|
||||
{0x000000, 0x100000, 0x900000, "fw_code", true, true},
|
||||
/* FW data RAM 128k */
|
||||
{0x800000, 0x820000, 0xa00000, "fw_data", true},
|
||||
{0x800000, 0x820000, 0xa00000, "fw_data", true, true},
|
||||
/* periph. data RAM 96k */
|
||||
{0x840000, 0x858000, 0xa20000, "fw_peri", true},
|
||||
{0x840000, 0x858000, 0xa20000, "fw_peri", true, true},
|
||||
/* various RGF 40k */
|
||||
{0x880000, 0x88a000, 0x880000, "rgf", true},
|
||||
{0x880000, 0x88a000, 0x880000, "rgf", true, true},
|
||||
/* AGC table 4k */
|
||||
{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true},
|
||||
{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
|
||||
/* Pcie_ext_rgf 4k */
|
||||
{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true},
|
||||
{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
|
||||
/* mac_ext_rgf 1344b */
|
||||
{0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true},
|
||||
{0x88c000, 0x88c540, 0x88c000, "mac_rgf_ext", true, true},
|
||||
/* ext USER RGF 4k */
|
||||
{0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true},
|
||||
{0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true},
|
||||
/* OTP 4k */
|
||||
{0x8a0000, 0x8a1000, 0x8a0000, "otp", true},
|
||||
{0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false},
|
||||
/* DMA EXT RGF 64k */
|
||||
{0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true},
|
||||
{0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true},
|
||||
/* upper area 1536k */
|
||||
{0x900000, 0xa80000, 0x900000, "upper", true},
|
||||
{0x900000, 0xa80000, 0x900000, "upper", true, true},
|
||||
/* UCODE areas - accessible by debugfs blobs but not by
|
||||
* wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
|
||||
*/
|
||||
/* ucode code RAM 256k */
|
||||
{0x000000, 0x040000, 0xa38000, "uc_code", false},
|
||||
{0x000000, 0x040000, 0xa38000, "uc_code", false, false},
|
||||
/* ucode data RAM 32k */
|
||||
{0x800000, 0x808000, 0xa78000, "uc_data", false},
|
||||
{0x800000, 0x808000, 0xa78000, "uc_data", false, false},
|
||||
};
|
||||
|
||||
/**
|
||||
* @talyn_mb_fw_mapping provides memory remapping table for Talyn-MB
|
||||
*
|
||||
* array size should be in sync with the declaration in the wil6210.h
|
||||
*
|
||||
* Talyn MB memory mapping:
|
||||
* Linker address PCI/Host address
|
||||
* 0x880000 .. 0xc80000 4Mb BAR0
|
||||
* 0x800000 .. 0x820000 0xa00000 .. 0xa20000 128k DCCM
|
||||
* 0x840000 .. 0x858000 0xa20000 .. 0xa38000 96k PERIPH
|
||||
*/
|
||||
const struct fw_map talyn_mb_fw_mapping[] = {
|
||||
/* FW code RAM 768k */
|
||||
{0x000000, 0x0c0000, 0x900000, "fw_code", true, true},
|
||||
/* FW data RAM 128k */
|
||||
{0x800000, 0x820000, 0xa00000, "fw_data", true, true},
|
||||
/* periph. data RAM 96k */
|
||||
{0x840000, 0x858000, 0xa20000, "fw_peri", true, true},
|
||||
/* various RGF 40k */
|
||||
{0x880000, 0x88a000, 0x880000, "rgf", true, true},
|
||||
/* AGC table 4k */
|
||||
{0x88a000, 0x88b000, 0x88a000, "AGC_tbl", true, true},
|
||||
/* Pcie_ext_rgf 4k */
|
||||
{0x88b000, 0x88c000, 0x88b000, "rgf_ext", true, true},
|
||||
/* mac_ext_rgf 2256b */
|
||||
{0x88c000, 0x88c8d0, 0x88c000, "mac_rgf_ext", true, true},
|
||||
/* ext USER RGF 4k */
|
||||
{0x88d000, 0x88e000, 0x88d000, "ext_user_rgf", true, true},
|
||||
/* SEC PKA 16k */
|
||||
{0x890000, 0x894000, 0x890000, "sec_pka", true, true},
|
||||
/* SEC KDF RGF 3096b */
|
||||
{0x898000, 0x898c18, 0x898000, "sec_kdf_rgf", true, true},
|
||||
/* SEC MAIN 2124b */
|
||||
{0x89a000, 0x89a84c, 0x89a000, "sec_main", true, true},
|
||||
/* OTP 4k */
|
||||
{0x8a0000, 0x8a1000, 0x8a0000, "otp", true, false},
|
||||
/* DMA EXT RGF 64k */
|
||||
{0x8b0000, 0x8c0000, 0x8b0000, "dma_ext_rgf", true, true},
|
||||
/* DUM USER RGF 528b */
|
||||
{0x8c0000, 0x8c0210, 0x8c0000, "dum_user_rgf", true, true},
|
||||
/* DMA OFU 296b */
|
||||
{0x8c2000, 0x8c2128, 0x8c2000, "dma_ofu", true, true},
|
||||
/* ucode debug 4k */
|
||||
{0x8c3000, 0x8c4000, 0x8c3000, "ucode_debug", true, true},
|
||||
/* upper area 1536k */
|
||||
{0x900000, 0xa80000, 0x900000, "upper", true, true},
|
||||
/* UCODE areas - accessible by debugfs blobs but not by
|
||||
* wmi_addr_remap. UCODE areas MUST be added AFTER FW areas!
|
||||
*/
|
||||
/* ucode code RAM 256k */
|
||||
{0x000000, 0x040000, 0xa38000, "uc_code", false, false},
|
||||
/* ucode data RAM 32k */
|
||||
{0x800000, 0x808000, 0xa78000, "uc_data", false, false},
|
||||
};
|
||||
|
||||
struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
|
||||
|
@ -365,14 +420,16 @@ static const char *cmdid2name(u16 cmdid)
|
|||
return "WMI_DEL_STA_CMD";
|
||||
case WMI_DISCONNECT_STA_CMDID:
|
||||
return "WMI_DISCONNECT_STA_CMD";
|
||||
case WMI_VRING_BA_EN_CMDID:
|
||||
return "WMI_VRING_BA_EN_CMD";
|
||||
case WMI_VRING_BA_DIS_CMDID:
|
||||
return "WMI_VRING_BA_DIS_CMD";
|
||||
case WMI_RING_BA_EN_CMDID:
|
||||
return "WMI_RING_BA_EN_CMD";
|
||||
case WMI_RING_BA_DIS_CMDID:
|
||||
return "WMI_RING_BA_DIS_CMD";
|
||||
case WMI_RCP_DELBA_CMDID:
|
||||
return "WMI_RCP_DELBA_CMD";
|
||||
case WMI_RCP_ADDBA_RESP_CMDID:
|
||||
return "WMI_RCP_ADDBA_RESP_CMD";
|
||||
case WMI_RCP_ADDBA_RESP_EDMA_CMDID:
|
||||
return "WMI_RCP_ADDBA_RESP_EDMA_CMD";
|
||||
case WMI_PS_DEV_PROFILE_CFG_CMDID:
|
||||
return "WMI_PS_DEV_PROFILE_CFG_CMD";
|
||||
case WMI_SET_MGMT_RETRY_LIMIT_CMDID:
|
||||
|
@ -395,6 +452,18 @@ static const char *cmdid2name(u16 cmdid)
|
|||
return "WMI_START_SCHED_SCAN_CMD";
|
||||
case WMI_STOP_SCHED_SCAN_CMDID:
|
||||
return "WMI_STOP_SCHED_SCAN_CMD";
|
||||
case WMI_TX_STATUS_RING_ADD_CMDID:
|
||||
return "WMI_TX_STATUS_RING_ADD_CMD";
|
||||
case WMI_RX_STATUS_RING_ADD_CMDID:
|
||||
return "WMI_RX_STATUS_RING_ADD_CMD";
|
||||
case WMI_TX_DESC_RING_ADD_CMDID:
|
||||
return "WMI_TX_DESC_RING_ADD_CMD";
|
||||
case WMI_RX_DESC_RING_ADD_CMDID:
|
||||
return "WMI_RX_DESC_RING_ADD_CMD";
|
||||
case WMI_BCAST_DESC_RING_ADD_CMDID:
|
||||
return "WMI_BCAST_DESC_RING_ADD_CMD";
|
||||
case WMI_CFG_DEF_RX_OFFLOAD_CMDID:
|
||||
return "WMI_CFG_DEF_RX_OFFLOAD_CMD";
|
||||
default:
|
||||
return "Untracked CMD";
|
||||
}
|
||||
|
@ -449,8 +518,8 @@ static const char *eventid2name(u16 eventid)
|
|||
return "WMI_RCP_ADDBA_REQ_EVENT";
|
||||
case WMI_DELBA_EVENTID:
|
||||
return "WMI_DELBA_EVENT";
|
||||
case WMI_VRING_EN_EVENTID:
|
||||
return "WMI_VRING_EN_EVENT";
|
||||
case WMI_RING_EN_EVENTID:
|
||||
return "WMI_RING_EN_EVENT";
|
||||
case WMI_DATA_PORT_OPEN_EVENTID:
|
||||
return "WMI_DATA_PORT_OPEN_EVENT";
|
||||
case WMI_AOA_MEAS_EVENTID:
|
||||
|
@ -519,6 +588,16 @@ static const char *eventid2name(u16 eventid)
|
|||
return "WMI_STOP_SCHED_SCAN_EVENT";
|
||||
case WMI_SCHED_SCAN_RESULT_EVENTID:
|
||||
return "WMI_SCHED_SCAN_RESULT_EVENT";
|
||||
case WMI_TX_STATUS_RING_CFG_DONE_EVENTID:
|
||||
return "WMI_TX_STATUS_RING_CFG_DONE_EVENT";
|
||||
case WMI_RX_STATUS_RING_CFG_DONE_EVENTID:
|
||||
return "WMI_RX_STATUS_RING_CFG_DONE_EVENT";
|
||||
case WMI_TX_DESC_RING_CFG_DONE_EVENTID:
|
||||
return "WMI_TX_DESC_RING_CFG_DONE_EVENT";
|
||||
case WMI_RX_DESC_RING_CFG_DONE_EVENTID:
|
||||
return "WMI_RX_DESC_RING_CFG_DONE_EVENT";
|
||||
case WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID:
|
||||
return "WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENT";
|
||||
default:
|
||||
return "Untracked EVENT";
|
||||
}
|
||||
|
@ -906,7 +985,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
|
|||
wil->sta[evt->cid].mid = vif->mid;
|
||||
wil->sta[evt->cid].status = wil_sta_conn_pending;
|
||||
|
||||
rc = wil_tx_init(vif, evt->cid);
|
||||
rc = wil_ring_init_tx(vif, evt->cid);
|
||||
if (rc) {
|
||||
wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n",
|
||||
evt->cid, rc);
|
||||
|
@ -1063,16 +1142,16 @@ static void wmi_evt_eapol_rx(struct wil6210_vif *vif, int id, void *d, int len)
|
|||
}
|
||||
}
|
||||
|
||||
static void wmi_evt_vring_en(struct wil6210_vif *vif, int id, void *d, int len)
|
||||
static void wmi_evt_ring_en(struct wil6210_vif *vif, int id, void *d, int len)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct wmi_vring_en_event *evt = d;
|
||||
u8 vri = evt->vring_index;
|
||||
struct wmi_ring_en_event *evt = d;
|
||||
u8 vri = evt->ring_index;
|
||||
struct wireless_dev *wdev = vif_to_wdev(vif);
|
||||
|
||||
wil_dbg_wmi(wil, "Enable vring %d MID %d\n", vri, vif->mid);
|
||||
|
||||
if (vri >= ARRAY_SIZE(wil->vring_tx)) {
|
||||
if (vri >= ARRAY_SIZE(wil->ring_tx)) {
|
||||
wil_err(wil, "Enable for invalid vring %d\n", vri);
|
||||
return;
|
||||
}
|
||||
|
@ -1081,8 +1160,8 @@ static void wmi_evt_vring_en(struct wil6210_vif *vif, int id, void *d, int len)
|
|||
/* in AP mode with disable_ap_sme, this is done by
|
||||
* wil_cfg80211_change_station()
|
||||
*/
|
||||
wil->vring_tx_data[vri].dot1x_open = true;
|
||||
if (vri == vif->bcast_vring) /* no BA for bcast */
|
||||
wil->ring_tx_data[vri].dot1x_open = true;
|
||||
if (vri == vif->bcast_ring) /* no BA for bcast */
|
||||
return;
|
||||
if (agg_wsize >= 0)
|
||||
wil_addba_tx_request(wil, vri, agg_wsize);
|
||||
|
@ -1093,7 +1172,7 @@ static void wmi_evt_ba_status(struct wil6210_vif *vif, int id,
|
|||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct wmi_ba_status_event *evt = d;
|
||||
struct vring_tx_data *txdata;
|
||||
struct wil_ring_tx_data *txdata;
|
||||
|
||||
wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
|
||||
evt->ringid,
|
||||
|
@ -1112,7 +1191,7 @@ static void wmi_evt_ba_status(struct wil6210_vif *vif, int id,
|
|||
evt->amsdu = 0;
|
||||
}
|
||||
|
||||
txdata = &wil->vring_tx_data[evt->ringid];
|
||||
txdata = &wil->ring_tx_data[evt->ringid];
|
||||
|
||||
txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
|
||||
txdata->agg_wsize = evt->agg_wsize;
|
||||
|
@ -1150,11 +1229,11 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
if (!evt->from_initiator) {
|
||||
int i;
|
||||
/* find Tx vring it belongs to */
|
||||
for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
|
||||
if ((wil->vring2cid_tid[i][0] == cid) &&
|
||||
(wil->vring2cid_tid[i][1] == tid)) {
|
||||
struct vring_tx_data *txdata =
|
||||
&wil->vring_tx_data[i];
|
||||
for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++) {
|
||||
if (wil->ring2cid_tid[i][0] == cid &&
|
||||
wil->ring2cid_tid[i][1] == tid) {
|
||||
struct wil_ring_tx_data *txdata =
|
||||
&wil->ring_tx_data[i];
|
||||
|
||||
wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
|
||||
txdata->agg_timeout = 0;
|
||||
|
@ -1164,7 +1243,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
|||
break; /* max. 1 matching ring */
|
||||
}
|
||||
}
|
||||
if (i >= ARRAY_SIZE(wil->vring2cid_tid))
|
||||
if (i >= ARRAY_SIZE(wil->ring2cid_tid))
|
||||
wil_err(wil, "DELBA: unable to find Tx vring\n");
|
||||
return;
|
||||
}
|
||||
|
@ -1277,7 +1356,7 @@ static const struct {
|
|||
{WMI_BA_STATUS_EVENTID, wmi_evt_ba_status},
|
||||
{WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req},
|
||||
{WMI_DELBA_EVENTID, wmi_evt_delba},
|
||||
{WMI_VRING_EN_EVENTID, wmi_evt_vring_en},
|
||||
{WMI_RING_EN_EVENTID, wmi_evt_ring_en},
|
||||
{WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore},
|
||||
{WMI_SCHED_SCAN_RESULT_EVENTID, wmi_evt_sched_scan_result},
|
||||
};
|
||||
|
@ -1909,7 +1988,7 @@ int wmi_rxon(struct wil6210_priv *wil, bool on)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
|
||||
int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring)
|
||||
{
|
||||
struct net_device *ndev = wil->main_ndev;
|
||||
struct wireless_dev *wdev = ndev->ieee80211_ptr;
|
||||
|
@ -2063,29 +2142,32 @@ int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac,
|
|||
int wmi_addba(struct wil6210_priv *wil, u8 mid,
|
||||
u8 ringid, u8 size, u16 timeout)
|
||||
{
|
||||
struct wmi_vring_ba_en_cmd cmd = {
|
||||
.ringid = ringid,
|
||||
u8 amsdu = wil->use_enhanced_dma_hw && wil->use_rx_hw_reordering &&
|
||||
test_bit(WMI_FW_CAPABILITY_AMSDU, wil->fw_capabilities) &&
|
||||
wil->amsdu_en;
|
||||
struct wmi_ring_ba_en_cmd cmd = {
|
||||
.ring_id = ringid,
|
||||
.agg_max_wsize = size,
|
||||
.ba_timeout = cpu_to_le16(timeout),
|
||||
.amsdu = 0,
|
||||
.amsdu = amsdu,
|
||||
};
|
||||
|
||||
wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size,
|
||||
timeout);
|
||||
wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d amsdu %d)\n",
|
||||
ringid, size, timeout, amsdu);
|
||||
|
||||
return wmi_send(wil, WMI_VRING_BA_EN_CMDID, mid, &cmd, sizeof(cmd));
|
||||
return wmi_send(wil, WMI_RING_BA_EN_CMDID, mid, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason)
|
||||
{
|
||||
struct wmi_vring_ba_dis_cmd cmd = {
|
||||
.ringid = ringid,
|
||||
struct wmi_ring_ba_dis_cmd cmd = {
|
||||
.ring_id = ringid,
|
||||
.reason = cpu_to_le16(reason),
|
||||
};
|
||||
|
||||
wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason);
|
||||
|
||||
return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd));
|
||||
return wmi_send(wil, WMI_RING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason)
|
||||
|
@ -2146,6 +2228,54 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil,
|
|||
return rc;
|
||||
}
|
||||
|
||||
int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid,
|
||||
u8 token, u16 status, bool amsdu, u16 agg_wsize,
|
||||
u16 timeout)
|
||||
{
|
||||
int rc;
|
||||
struct wmi_rcp_addba_resp_edma_cmd cmd = {
|
||||
.cid = cid,
|
||||
.tid = tid,
|
||||
.dialog_token = token,
|
||||
.status_code = cpu_to_le16(status),
|
||||
/* bit 0: A-MSDU supported
|
||||
* bit 1: policy (should be 0 for us)
|
||||
* bits 2..5: TID
|
||||
* bits 6..15: buffer size
|
||||
*/
|
||||
.ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
|
||||
(agg_wsize << 6)),
|
||||
.ba_timeout = cpu_to_le16(timeout),
|
||||
/* route all the connections to status ring 0 */
|
||||
.status_ring_id = WIL_DEFAULT_RX_STATUS_RING_ID,
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr wmi;
|
||||
struct wmi_rcp_addba_resp_sent_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)},
|
||||
};
|
||||
|
||||
wil_dbg_wmi(wil,
|
||||
"ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s, sring_id %d\n",
|
||||
cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-",
|
||||
WIL_DEFAULT_RX_STATUS_RING_ID);
|
||||
|
||||
rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_EDMA_CMDID, mid, &cmd,
|
||||
sizeof(cmd), WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply,
|
||||
sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (reply.evt.status) {
|
||||
wil_err(wil, "ADDBA response failed with status %d\n",
|
||||
le16_to_cpu(reply.evt.status));
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
|
||||
enum wmi_ps_profile_type ps_profile)
|
||||
{
|
||||
|
@ -2852,3 +2982,263 @@ int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len)
|
|||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int wil_wmi_tx_sring_cfg(struct wil6210_priv *wil, int ring_id)
|
||||
{
|
||||
int rc;
|
||||
struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
|
||||
struct wil_status_ring *sring = &wil->srings[ring_id];
|
||||
struct wmi_tx_status_ring_add_cmd cmd = {
|
||||
.ring_cfg = {
|
||||
.ring_size = cpu_to_le16(sring->size),
|
||||
},
|
||||
.irq_index = WIL_TX_STATUS_IRQ_IDX
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr hdr;
|
||||
struct wmi_tx_status_ring_cfg_done_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
|
||||
cmd.ring_cfg.ring_id = ring_id;
|
||||
|
||||
cmd.ring_cfg.ring_mem_base = cpu_to_le64(sring->pa);
|
||||
rc = wmi_call(wil, WMI_TX_STATUS_RING_ADD_CMDID, vif->mid, &cmd,
|
||||
sizeof(cmd), WMI_TX_STATUS_RING_CFG_DONE_EVENTID,
|
||||
&reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc) {
|
||||
wil_err(wil, "TX_STATUS_RING_ADD_CMD failed, rc %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
|
||||
wil_err(wil, "TX_STATUS_RING_ADD_CMD failed, status %d\n",
|
||||
reply.evt.status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wil_wmi_cfg_def_rx_offload(struct wil6210_priv *wil, u16 max_rx_pl_per_desc)
|
||||
{
|
||||
struct net_device *ndev = wil->main_ndev;
|
||||
struct wil6210_vif *vif = ndev_to_vif(ndev);
|
||||
int rc;
|
||||
struct wmi_cfg_def_rx_offload_cmd cmd = {
|
||||
.max_msdu_size = cpu_to_le16(wil_mtu2macbuf(WIL_MAX_ETH_MTU)),
|
||||
.max_rx_pl_per_desc = cpu_to_le16(max_rx_pl_per_desc),
|
||||
.decap_trans_type = WMI_DECAP_TYPE_802_3,
|
||||
.l2_802_3_offload_ctrl = 0,
|
||||
.l3_l4_ctrl = 1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS,
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr hdr;
|
||||
struct wmi_cfg_def_rx_offload_done_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
|
||||
rc = wmi_call(wil, WMI_CFG_DEF_RX_OFFLOAD_CMDID, vif->mid, &cmd,
|
||||
sizeof(cmd), WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID, &reply,
|
||||
sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc) {
|
||||
wil_err(wil, "WMI_CFG_DEF_RX_OFFLOAD_CMD failed, rc %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
|
||||
wil_err(wil, "WMI_CFG_DEF_RX_OFFLOAD_CMD failed, status %d\n",
|
||||
reply.evt.status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wil_wmi_rx_sring_add(struct wil6210_priv *wil, u16 ring_id)
|
||||
{
|
||||
struct net_device *ndev = wil->main_ndev;
|
||||
struct wil6210_vif *vif = ndev_to_vif(ndev);
|
||||
struct wil_status_ring *sring = &wil->srings[ring_id];
|
||||
int rc;
|
||||
struct wmi_rx_status_ring_add_cmd cmd = {
|
||||
.ring_cfg = {
|
||||
.ring_size = cpu_to_le16(sring->size),
|
||||
.ring_id = ring_id,
|
||||
},
|
||||
.rx_msg_type = wil->use_compressed_rx_status ?
|
||||
WMI_RX_MSG_TYPE_COMPRESSED :
|
||||
WMI_RX_MSG_TYPE_EXTENDED,
|
||||
.irq_index = WIL_RX_STATUS_IRQ_IDX,
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr hdr;
|
||||
struct wmi_rx_status_ring_cfg_done_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
|
||||
cmd.ring_cfg.ring_mem_base = cpu_to_le64(sring->pa);
|
||||
rc = wmi_call(wil, WMI_RX_STATUS_RING_ADD_CMDID, vif->mid, &cmd,
|
||||
sizeof(cmd), WMI_RX_STATUS_RING_CFG_DONE_EVENTID, &reply,
|
||||
sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc) {
|
||||
wil_err(wil, "RX_STATUS_RING_ADD_CMD failed, rc %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
|
||||
wil_err(wil, "RX_STATUS_RING_ADD_CMD failed, status %d\n",
|
||||
reply.evt.status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wil_wmi_rx_desc_ring_add(struct wil6210_priv *wil, int status_ring_id)
|
||||
{
|
||||
struct net_device *ndev = wil->main_ndev;
|
||||
struct wil6210_vif *vif = ndev_to_vif(ndev);
|
||||
struct wil_ring *ring = &wil->ring_rx;
|
||||
int rc;
|
||||
struct wmi_rx_desc_ring_add_cmd cmd = {
|
||||
.ring_cfg = {
|
||||
.ring_size = cpu_to_le16(ring->size),
|
||||
.ring_id = WIL_RX_DESC_RING_ID,
|
||||
},
|
||||
.status_ring_id = status_ring_id,
|
||||
.irq_index = WIL_RX_STATUS_IRQ_IDX,
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr hdr;
|
||||
struct wmi_rx_desc_ring_cfg_done_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
|
||||
cmd.ring_cfg.ring_mem_base = cpu_to_le64(ring->pa);
|
||||
cmd.sw_tail_host_addr = cpu_to_le64(ring->edma_rx_swtail.pa);
|
||||
rc = wmi_call(wil, WMI_RX_DESC_RING_ADD_CMDID, vif->mid, &cmd,
|
||||
sizeof(cmd), WMI_RX_DESC_RING_CFG_DONE_EVENTID, &reply,
|
||||
sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc) {
|
||||
wil_err(wil, "WMI_RX_DESC_RING_ADD_CMD failed, rc %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
|
||||
wil_err(wil, "WMI_RX_DESC_RING_ADD_CMD failed, status %d\n",
|
||||
reply.evt.status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wil_wmi_tx_desc_ring_add(struct wil6210_vif *vif, int ring_id, int cid,
|
||||
int tid)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
int sring_id = wil->tx_sring_idx; /* there is only one TX sring */
|
||||
int rc;
|
||||
struct wil_ring *ring = &wil->ring_tx[ring_id];
|
||||
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id];
|
||||
struct wmi_tx_desc_ring_add_cmd cmd = {
|
||||
.ring_cfg = {
|
||||
.ring_size = cpu_to_le16(ring->size),
|
||||
.ring_id = ring_id,
|
||||
},
|
||||
.status_ring_id = sring_id,
|
||||
.cid = cid,
|
||||
.tid = tid,
|
||||
.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
|
||||
.max_msdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
|
||||
.schd_params = {
|
||||
.priority = cpu_to_le16(0),
|
||||
.timeslot_us = cpu_to_le16(0xfff),
|
||||
}
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr hdr;
|
||||
struct wmi_tx_desc_ring_cfg_done_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
|
||||
cmd.ring_cfg.ring_mem_base = cpu_to_le64(ring->pa);
|
||||
rc = wmi_call(wil, WMI_TX_DESC_RING_ADD_CMDID, vif->mid, &cmd,
|
||||
sizeof(cmd), WMI_TX_DESC_RING_CFG_DONE_EVENTID, &reply,
|
||||
sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc) {
|
||||
wil_err(wil, "WMI_TX_DESC_RING_ADD_CMD failed, rc %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
|
||||
wil_err(wil, "WMI_TX_DESC_RING_ADD_CMD failed, status %d\n",
|
||||
reply.evt.status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_bh(&txdata->lock);
|
||||
ring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
|
||||
txdata->mid = vif->mid;
|
||||
txdata->enabled = 1;
|
||||
spin_unlock_bh(&txdata->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wil_wmi_bcast_desc_ring_add(struct wil6210_vif *vif, int ring_id)
|
||||
{
|
||||
struct wil6210_priv *wil = vif_to_wil(vif);
|
||||
struct wil_ring *ring = &wil->ring_tx[ring_id];
|
||||
int rc;
|
||||
struct wmi_bcast_desc_ring_add_cmd cmd = {
|
||||
.ring_cfg = {
|
||||
.ring_size = cpu_to_le16(ring->size),
|
||||
.ring_id = ring_id,
|
||||
},
|
||||
.status_ring_id = wil->tx_sring_idx,
|
||||
.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
|
||||
};
|
||||
struct {
|
||||
struct wmi_cmd_hdr hdr;
|
||||
struct wmi_rx_desc_ring_cfg_done_event evt;
|
||||
} __packed reply = {
|
||||
.evt = {.status = WMI_FW_STATUS_FAILURE},
|
||||
};
|
||||
struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id];
|
||||
|
||||
cmd.ring_cfg.ring_mem_base = cpu_to_le64(ring->pa);
|
||||
rc = wmi_call(wil, WMI_BCAST_DESC_RING_ADD_CMDID, vif->mid, &cmd,
|
||||
sizeof(cmd), WMI_TX_DESC_RING_CFG_DONE_EVENTID, &reply,
|
||||
sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS);
|
||||
if (rc) {
|
||||
wil_err(wil, "WMI_BCAST_DESC_RING_ADD_CMD failed, rc %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (reply.evt.status != WMI_FW_STATUS_SUCCESS) {
|
||||
wil_err(wil, "Broadcast Tx config failed, status %d\n",
|
||||
reply.evt.status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_bh(&txdata->lock);
|
||||
ring->hwtail = le32_to_cpu(reply.evt.ring_tail_ptr);
|
||||
txdata->mid = vif->mid;
|
||||
txdata->enabled = 1;
|
||||
spin_unlock_bh(&txdata->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ enum wmi_fw_capability {
|
|||
WMI_FW_CAPABILITY_PNO = 15,
|
||||
WMI_FW_CAPABILITY_REF_CLOCK_CONTROL = 18,
|
||||
WMI_FW_CAPABILITY_AP_SME_OFFLOAD_NONE = 19,
|
||||
WMI_FW_CAPABILITY_AMSDU = 23,
|
||||
WMI_FW_CAPABILITY_MAX,
|
||||
};
|
||||
|
||||
|
@ -148,8 +149,8 @@ enum wmi_command_id {
|
|||
WMI_CFG_RX_CHAIN_CMDID = 0x820,
|
||||
WMI_VRING_CFG_CMDID = 0x821,
|
||||
WMI_BCAST_VRING_CFG_CMDID = 0x822,
|
||||
WMI_VRING_BA_EN_CMDID = 0x823,
|
||||
WMI_VRING_BA_DIS_CMDID = 0x824,
|
||||
WMI_RING_BA_EN_CMDID = 0x823,
|
||||
WMI_RING_BA_DIS_CMDID = 0x824,
|
||||
WMI_RCP_ADDBA_RESP_CMDID = 0x825,
|
||||
WMI_RCP_DELBA_CMDID = 0x826,
|
||||
WMI_SET_SSID_CMDID = 0x827,
|
||||
|
@ -163,6 +164,7 @@ enum wmi_command_id {
|
|||
WMI_BF_SM_MGMT_CMDID = 0x838,
|
||||
WMI_BF_RXSS_MGMT_CMDID = 0x839,
|
||||
WMI_BF_TRIG_CMDID = 0x83A,
|
||||
WMI_RCP_ADDBA_RESP_EDMA_CMDID = 0x83B,
|
||||
WMI_LINK_MAINTAIN_CFG_WRITE_CMDID = 0x842,
|
||||
WMI_LINK_MAINTAIN_CFG_READ_CMDID = 0x843,
|
||||
WMI_SET_SECTORS_CMDID = 0x849,
|
||||
|
@ -235,6 +237,12 @@ enum wmi_command_id {
|
|||
WMI_PRIO_TX_SECTORS_NUMBER_CMDID = 0x9A6,
|
||||
WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_CMDID = 0x9A7,
|
||||
WMI_BF_CONTROL_CMDID = 0x9AA,
|
||||
WMI_TX_STATUS_RING_ADD_CMDID = 0x9C0,
|
||||
WMI_RX_STATUS_RING_ADD_CMDID = 0x9C1,
|
||||
WMI_TX_DESC_RING_ADD_CMDID = 0x9C2,
|
||||
WMI_RX_DESC_RING_ADD_CMDID = 0x9C3,
|
||||
WMI_BCAST_DESC_RING_ADD_CMDID = 0x9C4,
|
||||
WMI_CFG_DEF_RX_OFFLOAD_CMDID = 0x9C5,
|
||||
WMI_SCHEDULING_SCHEME_CMDID = 0xA01,
|
||||
WMI_FIXED_SCHEDULING_CONFIG_CMDID = 0xA02,
|
||||
WMI_ENABLE_FIXED_SCHEDULING_CMDID = 0xA03,
|
||||
|
@ -781,18 +789,90 @@ struct wmi_lo_power_calib_from_otp_event {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_VRING_BA_EN_CMDID */
|
||||
struct wmi_vring_ba_en_cmd {
|
||||
u8 ringid;
|
||||
struct wmi_edma_ring_cfg {
|
||||
__le64 ring_mem_base;
|
||||
/* size in number of items */
|
||||
__le16 ring_size;
|
||||
u8 ring_id;
|
||||
u8 reserved;
|
||||
} __packed;
|
||||
|
||||
enum wmi_rx_msg_type {
|
||||
WMI_RX_MSG_TYPE_COMPRESSED = 0x00,
|
||||
WMI_RX_MSG_TYPE_EXTENDED = 0x01,
|
||||
};
|
||||
|
||||
struct wmi_tx_status_ring_add_cmd {
|
||||
struct wmi_edma_ring_cfg ring_cfg;
|
||||
u8 irq_index;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
struct wmi_rx_status_ring_add_cmd {
|
||||
struct wmi_edma_ring_cfg ring_cfg;
|
||||
u8 irq_index;
|
||||
/* wmi_rx_msg_type */
|
||||
u8 rx_msg_type;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
struct wmi_cfg_def_rx_offload_cmd {
|
||||
__le16 max_msdu_size;
|
||||
__le16 max_rx_pl_per_desc;
|
||||
u8 decap_trans_type;
|
||||
u8 l2_802_3_offload_ctrl;
|
||||
u8 l2_nwifi_offload_ctrl;
|
||||
u8 vlan_id;
|
||||
u8 nwifi_ds_trans_type;
|
||||
u8 l3_l4_ctrl;
|
||||
u8 reserved[6];
|
||||
} __packed;
|
||||
|
||||
struct wmi_tx_desc_ring_add_cmd {
|
||||
struct wmi_edma_ring_cfg ring_cfg;
|
||||
__le16 max_msdu_size;
|
||||
/* Correlated status ring (0-63) */
|
||||
u8 status_ring_id;
|
||||
u8 cid;
|
||||
u8 tid;
|
||||
u8 encap_trans_type;
|
||||
u8 mac_ctrl;
|
||||
u8 to_resolution;
|
||||
u8 agg_max_wsize;
|
||||
u8 reserved[3];
|
||||
struct wmi_vring_cfg_schd schd_params;
|
||||
} __packed;
|
||||
|
||||
struct wmi_rx_desc_ring_add_cmd {
|
||||
struct wmi_edma_ring_cfg ring_cfg;
|
||||
u8 irq_index;
|
||||
/* 0-63 status rings */
|
||||
u8 status_ring_id;
|
||||
u8 reserved[2];
|
||||
__le64 sw_tail_host_addr;
|
||||
} __packed;
|
||||
|
||||
struct wmi_bcast_desc_ring_add_cmd {
|
||||
struct wmi_edma_ring_cfg ring_cfg;
|
||||
__le16 max_msdu_size;
|
||||
/* Correlated status ring (0-63) */
|
||||
u8 status_ring_id;
|
||||
u8 encap_trans_type;
|
||||
u8 reserved[4];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RING_BA_EN_CMDID */
|
||||
struct wmi_ring_ba_en_cmd {
|
||||
u8 ring_id;
|
||||
u8 agg_max_wsize;
|
||||
__le16 ba_timeout;
|
||||
u8 amsdu;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_VRING_BA_DIS_CMDID */
|
||||
struct wmi_vring_ba_dis_cmd {
|
||||
u8 ringid;
|
||||
/* WMI_RING_BA_DIS_CMDID */
|
||||
struct wmi_ring_ba_dis_cmd {
|
||||
u8 ring_id;
|
||||
u8 reserved;
|
||||
__le16 reason;
|
||||
} __packed;
|
||||
|
@ -950,6 +1030,21 @@ struct wmi_rcp_addba_resp_cmd {
|
|||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_RCP_ADDBA_RESP_EDMA_CMDID */
|
||||
struct wmi_rcp_addba_resp_edma_cmd {
|
||||
u8 cid;
|
||||
u8 tid;
|
||||
u8 dialog_token;
|
||||
u8 reserved;
|
||||
__le16 status_code;
|
||||
/* ieee80211_ba_parameterset field to send */
|
||||
__le16 ba_param_set;
|
||||
__le16 ba_timeout;
|
||||
u8 status_ring_id;
|
||||
/* wmi_cfg_rx_chain_cmd_reorder_type */
|
||||
u8 reorder_type;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RCP_DELBA_CMDID */
|
||||
struct wmi_rcp_delba_cmd {
|
||||
/* Used for cid less than 8. For higher cid set
|
||||
|
@ -1535,7 +1630,7 @@ enum wmi_event_id {
|
|||
WMI_BF_CTRL_DONE_EVENTID = 0x1862,
|
||||
WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863,
|
||||
WMI_GET_STATUS_DONE_EVENTID = 0x1864,
|
||||
WMI_VRING_EN_EVENTID = 0x1865,
|
||||
WMI_RING_EN_EVENTID = 0x1865,
|
||||
WMI_GET_RF_STATUS_EVENTID = 0x1866,
|
||||
WMI_GET_BASEBAND_TYPE_EVENTID = 0x1867,
|
||||
WMI_VRING_SWITCH_TIMING_CONFIG_EVENTID = 0x1868,
|
||||
|
@ -1587,6 +1682,11 @@ enum wmi_event_id {
|
|||
WMI_PRIO_TX_SECTORS_NUMBER_EVENTID = 0x19A6,
|
||||
WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID = 0x19A7,
|
||||
WMI_BF_CONTROL_EVENTID = 0x19AA,
|
||||
WMI_TX_STATUS_RING_CFG_DONE_EVENTID = 0x19C0,
|
||||
WMI_RX_STATUS_RING_CFG_DONE_EVENTID = 0x19C1,
|
||||
WMI_TX_DESC_RING_CFG_DONE_EVENTID = 0x19C2,
|
||||
WMI_RX_DESC_RING_CFG_DONE_EVENTID = 0x19C3,
|
||||
WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID = 0x19C5,
|
||||
WMI_SCHEDULING_SCHEME_EVENTID = 0x1A01,
|
||||
WMI_FIXED_SCHEDULING_CONFIG_COMPLETE_EVENTID = 0x1A02,
|
||||
WMI_ENABLE_FIXED_SCHEDULING_COMPLETE_EVENTID = 0x1A03,
|
||||
|
@ -1997,6 +2097,49 @@ struct wmi_rcp_addba_resp_sent_event {
|
|||
u8 reserved2[2];
|
||||
} __packed;
|
||||
|
||||
/* WMI_TX_STATUS_RING_CFG_DONE_EVENTID */
|
||||
struct wmi_tx_status_ring_cfg_done_event {
|
||||
u8 ring_id;
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[2];
|
||||
__le32 ring_tail_ptr;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RX_STATUS_RING_CFG_DONE_EVENTID */
|
||||
struct wmi_rx_status_ring_cfg_done_event {
|
||||
u8 ring_id;
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[2];
|
||||
__le32 ring_tail_ptr;
|
||||
} __packed;
|
||||
|
||||
/* WMI_CFG_DEF_RX_OFFLOAD_DONE_EVENTID */
|
||||
struct wmi_cfg_def_rx_offload_done_event {
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_TX_DESC_RING_CFG_DONE_EVENTID */
|
||||
struct wmi_tx_desc_ring_cfg_done_event {
|
||||
u8 ring_id;
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[2];
|
||||
__le32 ring_tail_ptr;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RX_DESC_RING_CFG_DONE_EVENTID */
|
||||
struct wmi_rx_desc_ring_cfg_done_event {
|
||||
u8 ring_id;
|
||||
/* wmi_fw_status */
|
||||
u8 status;
|
||||
u8 reserved[2];
|
||||
__le32 ring_tail_ptr;
|
||||
} __packed;
|
||||
|
||||
/* WMI_RCP_ADDBA_REQ_EVENTID */
|
||||
struct wmi_rcp_addba_req_event {
|
||||
/* Used for cid less than 8. For higher cid set
|
||||
|
@ -2047,9 +2190,9 @@ struct wmi_data_port_open_event {
|
|||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
/* WMI_VRING_EN_EVENTID */
|
||||
struct wmi_vring_en_event {
|
||||
u8 vring_index;
|
||||
/* WMI_RING_EN_EVENTID */
|
||||
struct wmi_ring_en_event {
|
||||
u8 ring_index;
|
||||
u8 reserved[3];
|
||||
} __packed;
|
||||
|
||||
|
|
|
@ -1399,6 +1399,7 @@ static int atmel_validate_channel(struct atmel_private *priv, int channel)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int atmel_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct atmel_private *priv = m->private;
|
||||
|
@ -1481,6 +1482,7 @@ static int atmel_proc_show(struct seq_file *m, void *v)
|
|||
seq_printf(m, "Current state:\t\t%s\n", s);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct net_device_ops atmel_netdev_ops = {
|
||||
.ndo_open = atmel_open,
|
||||
|
@ -3675,7 +3677,7 @@ static int probe_atmel_card(struct net_device *dev)
|
|||
atmel_write16(dev, GCR, 0x0060);
|
||||
|
||||
atmel_write16(dev, GCR, 0x0040);
|
||||
mdelay(500);
|
||||
msleep(500);
|
||||
|
||||
if (atmel_read16(dev, MR2) == 0) {
|
||||
/* No stored firmware so load a small stub which just
|
||||
|
|
|
@ -93,6 +93,42 @@ static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
|
|||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
struct brcmf_feat_fwfeat {
|
||||
const char * const fwid;
|
||||
u32 feat_flags;
|
||||
};
|
||||
|
||||
static const struct brcmf_feat_fwfeat brcmf_feat_fwfeat_map[] = {
|
||||
/* brcmfmac43602-pcie.ap.bin from linux-firmware.git commit ea1178515b88 */
|
||||
{ "01-6cb8e269", BIT(BRCMF_FEAT_MONITOR) },
|
||||
/* brcmfmac4366b-pcie.bin from linux-firmware.git commit 52442afee990 */
|
||||
{ "01-c47a91a4", BIT(BRCMF_FEAT_MONITOR) },
|
||||
};
|
||||
|
||||
static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv)
|
||||
{
|
||||
const struct brcmf_feat_fwfeat *e;
|
||||
u32 feat_flags = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(brcmf_feat_fwfeat_map); i++) {
|
||||
e = &brcmf_feat_fwfeat_map[i];
|
||||
if (!strcmp(e->fwid, drv->fwver)) {
|
||||
feat_flags = e->feat_flags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!feat_flags)
|
||||
return;
|
||||
|
||||
for (i = 0; i < BRCMF_FEAT_LAST; i++)
|
||||
if (feat_flags & BIT(i))
|
||||
brcmf_dbg(INFO, "enabling firmware feature: %s\n",
|
||||
brcmf_feat_names[i]);
|
||||
drv->feat_flags |= feat_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* brcmf_feat_iovar_int_get() - determine feature through iovar query.
|
||||
*
|
||||
|
@ -253,6 +289,8 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
|
|||
}
|
||||
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
|
||||
|
||||
brcmf_feat_firmware_overrides(drvr);
|
||||
|
||||
/* set chip related quirks */
|
||||
switch (drvr->bus_if->chip) {
|
||||
case BRCM_CC_43236_CHIP_ID:
|
||||
|
|
|
@ -3419,7 +3419,7 @@ done:
|
|||
|
||||
static void airo_handle_tx(struct airo_info *ai, u16 status)
|
||||
{
|
||||
int i, len = 0, index = -1;
|
||||
int i, index = -1;
|
||||
u16 fid;
|
||||
|
||||
if (test_bit(FLAG_MPI, &ai->flags)) {
|
||||
|
@ -3443,11 +3443,9 @@ static void airo_handle_tx(struct airo_info *ai, u16 status)
|
|||
|
||||
fid = IN4500(ai, TXCOMPLFID);
|
||||
|
||||
for(i = 0; i < MAX_FIDS; i++) {
|
||||
if ((ai->fids[i] & 0xffff) == fid) {
|
||||
len = ai->fids[i] >> 16;
|
||||
for (i = 0; i < MAX_FIDS; i++) {
|
||||
if ((ai->fids[i] & 0xffff) == fid)
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (index != -1) {
|
||||
|
|
|
@ -102,11 +102,8 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
|
|||
|
||||
static int airo_config(struct pcmcia_device *link)
|
||||
{
|
||||
struct local_info *dev;
|
||||
int ret;
|
||||
|
||||
dev = link->priv;
|
||||
|
||||
dev_dbg(&link->dev, "airo_config\n");
|
||||
|
||||
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
|
||||
|
|
|
@ -5112,11 +5112,9 @@ static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv)
|
|||
.host_command_length = ETH_ALEN
|
||||
};
|
||||
int err;
|
||||
int len;
|
||||
|
||||
IPW_DEBUG_HC("DISASSOCIATION_BSSID\n");
|
||||
|
||||
len = ETH_ALEN;
|
||||
/* The Firmware currently ignores the BSSID and just disassociates from
|
||||
* the currently associated AP -- but in the off chance that a future
|
||||
* firmware does use the BSSID provided here, we go ahead and try and
|
||||
|
@ -7723,7 +7721,6 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
|
|||
struct libipw_device *ieee = priv->ieee;
|
||||
struct lib80211_crypt_data *crypt;
|
||||
struct iw_param *param = &wrqu->param;
|
||||
int ret = 0;
|
||||
|
||||
switch (param->flags & IW_AUTH_INDEX) {
|
||||
case IW_AUTH_WPA_VERSION:
|
||||
|
@ -7733,7 +7730,6 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
|
|||
/*
|
||||
* wpa_supplicant will control these internally
|
||||
*/
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
|
||||
case IW_AUTH_TKIP_COUNTERMEASURES:
|
||||
|
@ -7801,9 +7797,6 @@ static int ipw2100_wx_set_mlme(struct net_device *dev,
|
|||
{
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
struct iw_mlme *mlme = (struct iw_mlme *)extra;
|
||||
__le16 reason;
|
||||
|
||||
reason = cpu_to_le16(mlme->reason_code);
|
||||
|
||||
switch (mlme->cmd) {
|
||||
case IW_MLME_DEAUTH:
|
||||
|
|
|
@ -479,7 +479,6 @@ int libipw_wx_get_encode(struct libipw_device *ieee,
|
|||
{
|
||||
struct iw_point *erq = &(wrqu->encoding);
|
||||
int len, key;
|
||||
struct lib80211_crypt_data *crypt;
|
||||
struct libipw_security *sec = &ieee->sec;
|
||||
|
||||
LIBIPW_DEBUG_WX("GET_ENCODE\n");
|
||||
|
@ -492,7 +491,6 @@ int libipw_wx_get_encode(struct libipw_device *ieee,
|
|||
} else
|
||||
key = ieee->crypt_info.tx_keyidx;
|
||||
|
||||
crypt = ieee->crypt_info.crypt[key];
|
||||
erq->flags = key + 1;
|
||||
|
||||
if (!sec->enabled) {
|
||||
|
|
|
@ -476,8 +476,6 @@ il3945_tx_skb(struct il_priv *il,
|
|||
int txq_id = skb_get_queue_mapping(skb);
|
||||
u16 len, idx, hdr_len;
|
||||
u16 firstlen, secondlen;
|
||||
u8 id;
|
||||
u8 unicast;
|
||||
u8 sta_id;
|
||||
u8 tid = 0;
|
||||
__le16 fc;
|
||||
|
@ -496,9 +494,6 @@ il3945_tx_skb(struct il_priv *il,
|
|||
goto drop_unlock;
|
||||
}
|
||||
|
||||
unicast = !is_multicast_ether_addr(hdr->addr1);
|
||||
id = 0;
|
||||
|
||||
fc = hdr->frame_control;
|
||||
|
||||
#ifdef CONFIG_IWLEGACY_DEBUG
|
||||
|
@ -957,10 +952,8 @@ il3945_rx_queue_restock(struct il_priv *il)
|
|||
struct list_head *element;
|
||||
struct il_rx_buf *rxb;
|
||||
unsigned long flags;
|
||||
int write;
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
write = rxq->write & ~0x7;
|
||||
while (il_rx_queue_space(rxq) > 0 && rxq->free_count) {
|
||||
/* Get next free Rx buffer, remove from free list */
|
||||
element = rxq->rx_free.next;
|
||||
|
@ -2725,7 +2718,6 @@ void
|
|||
il3945_post_associate(struct il_priv *il)
|
||||
{
|
||||
int rc = 0;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
|
||||
if (!il->vif || !il->is_open)
|
||||
return;
|
||||
|
@ -2738,8 +2730,6 @@ il3945_post_associate(struct il_priv *il)
|
|||
|
||||
il_scan_cancel_timeout(il, 200);
|
||||
|
||||
conf = &il->hw->conf;
|
||||
|
||||
il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
il3945_commit_rxon(il);
|
||||
|
||||
|
|
|
@ -1634,7 +1634,6 @@ il3945_hw_reg_set_txpower(struct il_priv *il, s8 power)
|
|||
{
|
||||
struct il_channel_info *ch_info;
|
||||
s8 max_power;
|
||||
u8 a_band;
|
||||
u8 i;
|
||||
|
||||
if (il->tx_power_user_lmt == power) {
|
||||
|
@ -1650,7 +1649,6 @@ il3945_hw_reg_set_txpower(struct il_priv *il, s8 power)
|
|||
|
||||
for (i = 0; i < il->channel_count; i++) {
|
||||
ch_info = &il->channel_info[i];
|
||||
a_band = il_is_channel_a_band(ch_info);
|
||||
|
||||
/* find minimum power of all user and regulatory constraints
|
||||
* (does not consider h/w clipping limitations) */
|
||||
|
|
|
@ -1338,15 +1338,12 @@ il4965_accumulative_stats(struct il_priv *il, __le32 * stats)
|
|||
u32 *accum_stats;
|
||||
u32 *delta, *max_delta;
|
||||
struct stats_general_common *general, *accum_general;
|
||||
struct stats_tx *tx, *accum_tx;
|
||||
|
||||
prev_stats = (__le32 *) &il->_4965.stats;
|
||||
accum_stats = (u32 *) &il->_4965.accum_stats;
|
||||
size = sizeof(struct il_notif_stats);
|
||||
general = &il->_4965.stats.general.common;
|
||||
accum_general = &il->_4965.accum_stats.general.common;
|
||||
tx = &il->_4965.stats.tx;
|
||||
accum_tx = &il->_4965.accum_stats.tx;
|
||||
delta = (u32 *) &il->_4965.delta_stats;
|
||||
max_delta = (u32 *) &il->_4965.max_delta;
|
||||
|
||||
|
@ -4784,7 +4781,6 @@ static void
|
|||
il4965_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
{
|
||||
struct il_priv *il = context;
|
||||
struct il_ucode_header *ucode;
|
||||
int err;
|
||||
struct il4965_firmware_pieces pieces;
|
||||
const unsigned int api_max = il->cfg->ucode_api_max;
|
||||
|
@ -4814,8 +4810,6 @@ il4965_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
}
|
||||
|
||||
/* Data from ucode file: header followed by uCode images */
|
||||
ucode = (struct il_ucode_header *)ucode_raw->data;
|
||||
|
||||
err = il4965_load_firmware(il, ucode_raw, &pieces);
|
||||
|
||||
if (err)
|
||||
|
|
|
@ -7,13 +7,13 @@ iwlwifi-objs += iwl-debug.o
|
|||
iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
|
||||
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
|
||||
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
|
||||
iwlwifi-objs += pcie/ctxt-info.o pcie/trans-gen2.o pcie/tx-gen2.o
|
||||
iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-gen3.o
|
||||
iwlwifi-objs += pcie/trans-gen2.o pcie/tx-gen2.o
|
||||
iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o
|
||||
iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o
|
||||
iwlwifi-objs += iwl-trans.o
|
||||
iwlwifi-objs += fw/notif-wait.o
|
||||
iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o fw/dbg.o
|
||||
iwlwifi-$(CONFIG_IWLMVM) += fw/common_rx.o
|
||||
iwlwifi-$(CONFIG_ACPI) += fw/acpi.o
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += fw/debugfs.o
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
static const struct iwl_base_params iwl2000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.max_tfd_queue_size = 256,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
|
@ -76,6 +77,7 @@ static const struct iwl_base_params iwl2000_base_params = {
|
|||
static const struct iwl_base_params iwl2030_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.max_tfd_queue_size = 256,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
#define IWL_22000_UCODE_API_MAX 38
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MIN 24
|
||||
#define IWL_22000_UCODE_API_MIN 39
|
||||
|
||||
/* NVM versions */
|
||||
#define IWL_22000_NVM_VERSION 0x0a1d
|
||||
|
@ -73,29 +73,48 @@
|
|||
#define IWL_22000_SMEM_OFFSET 0x400000
|
||||
#define IWL_22000_SMEM_LEN 0xD0000
|
||||
|
||||
#define IWL_22000_JF_FW_PRE "iwlwifi-Qu-a0-jf-b0-"
|
||||
#define IWL_22000_HR_FW_PRE "iwlwifi-Qu-a0-hr-a0-"
|
||||
#define IWL_22000_HR_CDB_FW_PRE "iwlwifi-QuIcp-z0-hrcdb-a0-"
|
||||
#define IWL_22000_HR_F0_FW_PRE "iwlwifi-QuQnj-f0-hr-a0-"
|
||||
#define IWL_22000_JF_B0_FW_PRE "iwlwifi-QuQnj-a0-jf-b0-"
|
||||
#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-"
|
||||
#define IWL_22000_JF_FW_PRE "iwlwifi-Qu-a0-jf-b0-"
|
||||
#define IWL_22000_HR_FW_PRE "iwlwifi-Qu-a0-hr-a0-"
|
||||
#define IWL_22000_HR_CDB_FW_PRE "iwlwifi-QuIcp-z0-hrcdb-a0-"
|
||||
#define IWL_22000_HR_A_F0_FW_PRE "iwlwifi-QuQnj-f0-hr-a0-"
|
||||
#define IWL_22000_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
|
||||
#define IWL_22000_JF_B0_FW_PRE "iwlwifi-QuQnj-a0-jf-b0-"
|
||||
#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-"
|
||||
#define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-"
|
||||
|
||||
#define IWL_22000_HR_MODULE_FIRMWARE(api) \
|
||||
IWL_22000_HR_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_22000_JF_MODULE_FIRMWARE(api) \
|
||||
IWL_22000_JF_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_22000_HR_F0_QNJ_MODULE_FIRMWARE(api) \
|
||||
IWL_22000_HR_F0_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(api) \
|
||||
IWL_22000_HR_A_F0_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \
|
||||
IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(api) \
|
||||
IWL_22000_JF_B0_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \
|
||||
IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \
|
||||
IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
#define NVM_HW_SECTION_NUM_FAMILY_22000 10
|
||||
|
||||
static const struct iwl_base_params iwl_22000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_22000,
|
||||
.num_of_queues = 512,
|
||||
.max_tfd_queue_size = 256,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
.max_event_log_size = 512,
|
||||
.shadow_reg_enable = true,
|
||||
.pcie_l1_allowed = true,
|
||||
};
|
||||
|
||||
static const struct iwl_base_params iwl_22560_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_22000,
|
||||
.num_of_queues = 512,
|
||||
.max_tfd_queue_size = 65536,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
|
@ -110,11 +129,9 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
|||
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ),
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_22000 \
|
||||
#define IWL_DEVICE_22000_COMMON \
|
||||
.ucode_api_max = IWL_22000_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL_22000_UCODE_API_MIN, \
|
||||
.device_family = IWL_DEVICE_FAMILY_22000, \
|
||||
.base_params = &iwl_22000_base_params, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_22000, \
|
||||
.non_shared_ant = ANT_A, \
|
||||
|
@ -129,6 +146,10 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
|||
.mq_rx_supported = true, \
|
||||
.vht_mu_mimo_supported = true, \
|
||||
.mac_addr_from_csr = true, \
|
||||
.ht_params = &iwl_22000_ht_params, \
|
||||
.nvm_ver = IWL_22000_NVM_VERSION, \
|
||||
.nvm_calib_ver = IWL_22000_TX_POWER_VERSION, \
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
|
||||
.use_tfh = true, \
|
||||
.rf_id = true, \
|
||||
.gen2 = true, \
|
||||
|
@ -136,86 +157,114 @@ static const struct iwl_ht_params iwl_22000_ht_params = {
|
|||
.dbgc_supported = true, \
|
||||
.min_umac_error_event_table = 0x400000
|
||||
|
||||
#define IWL_DEVICE_22500 \
|
||||
IWL_DEVICE_22000_COMMON, \
|
||||
.device_family = IWL_DEVICE_FAMILY_22000, \
|
||||
.base_params = &iwl_22000_base_params, \
|
||||
.csr = &iwl_csr_v1
|
||||
|
||||
#define IWL_DEVICE_22560 \
|
||||
IWL_DEVICE_22000_COMMON, \
|
||||
.device_family = IWL_DEVICE_FAMILY_22560, \
|
||||
.base_params = &iwl_22560_base_params, \
|
||||
.csr = &iwl_csr_v2
|
||||
|
||||
const struct iwl_cfg iwl22000_2ac_cfg_hr = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 22000",
|
||||
.fw_name_pre = IWL_22000_HR_FW_PRE,
|
||||
IWL_DEVICE_22000,
|
||||
.csr = &iwl_csr_v1,
|
||||
.ht_params = &iwl_22000_ht_params,
|
||||
.nvm_ver = IWL_22000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL_22000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
IWL_DEVICE_22500,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 22000",
|
||||
.fw_name_pre = IWL_22000_HR_CDB_FW_PRE,
|
||||
IWL_DEVICE_22000,
|
||||
.csr = &iwl_csr_v1,
|
||||
.ht_params = &iwl_22000_ht_params,
|
||||
.nvm_ver = IWL_22000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL_22000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
IWL_DEVICE_22500,
|
||||
.cdb = true,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl22000_2ac_cfg_jf = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 22000",
|
||||
.fw_name_pre = IWL_22000_JF_FW_PRE,
|
||||
IWL_DEVICE_22000,
|
||||
.csr = &iwl_csr_v1,
|
||||
.ht_params = &iwl_22000_ht_params,
|
||||
.nvm_ver = IWL_22000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL_22000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
IWL_DEVICE_22500,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl22000_2ax_cfg_hr = {
|
||||
.name = "Intel(R) Dual Band Wireless AX 22000",
|
||||
.fw_name_pre = IWL_22000_HR_FW_PRE,
|
||||
IWL_DEVICE_22000,
|
||||
.csr = &iwl_csr_v1,
|
||||
.ht_params = &iwl_22000_ht_params,
|
||||
.nvm_ver = IWL_22000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL_22000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_f0 = {
|
||||
const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0 = {
|
||||
.name = "Intel(R) Dual Band Wireless AX 22000",
|
||||
.fw_name_pre = IWL_22000_HR_F0_FW_PRE,
|
||||
IWL_DEVICE_22000,
|
||||
.csr = &iwl_csr_v1,
|
||||
.ht_params = &iwl_22000_ht_params,
|
||||
.nvm_ver = IWL_22000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL_22000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
.fw_name_pre = IWL_22000_HR_A_F0_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = {
|
||||
.name = "Intel(R) Dual Band Wireless AX 22000",
|
||||
.fw_name_pre = IWL_22000_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0 = {
|
||||
.name = "Intel(R) Dual Band Wireless AX 22000",
|
||||
.fw_name_pre = IWL_22000_JF_B0_FW_PRE,
|
||||
IWL_DEVICE_22000,
|
||||
.csr = &iwl_csr_v1,
|
||||
.ht_params = &iwl_22000_ht_params,
|
||||
.nvm_ver = IWL_22000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL_22000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = {
|
||||
.name = "Intel(R) Dual Band Wireless AX 22000",
|
||||
.fw_name_pre = IWL_22000_HR_A0_FW_PRE,
|
||||
IWL_DEVICE_22000,
|
||||
.csr = &iwl_csr_v1,
|
||||
.ht_params = &iwl_22000_ht_params,
|
||||
.nvm_ver = IWL_22000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL_22000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl22560_2ax_cfg_su_cdb = {
|
||||
.name = "Intel(R) Dual Band Wireless AX 22560",
|
||||
.fw_name_pre = IWL_22000_SU_Z0_FW_PRE,
|
||||
IWL_DEVICE_22560,
|
||||
.cdb = true,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_22000_HR_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
static const struct iwl_base_params iwl5000_base_params = {
|
||||
.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.max_tfd_queue_size = 256,
|
||||
.pll_cfg = true,
|
||||
.led_compensation = 51,
|
||||
.wd_timeout = IWL_WATCHDOG_DISABLED,
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
static const struct iwl_base_params iwl6000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.max_tfd_queue_size = 256,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
|
@ -84,6 +85,7 @@ static const struct iwl_base_params iwl6000_base_params = {
|
|||
static const struct iwl_base_params iwl6050_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.max_tfd_queue_size = 256,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
|
@ -96,6 +98,7 @@ static const struct iwl_base_params iwl6050_base_params = {
|
|||
static const struct iwl_base_params iwl6000_g2_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.max_tfd_queue_size = 256,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
|
|
|
@ -123,6 +123,7 @@
|
|||
static const struct iwl_base_params iwl7000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_7000,
|
||||
.num_of_queues = 31,
|
||||
.max_tfd_queue_size = 256,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
static const struct iwl_base_params iwl8000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
|
||||
.num_of_queues = 31,
|
||||
.max_tfd_queue_size = 256,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
static const struct iwl_base_params iwl9000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_9000,
|
||||
.num_of_queues = 31,
|
||||
.max_tfd_queue_size = 256,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -30,6 +31,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -187,20 +189,4 @@ struct iwl_card_state_notif {
|
|||
__le32 flags;
|
||||
} __packed; /* CARD_STATE_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_fseq_ver_mismatch_nty - Notification about version
|
||||
*
|
||||
* This notification does not have a direct impact on the init flow.
|
||||
* It means that another core (not WiFi) has initiated the FSEQ flow
|
||||
* and updated the FSEQ version. The driver only prints an error when
|
||||
* this occurs.
|
||||
*
|
||||
* @aux_read_fseq_ver: auxiliary read FSEQ version
|
||||
* @wifi_fseq_ver: FSEQ version (embedded in WiFi)
|
||||
*/
|
||||
struct iwl_fseq_ver_mismatch_ntf {
|
||||
__le32 aux_read_fseq_ver;
|
||||
__le32 wifi_fseq_ver;
|
||||
} __packed; /* FSEQ_VER_MISMATCH_NTFY_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_alive_h__ */
|
||||
|
|
|
@ -193,7 +193,8 @@ enum iwl_legacy_cmds {
|
|||
FW_GET_ITEM_CMD = 0x1a,
|
||||
|
||||
/**
|
||||
* @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2,
|
||||
* @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or
|
||||
* &struct iwl_tx_cmd_gen3,
|
||||
* response in &struct iwl_mvm_tx_resp or
|
||||
* &struct iwl_mvm_tx_resp_v3
|
||||
*/
|
||||
|
@ -646,13 +647,6 @@ enum iwl_system_subcmd_ids {
|
|||
* @INIT_EXTENDED_CFG_CMD: &struct iwl_init_extended_cfg_cmd
|
||||
*/
|
||||
INIT_EXTENDED_CFG_CMD = 0x03,
|
||||
|
||||
/**
|
||||
* @FSEQ_VER_MISMATCH_NTF: Notification about fseq version
|
||||
* mismatch during init. The format is specified in
|
||||
* &struct iwl_fseq_ver_mismatch_ntf.
|
||||
*/
|
||||
FSEQ_VER_MISMATCH_NTF = 0xFF,
|
||||
};
|
||||
|
||||
#endif /* __iwl_fw_api_commands_h__ */
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -30,6 +31,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -82,6 +84,16 @@ enum iwl_data_path_subcmd_ids {
|
|||
*/
|
||||
TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
|
||||
|
||||
/**
|
||||
* @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd
|
||||
*/
|
||||
STA_HE_CTXT_CMD = 0x7,
|
||||
|
||||
/**
|
||||
* @RFH_QUEUE_CONFIG_CMD: &struct iwl_rfh_queue_config
|
||||
*/
|
||||
RFH_QUEUE_CONFIG_CMD = 0xD,
|
||||
|
||||
/**
|
||||
* @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd
|
||||
*/
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -28,6 +29,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -279,6 +281,10 @@ enum iwl_mac_filter_flags {
|
|||
MAC_FILTER_OUT_BCAST = BIT(8),
|
||||
MAC_FILTER_IN_CRC32 = BIT(11),
|
||||
MAC_FILTER_IN_PROBE_REQUEST = BIT(12),
|
||||
/**
|
||||
* @MAC_FILTER_IN_11AX: mark BSS as supporting 802.11ax
|
||||
*/
|
||||
MAC_FILTER_IN_11AX = BIT(14),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -406,4 +412,170 @@ struct iwl_missed_beacons_notif {
|
|||
__le32 num_recvd_beacons;
|
||||
} __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_he_backoff_conf - used for backoff configuration
|
||||
* Per each trigger-based AC, (set by MU EDCA Parameter set info-element)
|
||||
* used for backoff configuration of TXF5..TXF8 trigger based.
|
||||
* The MU-TIMER is reloaded w/ MU_TIME each time a frame from the AC is sent via
|
||||
* trigger-based TX.
|
||||
* @cwmin: CW min
|
||||
* @cwmax: CW max
|
||||
* @aifsn: AIFSN
|
||||
* AIFSN=0, means that no backoff from the specified TRIG-BASED AC is
|
||||
* allowed till the MU-TIMER is 0
|
||||
* @mu_time: MU time in 8TU units
|
||||
*/
|
||||
struct iwl_he_backoff_conf {
|
||||
__le16 cwmin;
|
||||
__le16 cwmax;
|
||||
__le16 aifsn;
|
||||
__le16 mu_time;
|
||||
} __packed; /* AC_QOS_DOT11AX_API_S */
|
||||
|
||||
#define MAX_HE_SUPP_NSS 2
|
||||
#define MAX_HE_CHANNEL_BW_INDX 4
|
||||
|
||||
/**
|
||||
* struct iwl_he_pkt_ext - QAM thresholds
|
||||
* The required PPE is set via HE Capabilities IE, per Nss x BW x MCS
|
||||
* The IE is organized in the following way:
|
||||
* Support for Nss x BW (or RU) matrix:
|
||||
* (0=SISO, 1=MIMO2) x (0-20MHz, 1-40MHz, 2-80MHz, 3-160MHz)
|
||||
* Each entry contains 2 QAM thresholds for 8us and 16us:
|
||||
* 0=BPSK, 1=QPSK, 2=16QAM, 3=64QAM, 4=256QAM, 5=1024QAM, 6/7=RES
|
||||
* i.e. QAM_th1 < QAM_th2 such if TX uses QAM_tx:
|
||||
* QAM_tx < QAM_th1 --> PPE=0us
|
||||
* QAM_th1 <= QAM_tx < QAM_th2 --> PPE=8us
|
||||
* QAM_th2 <= QAM_tx --> PPE=16us
|
||||
* @pkt_ext_qam_th: QAM thresholds
|
||||
* For each Nss/Bw define 2 QAM thrsholds (0..5)
|
||||
* For rates below the low_th, no need for PPE
|
||||
* For rates between low_th and high_th, need 8us PPE
|
||||
* For rates equal or higher then the high_th, need 16us PPE
|
||||
* Nss (0-siso, 1-mimo2) x BW (0-20MHz, 1-40MHz, 2-80MHz, 3-160MHz) x
|
||||
* (0-low_th, 1-high_th)
|
||||
*/
|
||||
struct iwl_he_pkt_ext {
|
||||
u8 pkt_ext_qam_th[MAX_HE_SUPP_NSS][MAX_HE_CHANNEL_BW_INDX][2];
|
||||
} __packed; /* PKT_EXT_DOT11AX_API_S */
|
||||
|
||||
/**
|
||||
* enum iwl_he_sta_ctxt_flags - HE STA context flags
|
||||
* @STA_CTXT_HE_REF_BSSID_VALID: ref bssid addr valid (for receiving specific
|
||||
* control frames such as TRIG, NDPA, BACK)
|
||||
* @STA_CTXT_HE_BSS_COLOR_DIS: BSS color disable, don't use the BSS
|
||||
* color for RX filter but use MAC header
|
||||
* @STA_CTXT_HE_PARTIAL_BSS_COLOR: partial BSS color allocation
|
||||
* @STA_CTXT_HE_32BIT_BA_BITMAP: indicates the receiver supports BA bitmap
|
||||
* of 32-bits
|
||||
* @STA_CTXT_HE_PACKET_EXT: indicates that the packet-extension info is valid
|
||||
* and should be used
|
||||
* @STA_CTXT_HE_TRIG_RND_ALLOC: indicates that trigger based random allocation
|
||||
* is enabled according to UORA element existence
|
||||
* @STA_CTXT_HE_CONST_TRIG_RND_ALLOC: used for AV testing
|
||||
* @STA_CTXT_HE_ACK_ENABLED: indicates that the AP supports receiving ACK-
|
||||
* enabled AGG, i.e. both BACK and non-BACK frames in a single AGG
|
||||
* @STA_CTXT_HE_MU_EDCA_CW: indicates that there is an element of MU EDCA
|
||||
* parameter set, i.e. the backoff counters for trig-based ACs
|
||||
*/
|
||||
enum iwl_he_sta_ctxt_flags {
|
||||
STA_CTXT_HE_REF_BSSID_VALID = BIT(4),
|
||||
STA_CTXT_HE_BSS_COLOR_DIS = BIT(5),
|
||||
STA_CTXT_HE_PARTIAL_BSS_COLOR = BIT(6),
|
||||
STA_CTXT_HE_32BIT_BA_BITMAP = BIT(7),
|
||||
STA_CTXT_HE_PACKET_EXT = BIT(8),
|
||||
STA_CTXT_HE_TRIG_RND_ALLOC = BIT(9),
|
||||
STA_CTXT_HE_CONST_TRIG_RND_ALLOC = BIT(10),
|
||||
STA_CTXT_HE_ACK_ENABLED = BIT(11),
|
||||
STA_CTXT_HE_MU_EDCA_CW = BIT(12),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_he_htc_flags - HE HTC support flags
|
||||
* @IWL_HE_HTC_SUPPORT: HE-HTC support
|
||||
* @IWL_HE_HTC_UL_MU_RESP_SCHED: HE UL MU response schedule
|
||||
* support via A-control field
|
||||
* @IWL_HE_HTC_BSR_SUPP: BSR support in A-control field
|
||||
* @IWL_HE_HTC_OMI_SUPP: A-OMI support in A-control field
|
||||
* @IWL_HE_HTC_BQR_SUPP: A-BQR support in A-control field
|
||||
*/
|
||||
enum iwl_he_htc_flags {
|
||||
IWL_HE_HTC_SUPPORT = BIT(0),
|
||||
IWL_HE_HTC_UL_MU_RESP_SCHED = BIT(3),
|
||||
IWL_HE_HTC_BSR_SUPP = BIT(4),
|
||||
IWL_HE_HTC_OMI_SUPP = BIT(5),
|
||||
IWL_HE_HTC_BQR_SUPP = BIT(6),
|
||||
};
|
||||
|
||||
/*
|
||||
* @IWL_HE_HTC_LINK_ADAP_NO_FEEDBACK: the STA does not provide HE MFB
|
||||
* @IWL_HE_HTC_LINK_ADAP_UNSOLICITED: the STA provides only unsolicited HE MFB
|
||||
* @IWL_HE_HTC_LINK_ADAP_BOTH: the STA is capable of providing HE MFB in
|
||||
* response to HE MRQ and if the STA provides unsolicited HE MFB
|
||||
*/
|
||||
#define IWL_HE_HTC_LINK_ADAP_POS (1)
|
||||
#define IWL_HE_HTC_LINK_ADAP_NO_FEEDBACK (0)
|
||||
#define IWL_HE_HTC_LINK_ADAP_UNSOLICITED (2 << IWL_HE_HTC_LINK_ADAP_POS)
|
||||
#define IWL_HE_HTC_LINK_ADAP_BOTH (3 << IWL_HE_HTC_LINK_ADAP_POS)
|
||||
|
||||
/**
|
||||
* struct iwl_he_sta_context_cmd - configure FW to work with HE AP
|
||||
* @sta_id: STA id
|
||||
* @tid_limit: max num of TIDs in TX HE-SU multi-TID agg
|
||||
* 0 - bad value, 1 - multi-tid not supported, 2..8 - tid limit
|
||||
* @reserved1: reserved byte for future use
|
||||
* @reserved2: reserved byte for future use
|
||||
* @flags: see %iwl_11ax_sta_ctxt_flags
|
||||
* @ref_bssid_addr: reference BSSID used by the AP
|
||||
* @reserved0: reserved 2 bytes for aligning the ref_bssid_addr field to 8 bytes
|
||||
* @htc_flags: which features are supported in HTC
|
||||
* @frag_flags: frag support in A-MSDU
|
||||
* @frag_level: frag support level
|
||||
* @frag_max_num: max num of "open" MSDUs in the receiver (in power of 2)
|
||||
* @frag_min_size: min frag size (except last frag)
|
||||
* @pkt_ext: optional, exists according to PPE-present bit in the HE-PHY capa
|
||||
* @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
|
||||
* @htc_trig_based_pkt_ext: default PE in 4us units
|
||||
* @frame_time_rts_th: HE duration RTS threshold, in units of 32us
|
||||
* @rand_alloc_ecwmin: random CWmin = 2**ECWmin-1
|
||||
* @rand_alloc_ecwmax: random CWmax = 2**ECWmax-1
|
||||
* @reserved3: reserved byte for future use
|
||||
* @trig_based_txf: MU EDCA Parameter set for the trigger based traffic queues
|
||||
*/
|
||||
struct iwl_he_sta_context_cmd {
|
||||
u8 sta_id;
|
||||
u8 tid_limit;
|
||||
u8 reserved1;
|
||||
u8 reserved2;
|
||||
__le32 flags;
|
||||
|
||||
/* The below fields are set via Multiple BSSID IE */
|
||||
u8 ref_bssid_addr[6];
|
||||
__le16 reserved0;
|
||||
|
||||
/* The below fields are set via HE-capabilities IE */
|
||||
__le32 htc_flags;
|
||||
|
||||
u8 frag_flags;
|
||||
u8 frag_level;
|
||||
u8 frag_max_num;
|
||||
u8 frag_min_size;
|
||||
|
||||
/* The below fields are set via PPE thresholds element */
|
||||
struct iwl_he_pkt_ext pkt_ext;
|
||||
|
||||
/* The below fields are set via HE-Operation IE */
|
||||
u8 bss_color;
|
||||
u8 htc_trig_based_pkt_ext;
|
||||
__le16 frame_time_rts_th;
|
||||
|
||||
/* Random access parameter set (i.e. RAPS) */
|
||||
u8 rand_alloc_ecwmin;
|
||||
u8 rand_alloc_ecwmax;
|
||||
__le16 reserved3;
|
||||
|
||||
/* The below fields are set via MU EDCA parameter set element */
|
||||
struct iwl_he_backoff_conf trig_based_txf[AC_NUM];
|
||||
} __packed; /* STA_CONTEXT_DOT11AX_API_S */
|
||||
|
||||
#endif /* __iwl_fw_api_mac_h__ */
|
||||
|
|
|
@ -195,7 +195,6 @@ struct iwl_nvm_get_info_general {
|
|||
* @NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED: true if 5.2 band enabled
|
||||
* @NVM_MAC_SKU_FLAGS_802_11N_ENABLED: true if 11n enabled
|
||||
* @NVM_MAC_SKU_FLAGS_802_11AC_ENABLED: true if 11ac enabled
|
||||
* @NVM_MAC_SKU_FLAGS_802_11AX_ENABLED: true if 11ax enabled
|
||||
* @NVM_MAC_SKU_FLAGS_MIMO_DISABLED: true if MIMO disabled
|
||||
* @NVM_MAC_SKU_FLAGS_WAPI_ENABLED: true if WAPI enabled
|
||||
* @NVM_MAC_SKU_FLAGS_REG_CHECK_ENABLED: true if regulatory checker enabled
|
||||
|
@ -206,6 +205,9 @@ enum iwl_nvm_mac_sku_flags {
|
|||
NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED = BIT(1),
|
||||
NVM_MAC_SKU_FLAGS_802_11N_ENABLED = BIT(2),
|
||||
NVM_MAC_SKU_FLAGS_802_11AC_ENABLED = BIT(3),
|
||||
/**
|
||||
* @NVM_MAC_SKU_FLAGS_802_11AX_ENABLED: true if 11ax enabled
|
||||
*/
|
||||
NVM_MAC_SKU_FLAGS_802_11AX_ENABLED = BIT(4),
|
||||
NVM_MAC_SKU_FLAGS_MIMO_DISABLED = BIT(5),
|
||||
NVM_MAC_SKU_FLAGS_WAPI_ENABLED = BIT(8),
|
||||
|
|
|
@ -314,8 +314,11 @@ enum {
|
|||
IWL_RATE_MCS_8_INDEX,
|
||||
IWL_RATE_MCS_9_INDEX,
|
||||
IWL_LAST_VHT_RATE = IWL_RATE_MCS_9_INDEX,
|
||||
IWL_RATE_MCS_10_INDEX,
|
||||
IWL_RATE_MCS_11_INDEX,
|
||||
IWL_LAST_HE_RATE = IWL_RATE_MCS_11_INDEX,
|
||||
IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1,
|
||||
IWL_RATE_COUNT = IWL_LAST_VHT_RATE + 1,
|
||||
IWL_RATE_COUNT = IWL_LAST_HE_RATE + 1,
|
||||
};
|
||||
|
||||
#define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX)
|
||||
|
@ -440,8 +443,8 @@ enum {
|
|||
#define RATE_LEGACY_RATE_MSK 0xff
|
||||
|
||||
/* Bit 10 - OFDM HE */
|
||||
#define RATE_MCS_OFDM_HE_POS 10
|
||||
#define RATE_MCS_OFDM_HE_MSK BIT(RATE_MCS_OFDM_HE_POS)
|
||||
#define RATE_MCS_HE_POS 10
|
||||
#define RATE_MCS_HE_MSK BIT(RATE_MCS_HE_POS)
|
||||
|
||||
/*
|
||||
* Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz
|
||||
|
@ -482,15 +485,33 @@ enum {
|
|||
#define RATE_MCS_BF_MSK (1 << RATE_MCS_BF_POS)
|
||||
|
||||
/*
|
||||
* Bit 20-21: HE guard interval and LTF type.
|
||||
* (0) 1xLTF+1.6us, (1) 2xLTF+0.8us,
|
||||
* (2) 2xLTF+1.6us, (3) 4xLTF+3.2us
|
||||
* Bit 20-21: HE LTF type and guard interval
|
||||
* HE (ext) SU:
|
||||
* 0 1xLTF+0.8us
|
||||
* 1 2xLTF+0.8us
|
||||
* 2 2xLTF+1.6us
|
||||
* 3 & SGI (bit 13) clear 4xLTF+3.2us
|
||||
* 3 & SGI (bit 13) set 4xLTF+0.8us
|
||||
* HE MU:
|
||||
* 0 4xLTF+0.8us
|
||||
* 1 2xLTF+0.8us
|
||||
* 2 2xLTF+1.6us
|
||||
* 3 4xLTF+3.2us
|
||||
* HE TRIG:
|
||||
* 0 1xLTF+1.6us
|
||||
* 1 2xLTF+1.6us
|
||||
* 2 4xLTF+3.2us
|
||||
* 3 (does not occur)
|
||||
*/
|
||||
#define RATE_MCS_HE_GI_LTF_POS 20
|
||||
#define RATE_MCS_HE_GI_LTF_MSK (3 << RATE_MCS_HE_GI_LTF_POS)
|
||||
|
||||
/* Bit 22-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */
|
||||
#define RATE_MCS_HE_TYPE_POS 22
|
||||
#define RATE_MCS_HE_TYPE_SU (0 << RATE_MCS_HE_TYPE_POS)
|
||||
#define RATE_MCS_HE_TYPE_EXT_SU (1 << RATE_MCS_HE_TYPE_POS)
|
||||
#define RATE_MCS_HE_TYPE_MU (2 << RATE_MCS_HE_TYPE_POS)
|
||||
#define RATE_MCS_HE_TYPE_TRIG (3 << RATE_MCS_HE_TYPE_POS)
|
||||
#define RATE_MCS_HE_TYPE_MSK (3 << RATE_MCS_HE_TYPE_POS)
|
||||
|
||||
/* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */
|
||||
|
@ -501,6 +522,9 @@ enum {
|
|||
#define RATE_MCS_LDPC_POS 27
|
||||
#define RATE_MCS_LDPC_MSK (1 << RATE_MCS_LDPC_POS)
|
||||
|
||||
/* Bit 28: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */
|
||||
#define RATE_MCS_HE_106T_POS 28
|
||||
#define RATE_MCS_HE_106T_MSK (1 << RATE_MCS_HE_106T_POS)
|
||||
|
||||
/* Link Quality definitions */
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -30,6 +31,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -343,6 +345,169 @@ enum iwl_rx_mpdu_mac_info {
|
|||
IWL_RX_MPDU_PHY_PHY_INDEX_MASK = 0xf0,
|
||||
};
|
||||
|
||||
/*
|
||||
* enum iwl_rx_he_phy - HE PHY data
|
||||
*/
|
||||
enum iwl_rx_he_phy {
|
||||
IWL_RX_HE_PHY_BEAM_CHNG = BIT(0),
|
||||
IWL_RX_HE_PHY_UPLINK = BIT(1),
|
||||
IWL_RX_HE_PHY_BSS_COLOR_MASK = 0xfc,
|
||||
IWL_RX_HE_PHY_SPATIAL_REUSE_MASK = 0xf00,
|
||||
IWL_RX_HE_PHY_SU_EXT_BW10 = BIT(12),
|
||||
IWL_RX_HE_PHY_TXOP_DUR_MASK = 0xfe000,
|
||||
IWL_RX_HE_PHY_LDPC_EXT_SYM = BIT(20),
|
||||
IWL_RX_HE_PHY_PRE_FEC_PAD_MASK = 0x600000,
|
||||
IWL_RX_HE_PHY_PE_DISAMBIG = BIT(23),
|
||||
IWL_RX_HE_PHY_DOPPLER = BIT(24),
|
||||
/* 6 bits reserved */
|
||||
IWL_RX_HE_PHY_DELIM_EOF = BIT(31),
|
||||
|
||||
/* second dword - MU data */
|
||||
IWL_RX_HE_PHY_SIGB_COMPRESSION = BIT_ULL(32 + 0),
|
||||
IWL_RX_HE_PHY_SIBG_SYM_OR_USER_NUM_MASK = 0x1e00000000ULL,
|
||||
IWL_RX_HE_PHY_HE_LTF_NUM_MASK = 0xe000000000ULL,
|
||||
IWL_RX_HE_PHY_RU_ALLOC_SEC80 = BIT_ULL(32 + 8),
|
||||
/* trigger encoded */
|
||||
IWL_RX_HE_PHY_RU_ALLOC_MASK = 0xfe0000000000ULL,
|
||||
IWL_RX_HE_PHY_SIGB_MCS_MASK = 0xf000000000000ULL,
|
||||
/* 1 bit reserved */
|
||||
IWL_RX_HE_PHY_SIGB_DCM = BIT_ULL(32 + 21),
|
||||
IWL_RX_HE_PHY_PREAMBLE_PUNC_TYPE_MASK = 0xc0000000000000ULL,
|
||||
/* 8 bits reserved */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_rx_mpdu_desc_v1 - RX MPDU descriptor
|
||||
*/
|
||||
struct iwl_rx_mpdu_desc_v1 {
|
||||
/* DW7 - carries rss_hash only when rpa_en == 1 */
|
||||
/**
|
||||
* @rss_hash: RSS hash value
|
||||
*/
|
||||
__le32 rss_hash;
|
||||
/* DW8 - carries filter_match only when rpa_en == 1 */
|
||||
/**
|
||||
* @filter_match: filter match value
|
||||
*/
|
||||
__le32 filter_match;
|
||||
/* DW9 */
|
||||
/**
|
||||
* @rate_n_flags: RX rate/flags encoding
|
||||
*/
|
||||
__le32 rate_n_flags;
|
||||
/* DW10 */
|
||||
/**
|
||||
* @energy_a: energy chain A
|
||||
*/
|
||||
u8 energy_a;
|
||||
/**
|
||||
* @energy_b: energy chain B
|
||||
*/
|
||||
u8 energy_b;
|
||||
/**
|
||||
* @channel: channel number
|
||||
*/
|
||||
u8 channel;
|
||||
/**
|
||||
* @mac_context: MAC context mask
|
||||
*/
|
||||
u8 mac_context;
|
||||
/* DW11 */
|
||||
/**
|
||||
* @gp2_on_air_rise: GP2 timer value on air rise (INA)
|
||||
*/
|
||||
__le32 gp2_on_air_rise;
|
||||
/* DW12 & DW13 */
|
||||
union {
|
||||
/**
|
||||
* @tsf_on_air_rise:
|
||||
* TSF value on air rise (INA), only valid if
|
||||
* %IWL_RX_MPDU_PHY_TSF_OVERLOAD isn't set
|
||||
*/
|
||||
__le64 tsf_on_air_rise;
|
||||
/**
|
||||
* @he_phy_data:
|
||||
* HE PHY data, see &enum iwl_rx_he_phy, valid
|
||||
* only if %IWL_RX_MPDU_PHY_TSF_OVERLOAD is set
|
||||
*/
|
||||
__le64 he_phy_data;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_rx_mpdu_desc_v3 - RX MPDU descriptor
|
||||
*/
|
||||
struct iwl_rx_mpdu_desc_v3 {
|
||||
/* DW7 - carries filter_match only when rpa_en == 1 */
|
||||
/**
|
||||
* @filter_match: filter match value
|
||||
*/
|
||||
__le32 filter_match;
|
||||
/* DW8 - carries rss_hash only when rpa_en == 1 */
|
||||
/**
|
||||
* @rss_hash: RSS hash value
|
||||
*/
|
||||
__le32 rss_hash;
|
||||
/* DW9 */
|
||||
/**
|
||||
* @partial_hash: 31:0 ip/tcp header hash
|
||||
* w/o some fields (such as IP SRC addr)
|
||||
*/
|
||||
__le32 partial_hash;
|
||||
/* DW10 */
|
||||
/**
|
||||
* @raw_xsum: raw xsum value
|
||||
*/
|
||||
__le32 raw_xsum;
|
||||
/* DW11 */
|
||||
/**
|
||||
* @rate_n_flags: RX rate/flags encoding
|
||||
*/
|
||||
__le32 rate_n_flags;
|
||||
/* DW12 */
|
||||
/**
|
||||
* @energy_a: energy chain A
|
||||
*/
|
||||
u8 energy_a;
|
||||
/**
|
||||
* @energy_b: energy chain B
|
||||
*/
|
||||
u8 energy_b;
|
||||
/**
|
||||
* @channel: channel number
|
||||
*/
|
||||
u8 channel;
|
||||
/**
|
||||
* @mac_context: MAC context mask
|
||||
*/
|
||||
u8 mac_context;
|
||||
/* DW13 */
|
||||
/**
|
||||
* @gp2_on_air_rise: GP2 timer value on air rise (INA)
|
||||
*/
|
||||
__le32 gp2_on_air_rise;
|
||||
/* DW14 & DW15 */
|
||||
union {
|
||||
/**
|
||||
* @tsf_on_air_rise:
|
||||
* TSF value on air rise (INA), only valid if
|
||||
* %IWL_RX_MPDU_PHY_TSF_OVERLOAD isn't set
|
||||
*/
|
||||
__le64 tsf_on_air_rise;
|
||||
/**
|
||||
* @he_phy_data:
|
||||
* HE PHY data, see &enum iwl_rx_he_phy, valid
|
||||
* only if %IWL_RX_MPDU_PHY_TSF_OVERLOAD is set
|
||||
*/
|
||||
__le64 he_phy_data;
|
||||
};
|
||||
/* DW16 & DW17 */
|
||||
/**
|
||||
* @reserved: reserved
|
||||
*/
|
||||
__le32 reserved[2];
|
||||
} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */
|
||||
|
||||
/**
|
||||
* struct iwl_rx_mpdu_desc - RX MPDU descriptor
|
||||
*/
|
||||
|
@ -400,51 +565,14 @@ struct iwl_rx_mpdu_desc {
|
|||
* @reorder_data: &enum iwl_rx_mpdu_reorder_data
|
||||
*/
|
||||
__le32 reorder_data;
|
||||
/* DW7 - carries rss_hash only when rpa_en == 1 */
|
||||
/**
|
||||
* @rss_hash: RSS hash value
|
||||
*/
|
||||
__le32 rss_hash;
|
||||
/* DW8 - carries filter_match only when rpa_en == 1 */
|
||||
/**
|
||||
* @filter_match: filter match value
|
||||
*/
|
||||
__le32 filter_match;
|
||||
/* DW9 */
|
||||
/**
|
||||
* @rate_n_flags: RX rate/flags encoding
|
||||
*/
|
||||
__le32 rate_n_flags;
|
||||
/* DW10 */
|
||||
/**
|
||||
* @energy_a: energy chain A
|
||||
*/
|
||||
u8 energy_a;
|
||||
/**
|
||||
* @energy_b: energy chain B
|
||||
*/
|
||||
u8 energy_b;
|
||||
/**
|
||||
* @channel: channel number
|
||||
*/
|
||||
u8 channel;
|
||||
/**
|
||||
* @mac_context: MAC context mask
|
||||
*/
|
||||
u8 mac_context;
|
||||
/* DW11 */
|
||||
/**
|
||||
* @gp2_on_air_rise: GP2 timer value on air rise (INA)
|
||||
*/
|
||||
__le32 gp2_on_air_rise;
|
||||
/* DW12 & DW13 */
|
||||
/**
|
||||
* @tsf_on_air_rise:
|
||||
* TSF value on air rise (INA), only valid if
|
||||
* %IWL_RX_MPDU_PHY_TSF_OVERLOAD isn't set
|
||||
*/
|
||||
__le64 tsf_on_air_rise;
|
||||
} __packed;
|
||||
|
||||
union {
|
||||
struct iwl_rx_mpdu_desc_v1 v1;
|
||||
struct iwl_rx_mpdu_desc_v3 v3;
|
||||
};
|
||||
} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */
|
||||
|
||||
#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
|
||||
|
||||
struct iwl_frame_release {
|
||||
u8 baid;
|
||||
|
@ -587,4 +715,36 @@ struct iwl_ba_window_status_notif {
|
|||
__le16 mpdu_rx_count[BA_WINDOW_STREAMS_MAX];
|
||||
} __packed; /* BA_WINDOW_STATUS_NTFY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_rfh_queue_config - RX queue configuration
|
||||
* @q_num: Q num
|
||||
* @enable: enable queue
|
||||
* @reserved: alignment
|
||||
* @urbd_stts_wrptr: DMA address of urbd_stts_wrptr
|
||||
* @fr_bd_cb: DMA address of freeRB table
|
||||
* @ur_bd_cb: DMA address of used RB table
|
||||
* @fr_bd_wid: Initial index of the free table
|
||||
*/
|
||||
struct iwl_rfh_queue_data {
|
||||
u8 q_num;
|
||||
u8 enable;
|
||||
__le16 reserved;
|
||||
__le64 urbd_stts_wrptr;
|
||||
__le64 fr_bd_cb;
|
||||
__le64 ur_bd_cb;
|
||||
__le32 fr_bd_wid;
|
||||
} __packed; /* RFH_QUEUE_CONFIG_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_rfh_queue_config - RX queue configuration
|
||||
* @num_queues: number of queues configured
|
||||
* @reserved: alignment
|
||||
* @data: DMA addresses per-queue
|
||||
*/
|
||||
struct iwl_rfh_queue_config {
|
||||
u8 num_queues;
|
||||
u8 reserved[3];
|
||||
struct iwl_rfh_queue_data data[];
|
||||
} __packed; /* RFH_QUEUE_CONFIG_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_rx_h__ */
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -28,6 +29,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -320,6 +322,29 @@ struct iwl_tx_cmd_gen2 {
|
|||
struct ieee80211_hdr hdr[0];
|
||||
} __packed; /* TX_CMD_API_S_VER_7 */
|
||||
|
||||
/**
|
||||
* struct iwl_tx_cmd_gen3 - TX command struct to FW for 22560 devices
|
||||
* ( TX_CMD = 0x1c )
|
||||
* @len: in bytes of the payload, see below for details
|
||||
* @flags: combination of &enum iwl_tx_cmd_flags
|
||||
* @offload_assist: TX offload configuration
|
||||
* @dram_info: FW internal DRAM storage
|
||||
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
|
||||
* cleared. Combination of RATE_MCS_*
|
||||
* @ttl: time to live - packet lifetime limit. The FW should drop if
|
||||
* passed.
|
||||
* @hdr: 802.11 header
|
||||
*/
|
||||
struct iwl_tx_cmd_gen3 {
|
||||
__le16 len;
|
||||
__le16 flags;
|
||||
__le32 offload_assist;
|
||||
struct iwl_dram_sec_info dram_info;
|
||||
__le32 rate_n_flags;
|
||||
__le64 ttl;
|
||||
struct ieee80211_hdr hdr[0];
|
||||
} __packed; /* TX_CMD_API_S_VER_8 */
|
||||
|
||||
/*
|
||||
* TX response related data
|
||||
*/
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <linuxwifi@intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "iwl-drv.h"
|
||||
#include "runtime.h"
|
||||
#include "fw/api/commands.h"
|
||||
#include "fw/api/alive.h"
|
||||
|
||||
static void iwl_fwrt_fseq_ver_mismatch(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_fseq_ver_mismatch_ntf *fseq = (void *)pkt->data;
|
||||
|
||||
IWL_ERR(fwrt, "FSEQ version mismatch (aux: %d, wifi: %d)\n",
|
||||
__le32_to_cpu(fseq->aux_read_fseq_ver),
|
||||
__le32_to_cpu(fseq->wifi_fseq_ver));
|
||||
}
|
||||
|
||||
void iwl_fwrt_handle_notification(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u32 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case WIDE_ID(SYSTEM_GROUP, FSEQ_VER_MISMATCH_NTF):
|
||||
iwl_fwrt_fseq_ver_mismatch(fwrt, rxb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fwrt_handle_notification);
|
|
@ -243,39 +243,47 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt,
|
|||
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
|
||||
return;
|
||||
|
||||
/* Pull RXF1 */
|
||||
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->lmac[0].rxfifo1_size, 0, 0);
|
||||
/* Pull RXF2 */
|
||||
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
|
||||
RXF_DIFF_FROM_PREV, 1);
|
||||
/* Pull LMAC2 RXF1 */
|
||||
if (fwrt->smem_cfg.num_lmacs > 1)
|
||||
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->lmac[1].rxfifo1_size,
|
||||
LMAC2_PRPH_OFFSET, 2);
|
||||
|
||||
/* Pull TXF data from LMAC1 */
|
||||
for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
|
||||
/* Mark the number of TXF we're pulling now */
|
||||
iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
|
||||
iwl_fwrt_dump_txf(fwrt, dump_data, cfg->lmac[0].txfifo_size[i],
|
||||
0, i);
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) {
|
||||
/* Pull RXF1 */
|
||||
iwl_fwrt_dump_rxf(fwrt, dump_data,
|
||||
cfg->lmac[0].rxfifo1_size, 0, 0);
|
||||
/* Pull RXF2 */
|
||||
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
|
||||
RXF_DIFF_FROM_PREV, 1);
|
||||
/* Pull LMAC2 RXF1 */
|
||||
if (fwrt->smem_cfg.num_lmacs > 1)
|
||||
iwl_fwrt_dump_rxf(fwrt, dump_data,
|
||||
cfg->lmac[1].rxfifo1_size,
|
||||
LMAC2_PRPH_OFFSET, 2);
|
||||
}
|
||||
|
||||
/* Pull TXF data from LMAC2 */
|
||||
if (fwrt->smem_cfg.num_lmacs > 1) {
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) {
|
||||
/* Pull TXF data from LMAC1 */
|
||||
for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
|
||||
/* Mark the number of TXF we're pulling now */
|
||||
iwl_trans_write_prph(fwrt->trans,
|
||||
TXF_LARC_NUM + LMAC2_PRPH_OFFSET,
|
||||
i);
|
||||
iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
|
||||
iwl_fwrt_dump_txf(fwrt, dump_data,
|
||||
cfg->lmac[1].txfifo_size[i],
|
||||
LMAC2_PRPH_OFFSET,
|
||||
i + cfg->num_txfifo_entries);
|
||||
cfg->lmac[0].txfifo_size[i], 0, i);
|
||||
}
|
||||
|
||||
/* Pull TXF data from LMAC2 */
|
||||
if (fwrt->smem_cfg.num_lmacs > 1) {
|
||||
for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries;
|
||||
i++) {
|
||||
/* Mark the number of TXF we're pulling now */
|
||||
iwl_trans_write_prph(fwrt->trans,
|
||||
TXF_LARC_NUM +
|
||||
LMAC2_PRPH_OFFSET, i);
|
||||
iwl_fwrt_dump_txf(fwrt, dump_data,
|
||||
cfg->lmac[1].txfifo_size[i],
|
||||
LMAC2_PRPH_OFFSET,
|
||||
i + cfg->num_txfifo_entries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
|
||||
fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
|
||||
/* Pull UMAC internal TXF data from all TXFs */
|
||||
for (i = 0;
|
||||
|
@ -600,42 +608,54 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
|
||||
fifo_data_len = 0;
|
||||
|
||||
/* Count RXF2 size */
|
||||
if (mem_cfg->rxfifo2_size) {
|
||||
/* Add header info */
|
||||
fifo_data_len += mem_cfg->rxfifo2_size +
|
||||
sizeof(*dump_data) +
|
||||
sizeof(struct iwl_fw_error_dump_fifo);
|
||||
}
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) {
|
||||
|
||||
/* Count RXF1 sizes */
|
||||
for (i = 0; i < mem_cfg->num_lmacs; i++) {
|
||||
if (!mem_cfg->lmac[i].rxfifo1_size)
|
||||
continue;
|
||||
/* Count RXF2 size */
|
||||
if (mem_cfg->rxfifo2_size) {
|
||||
/* Add header info */
|
||||
fifo_data_len +=
|
||||
mem_cfg->rxfifo2_size +
|
||||
sizeof(*dump_data) +
|
||||
sizeof(struct iwl_fw_error_dump_fifo);
|
||||
}
|
||||
|
||||
/* Add header info */
|
||||
fifo_data_len += mem_cfg->lmac[i].rxfifo1_size +
|
||||
sizeof(*dump_data) +
|
||||
sizeof(struct iwl_fw_error_dump_fifo);
|
||||
}
|
||||
|
||||
/* Count TXF sizes */
|
||||
for (i = 0; i < mem_cfg->num_lmacs; i++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < mem_cfg->num_txfifo_entries; j++) {
|
||||
if (!mem_cfg->lmac[i].txfifo_size[j])
|
||||
/* Count RXF1 sizes */
|
||||
for (i = 0; i < mem_cfg->num_lmacs; i++) {
|
||||
if (!mem_cfg->lmac[i].rxfifo1_size)
|
||||
continue;
|
||||
|
||||
/* Add header info */
|
||||
fifo_data_len +=
|
||||
mem_cfg->lmac[i].txfifo_size[j] +
|
||||
mem_cfg->lmac[i].rxfifo1_size +
|
||||
sizeof(*dump_data) +
|
||||
sizeof(struct iwl_fw_error_dump_fifo);
|
||||
}
|
||||
}
|
||||
|
||||
if (fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) {
|
||||
size_t fifo_const_len = sizeof(*dump_data) +
|
||||
sizeof(struct iwl_fw_error_dump_fifo);
|
||||
|
||||
/* Count TXF sizes */
|
||||
for (i = 0; i < mem_cfg->num_lmacs; i++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < mem_cfg->num_txfifo_entries;
|
||||
j++) {
|
||||
if (!mem_cfg->lmac[i].txfifo_size[j])
|
||||
continue;
|
||||
|
||||
/* Add header info */
|
||||
fifo_data_len +=
|
||||
fifo_const_len +
|
||||
mem_cfg->lmac[i].txfifo_size[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((fwrt->fw->dbg_dump_mask &
|
||||
BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF)) &&
|
||||
fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
|
||||
for (i = 0;
|
||||
i < ARRAY_SIZE(mem_cfg->internal_txfifo_size);
|
||||
|
@ -652,7 +672,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
}
|
||||
|
||||
/* Make room for PRPH registers */
|
||||
if (!fwrt->trans->cfg->gen2) {
|
||||
if (!fwrt->trans->cfg->gen2 &&
|
||||
fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PRPH)) {
|
||||
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr_comm);
|
||||
i++) {
|
||||
/* The range includes both boundaries */
|
||||
|
@ -667,7 +688,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
}
|
||||
|
||||
if (!fwrt->trans->cfg->gen2 &&
|
||||
fwrt->trans->cfg->mq_rx_supported) {
|
||||
fwrt->trans->cfg->mq_rx_supported &&
|
||||
fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PRPH)) {
|
||||
for (i = 0; i <
|
||||
ARRAY_SIZE(iwl_prph_dump_addr_9000); i++) {
|
||||
/* The range includes both boundaries */
|
||||
|
@ -681,34 +703,42 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
}
|
||||
}
|
||||
|
||||
if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000)
|
||||
if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 &&
|
||||
fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RADIO_REG))
|
||||
radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
|
||||
}
|
||||
|
||||
file_len = sizeof(*dump_file) +
|
||||
sizeof(*dump_data) * 3 +
|
||||
sizeof(*dump_smem_cfg) +
|
||||
fifo_data_len +
|
||||
prph_len +
|
||||
radio_len +
|
||||
sizeof(*dump_info);
|
||||
radio_len;
|
||||
|
||||
/* Make room for the SMEM, if it exists */
|
||||
if (smem_len)
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + smem_len;
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO))
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_info);
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG))
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_smem_cfg);
|
||||
|
||||
/* Make room for the secondary SRAM, if it exists */
|
||||
if (sram2_len)
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len;
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
|
||||
/* Make room for the SMEM, if it exists */
|
||||
if (smem_len)
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
|
||||
smem_len;
|
||||
|
||||
/* Make room for MEM segments */
|
||||
for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) {
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
|
||||
le32_to_cpu(fw_dbg_mem[i].len);
|
||||
/* Make room for the secondary SRAM, if it exists */
|
||||
if (sram2_len)
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
|
||||
sram2_len;
|
||||
|
||||
/* Make room for MEM segments */
|
||||
for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) {
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
|
||||
le32_to_cpu(fw_dbg_mem[i].len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make room for fw's virtual image pages, if it exists */
|
||||
if (!fwrt->trans->cfg->gen2 &&
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) &&
|
||||
!fwrt->trans->cfg->gen2 &&
|
||||
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
|
||||
fwrt->fw_paging_db[0].fw_paging_block)
|
||||
file_len += fwrt->num_of_paging_blk *
|
||||
|
@ -722,12 +752,14 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
sizeof(*dump_info) + sizeof(*dump_smem_cfg);
|
||||
}
|
||||
|
||||
if (fwrt->dump.desc)
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) &&
|
||||
fwrt->dump.desc)
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
|
||||
fwrt->dump.desc->len;
|
||||
|
||||
if (!fwrt->fw->n_dbg_mem_tlv)
|
||||
file_len += sram_len + sizeof(*dump_mem);
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM) &&
|
||||
!fwrt->fw->n_dbg_mem_tlv)
|
||||
file_len += sizeof(*dump_data) + sram_len + sizeof(*dump_mem);
|
||||
|
||||
dump_file = vzalloc(file_len);
|
||||
if (!dump_file) {
|
||||
|
@ -740,48 +772,56 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
|
||||
dump_data = (void *)dump_file->data;
|
||||
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
|
||||
dump_data->len = cpu_to_le32(sizeof(*dump_info));
|
||||
dump_info = (void *)dump_data->data;
|
||||
dump_info->device_family =
|
||||
fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 ?
|
||||
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
|
||||
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
|
||||
dump_info->hw_step = cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
|
||||
memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
|
||||
sizeof(dump_info->fw_human_readable));
|
||||
strncpy(dump_info->dev_human_readable, fwrt->trans->cfg->name,
|
||||
sizeof(dump_info->dev_human_readable));
|
||||
strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name,
|
||||
sizeof(dump_info->bus_human_readable));
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO)) {
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
|
||||
dump_data->len = cpu_to_le32(sizeof(*dump_info));
|
||||
dump_info = (void *)dump_data->data;
|
||||
dump_info->device_family =
|
||||
fwrt->trans->cfg->device_family ==
|
||||
IWL_DEVICE_FAMILY_7000 ?
|
||||
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
|
||||
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
|
||||
dump_info->hw_step =
|
||||
cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
|
||||
memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
|
||||
sizeof(dump_info->fw_human_readable));
|
||||
strncpy(dump_info->dev_human_readable, fwrt->trans->cfg->name,
|
||||
sizeof(dump_info->dev_human_readable) - 1);
|
||||
strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name,
|
||||
sizeof(dump_info->bus_human_readable) - 1);
|
||||
|
||||
dump_data = iwl_fw_error_next_data(dump_data);
|
||||
|
||||
/* Dump shared memory configuration */
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
|
||||
dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
|
||||
dump_smem_cfg = (void *)dump_data->data;
|
||||
dump_smem_cfg->num_lmacs = cpu_to_le32(mem_cfg->num_lmacs);
|
||||
dump_smem_cfg->num_txfifo_entries =
|
||||
cpu_to_le32(mem_cfg->num_txfifo_entries);
|
||||
for (i = 0; i < MAX_NUM_LMAC; i++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < TX_FIFO_MAX_NUM; j++)
|
||||
dump_smem_cfg->lmac[i].txfifo_size[j] =
|
||||
cpu_to_le32(mem_cfg->lmac[i].txfifo_size[j]);
|
||||
dump_smem_cfg->lmac[i].rxfifo1_size =
|
||||
cpu_to_le32(mem_cfg->lmac[i].rxfifo1_size);
|
||||
}
|
||||
dump_smem_cfg->rxfifo2_size = cpu_to_le32(mem_cfg->rxfifo2_size);
|
||||
dump_smem_cfg->internal_txfifo_addr =
|
||||
cpu_to_le32(mem_cfg->internal_txfifo_addr);
|
||||
for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
|
||||
dump_smem_cfg->internal_txfifo_size[i] =
|
||||
cpu_to_le32(mem_cfg->internal_txfifo_size[i]);
|
||||
dump_data = iwl_fw_error_next_data(dump_data);
|
||||
}
|
||||
|
||||
dump_data = iwl_fw_error_next_data(dump_data);
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG)) {
|
||||
/* Dump shared memory configuration */
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
|
||||
dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
|
||||
dump_smem_cfg = (void *)dump_data->data;
|
||||
dump_smem_cfg->num_lmacs = cpu_to_le32(mem_cfg->num_lmacs);
|
||||
dump_smem_cfg->num_txfifo_entries =
|
||||
cpu_to_le32(mem_cfg->num_txfifo_entries);
|
||||
for (i = 0; i < MAX_NUM_LMAC; i++) {
|
||||
int j;
|
||||
u32 *txf_size = mem_cfg->lmac[i].txfifo_size;
|
||||
|
||||
for (j = 0; j < TX_FIFO_MAX_NUM; j++)
|
||||
dump_smem_cfg->lmac[i].txfifo_size[j] =
|
||||
cpu_to_le32(txf_size[j]);
|
||||
dump_smem_cfg->lmac[i].rxfifo1_size =
|
||||
cpu_to_le32(mem_cfg->lmac[i].rxfifo1_size);
|
||||
}
|
||||
dump_smem_cfg->rxfifo2_size =
|
||||
cpu_to_le32(mem_cfg->rxfifo2_size);
|
||||
dump_smem_cfg->internal_txfifo_addr =
|
||||
cpu_to_le32(mem_cfg->internal_txfifo_addr);
|
||||
for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
|
||||
dump_smem_cfg->internal_txfifo_size[i] =
|
||||
cpu_to_le32(mem_cfg->internal_txfifo_size[i]);
|
||||
}
|
||||
|
||||
dump_data = iwl_fw_error_next_data(dump_data);
|
||||
}
|
||||
|
||||
/* We only dump the FIFOs if the FW is in error state */
|
||||
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
|
||||
|
@ -790,7 +830,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
iwl_read_radio_regs(fwrt, &dump_data);
|
||||
}
|
||||
|
||||
if (fwrt->dump.desc) {
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) &&
|
||||
fwrt->dump.desc) {
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
|
||||
dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
|
||||
fwrt->dump.desc->len);
|
||||
|
@ -805,7 +846,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
if (monitor_dump_only)
|
||||
goto dump_trans_data;
|
||||
|
||||
if (!fwrt->fw->n_dbg_mem_tlv) {
|
||||
if (!fwrt->fw->n_dbg_mem_tlv &&
|
||||
fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||
dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem));
|
||||
dump_mem = (void *)dump_data->data;
|
||||
|
@ -821,6 +863,9 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
|
||||
bool success;
|
||||
|
||||
if (!(fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)))
|
||||
break;
|
||||
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||
dump_data->len = cpu_to_le32(len + sizeof(*dump_mem));
|
||||
dump_mem = (void *)dump_data->data;
|
||||
|
@ -854,7 +899,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
dump_data = iwl_fw_error_next_data(dump_data);
|
||||
}
|
||||
|
||||
if (smem_len) {
|
||||
if (smem_len && fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
|
||||
IWL_DEBUG_INFO(fwrt, "WRT SMEM dump\n");
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||
dump_data->len = cpu_to_le32(smem_len + sizeof(*dump_mem));
|
||||
|
@ -867,7 +912,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
dump_data = iwl_fw_error_next_data(dump_data);
|
||||
}
|
||||
|
||||
if (sram2_len) {
|
||||
if (sram2_len && fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
|
||||
IWL_DEBUG_INFO(fwrt, "WRT SRAM dump\n");
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||
dump_data->len = cpu_to_le32(sram2_len + sizeof(*dump_mem));
|
||||
|
@ -881,7 +926,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
|
|||
}
|
||||
|
||||
/* Dump fw's virtual image */
|
||||
if (!fwrt->trans->cfg->gen2 &&
|
||||
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) &&
|
||||
!fwrt->trans->cfg->gen2 &&
|
||||
fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
|
||||
fwrt->fw_paging_db[0].fw_paging_block) {
|
||||
IWL_DEBUG_INFO(fwrt, "WRT paging dump\n");
|
||||
|
|
|
@ -146,6 +146,9 @@ enum iwl_ucode_tlv_type {
|
|||
IWL_UCODE_TLV_FW_GSCAN_CAPA = 50,
|
||||
IWL_UCODE_TLV_FW_MEM_SEG = 51,
|
||||
IWL_UCODE_TLV_IML = 52,
|
||||
|
||||
/* TLVs 0x1000-0x2000 are for internal driver usage */
|
||||
IWL_UCODE_TLV_FW_DBG_DUMP_LST = 0x1000,
|
||||
};
|
||||
|
||||
struct iwl_ucode_tlv {
|
||||
|
@ -318,7 +321,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
|
|||
* IWL_UCODE_TLV_API_WIFI_MCC_UPDATE. When either is set, multi-source LAR
|
||||
* is supported.
|
||||
* @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
|
||||
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan
|
||||
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan (no longer used)
|
||||
* @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification
|
||||
* @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm
|
||||
* @IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA: firmware implements quota related
|
||||
|
@ -889,39 +892,4 @@ struct iwl_fw_dbg_conf_tlv {
|
|||
struct iwl_fw_dbg_conf_hcmd hcmd;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_gscan_capabilities - gscan capabilities supported by FW
|
||||
* @max_scan_cache_size: total space allocated for scan results (in bytes).
|
||||
* @max_scan_buckets: maximum number of channel buckets.
|
||||
* @max_ap_cache_per_scan: maximum number of APs that can be stored per scan.
|
||||
* @max_rssi_sample_size: number of RSSI samples used for averaging RSSI.
|
||||
* @max_scan_reporting_threshold: max possible report threshold. in percentage.
|
||||
* @max_hotlist_aps: maximum number of entries for hotlist APs.
|
||||
* @max_significant_change_aps: maximum number of entries for significant
|
||||
* change APs.
|
||||
* @max_bssid_history_entries: number of BSSID/RSSI entries that the device can
|
||||
* hold.
|
||||
* @max_hotlist_ssids: maximum number of entries for hotlist SSIDs.
|
||||
* @max_number_epno_networks: max number of epno entries.
|
||||
* @max_number_epno_networks_by_ssid: max number of epno entries if ssid is
|
||||
* specified.
|
||||
* @max_number_of_white_listed_ssid: max number of white listed SSIDs.
|
||||
* @max_number_of_black_listed_ssid: max number of black listed SSIDs.
|
||||
*/
|
||||
struct iwl_fw_gscan_capabilities {
|
||||
__le32 max_scan_cache_size;
|
||||
__le32 max_scan_buckets;
|
||||
__le32 max_ap_cache_per_scan;
|
||||
__le32 max_rssi_sample_size;
|
||||
__le32 max_scan_reporting_threshold;
|
||||
__le32 max_hotlist_aps;
|
||||
__le32 max_significant_change_aps;
|
||||
__le32 max_bssid_history_entries;
|
||||
__le32 max_hotlist_ssids;
|
||||
__le32 max_number_epno_networks;
|
||||
__le32 max_number_epno_networks_by_ssid;
|
||||
__le32 max_number_of_white_listed_ssid;
|
||||
__le32 max_number_of_black_listed_ssid;
|
||||
} __packed;
|
||||
|
||||
#endif /* __iwl_fw_file_h__ */
|
||||
|
|
|
@ -192,41 +192,6 @@ struct iwl_fw_cscheme_list {
|
|||
struct iwl_fw_cipher_scheme cs[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_gscan_capabilities - gscan capabilities supported by FW
|
||||
* @max_scan_cache_size: total space allocated for scan results (in bytes).
|
||||
* @max_scan_buckets: maximum number of channel buckets.
|
||||
* @max_ap_cache_per_scan: maximum number of APs that can be stored per scan.
|
||||
* @max_rssi_sample_size: number of RSSI samples used for averaging RSSI.
|
||||
* @max_scan_reporting_threshold: max possible report threshold. in percentage.
|
||||
* @max_hotlist_aps: maximum number of entries for hotlist APs.
|
||||
* @max_significant_change_aps: maximum number of entries for significant
|
||||
* change APs.
|
||||
* @max_bssid_history_entries: number of BSSID/RSSI entries that the device can
|
||||
* hold.
|
||||
* @max_hotlist_ssids: maximum number of entries for hotlist SSIDs.
|
||||
* @max_number_epno_networks: max number of epno entries.
|
||||
* @max_number_epno_networks_by_ssid: max number of epno entries if ssid is
|
||||
* specified.
|
||||
* @max_number_of_white_listed_ssid: max number of white listed SSIDs.
|
||||
* @max_number_of_black_listed_ssid: max number of black listed SSIDs.
|
||||
*/
|
||||
struct iwl_gscan_capabilities {
|
||||
u32 max_scan_cache_size;
|
||||
u32 max_scan_buckets;
|
||||
u32 max_ap_cache_per_scan;
|
||||
u32 max_rssi_sample_size;
|
||||
u32 max_scan_reporting_threshold;
|
||||
u32 max_hotlist_aps;
|
||||
u32 max_significant_change_aps;
|
||||
u32 max_bssid_history_entries;
|
||||
u32 max_hotlist_ssids;
|
||||
u32 max_number_epno_networks;
|
||||
u32 max_number_epno_networks_by_ssid;
|
||||
u32 max_number_of_white_listed_ssid;
|
||||
u32 max_number_of_black_listed_ssid;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_fw_type - iwlwifi firmware type
|
||||
* @IWL_FW_DVM: DVM firmware
|
||||
|
@ -298,7 +263,7 @@ struct iwl_fw {
|
|||
size_t n_dbg_mem_tlv;
|
||||
size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX];
|
||||
u8 dbg_dest_reg_num;
|
||||
struct iwl_gscan_capabilities gscan_capa;
|
||||
u32 dbg_dump_mask;
|
||||
};
|
||||
|
||||
static inline const char *get_fw_dbg_mode_string(int mode)
|
||||
|
|
|
@ -168,7 +168,4 @@ void iwl_free_fw_paging(struct iwl_fw_runtime *fwrt);
|
|||
|
||||
void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt);
|
||||
|
||||
void iwl_fwrt_handle_notification(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
|
||||
#endif /* __iwl_fw_runtime_h__ */
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -30,6 +31,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -143,7 +145,7 @@ void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt)
|
|||
return;
|
||||
|
||||
pkt = cmd.resp_pkt;
|
||||
if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_22000)
|
||||
if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||
iwl_parse_shared_mem_22000(fwrt, pkt);
|
||||
else
|
||||
iwl_parse_shared_mem(fwrt, pkt);
|
||||
|
|
|
@ -93,6 +93,7 @@ enum iwl_device_family {
|
|||
IWL_DEVICE_FAMILY_8000,
|
||||
IWL_DEVICE_FAMILY_9000,
|
||||
IWL_DEVICE_FAMILY_22000,
|
||||
IWL_DEVICE_FAMILY_22560,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -176,6 +177,7 @@ static inline u8 num_of_ant(u8 mask)
|
|||
* @apmg_wake_up_wa: should the MAC access REQ be asserted when a command
|
||||
* is in flight. This is due to a HW bug in 7260, 3160 and 7265.
|
||||
* @scd_chain_ext_wa: should the chain extension feature in SCD be disabled.
|
||||
* @max_tfd_queue_size: max number of entries in tfd queue.
|
||||
*/
|
||||
struct iwl_base_params {
|
||||
unsigned int wd_timeout;
|
||||
|
@ -191,6 +193,7 @@ struct iwl_base_params {
|
|||
scd_chain_ext_wa:1;
|
||||
|
||||
u16 num_of_queues; /* def: HW dependent */
|
||||
u32 max_tfd_queue_size; /* def: HW dependent */
|
||||
|
||||
u8 max_ll_items;
|
||||
u8 led_compensation;
|
||||
|
@ -571,9 +574,11 @@ extern const struct iwl_cfg iwl22000_2ac_cfg_hr;
|
|||
extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb;
|
||||
extern const struct iwl_cfg iwl22000_2ac_cfg_jf;
|
||||
extern const struct iwl_cfg iwl22000_2ax_cfg_hr;
|
||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_f0;
|
||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0;
|
||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0;
|
||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0;
|
||||
extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0;
|
||||
extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb;
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
#endif /* __IWL_CONFIG_H__ */
|
||||
|
|
286
drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
Normal file
286
drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
Normal file
|
@ -0,0 +1,286 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __iwl_context_info_file_gen3_h__
|
||||
#define __iwl_context_info_file_gen3_h__
|
||||
|
||||
#include "iwl-context-info.h"
|
||||
|
||||
#define CSR_CTXT_INFO_BOOT_CTRL 0x0
|
||||
#define CSR_CTXT_INFO_ADDR 0x118
|
||||
#define CSR_IML_DATA_ADDR 0x120
|
||||
#define CSR_IML_SIZE_ADDR 0x128
|
||||
#define CSR_IML_RESP_ADDR 0x12c
|
||||
|
||||
/* Set bit for enabling automatic function boot */
|
||||
#define CSR_AUTO_FUNC_BOOT_ENA BIT(1)
|
||||
/* Set bit for initiating function boot */
|
||||
#define CSR_AUTO_FUNC_INIT BIT(7)
|
||||
|
||||
/**
|
||||
* enum iwl_prph_scratch_mtr_format - tfd size configuration
|
||||
* @IWL_PRPH_MTR_FORMAT_16B: 16 bit tfd
|
||||
* @IWL_PRPH_MTR_FORMAT_32B: 32 bit tfd
|
||||
* @IWL_PRPH_MTR_FORMAT_64B: 64 bit tfd
|
||||
* @IWL_PRPH_MTR_FORMAT_256B: 256 bit tfd
|
||||
*/
|
||||
enum iwl_prph_scratch_mtr_format {
|
||||
IWL_PRPH_MTR_FORMAT_16B = 0x0,
|
||||
IWL_PRPH_MTR_FORMAT_32B = 0x40000,
|
||||
IWL_PRPH_MTR_FORMAT_64B = 0x80000,
|
||||
IWL_PRPH_MTR_FORMAT_256B = 0xC0000,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_prph_scratch_flags - PRPH scratch control flags
|
||||
* @IWL_PRPH_SCRATCH_EARLY_DEBUG_EN: enable early debug conf
|
||||
* @IWL_PRPH_SCRATCH_EDBG_DEST_DRAM: use DRAM, with size allocated
|
||||
* in hwm config.
|
||||
* @IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL: use buffer on SRAM
|
||||
* @IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER: use st arbiter, mainly for
|
||||
* multicomm.
|
||||
* @IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF: route debug data to SoC HW
|
||||
* @IWL_PRPH_SCTATCH_RB_SIZE_4K: Use 4K RB size (the default is 2K)
|
||||
* @IWL_PRPH_SCRATCH_MTR_MODE: format used for completion - 0: for
|
||||
* completion descriptor, 1 for responses (legacy)
|
||||
* @IWL_PRPH_SCRATCH_MTR_FORMAT: a mask for the size of the tfd.
|
||||
* There are 4 optional values: 0: 16 bit, 1: 32 bit, 2: 64 bit,
|
||||
* 3: 256 bit.
|
||||
*/
|
||||
enum iwl_prph_scratch_flags {
|
||||
IWL_PRPH_SCRATCH_EARLY_DEBUG_EN = BIT(4),
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_DRAM = BIT(8),
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL = BIT(9),
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER = BIT(10),
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF = BIT(11),
|
||||
IWL_PRPH_SCRATCH_RB_SIZE_4K = BIT(16),
|
||||
IWL_PRPH_SCRATCH_MTR_MODE = BIT(17),
|
||||
IWL_PRPH_SCRATCH_MTR_FORMAT = BIT(18) | BIT(19),
|
||||
};
|
||||
|
||||
/*
|
||||
* struct iwl_prph_scratch_version - version structure
|
||||
* @mac_id: SKU and revision id
|
||||
* @version: prph scratch information version id
|
||||
* @size: the size of the context information in DWs
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch_version {
|
||||
__le16 mac_id;
|
||||
__le16 version;
|
||||
__le16 size;
|
||||
__le16 reserved;
|
||||
} __packed; /* PERIPH_SCRATCH_VERSION_S */
|
||||
|
||||
/*
|
||||
* struct iwl_prph_scratch_control - control structure
|
||||
* @control_flags: context information flags see &enum iwl_prph_scratch_flags
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch_control {
|
||||
__le32 control_flags;
|
||||
__le32 reserved;
|
||||
} __packed; /* PERIPH_SCRATCH_CONTROL_S */
|
||||
|
||||
/*
|
||||
* struct iwl_prph_scratch_ror_cfg - ror config
|
||||
* @ror_base_addr: ror start address
|
||||
* @ror_size: ror size in DWs
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch_ror_cfg {
|
||||
__le64 ror_base_addr;
|
||||
__le32 ror_size;
|
||||
__le32 reserved;
|
||||
} __packed; /* PERIPH_SCRATCH_ROR_CFG_S */
|
||||
|
||||
/*
|
||||
* struct iwl_prph_scratch_hwm_cfg - hwm config
|
||||
* @hwm_base_addr: hwm start address
|
||||
* @hwm_size: hwm size in DWs
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch_hwm_cfg {
|
||||
__le64 hwm_base_addr;
|
||||
__le32 hwm_size;
|
||||
__le32 reserved;
|
||||
} __packed; /* PERIPH_SCRATCH_HWM_CFG_S */
|
||||
|
||||
/*
|
||||
* struct iwl_prph_scratch_rbd_cfg - RBDs configuration
|
||||
* @free_rbd_addr: default queue free RB CB base address
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch_rbd_cfg {
|
||||
__le64 free_rbd_addr;
|
||||
__le32 reserved;
|
||||
} __packed; /* PERIPH_SCRATCH_RBD_CFG_S */
|
||||
|
||||
/*
|
||||
* struct iwl_prph_scratch_ctrl_cfg - prph scratch ctrl and config
|
||||
* @version: version information of context info and HW
|
||||
* @control: control flags of FH configurations
|
||||
* @ror_cfg: ror configuration
|
||||
* @hwm_cfg: hwm configuration
|
||||
* @rbd_cfg: default RX queue configuration
|
||||
*/
|
||||
struct iwl_prph_scratch_ctrl_cfg {
|
||||
struct iwl_prph_scratch_version version;
|
||||
struct iwl_prph_scratch_control control;
|
||||
struct iwl_prph_scratch_ror_cfg ror_cfg;
|
||||
struct iwl_prph_scratch_hwm_cfg hwm_cfg;
|
||||
struct iwl_prph_scratch_rbd_cfg rbd_cfg;
|
||||
} __packed; /* PERIPH_SCRATCH_CTRL_CFG_S */
|
||||
|
||||
/*
|
||||
* struct iwl_prph_scratch - peripheral scratch mapping
|
||||
* @ctrl_cfg: control and configuration of prph scratch
|
||||
* @dram: firmware images addresses in DRAM
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_scratch {
|
||||
struct iwl_prph_scratch_ctrl_cfg ctrl_cfg;
|
||||
__le32 reserved[16];
|
||||
struct iwl_context_info_dram dram;
|
||||
} __packed; /* PERIPH_SCRATCH_S */
|
||||
|
||||
/*
|
||||
* struct iwl_prph_info - peripheral information
|
||||
* @boot_stage_mirror: reflects the value in the Boot Stage CSR register
|
||||
* @ipc_status_mirror: reflects the value in the IPC Status CSR register
|
||||
* @sleep_notif: indicates the peripheral sleep status
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_prph_info {
|
||||
__le32 boot_stage_mirror;
|
||||
__le32 ipc_status_mirror;
|
||||
__le32 sleep_notif;
|
||||
__le32 reserved;
|
||||
} __packed; /* PERIPH_INFO_S */
|
||||
|
||||
/*
|
||||
* struct iwl_context_info_gen3 - device INIT configuration
|
||||
* @version: version of the context information
|
||||
* @size: size of context information in DWs
|
||||
* @config: context in which the peripheral would execute - a subset of
|
||||
* capability csr register published by the peripheral
|
||||
* @prph_info_base_addr: the peripheral information structure start address
|
||||
* @cr_head_idx_arr_base_addr: the completion ring head index array
|
||||
* start address
|
||||
* @tr_tail_idx_arr_base_addr: the transfer ring tail index array
|
||||
* start address
|
||||
* @cr_tail_idx_arr_base_addr: the completion ring tail index array
|
||||
* start address
|
||||
* @tr_head_idx_arr_base_addr: the transfer ring head index array
|
||||
* start address
|
||||
* @cr_idx_arr_size: number of entries in the completion ring index array
|
||||
* @tr_idx_arr_size: number of entries in the transfer ring index array
|
||||
* @mtr_base_addr: the message transfer ring start address
|
||||
* @mcr_base_addr: the message completion ring start address
|
||||
* @mtr_size: number of entries which the message transfer ring can hold
|
||||
* @mcr_size: number of entries which the message completion ring can hold
|
||||
* @mtr_doorbell_vec: the doorbell vector associated with the message
|
||||
* transfer ring
|
||||
* @mcr_doorbell_vec: the doorbell vector associated with the message
|
||||
* completion ring
|
||||
* @mtr_msi_vec: the MSI which shall be generated by the peripheral after
|
||||
* completing a transfer descriptor in the message transfer ring
|
||||
* @mcr_msi_vec: the MSI which shall be generated by the peripheral after
|
||||
* completing a completion descriptor in the message completion ring
|
||||
* @mtr_opt_header_size: the size of the optional header in the transfer
|
||||
* descriptor associated with the message transfer ring in DWs
|
||||
* @mtr_opt_footer_size: the size of the optional footer in the transfer
|
||||
* descriptor associated with the message transfer ring in DWs
|
||||
* @mcr_opt_header_size: the size of the optional header in the completion
|
||||
* descriptor associated with the message completion ring in DWs
|
||||
* @mcr_opt_footer_size: the size of the optional footer in the completion
|
||||
* descriptor associated with the message completion ring in DWs
|
||||
* @msg_rings_ctrl_flags: message rings control flags
|
||||
* @prph_info_msi_vec: the MSI which shall be generated by the peripheral
|
||||
* after updating the Peripheral Information structure
|
||||
* @prph_scratch_base_addr: the peripheral scratch structure start address
|
||||
* @prph_scratch_size: the size of the peripheral scratch structure in DWs
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_context_info_gen3 {
|
||||
__le16 version;
|
||||
__le16 size;
|
||||
__le32 config;
|
||||
__le64 prph_info_base_addr;
|
||||
__le64 cr_head_idx_arr_base_addr;
|
||||
__le64 tr_tail_idx_arr_base_addr;
|
||||
__le64 cr_tail_idx_arr_base_addr;
|
||||
__le64 tr_head_idx_arr_base_addr;
|
||||
__le16 cr_idx_arr_size;
|
||||
__le16 tr_idx_arr_size;
|
||||
__le64 mtr_base_addr;
|
||||
__le64 mcr_base_addr;
|
||||
__le16 mtr_size;
|
||||
__le16 mcr_size;
|
||||
__le16 mtr_doorbell_vec;
|
||||
__le16 mcr_doorbell_vec;
|
||||
__le16 mtr_msi_vec;
|
||||
__le16 mcr_msi_vec;
|
||||
u8 mtr_opt_header_size;
|
||||
u8 mtr_opt_footer_size;
|
||||
u8 mcr_opt_header_size;
|
||||
u8 mcr_opt_footer_size;
|
||||
__le16 msg_rings_ctrl_flags;
|
||||
__le16 prph_info_msi_vec;
|
||||
__le64 prph_scratch_base_addr;
|
||||
__le32 prph_scratch_size;
|
||||
__le32 reserved;
|
||||
} __packed; /* IPC_CONTEXT_INFO_S */
|
||||
|
||||
int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
|
||||
const struct fw_img *fw);
|
||||
void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans);
|
||||
|
||||
#endif /* __iwl_context_info_file_gen3_h__ */
|
|
@ -6,6 +6,7 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -19,6 +20,7 @@
|
|||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -199,5 +201,8 @@ struct iwl_context_info {
|
|||
int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, const struct fw_img *fw);
|
||||
void iwl_pcie_ctxt_info_free(struct iwl_trans *trans);
|
||||
void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans);
|
||||
int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
|
||||
const struct fw_img *fw,
|
||||
struct iwl_context_info_dram *ctxt_dram);
|
||||
|
||||
#endif /* __iwl_context_info_file_h__ */
|
||||
|
|
|
@ -339,6 +339,9 @@ enum {
|
|||
/* HW_RF CHIP ID */
|
||||
#define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF)
|
||||
|
||||
/* HW_RF CHIP STEP */
|
||||
#define CSR_HW_RF_STEP(_val) (((_val) >> 8) & 0xF)
|
||||
|
||||
/* EEPROM REG */
|
||||
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
|
||||
#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
|
||||
|
@ -592,6 +595,8 @@ enum msix_fh_int_causes {
|
|||
enum msix_hw_int_causes {
|
||||
MSIX_HW_INT_CAUSES_REG_ALIVE = BIT(0),
|
||||
MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1),
|
||||
MSIX_HW_INT_CAUSES_REG_IPC = BIT(1),
|
||||
MSIX_HW_INT_CAUSES_REG_SW_ERR_V2 = BIT(5),
|
||||
MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6),
|
||||
MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7),
|
||||
MSIX_HW_INT_CAUSES_REG_PERIODIC = BIT(8),
|
||||
|
|
|
@ -402,35 +402,6 @@ static int iwl_store_cscheme(struct iwl_fw *fw, const u8 *data, const u32 len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_store_gscan_capa(struct iwl_fw *fw, const u8 *data,
|
||||
const u32 len)
|
||||
{
|
||||
struct iwl_fw_gscan_capabilities *fw_capa = (void *)data;
|
||||
struct iwl_gscan_capabilities *capa = &fw->gscan_capa;
|
||||
|
||||
capa->max_scan_cache_size = le32_to_cpu(fw_capa->max_scan_cache_size);
|
||||
capa->max_scan_buckets = le32_to_cpu(fw_capa->max_scan_buckets);
|
||||
capa->max_ap_cache_per_scan =
|
||||
le32_to_cpu(fw_capa->max_ap_cache_per_scan);
|
||||
capa->max_rssi_sample_size = le32_to_cpu(fw_capa->max_rssi_sample_size);
|
||||
capa->max_scan_reporting_threshold =
|
||||
le32_to_cpu(fw_capa->max_scan_reporting_threshold);
|
||||
capa->max_hotlist_aps = le32_to_cpu(fw_capa->max_hotlist_aps);
|
||||
capa->max_significant_change_aps =
|
||||
le32_to_cpu(fw_capa->max_significant_change_aps);
|
||||
capa->max_bssid_history_entries =
|
||||
le32_to_cpu(fw_capa->max_bssid_history_entries);
|
||||
capa->max_hotlist_ssids = le32_to_cpu(fw_capa->max_hotlist_ssids);
|
||||
capa->max_number_epno_networks =
|
||||
le32_to_cpu(fw_capa->max_number_epno_networks);
|
||||
capa->max_number_epno_networks_by_ssid =
|
||||
le32_to_cpu(fw_capa->max_number_epno_networks_by_ssid);
|
||||
capa->max_number_of_white_listed_ssid =
|
||||
le32_to_cpu(fw_capa->max_number_of_white_listed_ssid);
|
||||
capa->max_number_of_black_listed_ssid =
|
||||
le32_to_cpu(fw_capa->max_number_of_black_listed_ssid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets uCode section from tlv.
|
||||
*/
|
||||
|
@ -644,7 +615,6 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
u32 build, paging_mem_size;
|
||||
int num_of_cpus;
|
||||
bool usniffer_req = false;
|
||||
bool gscan_capa = false;
|
||||
|
||||
if (len < sizeof(*ucode)) {
|
||||
IWL_ERR(drv, "uCode has invalid length: %zd\n", len);
|
||||
|
@ -1043,6 +1013,17 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
pieces->dbg_trigger_tlv_len[trigger_id] = tlv_len;
|
||||
break;
|
||||
}
|
||||
case IWL_UCODE_TLV_FW_DBG_DUMP_LST: {
|
||||
if (tlv_len != sizeof(u32)) {
|
||||
IWL_ERR(drv,
|
||||
"dbg lst mask size incorrect, skip\n");
|
||||
break;
|
||||
}
|
||||
|
||||
drv->fw.dbg_dump_mask =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
}
|
||||
case IWL_UCODE_TLV_SEC_RT_USNIFFER:
|
||||
*usniffer_images = true;
|
||||
iwl_store_ucode_sec(pieces, tlv_data,
|
||||
|
@ -1079,16 +1060,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
paging_mem_size;
|
||||
break;
|
||||
case IWL_UCODE_TLV_FW_GSCAN_CAPA:
|
||||
/*
|
||||
* Don't return an error in case of a shorter tlv_len
|
||||
* to enable loading of FW that has an old format
|
||||
* of GSCAN capabilities TLV.
|
||||
*/
|
||||
if (tlv_len < sizeof(struct iwl_fw_gscan_capabilities))
|
||||
break;
|
||||
|
||||
iwl_store_gscan_capa(&drv->fw, tlv_data, tlv_len);
|
||||
gscan_capa = true;
|
||||
/* ignored */
|
||||
break;
|
||||
case IWL_UCODE_TLV_FW_MEM_SEG: {
|
||||
struct iwl_fw_dbg_mem_seg_tlv *dbg_mem =
|
||||
|
@ -1153,19 +1125,6 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If ucode advertises that it supports GSCAN but GSCAN
|
||||
* capabilities TLV is not present, or if it has an old format,
|
||||
* warn and continue without GSCAN.
|
||||
*/
|
||||
if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT) &&
|
||||
!gscan_capa) {
|
||||
IWL_DEBUG_INFO(drv,
|
||||
"GSCAN is supported but capabilities TLV is unavailable\n");
|
||||
__clear_bit((__force long)IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT,
|
||||
capa->_capa);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
invalid_tlv_len:
|
||||
|
@ -1316,6 +1275,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
|||
fw->ucode_capa.standard_phy_calibration_size =
|
||||
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
|
||||
fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
|
||||
/* dump all fw memory areas by default */
|
||||
fw->dbg_dump_mask = 0xffffffff;
|
||||
|
||||
pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
|
||||
if (!pieces)
|
||||
|
@ -1787,7 +1748,8 @@ MODULE_PARM_DESC(11n_disable,
|
|||
"disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX");
|
||||
module_param_named(amsdu_size, iwlwifi_mod_params.amsdu_size, int, 0444);
|
||||
MODULE_PARM_DESC(amsdu_size,
|
||||
"amsdu size 0: 12K for multi Rx queue devices, 4K for other devices 1:4K 2:8K 3:12K (default 0)");
|
||||
"amsdu size 0: 12K for multi Rx queue devices, 2K for 22560 devices, "
|
||||
"4K for other devices 1:4K 2:8K 3:12K 4: 2K (default 0)");
|
||||
module_param_named(fw_restart, iwlwifi_mod_params.fw_restart, bool, 0444);
|
||||
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)");
|
||||
|
||||
|
@ -1856,3 +1818,7 @@ module_param_named(remove_when_gone,
|
|||
0444);
|
||||
MODULE_PARM_DESC(remove_when_gone,
|
||||
"Remove dev from PCIe bus if it is deemed inaccessible (default: false)");
|
||||
|
||||
module_param_named(disable_11ax, iwlwifi_mod_params.disable_11ax, bool,
|
||||
S_IRUGO);
|
||||
MODULE_PARM_DESC(disable_11ax, "Disable HE capabilities (default: false)");
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -18,9 +19,7 @@
|
|||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
* along with this program;
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
|
@ -33,6 +32,7 @@
|
|||
*
|
||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -767,7 +767,7 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
|||
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
if ((cfg->mq_rx_supported &&
|
||||
iwlwifi_mod_params.amsdu_size != IWL_AMSDU_4K) ||
|
||||
iwlwifi_mod_params.amsdu_size == IWL_AMSDU_DEF) ||
|
||||
iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -18,9 +19,7 @@
|
|||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
* along with this program.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
|
@ -33,6 +32,7 @@
|
|||
*
|
||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -434,13 +434,15 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
* RXF to DRAM.
|
||||
* Once the RXF-to-DRAM DMA is active, this flag is immediately turned off.
|
||||
*/
|
||||
#define RFH_GEN_STATUS 0xA09808
|
||||
#define RFH_GEN_STATUS 0xA09808
|
||||
#define RFH_GEN_STATUS_GEN3 0xA07824
|
||||
#define RBD_FETCH_IDLE BIT(29)
|
||||
#define SRAM_DMA_IDLE BIT(30)
|
||||
#define RXF_DMA_IDLE BIT(31)
|
||||
|
||||
/* DMA configuration */
|
||||
#define RFH_RXF_DMA_CFG 0xA09820
|
||||
#define RFH_RXF_DMA_CFG 0xA09820
|
||||
#define RFH_RXF_DMA_CFG_GEN3 0xA07880
|
||||
/* RB size */
|
||||
#define RFH_RXF_DMA_RB_SIZE_MASK (0x000F0000) /* bits 16-19 */
|
||||
#define RFH_RXF_DMA_RB_SIZE_POS 16
|
||||
|
@ -643,10 +645,13 @@ struct iwl_rb_status {
|
|||
|
||||
|
||||
#define TFD_QUEUE_SIZE_MAX (256)
|
||||
#define TFD_QUEUE_SIZE_MAX_GEN3 (65536)
|
||||
/* cb size is the exponent - 3 */
|
||||
#define TFD_QUEUE_CB_SIZE(x) (ilog2(x) - 3)
|
||||
#define TFD_QUEUE_SIZE_BC_DUP (64)
|
||||
#define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
|
||||
#define TFD_QUEUE_BC_SIZE_GEN3 (TFD_QUEUE_SIZE_MAX_GEN3 + \
|
||||
TFD_QUEUE_SIZE_BC_DUP)
|
||||
#define IWL_TX_DMA_MASK DMA_BIT_MASK(36)
|
||||
#define IWL_NUM_OF_TBS 20
|
||||
#define IWL_TFH_NUM_TBS 25
|
||||
|
@ -753,7 +758,7 @@ struct iwl_tfh_tfd {
|
|||
* For devices up to 22000:
|
||||
* @tfd_offset 0-12 - tx command byte count
|
||||
* 12-16 - station index
|
||||
* For 22000 and on:
|
||||
* For 22000:
|
||||
* @tfd_offset 0-12 - tx command byte count
|
||||
* 12-13 - number of 64 byte chunks
|
||||
* 14-16 - reserved
|
||||
|
@ -762,4 +767,15 @@ struct iwlagn_scd_bc_tbl {
|
|||
__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_gen3_bc_tbl scheduler byte count table gen3
|
||||
* For 22560 and on:
|
||||
* @tfd_offset: 0-12 - tx command byte count
|
||||
* 12-13 - number of 64 byte chunks
|
||||
* 14-16 - reserved
|
||||
*/
|
||||
struct iwl_gen3_bc_tbl {
|
||||
__le16 tfd_offset[TFD_QUEUE_BC_SIZE_GEN3];
|
||||
} __packed;
|
||||
|
||||
#endif /* !__iwl_fh_h__ */
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -17,9 +18,7 @@
|
|||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
* along with this program;
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
|
@ -31,6 +30,7 @@
|
|||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -90,6 +90,8 @@ enum iwl_amsdu_size {
|
|||
IWL_AMSDU_4K = 1,
|
||||
IWL_AMSDU_8K = 2,
|
||||
IWL_AMSDU_12K = 3,
|
||||
/* Add 2K at the end to avoid breaking current API */
|
||||
IWL_AMSDU_2K = 4,
|
||||
};
|
||||
|
||||
enum iwl_uapsd_disable {
|
||||
|
@ -144,6 +146,10 @@ struct iwl_mod_params {
|
|||
bool lar_disable;
|
||||
bool fw_monitor;
|
||||
bool disable_11ac;
|
||||
/**
|
||||
* @disable_11ax: disable HE capabilities, default = false
|
||||
*/
|
||||
bool disable_11ax;
|
||||
bool remove_when_gone;
|
||||
};
|
||||
|
||||
|
|
|
@ -430,6 +430,13 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
|
|||
else
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
|
||||
break;
|
||||
case IWL_AMSDU_2K:
|
||||
if (cfg->mq_rx_supported)
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
|
||||
else
|
||||
WARN(1, "RB size of 2K is not supported by this device\n");
|
||||
break;
|
||||
case IWL_AMSDU_4K:
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
|
||||
break;
|
||||
|
@ -463,6 +470,101 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
|
|||
vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
|
||||
}
|
||||
|
||||
static struct ieee80211_sband_iftype_data iwl_he_capa = {
|
||||
.types_mask = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP),
|
||||
.he_cap = {
|
||||
.has_he = true,
|
||||
.he_cap_elem = {
|
||||
.mac_cap_info[0] =
|
||||
IEEE80211_HE_MAC_CAP0_HTC_HE,
|
||||
.mac_cap_info[1] =
|
||||
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
|
||||
IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_8,
|
||||
.mac_cap_info[2] =
|
||||
IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP |
|
||||
IEEE80211_HE_MAC_CAP2_ACK_EN,
|
||||
.mac_cap_info[3] =
|
||||
IEEE80211_HE_MAC_CAP3_GRP_ADDR_MULTI_STA_BA_DL_MU |
|
||||
IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_VHT_2,
|
||||
.mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU,
|
||||
.phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_DUAL_BAND |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G,
|
||||
.phy_cap_info[1] =
|
||||
IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD |
|
||||
IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_MAX_NSTS,
|
||||
.phy_cap_info[2] =
|
||||
IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
|
||||
IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
|
||||
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ,
|
||||
.phy_cap_info[3] =
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK |
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 |
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK |
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1,
|
||||
.phy_cap_info[4] =
|
||||
IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
|
||||
IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8 |
|
||||
IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8,
|
||||
.phy_cap_info[5] =
|
||||
IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 |
|
||||
IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2,
|
||||
.phy_cap_info[6] =
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,
|
||||
.phy_cap_info[7] =
|
||||
IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR |
|
||||
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI |
|
||||
IEEE80211_HE_PHY_CAP7_MAX_NC_7,
|
||||
.phy_cap_info[8] =
|
||||
IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
|
||||
IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU,
|
||||
},
|
||||
/*
|
||||
* Set default Tx/Rx HE MCS NSS Support field. Indicate support
|
||||
* for up to 2 spatial streams and all MCS, without any special
|
||||
* cases
|
||||
*/
|
||||
.he_mcs_nss_supp = {
|
||||
.rx_mcs_80 = cpu_to_le16(0xfffa),
|
||||
.tx_mcs_80 = cpu_to_le16(0xfffa),
|
||||
.rx_mcs_160 = cpu_to_le16(0xfffa),
|
||||
.tx_mcs_160 = cpu_to_le16(0xfffa),
|
||||
.rx_mcs_80p80 = cpu_to_le16(0xffff),
|
||||
.tx_mcs_80p80 = cpu_to_le16(0xffff),
|
||||
},
|
||||
/*
|
||||
* Set default PPE thresholds, with PPET16 set to 0, PPET8 set
|
||||
* to 7
|
||||
*/
|
||||
.ppe_thres = {0x61, 0x1c, 0xc7, 0x71},
|
||||
},
|
||||
};
|
||||
|
||||
static void iwl_init_he_hw_capab(struct ieee80211_supported_band *sband,
|
||||
u8 tx_chains, u8 rx_chains)
|
||||
{
|
||||
if (sband->band == NL80211_BAND_2GHZ ||
|
||||
sband->band == NL80211_BAND_5GHZ)
|
||||
sband->iftype_data = &iwl_he_capa;
|
||||
else
|
||||
return;
|
||||
|
||||
sband->n_iftype_data = 1;
|
||||
|
||||
/* If not 2x2, we need to indicate 1x1 in the Midamble RX Max NSTS */
|
||||
if ((tx_chains & rx_chains) != ANT_AB) {
|
||||
iwl_he_capa.he_cap.he_cap_elem.phy_cap_info[1] &=
|
||||
~IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_MAX_NSTS;
|
||||
iwl_he_capa.he_cap.he_cap_elem.phy_cap_info[2] &=
|
||||
~IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_MAX_NSTS;
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
const __le16 *nvm_ch_flags, u8 tx_chains,
|
||||
|
@ -483,6 +585,9 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
|||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_2GHZ,
|
||||
tx_chains, rx_chains);
|
||||
|
||||
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
|
||||
iwl_init_he_hw_capab(sband, tx_chains, rx_chains);
|
||||
|
||||
sband = &data->bands[NL80211_BAND_5GHZ];
|
||||
sband->band = NL80211_BAND_5GHZ;
|
||||
sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
|
||||
|
@ -495,6 +600,9 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
|||
iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap,
|
||||
tx_chains, rx_chains);
|
||||
|
||||
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
|
||||
iwl_init_he_hw_capab(sband, tx_chains, rx_chains);
|
||||
|
||||
if (n_channels != n_used)
|
||||
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
|
||||
n_used, n_channels);
|
||||
|
@ -1293,6 +1401,8 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
|||
!!(mac_flags & NVM_MAC_SKU_FLAGS_802_11AC_ENABLED);
|
||||
nvm->sku_cap_11n_enable =
|
||||
!!(mac_flags & NVM_MAC_SKU_FLAGS_802_11N_ENABLED);
|
||||
nvm->sku_cap_11ax_enable =
|
||||
!!(mac_flags & NVM_MAC_SKU_FLAGS_802_11AX_ENABLED);
|
||||
nvm->sku_cap_band_24ghz_enable =
|
||||
!!(mac_flags & NVM_MAC_SKU_FLAGS_BAND_2_4_ENABLED);
|
||||
nvm->sku_cap_band_52ghz_enable =
|
||||
|
|
|
@ -350,6 +350,8 @@ static inline int
|
|||
iwl_trans_get_rb_size_order(enum iwl_amsdu_size rb_size)
|
||||
{
|
||||
switch (rb_size) {
|
||||
case IWL_AMSDU_2K:
|
||||
return get_order(2 * 1024);
|
||||
case IWL_AMSDU_4K:
|
||||
return get_order(4 * 1024);
|
||||
case IWL_AMSDU_8K:
|
||||
|
@ -437,6 +439,20 @@ struct iwl_trans_txq_scd_cfg {
|
|||
int frame_limit;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans_rxq_dma_data - RX queue DMA data
|
||||
* @fr_bd_cb: DMA address of free BD cyclic buffer
|
||||
* @fr_bd_wid: Initial write index of the free BD cyclic buffer
|
||||
* @urbd_stts_wrptr: DMA address of urbd_stts_wrptr
|
||||
* @ur_bd_cb: DMA address of used BD cyclic buffer
|
||||
*/
|
||||
struct iwl_trans_rxq_dma_data {
|
||||
u64 fr_bd_cb;
|
||||
u32 fr_bd_wid;
|
||||
u64 urbd_stts_wrptr;
|
||||
u64 ur_bd_cb;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans_ops - transport specific operations
|
||||
*
|
||||
|
@ -557,6 +573,8 @@ struct iwl_trans_ops {
|
|||
int cmd_id, int size,
|
||||
unsigned int queue_wdg_timeout);
|
||||
void (*txq_free)(struct iwl_trans *trans, int queue);
|
||||
int (*rxq_dma_data)(struct iwl_trans *trans, int queue,
|
||||
struct iwl_trans_rxq_dma_data *data);
|
||||
|
||||
void (*txq_set_shared_mode)(struct iwl_trans *trans, u32 txq_id,
|
||||
bool shared);
|
||||
|
@ -753,6 +771,7 @@ struct iwl_trans {
|
|||
const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv;
|
||||
const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
|
||||
struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv;
|
||||
u32 dbg_dump_mask;
|
||||
u8 dbg_dest_reg_num;
|
||||
|
||||
enum iwl_plat_pm_mode system_pm_mode;
|
||||
|
@ -945,6 +964,16 @@ iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn,
|
|||
cfg, queue_wdg_timeout);
|
||||
}
|
||||
|
||||
static inline int
|
||||
iwl_trans_get_rxq_dma_data(struct iwl_trans *trans, int queue,
|
||||
struct iwl_trans_rxq_dma_data *data)
|
||||
{
|
||||
if (WARN_ON_ONCE(!trans->ops->rxq_dma_data))
|
||||
return -ENOTSUPP;
|
||||
|
||||
return trans->ops->rxq_dma_data(trans, queue, data);
|
||||
}
|
||||
|
||||
static inline void
|
||||
iwl_trans_txq_free(struct iwl_trans *trans, int queue)
|
||||
{
|
||||
|
|
|
@ -1037,6 +1037,13 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
|
|||
cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TODO: this is needed because the firmware is not stopping
|
||||
* the recording automatically before entering D3. This can
|
||||
* be removed once the FW starts doing that.
|
||||
*/
|
||||
iwl_fw_dbg_stop_recording(&mvm->fwrt);
|
||||
|
||||
/* must be last -- this switches firmware state */
|
||||
ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
|
||||
if (ret)
|
||||
|
|
|
@ -1150,6 +1150,10 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
|
|||
struct iwl_rx_mpdu_desc *desc;
|
||||
int bin_len = count / 2;
|
||||
int ret = -EINVAL;
|
||||
size_t mpdu_cmd_hdr_size =
|
||||
(mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) ?
|
||||
sizeof(struct iwl_rx_mpdu_desc) :
|
||||
IWL_RX_DESC_SIZE_V1;
|
||||
|
||||
if (!iwl_mvm_firmware_running(mvm))
|
||||
return -EIO;
|
||||
|
@ -1168,7 +1172,7 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
|
|||
goto out;
|
||||
|
||||
/* avoid invalid memory access */
|
||||
if (bin_len < sizeof(*pkt) + sizeof(*desc))
|
||||
if (bin_len < sizeof(*pkt) + mpdu_cmd_hdr_size)
|
||||
goto out;
|
||||
|
||||
/* check this is RX packet */
|
||||
|
@ -1179,7 +1183,7 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
|
|||
/* check the length in metadata matches actual received length */
|
||||
desc = (void *)pkt->data;
|
||||
if (le16_to_cpu(desc->mpdu_len) !=
|
||||
(bin_len - sizeof(*desc) - sizeof(*pkt)))
|
||||
(bin_len - mpdu_cmd_hdr_size - sizeof(*pkt)))
|
||||
goto out;
|
||||
|
||||
local_bh_disable();
|
||||
|
|
|
@ -130,6 +130,41 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm)
|
|||
return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
static int iwl_configure_rxq(struct iwl_mvm *mvm)
|
||||
{
|
||||
int i, num_queues, size;
|
||||
struct iwl_rfh_queue_config *cmd;
|
||||
|
||||
/* Do not configure default queue, it is configured via context info */
|
||||
num_queues = mvm->trans->num_rx_queues - 1;
|
||||
|
||||
size = sizeof(*cmd) + num_queues * sizeof(struct iwl_rfh_queue_data);
|
||||
|
||||
cmd = kzalloc(size, GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd->num_queues = num_queues;
|
||||
|
||||
for (i = 0; i < num_queues; i++) {
|
||||
struct iwl_trans_rxq_dma_data data;
|
||||
|
||||
cmd->data[i].q_num = i + 1;
|
||||
iwl_trans_get_rxq_dma_data(mvm->trans, i + 1, &data);
|
||||
|
||||
cmd->data[i].fr_bd_cb = cpu_to_le64(data.fr_bd_cb);
|
||||
cmd->data[i].urbd_stts_wrptr =
|
||||
cpu_to_le64(data.urbd_stts_wrptr);
|
||||
cmd->data[i].ur_bd_cb = cpu_to_le64(data.ur_bd_cb);
|
||||
cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid);
|
||||
}
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(DATA_PATH_GROUP,
|
||||
RFH_QUEUE_CONFIG_CMD),
|
||||
0, size, cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_send_dqa_cmd(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_dqa_enable_cmd dqa_cmd = {
|
||||
|
@ -301,7 +336,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
if (ret) {
|
||||
struct iwl_trans *trans = mvm->trans;
|
||||
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22000)
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000)
|
||||
IWL_ERR(mvm,
|
||||
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
|
||||
iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS),
|
||||
|
@ -1007,9 +1042,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
goto error;
|
||||
|
||||
/* Init RSS configuration */
|
||||
/* TODO - remove 22000 disablement when we have RXQ config API */
|
||||
if (iwl_mvm_has_new_rx_api(mvm) &&
|
||||
mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_22000) {
|
||||
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
|
||||
ret = iwl_configure_rxq(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to configure RX queues: %d\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (iwl_mvm_has_new_rx_api(mvm)) {
|
||||
ret = iwl_send_rss_cfg_cmd(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to configure RSS queues: %d\n",
|
||||
|
|
|
@ -780,6 +780,10 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
|||
if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p)
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
|
||||
if (vif->bss_conf.assoc && vif->bss_conf.he_support &&
|
||||
!iwlwifi_mod_params.disable_11ax)
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
|
||||
|
||||
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -914,7 +915,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||
enum ieee80211_ampdu_mlme_action action = params->action;
|
||||
u16 tid = params->tid;
|
||||
u16 *ssn = ¶ms->ssn;
|
||||
u8 buf_size = params->buf_size;
|
||||
u16 buf_size = params->buf_size;
|
||||
bool amsdu = params->amsdu;
|
||||
u16 timeout = params->timeout;
|
||||
|
||||
|
@ -1897,6 +1898,194 @@ void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm,
|
|||
iwl_mvm_mu_mimo_iface_iterator, notif);
|
||||
}
|
||||
|
||||
static u8 iwl_mvm_he_get_ppe_val(u8 *ppe, u8 ppe_pos_bit)
|
||||
{
|
||||
u8 byte_num = ppe_pos_bit / 8;
|
||||
u8 bit_num = ppe_pos_bit % 8;
|
||||
u8 residue_bits;
|
||||
u8 res;
|
||||
|
||||
if (bit_num <= 5)
|
||||
return (ppe[byte_num] >> bit_num) &
|
||||
(BIT(IEEE80211_PPE_THRES_INFO_PPET_SIZE) - 1);
|
||||
|
||||
/*
|
||||
* If bit_num > 5, we have to combine bits with next byte.
|
||||
* Calculate how many bits we need to take from current byte (called
|
||||
* here "residue_bits"), and add them to bits from next byte.
|
||||
*/
|
||||
|
||||
residue_bits = 8 - bit_num;
|
||||
|
||||
res = (ppe[byte_num + 1] &
|
||||
(BIT(IEEE80211_PPE_THRES_INFO_PPET_SIZE - residue_bits) - 1)) <<
|
||||
residue_bits;
|
||||
res += (ppe[byte_num] >> bit_num) & (BIT(residue_bits) - 1);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif, u8 sta_id)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_he_sta_context_cmd sta_ctxt_cmd = {
|
||||
.sta_id = sta_id,
|
||||
.tid_limit = IWL_MAX_TID_COUNT,
|
||||
.bss_color = vif->bss_conf.bss_color,
|
||||
.htc_trig_based_pkt_ext = vif->bss_conf.htc_trig_based_pkt_ext,
|
||||
.frame_time_rts_th =
|
||||
cpu_to_le16(vif->bss_conf.frame_time_rts_th),
|
||||
};
|
||||
struct ieee80211_sta *sta;
|
||||
u32 flags;
|
||||
int i;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_ctxt_cmd.sta_id]);
|
||||
if (IS_ERR(sta)) {
|
||||
rcu_read_unlock();
|
||||
WARN(1, "Can't find STA to configure HE\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sta->he_cap.has_he) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
|
||||
/* HTC flags */
|
||||
if (sta->he_cap.he_cap_elem.mac_cap_info[0] &
|
||||
IEEE80211_HE_MAC_CAP0_HTC_HE)
|
||||
sta_ctxt_cmd.htc_flags |= cpu_to_le32(IWL_HE_HTC_SUPPORT);
|
||||
if ((sta->he_cap.he_cap_elem.mac_cap_info[1] &
|
||||
IEEE80211_HE_MAC_CAP1_LINK_ADAPTATION) ||
|
||||
(sta->he_cap.he_cap_elem.mac_cap_info[2] &
|
||||
IEEE80211_HE_MAC_CAP2_LINK_ADAPTATION)) {
|
||||
u8 link_adap =
|
||||
((sta->he_cap.he_cap_elem.mac_cap_info[2] &
|
||||
IEEE80211_HE_MAC_CAP2_LINK_ADAPTATION) << 1) +
|
||||
(sta->he_cap.he_cap_elem.mac_cap_info[1] &
|
||||
IEEE80211_HE_MAC_CAP1_LINK_ADAPTATION);
|
||||
|
||||
if (link_adap == 2)
|
||||
sta_ctxt_cmd.htc_flags |=
|
||||
cpu_to_le32(IWL_HE_HTC_LINK_ADAP_UNSOLICITED);
|
||||
else if (link_adap == 3)
|
||||
sta_ctxt_cmd.htc_flags |=
|
||||
cpu_to_le32(IWL_HE_HTC_LINK_ADAP_BOTH);
|
||||
}
|
||||
if (sta->he_cap.he_cap_elem.mac_cap_info[2] &
|
||||
IEEE80211_HE_MAC_CAP2_UL_MU_RESP_SCHED)
|
||||
sta_ctxt_cmd.htc_flags |=
|
||||
cpu_to_le32(IWL_HE_HTC_UL_MU_RESP_SCHED);
|
||||
if (sta->he_cap.he_cap_elem.mac_cap_info[2] & IEEE80211_HE_MAC_CAP2_BSR)
|
||||
sta_ctxt_cmd.htc_flags |= cpu_to_le32(IWL_HE_HTC_BSR_SUPP);
|
||||
if (sta->he_cap.he_cap_elem.mac_cap_info[3] &
|
||||
IEEE80211_HE_MAC_CAP3_OMI_CONTROL)
|
||||
sta_ctxt_cmd.htc_flags |= cpu_to_le32(IWL_HE_HTC_OMI_SUPP);
|
||||
if (sta->he_cap.he_cap_elem.mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_BQR)
|
||||
sta_ctxt_cmd.htc_flags |= cpu_to_le32(IWL_HE_HTC_BQR_SUPP);
|
||||
|
||||
/* If PPE Thresholds exist, parse them into a FW-familiar format */
|
||||
if (sta->he_cap.he_cap_elem.phy_cap_info[6] &
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
|
||||
u8 nss = (sta->he_cap.ppe_thres[0] &
|
||||
IEEE80211_PPE_THRES_NSS_MASK) + 1;
|
||||
u8 ru_index_bitmap =
|
||||
(sta->he_cap.ppe_thres[0] &
|
||||
IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK) >>
|
||||
IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS;
|
||||
u8 *ppe = &sta->he_cap.ppe_thres[0];
|
||||
u8 ppe_pos_bit = 7; /* Starting after PPE header */
|
||||
|
||||
/*
|
||||
* FW currently supports only nss == MAX_HE_SUPP_NSS
|
||||
*
|
||||
* If nss > MAX: we can ignore values we don't support
|
||||
* If nss < MAX: we can set zeros in other streams
|
||||
*/
|
||||
if (nss > MAX_HE_SUPP_NSS) {
|
||||
IWL_INFO(mvm, "Got NSS = %d - trimming to %d\n", nss,
|
||||
MAX_HE_SUPP_NSS);
|
||||
nss = MAX_HE_SUPP_NSS;
|
||||
}
|
||||
|
||||
for (i = 0; i < nss; i++) {
|
||||
u8 ru_index_tmp = ru_index_bitmap << 1;
|
||||
u8 bw;
|
||||
|
||||
for (bw = 0; bw < MAX_HE_CHANNEL_BW_INDX; bw++) {
|
||||
ru_index_tmp >>= 1;
|
||||
if (!(ru_index_tmp & 1))
|
||||
continue;
|
||||
|
||||
sta_ctxt_cmd.pkt_ext.pkt_ext_qam_th[i][bw][1] =
|
||||
iwl_mvm_he_get_ppe_val(ppe,
|
||||
ppe_pos_bit);
|
||||
ppe_pos_bit +=
|
||||
IEEE80211_PPE_THRES_INFO_PPET_SIZE;
|
||||
sta_ctxt_cmd.pkt_ext.pkt_ext_qam_th[i][bw][0] =
|
||||
iwl_mvm_he_get_ppe_val(ppe,
|
||||
ppe_pos_bit);
|
||||
ppe_pos_bit +=
|
||||
IEEE80211_PPE_THRES_INFO_PPET_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
flags |= STA_CTXT_HE_PACKET_EXT;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
/* Mark MU EDCA as enabled, unless none detected on some AC */
|
||||
flags |= STA_CTXT_HE_MU_EDCA_CW;
|
||||
for (i = 0; i < AC_NUM; i++) {
|
||||
struct ieee80211_he_mu_edca_param_ac_rec *mu_edca =
|
||||
&mvmvif->queue_params[i].mu_edca_param_rec;
|
||||
|
||||
if (!mvmvif->queue_params[i].mu_edca) {
|
||||
flags &= ~STA_CTXT_HE_MU_EDCA_CW;
|
||||
break;
|
||||
}
|
||||
|
||||
sta_ctxt_cmd.trig_based_txf[i].cwmin =
|
||||
cpu_to_le16(mu_edca->ecw_min_max & 0xf);
|
||||
sta_ctxt_cmd.trig_based_txf[i].cwmax =
|
||||
cpu_to_le16((mu_edca->ecw_min_max & 0xf0) >> 4);
|
||||
sta_ctxt_cmd.trig_based_txf[i].aifsn =
|
||||
cpu_to_le16(mu_edca->aifsn);
|
||||
sta_ctxt_cmd.trig_based_txf[i].mu_time =
|
||||
cpu_to_le16(mu_edca->mu_edca_timer);
|
||||
}
|
||||
|
||||
if (vif->bss_conf.multi_sta_back_32bit)
|
||||
flags |= STA_CTXT_HE_32BIT_BA_BITMAP;
|
||||
|
||||
if (vif->bss_conf.ack_enabled)
|
||||
flags |= STA_CTXT_HE_ACK_ENABLED;
|
||||
|
||||
if (vif->bss_conf.uora_exists) {
|
||||
flags |= STA_CTXT_HE_TRIG_RND_ALLOC;
|
||||
|
||||
sta_ctxt_cmd.rand_alloc_ecwmin =
|
||||
vif->bss_conf.uora_ocw_range & 0x7;
|
||||
sta_ctxt_cmd.rand_alloc_ecwmax =
|
||||
(vif->bss_conf.uora_ocw_range >> 3) & 0x7;
|
||||
}
|
||||
|
||||
/* TODO: support Multi BSSID IE */
|
||||
|
||||
sta_ctxt_cmd.flags = cpu_to_le32(flags);
|
||||
|
||||
if (iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(STA_HE_CTXT_CMD,
|
||||
DATA_PATH_GROUP, 0),
|
||||
0, sizeof(sta_ctxt_cmd), &sta_ctxt_cmd))
|
||||
IWL_ERR(mvm, "Failed to config FW to work HE!\n");
|
||||
}
|
||||
|
||||
static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
|
@ -1910,8 +2099,13 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
|
|||
* beacon interval, which was not known when the station interface was
|
||||
* added.
|
||||
*/
|
||||
if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc)
|
||||
if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) {
|
||||
if (vif->bss_conf.he_support &&
|
||||
!iwlwifi_mod_params.disable_11ax)
|
||||
iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->ap_sta_id);
|
||||
|
||||
iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're not associated yet, take the (new) BSSID before associating
|
||||
|
@ -4364,13 +4558,6 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
|
|||
atomic_set(&mvm->queue_sync_counter,
|
||||
mvm->trans->num_rx_queues);
|
||||
|
||||
/* TODO - remove this when we have RXQ config API */
|
||||
if (mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_22000) {
|
||||
qmask = BIT(0);
|
||||
if (notif->sync)
|
||||
atomic_set(&mvm->queue_sync_counter, 1);
|
||||
}
|
||||
|
||||
ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif, size);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
|
||||
|
|
|
@ -654,7 +654,7 @@ struct iwl_mvm_tcm {
|
|||
struct iwl_mvm_reorder_buffer {
|
||||
u16 head_sn;
|
||||
u16 num_stored;
|
||||
u8 buf_size;
|
||||
u16 buf_size;
|
||||
int queue;
|
||||
u16 last_amsdu;
|
||||
u8 last_sub_index;
|
||||
|
|
|
@ -448,6 +448,8 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
|||
HCMD_NAME(DQA_ENABLE_CMD),
|
||||
HCMD_NAME(UPDATE_MU_GROUPS_CMD),
|
||||
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
|
||||
HCMD_NAME(STA_HE_CTXT_CMD),
|
||||
HCMD_NAME(RFH_QUEUE_CONFIG_CMD),
|
||||
HCMD_NAME(STA_PM_NOTIF),
|
||||
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
|
||||
HCMD_NAME(RX_QUEUES_NOTIFICATION),
|
||||
|
@ -620,7 +622,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
|
||||
if (iwl_mvm_has_new_rx_api(mvm)) {
|
||||
op_mode->ops = &iwl_mvm_ops_mq;
|
||||
trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc);
|
||||
trans->rx_mpdu_cmd_hdr_size =
|
||||
(trans->cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_22560) ?
|
||||
sizeof(struct iwl_rx_mpdu_desc) :
|
||||
IWL_RX_DESC_SIZE_V1;
|
||||
} else {
|
||||
op_mode->ops = &iwl_mvm_ops;
|
||||
trans->rx_mpdu_cmd_hdr_size =
|
||||
|
@ -703,11 +709,17 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
}
|
||||
|
||||
/* the hardware splits the A-MSDU */
|
||||
if (mvm->cfg->mq_rx_supported)
|
||||
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_2K;
|
||||
/* TODO: remove when balanced power mode is fw supported */
|
||||
iwlmvm_mod_params.power_scheme = IWL_POWER_SCHEME_CAM;
|
||||
} else if (mvm->cfg->mq_rx_supported) {
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
}
|
||||
|
||||
trans->wide_cmd_header = true;
|
||||
trans_cfg.bc_table_dword = true;
|
||||
trans_cfg.bc_table_dword =
|
||||
mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_22560;
|
||||
|
||||
trans_cfg.command_groups = iwl_mvm_groups;
|
||||
trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups);
|
||||
|
@ -738,6 +750,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv,
|
||||
sizeof(trans->dbg_conf_tlv));
|
||||
trans->dbg_trigger_tlv = mvm->fw->dbg_trigger_tlv;
|
||||
trans->dbg_dump_mask = mvm->fw->dbg_dump_mask;
|
||||
|
||||
trans->iml = mvm->fw->iml;
|
||||
trans->iml_len = mvm->fw->iml_len;
|
||||
|
@ -1003,10 +1016,8 @@ static void iwl_mvm_rx_common(struct iwl_mvm *mvm,
|
|||
list_add_tail(&entry->list, &mvm->async_handlers_list);
|
||||
spin_unlock(&mvm->async_handlers_lock);
|
||||
schedule_work(&mvm->async_handlers_wk);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
iwl_fwrt_handle_notification(&mvm->fwrt, rxb);
|
||||
}
|
||||
|
||||
static void iwl_mvm_rx(struct iwl_op_mode *op_mode,
|
||||
|
|
|
@ -183,6 +183,43 @@ rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
|
|||
}
|
||||
}
|
||||
|
||||
static u16 rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs)
|
||||
{
|
||||
switch (mcs) {
|
||||
case IEEE80211_HE_MCS_SUPPORT_0_7:
|
||||
return BIT(IWL_TLC_MNG_HT_RATE_MCS7 + 1) - 1;
|
||||
case IEEE80211_HE_MCS_SUPPORT_0_9:
|
||||
return BIT(IWL_TLC_MNG_HT_RATE_MCS9 + 1) - 1;
|
||||
case IEEE80211_HE_MCS_SUPPORT_0_11:
|
||||
return BIT(IWL_TLC_MNG_HT_RATE_MCS11 + 1) - 1;
|
||||
case IEEE80211_HE_MCS_NOT_SUPPORTED:
|
||||
return 0;
|
||||
}
|
||||
|
||||
WARN(1, "invalid HE MCS %d\n", mcs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
|
||||
const struct ieee80211_sta_he_cap *he_cap,
|
||||
struct iwl_tlc_config_cmd *cmd)
|
||||
{
|
||||
u16 mcs_160 = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_160);
|
||||
u16 mcs_80 = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sta->rx_nss && i < MAX_NSS; i++) {
|
||||
u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3;
|
||||
u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3;
|
||||
|
||||
cmd->ht_rates[i][0] =
|
||||
cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80));
|
||||
cmd->ht_rates[i][1] =
|
||||
cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160));
|
||||
}
|
||||
}
|
||||
|
||||
static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
|
||||
struct ieee80211_supported_band *sband,
|
||||
struct iwl_tlc_config_cmd *cmd)
|
||||
|
@ -192,6 +229,7 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
|
|||
unsigned long supp; /* must be unsigned long for for_each_set_bit */
|
||||
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
|
||||
const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
|
||||
|
||||
/* non HT rates */
|
||||
supp = 0;
|
||||
|
@ -202,7 +240,11 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
|
|||
cmd->non_ht_rates = cpu_to_le16(supp);
|
||||
cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
|
||||
|
||||
if (vht_cap && vht_cap->vht_supported) {
|
||||
/* HT/VHT rates */
|
||||
if (he_cap && he_cap->has_he) {
|
||||
cmd->mode = IWL_TLC_MNG_MODE_HE;
|
||||
rs_fw_he_set_enabled_rates(sta, he_cap, cmd);
|
||||
} else if (vht_cap && vht_cap->vht_supported) {
|
||||
cmd->mode = IWL_TLC_MNG_MODE_VHT;
|
||||
rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
|
||||
} else if (ht_cap && ht_cap->ht_supported) {
|
||||
|
|
|
@ -363,7 +363,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
|
|||
idx += 1;
|
||||
if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE))
|
||||
return idx;
|
||||
} else if (rate_n_flags & RATE_MCS_VHT_MSK) {
|
||||
} else if (rate_n_flags & RATE_MCS_VHT_MSK ||
|
||||
rate_n_flags & RATE_MCS_HE_MSK) {
|
||||
idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
|
||||
idx += IWL_RATE_MCS_0_INDEX;
|
||||
|
||||
|
@ -372,6 +373,9 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
|
|||
idx++;
|
||||
if ((idx >= IWL_FIRST_VHT_RATE) && (idx <= IWL_LAST_VHT_RATE))
|
||||
return idx;
|
||||
if ((rate_n_flags & RATE_MCS_HE_MSK) &&
|
||||
(idx <= IWL_LAST_HE_RATE))
|
||||
return idx;
|
||||
} else {
|
||||
/* legacy rate format, search for match in table */
|
||||
|
||||
|
@ -516,6 +520,8 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type)
|
|||
[LQ_HT_MIMO2] = "HT MIMO",
|
||||
[LQ_VHT_SISO] = "VHT SISO",
|
||||
[LQ_VHT_MIMO2] = "VHT MIMO",
|
||||
[LQ_HE_SISO] = "HE SISO",
|
||||
[LQ_HE_MIMO2] = "HE MIMO",
|
||||
};
|
||||
|
||||
if (type < LQ_NONE || type >= LQ_MAX)
|
||||
|
@ -900,7 +906,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
|
|||
|
||||
/* Legacy */
|
||||
if (!(ucode_rate & RATE_MCS_HT_MSK) &&
|
||||
!(ucode_rate & RATE_MCS_VHT_MSK)) {
|
||||
!(ucode_rate & RATE_MCS_VHT_MSK) &&
|
||||
!(ucode_rate & RATE_MCS_HE_MSK)) {
|
||||
if (num_of_ant == 1) {
|
||||
if (band == NL80211_BAND_5GHZ)
|
||||
rate->type = LQ_LEGACY_A;
|
||||
|
@ -911,7 +918,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* HT or VHT */
|
||||
/* HT, VHT or HE */
|
||||
if (ucode_rate & RATE_MCS_SGI_MSK)
|
||||
rate->sgi = true;
|
||||
if (ucode_rate & RATE_MCS_LDPC_MSK)
|
||||
|
@ -953,10 +960,24 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
|
|||
} else {
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
} else if (ucode_rate & RATE_MCS_HE_MSK) {
|
||||
nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>
|
||||
RATE_VHT_MCS_NSS_POS) + 1;
|
||||
|
||||
if (nss == 1) {
|
||||
rate->type = LQ_HE_SISO;
|
||||
WARN_ONCE(!rate->stbc && !rate->bfer && num_of_ant != 1,
|
||||
"stbc %d bfer %d", rate->stbc, rate->bfer);
|
||||
} else if (nss == 2) {
|
||||
rate->type = LQ_HE_MIMO2;
|
||||
WARN_ON_ONCE(num_of_ant != 2);
|
||||
} else {
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(rate->bw == RATE_MCS_CHAN_WIDTH_80 &&
|
||||
!is_vht(rate));
|
||||
!is_he(rate) && !is_vht(rate));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3606,7 +3627,8 @@ int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
|
|||
u8 ant = (rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS;
|
||||
|
||||
if (!(rate & RATE_MCS_HT_MSK) &&
|
||||
!(rate & RATE_MCS_VHT_MSK)) {
|
||||
!(rate & RATE_MCS_VHT_MSK) &&
|
||||
!(rate & RATE_MCS_HE_MSK)) {
|
||||
int index = iwl_hwrate_to_plcp_idx(rate);
|
||||
|
||||
return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps\n",
|
||||
|
@ -3625,6 +3647,11 @@ int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
|
|||
mcs = rate & RATE_HT_MCS_INDEX_MSK;
|
||||
nss = ((rate & RATE_HT_MCS_NSS_MSK)
|
||||
>> RATE_HT_MCS_NSS_POS) + 1;
|
||||
} else if (rate & RATE_MCS_HE_MSK) {
|
||||
type = "HE";
|
||||
mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
|
||||
nss = ((rate & RATE_VHT_MCS_NSS_MSK)
|
||||
>> RATE_VHT_MCS_NSS_POS) + 1;
|
||||
} else {
|
||||
type = "Unknown"; /* shouldn't happen */
|
||||
}
|
||||
|
@ -3886,6 +3913,8 @@ static ssize_t rs_sta_dbgfs_drv_tx_stats_read(struct file *file,
|
|||
[IWL_RATE_MCS_7_INDEX] = "MCS7",
|
||||
[IWL_RATE_MCS_8_INDEX] = "MCS8",
|
||||
[IWL_RATE_MCS_9_INDEX] = "MCS9",
|
||||
[IWL_RATE_MCS_10_INDEX] = "MCS10",
|
||||
[IWL_RATE_MCS_11_INDEX] = "MCS11",
|
||||
};
|
||||
|
||||
char *buff, *pos, *endpos;
|
||||
|
|
|
@ -144,8 +144,13 @@ enum {
|
|||
|
||||
#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63)
|
||||
#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63)
|
||||
#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (64)
|
||||
#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (64)
|
||||
/*
|
||||
* FIXME - various places in firmware API still use u8,
|
||||
* e.g. LQ command and SCD config command.
|
||||
* This should be 256 instead.
|
||||
*/
|
||||
#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (255)
|
||||
#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (255)
|
||||
#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0)
|
||||
|
||||
#define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */
|
||||
|
@ -162,6 +167,8 @@ enum iwl_table_type {
|
|||
LQ_HT_MIMO2,
|
||||
LQ_VHT_SISO, /* VHT types */
|
||||
LQ_VHT_MIMO2,
|
||||
LQ_HE_SISO, /* HE types */
|
||||
LQ_HE_MIMO2,
|
||||
LQ_MAX,
|
||||
};
|
||||
|
||||
|
@ -183,11 +190,16 @@ struct rs_rate {
|
|||
#define is_type_ht_mimo2(type) ((type) == LQ_HT_MIMO2)
|
||||
#define is_type_vht_siso(type) ((type) == LQ_VHT_SISO)
|
||||
#define is_type_vht_mimo2(type) ((type) == LQ_VHT_MIMO2)
|
||||
#define is_type_siso(type) (is_type_ht_siso(type) || is_type_vht_siso(type))
|
||||
#define is_type_mimo2(type) (is_type_ht_mimo2(type) || is_type_vht_mimo2(type))
|
||||
#define is_type_he_siso(type) ((type) == LQ_HE_SISO)
|
||||
#define is_type_he_mimo2(type) ((type) == LQ_HE_MIMO2)
|
||||
#define is_type_siso(type) (is_type_ht_siso(type) || is_type_vht_siso(type) || \
|
||||
is_type_he_siso(type))
|
||||
#define is_type_mimo2(type) (is_type_ht_mimo2(type) || \
|
||||
is_type_vht_mimo2(type) || is_type_he_mimo2(type))
|
||||
#define is_type_mimo(type) (is_type_mimo2(type))
|
||||
#define is_type_ht(type) (is_type_ht_siso(type) || is_type_ht_mimo2(type))
|
||||
#define is_type_vht(type) (is_type_vht_siso(type) || is_type_vht_mimo2(type))
|
||||
#define is_type_he(type) (is_type_he_siso(type) || is_type_he_mimo2(type))
|
||||
#define is_type_a_band(type) ((type) == LQ_LEGACY_A)
|
||||
#define is_type_g_band(type) ((type) == LQ_LEGACY_G)
|
||||
|
||||
|
@ -201,6 +213,7 @@ struct rs_rate {
|
|||
#define is_mimo(rate) is_type_mimo((rate)->type)
|
||||
#define is_ht(rate) is_type_ht((rate)->type)
|
||||
#define is_vht(rate) is_type_vht((rate)->type)
|
||||
#define is_he(rate) is_type_he((rate)->type)
|
||||
#define is_a_band(rate) is_type_a_band((rate)->type)
|
||||
#define is_g_band(rate) is_type_g_band((rate)->type)
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -30,6 +31,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -196,22 +198,31 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
|
|||
struct sk_buff *skb, int queue,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
if (iwl_mvm_check_pn(mvm, skb, queue, sta))
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
if (iwl_mvm_check_pn(mvm, skb, queue, sta)) {
|
||||
kfree_skb(skb);
|
||||
else
|
||||
} else {
|
||||
unsigned int radiotap_len = 0;
|
||||
|
||||
if (rx_status->flag & RX_FLAG_RADIOTAP_HE)
|
||||
radiotap_len += sizeof(struct ieee80211_radiotap_he);
|
||||
if (rx_status->flag & RX_FLAG_RADIOTAP_HE_MU)
|
||||
radiotap_len += sizeof(struct ieee80211_radiotap_he_mu);
|
||||
__skb_push(skb, radiotap_len);
|
||||
ieee80211_rx_napi(mvm->hw, sta, skb, napi);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_mpdu_desc *desc,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
u32 rate_n_flags, int energy_a,
|
||||
int energy_b)
|
||||
{
|
||||
int energy_a, energy_b, max_energy;
|
||||
u32 rate_flags = le32_to_cpu(desc->rate_n_flags);
|
||||
int max_energy;
|
||||
u32 rate_flags = rate_n_flags;
|
||||
|
||||
energy_a = desc->energy_a;
|
||||
energy_a = energy_a ? -energy_a : S8_MIN;
|
||||
energy_b = desc->energy_b;
|
||||
energy_b = energy_b ? -energy_b : S8_MIN;
|
||||
max_energy = max(energy_a, energy_b);
|
||||
|
||||
|
@ -356,7 +367,8 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
|
|||
tid = IWL_MAX_TID_COUNT;
|
||||
|
||||
/* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */
|
||||
sub_frame_idx = desc->amsdu_info & IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
|
||||
sub_frame_idx = desc->amsdu_info &
|
||||
IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
|
||||
|
||||
if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
|
||||
dup_data->last_seq[tid] == hdr->seq_ctrl &&
|
||||
|
@ -850,17 +862,41 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
struct ieee80211_rx_status *rx_status;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
|
||||
struct ieee80211_hdr *hdr = (void *)(pkt->data + sizeof(*desc));
|
||||
struct ieee80211_hdr *hdr;
|
||||
u32 len = le16_to_cpu(desc->mpdu_len);
|
||||
u32 rate_n_flags = le32_to_cpu(desc->rate_n_flags);
|
||||
u32 rate_n_flags, gp2_on_air_rise;
|
||||
u16 phy_info = le16_to_cpu(desc->phy_info);
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct sk_buff *skb;
|
||||
u8 crypt_len = 0;
|
||||
u8 crypt_len = 0, channel, energy_a, energy_b;
|
||||
struct ieee80211_radiotap_he *he = NULL;
|
||||
struct ieee80211_radiotap_he_mu *he_mu = NULL;
|
||||
u32 he_type = 0xffffffff;
|
||||
/* this is invalid e.g. because puncture type doesn't allow 0b11 */
|
||||
#define HE_PHY_DATA_INVAL ((u64)-1)
|
||||
u64 he_phy_data = HE_PHY_DATA_INVAL;
|
||||
size_t desc_size;
|
||||
|
||||
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
|
||||
return;
|
||||
|
||||
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
|
||||
rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
|
||||
channel = desc->v3.channel;
|
||||
gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
|
||||
energy_a = desc->v3.energy_a;
|
||||
energy_b = desc->v3.energy_b;
|
||||
desc_size = sizeof(*desc);
|
||||
} else {
|
||||
rate_n_flags = le32_to_cpu(desc->v1.rate_n_flags);
|
||||
channel = desc->v1.channel;
|
||||
gp2_on_air_rise = le32_to_cpu(desc->v1.gp2_on_air_rise);
|
||||
energy_a = desc->v1.energy_a;
|
||||
energy_b = desc->v1.energy_b;
|
||||
desc_size = IWL_RX_DESC_SIZE_V1;
|
||||
}
|
||||
|
||||
hdr = (void *)(pkt->data + desc_size);
|
||||
/* Dont use dev_alloc_skb(), we'll have enough headroom once
|
||||
* ieee80211_hdr pulled.
|
||||
*/
|
||||
|
@ -882,6 +918,51 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
|
||||
rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
if (rate_n_flags & RATE_MCS_HE_MSK) {
|
||||
static const struct ieee80211_radiotap_he known = {
|
||||
.data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
|
||||
IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN |
|
||||
IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN |
|
||||
IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN),
|
||||
.data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN |
|
||||
IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN),
|
||||
};
|
||||
static const struct ieee80211_radiotap_he_mu mu_known = {
|
||||
.flags1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN |
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN |
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN |
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN),
|
||||
.flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN),
|
||||
};
|
||||
unsigned int radiotap_len = 0;
|
||||
|
||||
he = skb_put_data(skb, &known, sizeof(known));
|
||||
radiotap_len += sizeof(known);
|
||||
rx_status->flag |= RX_FLAG_RADIOTAP_HE;
|
||||
|
||||
he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
|
||||
|
||||
if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) {
|
||||
if (mvm->trans->cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_22560)
|
||||
he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
|
||||
else
|
||||
he_phy_data = le64_to_cpu(desc->v1.he_phy_data);
|
||||
|
||||
if (he_type == RATE_MCS_HE_TYPE_MU) {
|
||||
he_mu = skb_put_data(skb, &mu_known,
|
||||
sizeof(mu_known));
|
||||
radiotap_len += sizeof(mu_known);
|
||||
rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU;
|
||||
}
|
||||
}
|
||||
|
||||
/* temporarily hide the radiotap data */
|
||||
__skb_pull(skb, radiotap_len);
|
||||
}
|
||||
|
||||
rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
if (iwl_mvm_rx_crypto(mvm, hdr, rx_status, phy_info, desc,
|
||||
le32_to_cpu(pkt->len_n_flags), queue,
|
||||
&crypt_len)) {
|
||||
|
@ -904,20 +985,80 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
|
||||
|
||||
if (likely(!(phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
|
||||
rx_status->mactime = le64_to_cpu(desc->tsf_on_air_rise);
|
||||
u64 tsf_on_air_rise;
|
||||
|
||||
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||
tsf_on_air_rise = le64_to_cpu(desc->v3.tsf_on_air_rise);
|
||||
else
|
||||
tsf_on_air_rise = le64_to_cpu(desc->v1.tsf_on_air_rise);
|
||||
|
||||
rx_status->mactime = tsf_on_air_rise;
|
||||
/* TSF as indicated by the firmware is at INA time */
|
||||
rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;
|
||||
} else if (he_type == RATE_MCS_HE_TYPE_SU) {
|
||||
u64 he_phy_data;
|
||||
|
||||
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||
he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
|
||||
else
|
||||
he_phy_data = le64_to_cpu(desc->v1.he_phy_data);
|
||||
|
||||
he->data1 |=
|
||||
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN);
|
||||
if (FIELD_GET(IWL_RX_HE_PHY_UPLINK,
|
||||
he_phy_data))
|
||||
he->data3 |=
|
||||
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA3_UL_DL);
|
||||
|
||||
if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
|
||||
rx_status->ampdu_reference = mvm->ampdu_ref;
|
||||
mvm->ampdu_ref++;
|
||||
|
||||
rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
|
||||
if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF,
|
||||
he_phy_data))
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
|
||||
}
|
||||
} else if (he_mu && he_phy_data != HE_PHY_DATA_INVAL) {
|
||||
he_mu->flags1 |=
|
||||
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIBG_SYM_OR_USER_NUM_MASK,
|
||||
he_phy_data),
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS);
|
||||
he_mu->flags1 |=
|
||||
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIGB_DCM,
|
||||
he_phy_data),
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM);
|
||||
he_mu->flags1 |=
|
||||
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIGB_MCS_MASK,
|
||||
he_phy_data),
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS);
|
||||
he_mu->flags2 |=
|
||||
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SIGB_COMPRESSION,
|
||||
he_phy_data),
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP);
|
||||
he_mu->flags2 |=
|
||||
le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_PREAMBLE_PUNC_TYPE_MASK,
|
||||
he_phy_data),
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
|
||||
}
|
||||
rx_status->device_timestamp = le32_to_cpu(desc->gp2_on_air_rise);
|
||||
rx_status->band = desc->channel > 14 ? NL80211_BAND_5GHZ :
|
||||
NL80211_BAND_2GHZ;
|
||||
rx_status->freq = ieee80211_channel_to_frequency(desc->channel,
|
||||
rx_status->device_timestamp = gp2_on_air_rise;
|
||||
rx_status->band = channel > 14 ? NL80211_BAND_5GHZ :
|
||||
NL80211_BAND_2GHZ;
|
||||
rx_status->freq = ieee80211_channel_to_frequency(channel,
|
||||
rx_status->band);
|
||||
iwl_mvm_get_signal_strength(mvm, desc, rx_status);
|
||||
iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags, energy_a,
|
||||
energy_b);
|
||||
|
||||
/* update aggregation data for monitor sake on default queue */
|
||||
if (!queue && (phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
|
||||
bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
|
||||
u64 he_phy_data;
|
||||
|
||||
if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||
he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
|
||||
else
|
||||
he_phy_data = le64_to_cpu(desc->v1.he_phy_data);
|
||||
|
||||
rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
rx_status->ampdu_reference = mvm->ampdu_ref;
|
||||
|
@ -925,6 +1066,15 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
if (toggle_bit != mvm->ampdu_toggle) {
|
||||
mvm->ampdu_ref++;
|
||||
mvm->ampdu_toggle = toggle_bit;
|
||||
|
||||
if (he_phy_data != HE_PHY_DATA_INVAL &&
|
||||
he_type == RATE_MCS_HE_TYPE_MU) {
|
||||
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
|
||||
if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF,
|
||||
he_phy_data))
|
||||
rx_status->flag |=
|
||||
RX_FLAG_AMPDU_EOF_BIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1033,7 +1183,6 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
}
|
||||
}
|
||||
|
||||
/* Set up the HT phy flags */
|
||||
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
|
||||
case RATE_MCS_CHAN_WIDTH_20:
|
||||
break;
|
||||
|
@ -1048,6 +1197,70 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
break;
|
||||
}
|
||||
|
||||
if (he_type == RATE_MCS_HE_TYPE_EXT_SU &&
|
||||
rate_n_flags & RATE_MCS_HE_106T_MSK) {
|
||||
rx_status->bw = RATE_INFO_BW_HE_RU;
|
||||
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
}
|
||||
|
||||
if (rate_n_flags & RATE_MCS_HE_MSK &&
|
||||
phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD &&
|
||||
he_type == RATE_MCS_HE_TYPE_MU) {
|
||||
/*
|
||||
* Unfortunately, we have to leave the mac80211 data
|
||||
* incorrect for the case that we receive an HE-MU
|
||||
* transmission and *don't* have the he_mu pointer,
|
||||
* i.e. we don't have the phy data (due to the bits
|
||||
* being used for TSF). This shouldn't happen though
|
||||
* as management frames where we need the TSF/timers
|
||||
* are not be transmitted in HE-MU, I think.
|
||||
*/
|
||||
u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data);
|
||||
u8 offs = 0;
|
||||
|
||||
rx_status->bw = RATE_INFO_BW_HE_RU;
|
||||
|
||||
switch (ru) {
|
||||
case 0 ... 36:
|
||||
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
|
||||
offs = ru;
|
||||
break;
|
||||
case 37 ... 52:
|
||||
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
|
||||
offs = ru - 37;
|
||||
break;
|
||||
case 53 ... 60:
|
||||
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
offs = ru - 53;
|
||||
break;
|
||||
case 61 ... 64:
|
||||
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
|
||||
offs = ru - 61;
|
||||
break;
|
||||
case 65 ... 66:
|
||||
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
|
||||
offs = ru - 65;
|
||||
break;
|
||||
case 67:
|
||||
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
|
||||
break;
|
||||
case 68:
|
||||
rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
|
||||
break;
|
||||
}
|
||||
he->data2 |=
|
||||
le16_encode_bits(offs,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
|
||||
he->data2 |=
|
||||
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN);
|
||||
if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80)
|
||||
he->data2 |=
|
||||
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC);
|
||||
} else if (he) {
|
||||
he->data1 |=
|
||||
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
|
||||
}
|
||||
|
||||
if (!(rate_n_flags & RATE_MCS_CCK_MSK) &&
|
||||
rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
|
@ -1072,6 +1285,119 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
|
||||
if (rate_n_flags & RATE_MCS_BF_MSK)
|
||||
rx_status->enc_flags |= RX_ENC_FLAG_BF;
|
||||
} else if (he) {
|
||||
u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
|
||||
RATE_MCS_STBC_POS;
|
||||
rx_status->nss =
|
||||
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
|
||||
RATE_VHT_MCS_NSS_POS) + 1;
|
||||
rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
|
||||
rx_status->encoding = RX_ENC_HE;
|
||||
rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
|
||||
if (rate_n_flags & RATE_MCS_BF_MSK)
|
||||
rx_status->enc_flags |= RX_ENC_FLAG_BF;
|
||||
|
||||
rx_status->he_dcm =
|
||||
!!(rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK);
|
||||
|
||||
#define CHECK_TYPE(F) \
|
||||
BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_ ## F != \
|
||||
(RATE_MCS_HE_TYPE_ ## F >> RATE_MCS_HE_TYPE_POS))
|
||||
|
||||
CHECK_TYPE(SU);
|
||||
CHECK_TYPE(EXT_SU);
|
||||
CHECK_TYPE(MU);
|
||||
CHECK_TYPE(TRIG);
|
||||
|
||||
he->data1 |= cpu_to_le16(he_type >> RATE_MCS_HE_TYPE_POS);
|
||||
|
||||
if (rate_n_flags & RATE_MCS_BF_POS)
|
||||
he->data5 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA5_TXBF);
|
||||
|
||||
switch ((rate_n_flags & RATE_MCS_HE_GI_LTF_MSK) >>
|
||||
RATE_MCS_HE_GI_LTF_POS) {
|
||||
case 0:
|
||||
rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
|
||||
break;
|
||||
case 1:
|
||||
rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
|
||||
break;
|
||||
case 2:
|
||||
rx_status->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
|
||||
break;
|
||||
case 3:
|
||||
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
|
||||
else
|
||||
rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (he_type) {
|
||||
case RATE_MCS_HE_TYPE_SU: {
|
||||
u16 val;
|
||||
|
||||
/* LTF syms correspond to streams */
|
||||
he->data2 |=
|
||||
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
|
||||
switch (rx_status->nss) {
|
||||
case 1:
|
||||
val = 0;
|
||||
break;
|
||||
case 2:
|
||||
val = 1;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
val = 2;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
val = 3;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
val = 4;
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "invalid nss: %d\n",
|
||||
rx_status->nss);
|
||||
val = 0;
|
||||
}
|
||||
he->data5 |=
|
||||
le16_encode_bits(val,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS);
|
||||
}
|
||||
break;
|
||||
case RATE_MCS_HE_TYPE_MU: {
|
||||
u16 val;
|
||||
u64 he_phy_data;
|
||||
|
||||
if (mvm->trans->cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_22560)
|
||||
he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
|
||||
else
|
||||
he_phy_data = le64_to_cpu(desc->v1.he_phy_data);
|
||||
|
||||
if (he_phy_data == HE_PHY_DATA_INVAL)
|
||||
break;
|
||||
|
||||
val = FIELD_GET(IWL_RX_HE_PHY_HE_LTF_NUM_MASK,
|
||||
he_phy_data);
|
||||
|
||||
he->data2 |=
|
||||
cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);
|
||||
he->data5 |=
|
||||
cpu_to_le16(FIELD_PREP(
|
||||
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS,
|
||||
val));
|
||||
}
|
||||
break;
|
||||
case RATE_MCS_HE_TYPE_EXT_SU:
|
||||
case RATE_MCS_HE_TYPE_TRIG:
|
||||
/* not supported yet */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
|
||||
rx_status->band);
|
||||
|
|
|
@ -2184,7 +2184,7 @@ static void iwl_mvm_free_reorder(struct iwl_mvm *mvm,
|
|||
|
||||
static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_baid_data *data,
|
||||
u16 ssn, u8 buf_size)
|
||||
u16 ssn, u16 buf_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -2211,7 +2211,7 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn, bool start, u8 buf_size, u16 timeout)
|
||||
int tid, u16 ssn, bool start, u16 buf_size, u16 timeout)
|
||||
{
|
||||
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_mvm_add_sta_cmd cmd = {};
|
||||
|
@ -2273,7 +2273,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
if (start) {
|
||||
cmd.add_immediate_ba_tid = (u8) tid;
|
||||
cmd.add_immediate_ba_ssn = cpu_to_le16(ssn);
|
||||
cmd.rx_ba_window = cpu_to_le16((u16)buf_size);
|
||||
cmd.rx_ba_window = cpu_to_le16(buf_size);
|
||||
} else {
|
||||
cmd.remove_immediate_ba_tid = (u8) tid;
|
||||
}
|
||||
|
@ -2559,7 +2559,7 @@ out:
|
|||
}
|
||||
|
||||
int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u8 buf_size,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 buf_size,
|
||||
bool amsdu)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
|
|
@ -412,7 +412,7 @@ struct iwl_mvm_sta {
|
|||
u32 tfd_queue_msk;
|
||||
u32 mac_id_n_color;
|
||||
u16 tid_disable_agg;
|
||||
u8 max_agg_bufsize;
|
||||
u16 max_agg_bufsize;
|
||||
enum iwl_sta_type sta_type;
|
||||
enum ieee80211_sta_state sta_state;
|
||||
bool bt_reduced_txpower;
|
||||
|
@ -518,11 +518,11 @@ void iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
|
|||
|
||||
/* AMPDU */
|
||||
int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn, bool start, u8 buf_size, u16 timeout);
|
||||
int tid, u16 ssn, bool start, u16 buf_size, u16 timeout);
|
||||
int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
|
||||
int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u8 buf_size,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 buf_size,
|
||||
bool amsdu);
|
||||
int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid);
|
||||
|
|
|
@ -484,13 +484,15 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
|
||||
/* Make sure we zero enough of dev_cmd */
|
||||
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) > sizeof(*tx_cmd));
|
||||
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) > sizeof(*tx_cmd));
|
||||
|
||||
memset(dev_cmd, 0, sizeof(dev_cmd->hdr) + sizeof(*tx_cmd));
|
||||
dev_cmd->hdr.cmd = TX_CMD;
|
||||
|
||||
if (iwl_mvm_has_new_tx_api(mvm)) {
|
||||
struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
|
||||
u16 offload_assist = 0;
|
||||
u32 rate_n_flags = 0;
|
||||
u16 flags = 0;
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
u8 *qc = ieee80211_get_qos_ctl(hdr);
|
||||
|
@ -507,25 +509,43 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
!(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
|
||||
offload_assist |= BIT(TX_CMD_OFFLD_PAD);
|
||||
|
||||
cmd->offload_assist |= cpu_to_le16(offload_assist);
|
||||
|
||||
/* Total # bytes to be transmitted */
|
||||
cmd->len = cpu_to_le16((u16)skb->len);
|
||||
|
||||
/* Copy MAC header from skb into command buffer */
|
||||
memcpy(cmd->hdr, hdr, hdrlen);
|
||||
|
||||
if (!info->control.hw_key)
|
||||
cmd->flags |= cpu_to_le32(IWL_TX_FLAGS_ENCRYPT_DIS);
|
||||
flags |= IWL_TX_FLAGS_ENCRYPT_DIS;
|
||||
|
||||
/* For data packets rate info comes from the fw */
|
||||
if (ieee80211_is_data(hdr->frame_control) && sta)
|
||||
goto out;
|
||||
if (!(ieee80211_is_data(hdr->frame_control) && sta)) {
|
||||
flags |= IWL_TX_FLAGS_CMD_RATE;
|
||||
rate_n_flags = iwl_mvm_get_tx_rate(mvm, info, sta);
|
||||
}
|
||||
|
||||
cmd->flags |= cpu_to_le32(IWL_TX_FLAGS_CMD_RATE);
|
||||
cmd->rate_n_flags =
|
||||
cpu_to_le32(iwl_mvm_get_tx_rate(mvm, info, sta));
|
||||
if (mvm->trans->cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_22560) {
|
||||
struct iwl_tx_cmd_gen3 *cmd = (void *)dev_cmd->payload;
|
||||
|
||||
cmd->offload_assist |= cpu_to_le32(offload_assist);
|
||||
|
||||
/* Total # bytes to be transmitted */
|
||||
cmd->len = cpu_to_le16((u16)skb->len);
|
||||
|
||||
/* Copy MAC header from skb into command buffer */
|
||||
memcpy(cmd->hdr, hdr, hdrlen);
|
||||
|
||||
cmd->flags = cpu_to_le16(flags);
|
||||
cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
|
||||
} else {
|
||||
struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
|
||||
|
||||
cmd->offload_assist |= cpu_to_le16(offload_assist);
|
||||
|
||||
/* Total # bytes to be transmitted */
|
||||
cmd->len = cpu_to_le16((u16)skb->len);
|
||||
|
||||
/* Copy MAC header from skb into command buffer */
|
||||
memcpy(cmd->hdr, hdr, hdrlen);
|
||||
|
||||
cmd->flags = cpu_to_le32(flags);
|
||||
cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
207
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
Normal file
207
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-fh.h"
|
||||
#include "iwl-context-info-gen3.h"
|
||||
#include "internal.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
|
||||
const struct fw_img *fw)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_context_info_gen3 *ctxt_info_gen3;
|
||||
struct iwl_prph_scratch *prph_scratch;
|
||||
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl;
|
||||
struct iwl_prph_info *prph_info;
|
||||
void *iml_img;
|
||||
u32 control_flags = 0;
|
||||
int ret;
|
||||
|
||||
/* Allocate prph scratch */
|
||||
prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch),
|
||||
&trans_pcie->prph_scratch_dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!prph_scratch)
|
||||
return -ENOMEM;
|
||||
|
||||
prph_sc_ctrl = &prph_scratch->ctrl_cfg;
|
||||
|
||||
prph_sc_ctrl->version.version = 0;
|
||||
prph_sc_ctrl->version.mac_id =
|
||||
cpu_to_le16((u16)iwl_read32(trans, CSR_HW_REV));
|
||||
prph_sc_ctrl->version.size = cpu_to_le16(sizeof(*prph_scratch) / 4);
|
||||
|
||||
control_flags = IWL_PRPH_SCRATCH_RB_SIZE_4K |
|
||||
IWL_PRPH_SCRATCH_MTR_MODE |
|
||||
(IWL_PRPH_MTR_FORMAT_256B &
|
||||
IWL_PRPH_SCRATCH_MTR_FORMAT) |
|
||||
IWL_PRPH_SCRATCH_EARLY_DEBUG_EN |
|
||||
IWL_PRPH_SCRATCH_EDBG_DEST_DRAM;
|
||||
prph_sc_ctrl->control.control_flags = cpu_to_le32(control_flags);
|
||||
|
||||
/* initialize RX default queue */
|
||||
prph_sc_ctrl->rbd_cfg.free_rbd_addr =
|
||||
cpu_to_le64(trans_pcie->rxq->bd_dma);
|
||||
|
||||
/* Configure debug, for integration */
|
||||
iwl_pcie_alloc_fw_monitor(trans, 0);
|
||||
prph_sc_ctrl->hwm_cfg.hwm_base_addr =
|
||||
cpu_to_le64(trans_pcie->fw_mon_phys);
|
||||
prph_sc_ctrl->hwm_cfg.hwm_size =
|
||||
cpu_to_le32(trans_pcie->fw_mon_size);
|
||||
|
||||
/* allocate ucode sections in dram and set addresses */
|
||||
ret = iwl_pcie_init_fw_sec(trans, fw, &prph_scratch->dram);
|
||||
if (ret) {
|
||||
dma_free_coherent(trans->dev,
|
||||
sizeof(*prph_scratch),
|
||||
prph_scratch,
|
||||
trans_pcie->prph_scratch_dma_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate prph information
|
||||
* currently we don't assign to the prph info anything, but it would get
|
||||
* assigned later */
|
||||
prph_info = dma_alloc_coherent(trans->dev, sizeof(*prph_info),
|
||||
&trans_pcie->prph_info_dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!prph_info)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Allocate context info */
|
||||
ctxt_info_gen3 = dma_alloc_coherent(trans->dev,
|
||||
sizeof(*ctxt_info_gen3),
|
||||
&trans_pcie->ctxt_info_dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!ctxt_info_gen3)
|
||||
return -ENOMEM;
|
||||
|
||||
ctxt_info_gen3->prph_info_base_addr =
|
||||
cpu_to_le64(trans_pcie->prph_info_dma_addr);
|
||||
ctxt_info_gen3->prph_scratch_base_addr =
|
||||
cpu_to_le64(trans_pcie->prph_scratch_dma_addr);
|
||||
ctxt_info_gen3->prph_scratch_size =
|
||||
cpu_to_le32(sizeof(*prph_scratch));
|
||||
ctxt_info_gen3->cr_head_idx_arr_base_addr =
|
||||
cpu_to_le64(trans_pcie->rxq->rb_stts_dma);
|
||||
ctxt_info_gen3->tr_tail_idx_arr_base_addr =
|
||||
cpu_to_le64(trans_pcie->rxq->tr_tail_dma);
|
||||
ctxt_info_gen3->cr_tail_idx_arr_base_addr =
|
||||
cpu_to_le64(trans_pcie->rxq->cr_tail_dma);
|
||||
ctxt_info_gen3->cr_idx_arr_size =
|
||||
cpu_to_le16(IWL_NUM_OF_COMPLETION_RINGS);
|
||||
ctxt_info_gen3->tr_idx_arr_size =
|
||||
cpu_to_le16(IWL_NUM_OF_TRANSFER_RINGS);
|
||||
ctxt_info_gen3->mtr_base_addr =
|
||||
cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
|
||||
ctxt_info_gen3->mcr_base_addr =
|
||||
cpu_to_le64(trans_pcie->rxq->used_bd_dma);
|
||||
ctxt_info_gen3->mtr_size =
|
||||
cpu_to_le16(TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS));
|
||||
ctxt_info_gen3->mcr_size =
|
||||
cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE));
|
||||
|
||||
trans_pcie->ctxt_info_gen3 = ctxt_info_gen3;
|
||||
trans_pcie->prph_info = prph_info;
|
||||
trans_pcie->prph_scratch = prph_scratch;
|
||||
|
||||
/* Allocate IML */
|
||||
iml_img = dma_alloc_coherent(trans->dev, trans->iml_len,
|
||||
&trans_pcie->iml_dma_addr, GFP_KERNEL);
|
||||
if (!iml_img)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(iml_img, trans->iml, trans->iml_len);
|
||||
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
/* kick FW self load */
|
||||
iwl_write64(trans, CSR_CTXT_INFO_ADDR,
|
||||
trans_pcie->ctxt_info_dma_addr);
|
||||
iwl_write64(trans, CSR_IML_DATA_ADDR,
|
||||
trans_pcie->iml_dma_addr);
|
||||
iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len);
|
||||
iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, CSR_AUTO_FUNC_BOOT_ENA);
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (!trans_pcie->ctxt_info_gen3)
|
||||
return;
|
||||
|
||||
dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_gen3),
|
||||
trans_pcie->ctxt_info_gen3,
|
||||
trans_pcie->ctxt_info_dma_addr);
|
||||
trans_pcie->ctxt_info_dma_addr = 0;
|
||||
trans_pcie->ctxt_info_gen3 = NULL;
|
||||
|
||||
iwl_pcie_ctxt_info_free_fw_img(trans);
|
||||
|
||||
dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_scratch),
|
||||
trans_pcie->prph_scratch,
|
||||
trans_pcie->prph_scratch_dma_addr);
|
||||
trans_pcie->prph_scratch_dma_addr = 0;
|
||||
trans_pcie->prph_scratch = NULL;
|
||||
|
||||
dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_info),
|
||||
trans_pcie->prph_info,
|
||||
trans_pcie->prph_info_dma_addr);
|
||||
trans_pcie->prph_info_dma_addr = 0;
|
||||
trans_pcie->prph_info = NULL;
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -19,6 +20,7 @@
|
|||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -55,57 +57,6 @@
|
|||
#include "internal.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
static int iwl_pcie_get_num_sections(const struct fw_img *fw,
|
||||
int start)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (start < fw->num_sec &&
|
||||
fw->sec[start].offset != CPU1_CPU2_SEPARATOR_SECTION &&
|
||||
fw->sec[start].offset != PAGING_SEPARATOR_SECTION) {
|
||||
start++;
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
|
||||
const struct fw_desc *sec,
|
||||
struct iwl_dram_data *dram)
|
||||
{
|
||||
dram->block = dma_alloc_coherent(trans->dev, sec->len,
|
||||
&dram->physical,
|
||||
GFP_KERNEL);
|
||||
if (!dram->block)
|
||||
return -ENOMEM;
|
||||
|
||||
dram->size = sec->len;
|
||||
memcpy(dram->block, sec->data, sec->len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
|
||||
int i;
|
||||
|
||||
if (!dram->fw) {
|
||||
WARN_ON(dram->fw_cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < dram->fw_cnt; i++)
|
||||
dma_free_coherent(trans->dev, dram->fw[i].size,
|
||||
dram->fw[i].block, dram->fw[i].physical);
|
||||
|
||||
kfree(dram->fw);
|
||||
dram->fw_cnt = 0;
|
||||
dram->fw = NULL;
|
||||
}
|
||||
|
||||
void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
@ -128,13 +79,12 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans)
|
|||
dram->paging = NULL;
|
||||
}
|
||||
|
||||
static int iwl_pcie_ctxt_info_init_fw_sec(struct iwl_trans *trans,
|
||||
const struct fw_img *fw,
|
||||
struct iwl_context_info *ctxt_info)
|
||||
int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
|
||||
const struct fw_img *fw,
|
||||
struct iwl_context_info_dram *ctxt_dram)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
|
||||
struct iwl_context_info_dram *ctxt_dram = &ctxt_info->dram;
|
||||
int i, ret, lmac_cnt, umac_cnt, paging_cnt;
|
||||
|
||||
if (WARN(dram->paging,
|
||||
|
@ -247,7 +197,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
|
|||
TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS);
|
||||
|
||||
/* allocate ucode sections in dram and set addresses */
|
||||
ret = iwl_pcie_ctxt_info_init_fw_sec(trans, fw, ctxt_info);
|
||||
ret = iwl_pcie_init_fw_sec(trans, fw, &ctxt_info->dram);
|
||||
if (ret) {
|
||||
dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info),
|
||||
ctxt_info, trans_pcie->ctxt_info_dma_addr);
|
||||
|
|
|
@ -828,19 +828,32 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
|||
{IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)},
|
||||
|
||||
/* 22000 Series */
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0A10, iwl22000_2ac_cfg_hr_cdb)},
|
||||
{IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22000_2ac_cfg_jf)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0000, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0040, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0078, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0030, iwl22000_2ac_cfg_hr_cdb)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x1080, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0310, iwl22000_2ac_cfg_hr_cdb)},
|
||||
{IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x34F0, 0x0040, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x34F0, 0x0078, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22000_2ac_cfg_jf)},
|
||||
{IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)},
|
||||
{IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)},
|
||||
{IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)},
|
||||
{IWL_PCI_DEVICE(0x40C0, 0x0310, iwl22560_2ax_cfg_su_cdb)},
|
||||
{IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22560_2ax_cfg_su_cdb)},
|
||||
{IWL_PCI_DEVICE(0x43F0, 0x0040, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x43F0, 0x0070, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x43F0, 0x0078, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl22000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl22000_2ax_cfg_hr)},
|
||||
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
|
@ -1003,6 +1016,10 @@ static int iwl_pci_resume(struct device *device)
|
|||
if (!trans->op_mode)
|
||||
return 0;
|
||||
|
||||
/* In WOWLAN, let iwl_trans_pcie_d3_resume do the rest of the work */
|
||||
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
|
||||
return 0;
|
||||
|
||||
/* reconfigure the MSI-X mapping to get the correct IRQ for rfkill */
|
||||
iwl_pcie_conf_msix_hw(trans_pcie);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -17,8 +18,7 @@
|
|||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
* this program.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
|
@ -45,6 +45,7 @@
|
|||
#include "iwl-debug.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-drv.h"
|
||||
|
||||
/* We need 2 entries for the TX command and header, and another one might
|
||||
* be needed for potential data in the SKB's head. The remaining ones can
|
||||
|
@ -59,6 +60,7 @@
|
|||
#define RX_POST_REQ_ALLOC 2
|
||||
#define RX_CLAIM_REQ_ALLOC 8
|
||||
#define RX_PENDING_WATERMARK 16
|
||||
#define FIRST_RX_QUEUE 512
|
||||
|
||||
struct iwl_host_cmd;
|
||||
|
||||
|
@ -71,6 +73,7 @@ struct iwl_host_cmd;
|
|||
* @page: driver's pointer to the rxb page
|
||||
* @invalid: rxb is in driver ownership - not owned by HW
|
||||
* @vid: index of this rxb in the global table
|
||||
* @size: size used from the buffer
|
||||
*/
|
||||
struct iwl_rx_mem_buffer {
|
||||
dma_addr_t page_dma;
|
||||
|
@ -78,6 +81,7 @@ struct iwl_rx_mem_buffer {
|
|||
u16 vid;
|
||||
bool invalid;
|
||||
struct list_head list;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -98,14 +102,121 @@ struct isr_statistics {
|
|||
u32 unhandled;
|
||||
};
|
||||
|
||||
#define IWL_CD_STTS_OPTIMIZED_POS 0
|
||||
#define IWL_CD_STTS_OPTIMIZED_MSK 0x01
|
||||
#define IWL_CD_STTS_TRANSFER_STATUS_POS 1
|
||||
#define IWL_CD_STTS_TRANSFER_STATUS_MSK 0x0E
|
||||
#define IWL_CD_STTS_WIFI_STATUS_POS 4
|
||||
#define IWL_CD_STTS_WIFI_STATUS_MSK 0xF0
|
||||
|
||||
/**
|
||||
* enum iwl_completion_desc_transfer_status - transfer status (bits 1-3)
|
||||
* @IWL_CD_STTS_END_TRANSFER: successful transfer complete.
|
||||
* In sniffer mode, when split is used, set in last CD completion. (RX)
|
||||
* @IWL_CD_STTS_OVERFLOW: In sniffer mode, when using split - used for
|
||||
* all CD completion. (RX)
|
||||
* @IWL_CD_STTS_ABORTED: CR abort / close flow. (RX)
|
||||
*/
|
||||
enum iwl_completion_desc_transfer_status {
|
||||
IWL_CD_STTS_UNUSED,
|
||||
IWL_CD_STTS_UNUSED_2,
|
||||
IWL_CD_STTS_END_TRANSFER,
|
||||
IWL_CD_STTS_OVERFLOW,
|
||||
IWL_CD_STTS_ABORTED,
|
||||
IWL_CD_STTS_ERROR,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_completion_desc_wifi_status - wifi status (bits 4-7)
|
||||
* @IWL_CD_STTS_VALID: the packet is valid (RX)
|
||||
* @IWL_CD_STTS_FCS_ERR: frame check sequence error (RX)
|
||||
* @IWL_CD_STTS_SEC_KEY_ERR: error handling the security key of rx (RX)
|
||||
* @IWL_CD_STTS_DECRYPTION_ERR: error decrypting the frame (RX)
|
||||
* @IWL_CD_STTS_DUP: duplicate packet (RX)
|
||||
* @IWL_CD_STTS_ICV_MIC_ERR: MIC error (RX)
|
||||
* @IWL_CD_STTS_INTERNAL_SNAP_ERR: problems removing the snap (RX)
|
||||
* @IWL_CD_STTS_SEC_PORT_FAIL: security port fail (RX)
|
||||
* @IWL_CD_STTS_BA_OLD_SN: block ack received old SN (RX)
|
||||
* @IWL_CD_STTS_QOS_NULL: QoS null packet (RX)
|
||||
* @IWL_CD_STTS_MAC_HDR_ERR: MAC header conversion error (RX)
|
||||
* @IWL_CD_STTS_MAX_RETRANS: reached max number of retransmissions (TX)
|
||||
* @IWL_CD_STTS_EX_LIFETIME: exceeded lifetime (TX)
|
||||
* @IWL_CD_STTS_NOT_USED: completed but not used (RX)
|
||||
* @IWL_CD_STTS_REPLAY_ERR: pn check failed, replay error (RX)
|
||||
*/
|
||||
enum iwl_completion_desc_wifi_status {
|
||||
IWL_CD_STTS_VALID,
|
||||
IWL_CD_STTS_FCS_ERR,
|
||||
IWL_CD_STTS_SEC_KEY_ERR,
|
||||
IWL_CD_STTS_DECRYPTION_ERR,
|
||||
IWL_CD_STTS_DUP,
|
||||
IWL_CD_STTS_ICV_MIC_ERR,
|
||||
IWL_CD_STTS_INTERNAL_SNAP_ERR,
|
||||
IWL_CD_STTS_SEC_PORT_FAIL,
|
||||
IWL_CD_STTS_BA_OLD_SN,
|
||||
IWL_CD_STTS_QOS_NULL,
|
||||
IWL_CD_STTS_MAC_HDR_ERR,
|
||||
IWL_CD_STTS_MAX_RETRANS,
|
||||
IWL_CD_STTS_EX_LIFETIME,
|
||||
IWL_CD_STTS_NOT_USED,
|
||||
IWL_CD_STTS_REPLAY_ERR,
|
||||
};
|
||||
|
||||
#define IWL_RX_TD_TYPE_MSK 0xff000000
|
||||
#define IWL_RX_TD_SIZE_MSK 0x00ffffff
|
||||
#define IWL_RX_TD_SIZE_2K BIT(11)
|
||||
#define IWL_RX_TD_TYPE 0
|
||||
|
||||
/**
|
||||
* struct iwl_rx_transfer_desc - transfer descriptor
|
||||
* @type_n_size: buffer type (bit 0: external buff valid,
|
||||
* bit 1: optional footer valid, bit 2-7: reserved)
|
||||
* and buffer size
|
||||
* @addr: ptr to free buffer start address
|
||||
* @rbid: unique tag of the buffer
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_rx_transfer_desc {
|
||||
__le32 type_n_size;
|
||||
__le64 addr;
|
||||
__le16 rbid;
|
||||
__le16 reserved;
|
||||
} __packed;
|
||||
|
||||
#define IWL_RX_CD_SIZE 0xffffff00
|
||||
|
||||
/**
|
||||
* struct iwl_rx_completion_desc - completion descriptor
|
||||
* @type: buffer type (bit 0: external buff valid,
|
||||
* bit 1: optional footer valid, bit 2-7: reserved)
|
||||
* @status: status of the completion
|
||||
* @reserved1: reserved
|
||||
* @rbid: unique tag of the received buffer
|
||||
* @size: buffer size, masked by IWL_RX_CD_SIZE
|
||||
* @reserved2: reserved
|
||||
*/
|
||||
struct iwl_rx_completion_desc {
|
||||
u8 type;
|
||||
u8 status;
|
||||
__le16 reserved1;
|
||||
__le16 rbid;
|
||||
__le32 size;
|
||||
u8 reserved2[22];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_rxq - Rx queue
|
||||
* @id: queue index
|
||||
* @bd: driver's pointer to buffer of receive buffer descriptors (rbd).
|
||||
* Address size is 32 bit in pre-9000 devices and 64 bit in 9000 devices.
|
||||
* In 22560 devices it is a pointer to a list of iwl_rx_transfer_desc's
|
||||
* @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
|
||||
* @ubd: driver's pointer to buffer of used receive buffer descriptors (rbd)
|
||||
* @ubd_dma: physical address of buffer of used receive buffer descriptors (rbd)
|
||||
* @tr_tail: driver's pointer to the transmission ring tail buffer
|
||||
* @tr_tail_dma: physical address of the buffer for the transmission ring tail
|
||||
* @cr_tail: driver's pointer to the completion ring tail buffer
|
||||
* @cr_tail_dma: physical address of the buffer for the completion ring tail
|
||||
* @read: Shared index to newest available Rx buffer
|
||||
* @write: Shared index to oldest written Rx packet
|
||||
* @free_count: Number of pre-allocated buffers in rx_free
|
||||
|
@ -125,8 +236,16 @@ struct iwl_rxq {
|
|||
int id;
|
||||
void *bd;
|
||||
dma_addr_t bd_dma;
|
||||
__le32 *used_bd;
|
||||
union {
|
||||
void *used_bd;
|
||||
__le32 *bd_32;
|
||||
struct iwl_rx_completion_desc *cd;
|
||||
};
|
||||
dma_addr_t used_bd_dma;
|
||||
__le16 *tr_tail;
|
||||
dma_addr_t tr_tail_dma;
|
||||
__le16 *cr_tail;
|
||||
dma_addr_t cr_tail_dma;
|
||||
u32 read;
|
||||
u32 write;
|
||||
u32 free_count;
|
||||
|
@ -136,7 +255,7 @@ struct iwl_rxq {
|
|||
struct list_head rx_free;
|
||||
struct list_head rx_used;
|
||||
bool need_update;
|
||||
struct iwl_rb_status *rb_stts;
|
||||
void *rb_stts;
|
||||
dma_addr_t rb_stts_dma;
|
||||
spinlock_t lock;
|
||||
struct napi_struct napi;
|
||||
|
@ -175,18 +294,36 @@ struct iwl_dma_ptr {
|
|||
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning
|
||||
* @index -- current index
|
||||
*/
|
||||
static inline int iwl_queue_inc_wrap(int index)
|
||||
static inline int iwl_queue_inc_wrap(struct iwl_trans *trans, int index)
|
||||
{
|
||||
return ++index & (TFD_QUEUE_SIZE_MAX - 1);
|
||||
return ++index & (trans->cfg->base_params->max_tfd_queue_size - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_get_closed_rb_stts - get closed rb stts from different structs
|
||||
* @rxq - the rxq to get the rb stts from
|
||||
*/
|
||||
static inline __le16 iwl_get_closed_rb_stts(struct iwl_trans *trans,
|
||||
struct iwl_rxq *rxq)
|
||||
{
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
|
||||
__le16 *rb_stts = rxq->rb_stts;
|
||||
|
||||
return READ_ONCE(*rb_stts);
|
||||
} else {
|
||||
struct iwl_rb_status *rb_stts = rxq->rb_stts;
|
||||
|
||||
return READ_ONCE(rb_stts->closed_rb_num);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_queue_dec_wrap - decrement queue index, wrap back to end
|
||||
* @index -- current index
|
||||
*/
|
||||
static inline int iwl_queue_dec_wrap(int index)
|
||||
static inline int iwl_queue_dec_wrap(struct iwl_trans *trans, int index)
|
||||
{
|
||||
return --index & (TFD_QUEUE_SIZE_MAX - 1);
|
||||
return --index & (trans->cfg->base_params->max_tfd_queue_size - 1);
|
||||
}
|
||||
|
||||
struct iwl_cmd_meta {
|
||||
|
@ -314,6 +451,18 @@ enum iwl_shared_irq_flags {
|
|||
IWL_SHARED_IRQ_FIRST_RSS = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_image_response_code - image response values
|
||||
* @IWL_IMAGE_RESP_DEF: the default value of the register
|
||||
* @IWL_IMAGE_RESP_SUCCESS: iml was read successfully
|
||||
* @IWL_IMAGE_RESP_FAIL: iml reading failed
|
||||
*/
|
||||
enum iwl_image_response_code {
|
||||
IWL_IMAGE_RESP_DEF = 0,
|
||||
IWL_IMAGE_RESP_SUCCESS = 1,
|
||||
IWL_IMAGE_RESP_FAIL = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_dram_data
|
||||
* @physical: page phy pointer
|
||||
|
@ -347,6 +496,12 @@ struct iwl_self_init_dram {
|
|||
* @global_table: table mapping received VID from hw to rxb
|
||||
* @rba: allocator for RX replenishing
|
||||
* @ctxt_info: context information for FW self init
|
||||
* @ctxt_info_gen3: context information for gen3 devices
|
||||
* @prph_info: prph info for self init
|
||||
* @prph_scratch: prph scratch for self init
|
||||
* @ctxt_info_dma_addr: dma addr of context information
|
||||
* @prph_info_dma_addr: dma addr of prph info
|
||||
* @prph_scratch_dma_addr: dma addr of prph scratch
|
||||
* @ctxt_info_dma_addr: dma addr of context information
|
||||
* @init_dram: DRAM data of firmware image (including paging).
|
||||
* Context information addresses will be taken from here.
|
||||
|
@ -391,8 +546,16 @@ struct iwl_trans_pcie {
|
|||
struct iwl_rx_mem_buffer rx_pool[RX_POOL_SIZE];
|
||||
struct iwl_rx_mem_buffer *global_table[RX_POOL_SIZE];
|
||||
struct iwl_rb_allocator rba;
|
||||
struct iwl_context_info *ctxt_info;
|
||||
union {
|
||||
struct iwl_context_info *ctxt_info;
|
||||
struct iwl_context_info_gen3 *ctxt_info_gen3;
|
||||
};
|
||||
struct iwl_prph_info *prph_info;
|
||||
struct iwl_prph_scratch *prph_scratch;
|
||||
dma_addr_t ctxt_info_dma_addr;
|
||||
dma_addr_t prph_info_dma_addr;
|
||||
dma_addr_t prph_scratch_dma_addr;
|
||||
dma_addr_t iml_dma_addr;
|
||||
struct iwl_self_init_dram init_dram;
|
||||
struct iwl_trans *trans;
|
||||
|
||||
|
@ -477,6 +640,20 @@ IWL_TRANS_GET_PCIE_TRANS(struct iwl_trans *trans)
|
|||
return (void *)trans->trans_specific;
|
||||
}
|
||||
|
||||
static inline void iwl_pcie_clear_irq(struct iwl_trans *trans,
|
||||
struct msix_entry *entry)
|
||||
{
|
||||
/*
|
||||
* Before sending the interrupt the HW disables it to prevent
|
||||
* a nested interrupt. This is done by writing 1 to the corresponding
|
||||
* bit in the mask register. After handling the interrupt, it should be
|
||||
* re-enabled by clearing this bit. This register is defined as
|
||||
* write 1 clear (W1C) register, meaning that it's being clear
|
||||
* by writing 1 to the bit.
|
||||
*/
|
||||
iwl_write32(trans, CSR_MSIX_AUTOMASK_ST_AD, BIT(entry->entry));
|
||||
}
|
||||
|
||||
static inline struct iwl_trans *
|
||||
iwl_trans_pcie_get_trans(struct iwl_trans_pcie *trans_pcie)
|
||||
{
|
||||
|
@ -504,6 +681,11 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id);
|
|||
irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id);
|
||||
int iwl_pcie_rx_stop(struct iwl_trans *trans);
|
||||
void iwl_pcie_rx_free(struct iwl_trans *trans);
|
||||
void iwl_pcie_free_rbs_pool(struct iwl_trans *trans);
|
||||
void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq);
|
||||
int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget);
|
||||
void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority,
|
||||
struct iwl_rxq *rxq);
|
||||
|
||||
/*****************************************************
|
||||
* ICT - interrupt handling
|
||||
|
@ -588,6 +770,60 @@ static inline void _iwl_disable_interrupts(struct iwl_trans *trans)
|
|||
IWL_DEBUG_ISR(trans, "Disabled interrupts\n");
|
||||
}
|
||||
|
||||
#define IWL_NUM_OF_COMPLETION_RINGS 31
|
||||
#define IWL_NUM_OF_TRANSFER_RINGS 527
|
||||
|
||||
static inline int iwl_pcie_get_num_sections(const struct fw_img *fw,
|
||||
int start)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (start < fw->num_sec &&
|
||||
fw->sec[start].offset != CPU1_CPU2_SEPARATOR_SECTION &&
|
||||
fw->sec[start].offset != PAGING_SEPARATOR_SECTION) {
|
||||
start++;
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
|
||||
const struct fw_desc *sec,
|
||||
struct iwl_dram_data *dram)
|
||||
{
|
||||
dram->block = dma_alloc_coherent(trans->dev, sec->len,
|
||||
&dram->physical,
|
||||
GFP_KERNEL);
|
||||
if (!dram->block)
|
||||
return -ENOMEM;
|
||||
|
||||
dram->size = sec->len;
|
||||
memcpy(dram->block, sec->data, sec->len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
|
||||
int i;
|
||||
|
||||
if (!dram->fw) {
|
||||
WARN_ON(dram->fw_cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < dram->fw_cnt; i++)
|
||||
dma_free_coherent(trans->dev, dram->fw[i].size,
|
||||
dram->fw[i].block, dram->fw[i].physical);
|
||||
|
||||
kfree(dram->fw);
|
||||
dram->fw_cnt = 0;
|
||||
dram->fw = NULL;
|
||||
}
|
||||
|
||||
static inline void iwl_disable_interrupts(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
@ -660,7 +896,7 @@ static inline void iwl_enable_fw_load_int(struct iwl_trans *trans)
|
|||
}
|
||||
}
|
||||
|
||||
static inline u8 iwl_pcie_get_cmd_index(struct iwl_txq *q, u32 index)
|
||||
static inline u16 iwl_pcie_get_cmd_index(const struct iwl_txq *q, u32 index)
|
||||
{
|
||||
return index & (q->n_window - 1);
|
||||
}
|
||||
|
@ -676,6 +912,29 @@ static inline void *iwl_pcie_get_tfd(struct iwl_trans *trans,
|
|||
return txq->tfds + trans_pcie->tfd_size * idx;
|
||||
}
|
||||
|
||||
static inline const char *queue_name(struct device *dev,
|
||||
struct iwl_trans_pcie *trans_p, int i)
|
||||
{
|
||||
if (trans_p->shared_vec_mask) {
|
||||
int vec = trans_p->shared_vec_mask &
|
||||
IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0;
|
||||
|
||||
if (i == 0)
|
||||
return DRV_NAME ": shared IRQ";
|
||||
|
||||
return devm_kasprintf(dev, GFP_KERNEL,
|
||||
DRV_NAME ": queue %d", i + vec);
|
||||
}
|
||||
if (i == 0)
|
||||
return DRV_NAME ": default queue";
|
||||
|
||||
if (i == trans_p->alloc_vecs - 1)
|
||||
return DRV_NAME ": exception";
|
||||
|
||||
return devm_kasprintf(dev, GFP_KERNEL,
|
||||
DRV_NAME ": queue %d", i);
|
||||
}
|
||||
|
||||
static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
@ -730,9 +989,13 @@ static inline void iwl_stop_queue(struct iwl_trans *trans,
|
|||
|
||||
static inline bool iwl_queue_used(const struct iwl_txq *q, int i)
|
||||
{
|
||||
return q->write_ptr >= q->read_ptr ?
|
||||
(i >= q->read_ptr && i < q->write_ptr) :
|
||||
!(i < q->read_ptr && i >= q->write_ptr);
|
||||
int index = iwl_pcie_get_cmd_index(q, i);
|
||||
int r = iwl_pcie_get_cmd_index(q, q->read_ptr);
|
||||
int w = iwl_pcie_get_cmd_index(q, q->write_ptr);
|
||||
|
||||
return w >= r ?
|
||||
(index >= r && index < w) :
|
||||
!(index < r && index >= w);
|
||||
}
|
||||
|
||||
static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
|
||||
|
@ -801,7 +1064,7 @@ bool iwl_pcie_check_hw_rf_kill(struct iwl_trans *trans);
|
|||
void iwl_trans_pcie_handle_stop_rfkill(struct iwl_trans *trans,
|
||||
bool was_in_rfkill);
|
||||
void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq);
|
||||
int iwl_queue_space(const struct iwl_txq *q);
|
||||
int iwl_queue_space(struct iwl_trans *trans, const struct iwl_txq *q);
|
||||
void iwl_pcie_apm_stop_master(struct iwl_trans *trans);
|
||||
void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie);
|
||||
int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
|
||||
|
@ -818,6 +1081,9 @@ void iwl_pcie_free_tso_page(struct iwl_trans_pcie *trans_pcie,
|
|||
struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len);
|
||||
#endif
|
||||
|
||||
/* common functions that are used by gen3 transport */
|
||||
void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power);
|
||||
|
||||
/* transport gen 2 exported functions */
|
||||
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
|
||||
const struct fw_img *fw, bool run_in_rfkill);
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
* this program.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
|
@ -37,6 +36,7 @@
|
|||
#include "iwl-io.h"
|
||||
#include "internal.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-context-info-gen3.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
|
@ -167,7 +167,12 @@ static inline __le32 iwl_pcie_dma_addr2rbd_ptr(dma_addr_t dma_addr)
|
|||
*/
|
||||
int iwl_pcie_rx_stop(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->cfg->mq_rx_supported) {
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
|
||||
/* TODO: remove this for 22560 once fw does it */
|
||||
iwl_write_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0);
|
||||
return iwl_poll_prph_bit(trans, RFH_GEN_STATUS_GEN3,
|
||||
RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
|
||||
} else if (trans->cfg->mq_rx_supported) {
|
||||
iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0);
|
||||
return iwl_poll_prph_bit(trans, RFH_GEN_STATUS,
|
||||
RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
|
||||
|
@ -209,7 +214,11 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans,
|
|||
}
|
||||
|
||||
rxq->write_actual = round_down(rxq->write, 8);
|
||||
if (trans->cfg->mq_rx_supported)
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||
iwl_write32(trans, HBUS_TARG_WRPTR,
|
||||
(rxq->write_actual |
|
||||
((FIRST_RX_QUEUE + rxq->id) << 16)));
|
||||
else if (trans->cfg->mq_rx_supported)
|
||||
iwl_write32(trans, RFH_Q_FRBDCB_WIDX_TRG(rxq->id),
|
||||
rxq->write_actual);
|
||||
else
|
||||
|
@ -233,6 +242,25 @@ static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans)
|
|||
}
|
||||
}
|
||||
|
||||
static void iwl_pcie_restock_bd(struct iwl_trans *trans,
|
||||
struct iwl_rxq *rxq,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
|
||||
struct iwl_rx_transfer_desc *bd = rxq->bd;
|
||||
|
||||
bd[rxq->write].type_n_size =
|
||||
cpu_to_le32((IWL_RX_TD_TYPE & IWL_RX_TD_TYPE_MSK) |
|
||||
((IWL_RX_TD_SIZE_2K >> 8) & IWL_RX_TD_SIZE_MSK));
|
||||
bd[rxq->write].addr = cpu_to_le64(rxb->page_dma);
|
||||
bd[rxq->write].rbid = cpu_to_le16(rxb->vid);
|
||||
} else {
|
||||
__le64 *bd = rxq->bd;
|
||||
|
||||
bd[rxq->write] = cpu_to_le64(rxb->page_dma | rxb->vid);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_pcie_rxmq_restock - restock implementation for multi-queue rx
|
||||
*/
|
||||
|
@ -254,8 +282,6 @@ static void iwl_pcie_rxmq_restock(struct iwl_trans *trans,
|
|||
|
||||
spin_lock(&rxq->lock);
|
||||
while (rxq->free_count) {
|
||||
__le64 *bd = (__le64 *)rxq->bd;
|
||||
|
||||
/* Get next free Rx buffer, remove from free list */
|
||||
rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer,
|
||||
list);
|
||||
|
@ -264,7 +290,7 @@ static void iwl_pcie_rxmq_restock(struct iwl_trans *trans,
|
|||
/* 12 first bits are expected to be empty */
|
||||
WARN_ON(rxb->page_dma & DMA_BIT_MASK(12));
|
||||
/* Point to Rx buffer via next RBD in circular buffer */
|
||||
bd[rxq->write] = cpu_to_le64(rxb->page_dma | rxb->vid);
|
||||
iwl_pcie_restock_bd(trans, rxq, rxb);
|
||||
rxq->write = (rxq->write + 1) & MQ_RX_TABLE_MASK;
|
||||
rxq->free_count--;
|
||||
}
|
||||
|
@ -391,8 +417,8 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans,
|
|||
* iwl_pcie_rxq_restock. The latter function will update the HW to use the newly
|
||||
* allocated buffers.
|
||||
*/
|
||||
static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority,
|
||||
struct iwl_rxq *rxq)
|
||||
void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority,
|
||||
struct iwl_rxq *rxq)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_rx_mem_buffer *rxb;
|
||||
|
@ -448,7 +474,7 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority,
|
|||
}
|
||||
}
|
||||
|
||||
static void iwl_pcie_free_rbs_pool(struct iwl_trans *trans)
|
||||
void iwl_pcie_free_rbs_pool(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int i;
|
||||
|
@ -608,14 +634,153 @@ void iwl_pcie_rx_allocator_work(struct work_struct *data)
|
|||
iwl_pcie_rx_allocator(trans_pcie->trans);
|
||||
}
|
||||
|
||||
static int iwl_pcie_free_bd_size(struct iwl_trans *trans, bool use_rx_td)
|
||||
{
|
||||
struct iwl_rx_transfer_desc *rx_td;
|
||||
|
||||
if (use_rx_td)
|
||||
return sizeof(*rx_td);
|
||||
else
|
||||
return trans->cfg->mq_rx_supported ? sizeof(__le64) :
|
||||
sizeof(__le32);
|
||||
}
|
||||
|
||||
static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
|
||||
struct iwl_rxq *rxq)
|
||||
{
|
||||
struct device *dev = trans->dev;
|
||||
bool use_rx_td = (trans->cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_22560);
|
||||
int free_size = iwl_pcie_free_bd_size(trans, use_rx_td);
|
||||
|
||||
if (rxq->bd)
|
||||
dma_free_coherent(trans->dev,
|
||||
free_size * rxq->queue_size,
|
||||
rxq->bd, rxq->bd_dma);
|
||||
rxq->bd_dma = 0;
|
||||
rxq->bd = NULL;
|
||||
|
||||
if (rxq->rb_stts)
|
||||
dma_free_coherent(trans->dev,
|
||||
use_rx_td ? sizeof(__le16) :
|
||||
sizeof(struct iwl_rb_status),
|
||||
rxq->rb_stts, rxq->rb_stts_dma);
|
||||
rxq->rb_stts_dma = 0;
|
||||
rxq->rb_stts = NULL;
|
||||
|
||||
if (rxq->used_bd)
|
||||
dma_free_coherent(trans->dev,
|
||||
(use_rx_td ? sizeof(*rxq->cd) :
|
||||
sizeof(__le32)) * rxq->queue_size,
|
||||
rxq->used_bd, rxq->used_bd_dma);
|
||||
rxq->used_bd_dma = 0;
|
||||
rxq->used_bd = NULL;
|
||||
|
||||
if (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560)
|
||||
return;
|
||||
|
||||
if (rxq->tr_tail)
|
||||
dma_free_coherent(dev, sizeof(__le16),
|
||||
rxq->tr_tail, rxq->tr_tail_dma);
|
||||
rxq->tr_tail_dma = 0;
|
||||
rxq->tr_tail = NULL;
|
||||
|
||||
if (rxq->cr_tail)
|
||||
dma_free_coherent(dev, sizeof(__le16),
|
||||
rxq->cr_tail, rxq->cr_tail_dma);
|
||||
rxq->cr_tail_dma = 0;
|
||||
rxq->cr_tail = NULL;
|
||||
}
|
||||
|
||||
static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
|
||||
struct iwl_rxq *rxq)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct device *dev = trans->dev;
|
||||
int i;
|
||||
int free_size;
|
||||
bool use_rx_td = (trans->cfg->device_family >=
|
||||
IWL_DEVICE_FAMILY_22560);
|
||||
|
||||
spin_lock_init(&rxq->lock);
|
||||
if (trans->cfg->mq_rx_supported)
|
||||
rxq->queue_size = MQ_RX_TABLE_SIZE;
|
||||
else
|
||||
rxq->queue_size = RX_QUEUE_SIZE;
|
||||
|
||||
free_size = iwl_pcie_free_bd_size(trans, use_rx_td);
|
||||
|
||||
/*
|
||||
* Allocate the circular buffer of Read Buffer Descriptors
|
||||
* (RBDs)
|
||||
*/
|
||||
rxq->bd = dma_zalloc_coherent(dev,
|
||||
free_size * rxq->queue_size,
|
||||
&rxq->bd_dma, GFP_KERNEL);
|
||||
if (!rxq->bd)
|
||||
goto err;
|
||||
|
||||
if (trans->cfg->mq_rx_supported) {
|
||||
rxq->used_bd = dma_zalloc_coherent(dev,
|
||||
(use_rx_td ?
|
||||
sizeof(*rxq->cd) :
|
||||
sizeof(__le32)) *
|
||||
rxq->queue_size,
|
||||
&rxq->used_bd_dma,
|
||||
GFP_KERNEL);
|
||||
if (!rxq->used_bd)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Allocate the driver's pointer to receive buffer status */
|
||||
rxq->rb_stts = dma_zalloc_coherent(dev, use_rx_td ?
|
||||
sizeof(__le16) :
|
||||
sizeof(struct iwl_rb_status),
|
||||
&rxq->rb_stts_dma,
|
||||
GFP_KERNEL);
|
||||
if (!rxq->rb_stts)
|
||||
goto err;
|
||||
|
||||
if (!use_rx_td)
|
||||
return 0;
|
||||
|
||||
/* Allocate the driver's pointer to TR tail */
|
||||
rxq->tr_tail = dma_zalloc_coherent(dev, sizeof(__le16),
|
||||
&rxq->tr_tail_dma,
|
||||
GFP_KERNEL);
|
||||
if (!rxq->tr_tail)
|
||||
goto err;
|
||||
|
||||
/* Allocate the driver's pointer to CR tail */
|
||||
rxq->cr_tail = dma_zalloc_coherent(dev, sizeof(__le16),
|
||||
&rxq->cr_tail_dma,
|
||||
GFP_KERNEL);
|
||||
if (!rxq->cr_tail)
|
||||
goto err;
|
||||
/*
|
||||
* W/A 22560 device step Z0 must be non zero bug
|
||||
* TODO: remove this when stop supporting Z0
|
||||
*/
|
||||
*rxq->cr_tail = cpu_to_le16(500);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (i = 0; i < trans->num_rx_queues; i++) {
|
||||
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
|
||||
|
||||
iwl_pcie_free_rxq_dma(trans, rxq);
|
||||
}
|
||||
kfree(trans_pcie->rxq);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_rb_allocator *rba = &trans_pcie->rba;
|
||||
struct device *dev = trans->dev;
|
||||
int i;
|
||||
int free_size = trans->cfg->mq_rx_supported ? sizeof(__le64) :
|
||||
sizeof(__le32);
|
||||
int i, ret;
|
||||
|
||||
if (WARN_ON(trans_pcie->rxq))
|
||||
return -EINVAL;
|
||||
|
@ -630,65 +795,11 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
|
|||
for (i = 0; i < trans->num_rx_queues; i++) {
|
||||
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
|
||||
|
||||
spin_lock_init(&rxq->lock);
|
||||
if (trans->cfg->mq_rx_supported)
|
||||
rxq->queue_size = MQ_RX_TABLE_SIZE;
|
||||
else
|
||||
rxq->queue_size = RX_QUEUE_SIZE;
|
||||
|
||||
/*
|
||||
* Allocate the circular buffer of Read Buffer Descriptors
|
||||
* (RBDs)
|
||||
*/
|
||||
rxq->bd = dma_zalloc_coherent(dev,
|
||||
free_size * rxq->queue_size,
|
||||
&rxq->bd_dma, GFP_KERNEL);
|
||||
if (!rxq->bd)
|
||||
goto err;
|
||||
|
||||
if (trans->cfg->mq_rx_supported) {
|
||||
rxq->used_bd = dma_zalloc_coherent(dev,
|
||||
sizeof(__le32) *
|
||||
rxq->queue_size,
|
||||
&rxq->used_bd_dma,
|
||||
GFP_KERNEL);
|
||||
if (!rxq->used_bd)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*Allocate the driver's pointer to receive buffer status */
|
||||
rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts),
|
||||
&rxq->rb_stts_dma,
|
||||
GFP_KERNEL);
|
||||
if (!rxq->rb_stts)
|
||||
goto err;
|
||||
ret = iwl_pcie_alloc_rxq_dma(trans, rxq);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (i = 0; i < trans->num_rx_queues; i++) {
|
||||
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
|
||||
|
||||
if (rxq->bd)
|
||||
dma_free_coherent(dev, free_size * rxq->queue_size,
|
||||
rxq->bd, rxq->bd_dma);
|
||||
rxq->bd_dma = 0;
|
||||
rxq->bd = NULL;
|
||||
|
||||
if (rxq->rb_stts)
|
||||
dma_free_coherent(trans->dev,
|
||||
sizeof(struct iwl_rb_status),
|
||||
rxq->rb_stts, rxq->rb_stts_dma);
|
||||
|
||||
if (rxq->used_bd)
|
||||
dma_free_coherent(dev, sizeof(__le32) * rxq->queue_size,
|
||||
rxq->used_bd, rxq->used_bd_dma);
|
||||
rxq->used_bd_dma = 0;
|
||||
rxq->used_bd = NULL;
|
||||
}
|
||||
kfree(trans_pcie->rxq);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
|
||||
|
@ -792,6 +903,9 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
|
|||
int i;
|
||||
|
||||
switch (trans_pcie->rx_buf_size) {
|
||||
case IWL_AMSDU_2K:
|
||||
rb_size = RFH_RXF_DMA_RB_SIZE_2K;
|
||||
break;
|
||||
case IWL_AMSDU_4K:
|
||||
rb_size = RFH_RXF_DMA_RB_SIZE_4K;
|
||||
break;
|
||||
|
@ -872,7 +986,7 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans)
|
|||
iwl_pcie_enable_rx_wake(trans, true);
|
||||
}
|
||||
|
||||
static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
|
||||
void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
|
||||
{
|
||||
lockdep_assert_held(&rxq->lock);
|
||||
|
||||
|
@ -882,7 +996,7 @@ static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
|
|||
rxq->used_count = 0;
|
||||
}
|
||||
|
||||
static int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget)
|
||||
int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
|
@ -931,7 +1045,9 @@ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
|
|||
rxq->read = 0;
|
||||
rxq->write = 0;
|
||||
rxq->write_actual = 0;
|
||||
memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
|
||||
memset(rxq->rb_stts, 0,
|
||||
(trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) ?
|
||||
sizeof(__le16) : sizeof(struct iwl_rb_status));
|
||||
|
||||
iwl_pcie_rx_init_rxb_lists(rxq);
|
||||
|
||||
|
@ -1002,8 +1118,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
|
|||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_rb_allocator *rba = &trans_pcie->rba;
|
||||
int free_size = trans->cfg->mq_rx_supported ? sizeof(__le64) :
|
||||
sizeof(__le32);
|
||||
int i;
|
||||
|
||||
/*
|
||||
|
@ -1022,27 +1136,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
|
|||
for (i = 0; i < trans->num_rx_queues; i++) {
|
||||
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
|
||||
|
||||
if (rxq->bd)
|
||||
dma_free_coherent(trans->dev,
|
||||
free_size * rxq->queue_size,
|
||||
rxq->bd, rxq->bd_dma);
|
||||
rxq->bd_dma = 0;
|
||||
rxq->bd = NULL;
|
||||
|
||||
if (rxq->rb_stts)
|
||||
dma_free_coherent(trans->dev,
|
||||
sizeof(struct iwl_rb_status),
|
||||
rxq->rb_stts, rxq->rb_stts_dma);
|
||||
else
|
||||
IWL_DEBUG_INFO(trans,
|
||||
"Free rxq->rb_stts which is NULL\n");
|
||||
|
||||
if (rxq->used_bd)
|
||||
dma_free_coherent(trans->dev,
|
||||
sizeof(__le32) * rxq->queue_size,
|
||||
rxq->used_bd, rxq->used_bd_dma);
|
||||
rxq->used_bd_dma = 0;
|
||||
rxq->used_bd = NULL;
|
||||
iwl_pcie_free_rxq_dma(trans, rxq);
|
||||
|
||||
if (rxq->napi.poll)
|
||||
netif_napi_del(&rxq->napi);
|
||||
|
@ -1202,6 +1296,8 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
|
|||
}
|
||||
|
||||
page_stolen |= rxcb._page_stolen;
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||
break;
|
||||
offset += ALIGN(len, FH_RSCSR_FRAME_ALIGN);
|
||||
}
|
||||
|
||||
|
@ -1236,6 +1332,45 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
|
|||
iwl_pcie_rx_reuse_rbd(trans, rxb, rxq, emergency);
|
||||
}
|
||||
|
||||
static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
|
||||
struct iwl_rxq *rxq, int i)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_rx_mem_buffer *rxb;
|
||||
u16 vid;
|
||||
|
||||
if (!trans->cfg->mq_rx_supported) {
|
||||
rxb = rxq->queue[i];
|
||||
rxq->queue[i] = NULL;
|
||||
return rxb;
|
||||
}
|
||||
|
||||
/* used_bd is a 32/16 bit but only 12 are used to retrieve the vid */
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||
vid = le16_to_cpu(rxq->cd[i].rbid) & 0x0FFF;
|
||||
else
|
||||
vid = le32_to_cpu(rxq->bd_32[i]) & 0x0FFF;
|
||||
|
||||
if (!vid || vid > ARRAY_SIZE(trans_pcie->global_table))
|
||||
goto out_err;
|
||||
|
||||
rxb = trans_pcie->global_table[vid - 1];
|
||||
if (rxb->invalid)
|
||||
goto out_err;
|
||||
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||
rxb->size = le32_to_cpu(rxq->cd[i].size) & IWL_RX_CD_SIZE;
|
||||
|
||||
rxb->invalid = true;
|
||||
|
||||
return rxb;
|
||||
|
||||
out_err:
|
||||
WARN(1, "Invalid rxb from HW %u\n", (u32)vid);
|
||||
iwl_force_nmi(trans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_pcie_rx_handle - Main entry function for receiving responses from fw
|
||||
*/
|
||||
|
@ -1250,7 +1385,7 @@ restart:
|
|||
spin_lock(&rxq->lock);
|
||||
/* uCode's read index (stored in shared DRAM) indicates the last Rx
|
||||
* buffer that the driver may process (last buffer filled by ucode). */
|
||||
r = le16_to_cpu(READ_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF;
|
||||
r = le16_to_cpu(iwl_get_closed_rb_stts(trans, rxq)) & 0x0FFF;
|
||||
i = rxq->read;
|
||||
|
||||
/* W/A 9000 device step A0 wrap-around bug */
|
||||
|
@ -1266,30 +1401,9 @@ restart:
|
|||
if (unlikely(rxq->used_count == rxq->queue_size / 2))
|
||||
emergency = true;
|
||||
|
||||
if (trans->cfg->mq_rx_supported) {
|
||||
/*
|
||||
* used_bd is a 32 bit but only 12 are used to retrieve
|
||||
* the vid
|
||||
*/
|
||||
u16 vid = le32_to_cpu(rxq->used_bd[i]) & 0x0FFF;
|
||||
|
||||
if (WARN(!vid ||
|
||||
vid > ARRAY_SIZE(trans_pcie->global_table),
|
||||
"Invalid rxb index from HW %u\n", (u32)vid)) {
|
||||
iwl_force_nmi(trans);
|
||||
goto out;
|
||||
}
|
||||
rxb = trans_pcie->global_table[vid - 1];
|
||||
if (WARN(rxb->invalid,
|
||||
"Invalid rxb from HW %u\n", (u32)vid)) {
|
||||
iwl_force_nmi(trans);
|
||||
goto out;
|
||||
}
|
||||
rxb->invalid = true;
|
||||
} else {
|
||||
rxb = rxq->queue[i];
|
||||
rxq->queue[i] = NULL;
|
||||
}
|
||||
rxb = iwl_pcie_get_rxb(trans, rxq, i);
|
||||
if (!rxb)
|
||||
goto out;
|
||||
|
||||
IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i);
|
||||
iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency);
|
||||
|
@ -1331,6 +1445,9 @@ restart:
|
|||
out:
|
||||
/* Backtrack one entry */
|
||||
rxq->read = i;
|
||||
/* update cr tail with the rxq read pointer */
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
|
||||
*rxq->cr_tail = cpu_to_le16(r);
|
||||
spin_unlock(&rxq->lock);
|
||||
|
||||
/*
|
||||
|
@ -1362,20 +1479,6 @@ static struct iwl_trans_pcie *iwl_pcie_get_trans_pcie(struct msix_entry *entry)
|
|||
return container_of(entries, struct iwl_trans_pcie, msix_entries[0]);
|
||||
}
|
||||
|
||||
static inline void iwl_pcie_clear_irq(struct iwl_trans *trans,
|
||||
struct msix_entry *entry)
|
||||
{
|
||||
/*
|
||||
* Before sending the interrupt the HW disables it to prevent
|
||||
* a nested interrupt. This is done by writing 1 to the corresponding
|
||||
* bit in the mask register. After handling the interrupt, it should be
|
||||
* re-enabled by clearing this bit. This register is defined as
|
||||
* write 1 clear (W1C) register, meaning that it's being clear
|
||||
* by writing 1 to the bit.
|
||||
*/
|
||||
iwl_write32(trans, CSR_MSIX_AUTOMASK_ST_AD, BIT(entry->entry));
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_pcie_rx_msix_handle - Main entry function for receiving responses from fw
|
||||
* This interrupt handler should be used with RSS queue only.
|
||||
|
@ -1970,7 +2073,8 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
|||
|
||||
/* Error detected by uCode */
|
||||
if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) ||
|
||||
(inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR)) {
|
||||
(inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR) ||
|
||||
(inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR_V2)) {
|
||||
IWL_ERR(trans,
|
||||
"Microcode SW error detected. Restarting 0x%X.\n",
|
||||
inta_fh);
|
||||
|
@ -1995,8 +2099,18 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
|||
}
|
||||
}
|
||||
|
||||
/* uCode wakes up after power-down sleep */
|
||||
if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) {
|
||||
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560 &&
|
||||
inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) {
|
||||
/* Reflect IML transfer status */
|
||||
int res = iwl_read32(trans, CSR_IML_RESP_ADDR);
|
||||
|
||||
IWL_DEBUG_ISR(trans, "IML transfer status: %d\n", res);
|
||||
if (res == IWL_IMAGE_RESP_FAIL) {
|
||||
isr_stats->sw++;
|
||||
iwl_pcie_irq_handle_error(trans);
|
||||
}
|
||||
} else if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) {
|
||||
/* uCode wakes up after power-down sleep */
|
||||
IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
|
||||
iwl_pcie_rxq_check_wrptr(trans);
|
||||
iwl_pcie_txq_check_wrptrs(trans);
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "iwl-trans.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-context-info.h"
|
||||
#include "iwl-context-info-gen3.h"
|
||||
#include "internal.h"
|
||||
|
||||
/*
|
||||
|
@ -188,7 +189,10 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power)
|
|||
}
|
||||
|
||||
iwl_pcie_ctxt_info_free_paging(trans);
|
||||
iwl_pcie_ctxt_info_free(trans);
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560)
|
||||
iwl_pcie_ctxt_info_gen3_free(trans);
|
||||
else
|
||||
iwl_pcie_ctxt_info_free(trans);
|
||||
|
||||
/* Make sure (redundant) we've released our request to stay awake */
|
||||
iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
|
@ -346,7 +350,10 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = iwl_pcie_ctxt_info_init(trans, fw);
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560)
|
||||
ret = iwl_pcie_ctxt_info_gen3_init(trans, fw);
|
||||
else
|
||||
ret = iwl_pcie_ctxt_info_init(trans, fw);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
#include "iwl-scd.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "fw/error-dump.h"
|
||||
#include "fw/dbg.h"
|
||||
#include "internal.h"
|
||||
#include "iwl-fh.h"
|
||||
|
||||
|
@ -203,7 +204,7 @@ static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
|
|||
trans_pcie->fw_mon_size = 0;
|
||||
}
|
||||
|
||||
static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
|
||||
void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct page *page = NULL;
|
||||
|
@ -1132,21 +1133,44 @@ static struct iwl_causes_list causes_list[] = {
|
|||
{MSIX_HW_INT_CAUSES_REG_HAP, CSR_MSIX_HW_INT_MASK_AD, 0x2E},
|
||||
};
|
||||
|
||||
static struct iwl_causes_list causes_list_v2[] = {
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH0_NUM, CSR_MSIX_FH_INT_MASK_AD, 0},
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH1_NUM, CSR_MSIX_FH_INT_MASK_AD, 0x1},
|
||||
{MSIX_FH_INT_CAUSES_S2D, CSR_MSIX_FH_INT_MASK_AD, 0x3},
|
||||
{MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5},
|
||||
{MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10},
|
||||
{MSIX_HW_INT_CAUSES_REG_IPC, CSR_MSIX_HW_INT_MASK_AD, 0x11},
|
||||
{MSIX_HW_INT_CAUSES_REG_SW_ERR_V2, CSR_MSIX_HW_INT_MASK_AD, 0x15},
|
||||
{MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16},
|
||||
{MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17},
|
||||
{MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18},
|
||||
{MSIX_HW_INT_CAUSES_REG_SCD, CSR_MSIX_HW_INT_MASK_AD, 0x2A},
|
||||
{MSIX_HW_INT_CAUSES_REG_FH_TX, CSR_MSIX_HW_INT_MASK_AD, 0x2B},
|
||||
{MSIX_HW_INT_CAUSES_REG_HW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x2D},
|
||||
{MSIX_HW_INT_CAUSES_REG_HAP, CSR_MSIX_HW_INT_MASK_AD, 0x2E},
|
||||
};
|
||||
|
||||
static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
|
||||
int i;
|
||||
int i, arr_size =
|
||||
(trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ?
|
||||
ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2);
|
||||
|
||||
/*
|
||||
* Access all non RX causes and map them to the default irq.
|
||||
* In case we are missing at least one interrupt vector,
|
||||
* the first interrupt vector will serve non-RX and FBQ causes.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(causes_list); i++) {
|
||||
iwl_write8(trans, CSR_MSIX_IVAR(causes_list[i].addr), val);
|
||||
iwl_clear_bit(trans, causes_list[i].mask_reg,
|
||||
causes_list[i].cause_num);
|
||||
for (i = 0; i < arr_size; i++) {
|
||||
struct iwl_causes_list *causes =
|
||||
(trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ?
|
||||
causes_list : causes_list_v2;
|
||||
|
||||
iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
|
||||
iwl_clear_bit(trans, causes[i].mask_reg,
|
||||
causes[i].cause_num);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1539,18 +1563,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
|||
|
||||
iwl_pcie_enable_rx_wake(trans, true);
|
||||
|
||||
/*
|
||||
* Reconfigure IVAR table in case of MSIX or reset ict table in
|
||||
* MSI mode since HW reset erased it.
|
||||
* Also enables interrupts - none will happen as
|
||||
* the device doesn't know we're waking it up, only when
|
||||
* the opmode actually tells it after this call.
|
||||
*/
|
||||
iwl_pcie_conf_msix_hw(trans_pcie);
|
||||
if (!trans_pcie->msix_enabled)
|
||||
iwl_pcie_reset_ict(trans);
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
BIT(trans->cfg->csr->flag_mac_access_req));
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
|
@ -1568,6 +1580,18 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reconfigure IVAR table in case of MSIX or reset ict table in
|
||||
* MSI mode since HW reset erased it.
|
||||
* Also enables interrupts - none will happen as
|
||||
* the device doesn't know we're waking it up, only when
|
||||
* the opmode actually tells it after this call.
|
||||
*/
|
||||
iwl_pcie_conf_msix_hw(trans_pcie);
|
||||
if (!trans_pcie->msix_enabled)
|
||||
iwl_pcie_reset_ict(trans);
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
iwl_pcie_set_pwr(trans, false);
|
||||
|
||||
if (!reset) {
|
||||
|
@ -1685,29 +1709,6 @@ static void iwl_pcie_irq_set_affinity(struct iwl_trans *trans)
|
|||
}
|
||||
}
|
||||
|
||||
static const char *queue_name(struct device *dev,
|
||||
struct iwl_trans_pcie *trans_p, int i)
|
||||
{
|
||||
if (trans_p->shared_vec_mask) {
|
||||
int vec = trans_p->shared_vec_mask &
|
||||
IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0;
|
||||
|
||||
if (i == 0)
|
||||
return DRV_NAME ": shared IRQ";
|
||||
|
||||
return devm_kasprintf(dev, GFP_KERNEL,
|
||||
DRV_NAME ": queue %d", i + vec);
|
||||
}
|
||||
if (i == 0)
|
||||
return DRV_NAME ": default queue";
|
||||
|
||||
if (i == trans_p->alloc_vecs - 1)
|
||||
return DRV_NAME ": exception";
|
||||
|
||||
return devm_kasprintf(dev, GFP_KERNEL,
|
||||
DRV_NAME ": queue %d", i);
|
||||
}
|
||||
|
||||
static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
|
||||
struct iwl_trans_pcie *trans_pcie)
|
||||
{
|
||||
|
@ -2236,12 +2237,28 @@ void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
|
|||
jiffies_to_msecs(txq->wd_timeout),
|
||||
txq->read_ptr, txq->write_ptr,
|
||||
iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) &
|
||||
(TFD_QUEUE_SIZE_MAX - 1),
|
||||
(trans->cfg->base_params->max_tfd_queue_size - 1),
|
||||
iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) &
|
||||
(TFD_QUEUE_SIZE_MAX - 1),
|
||||
(trans->cfg->base_params->max_tfd_queue_size - 1),
|
||||
iwl_read_direct32(trans, FH_TX_TRB_REG(fifo)));
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_rxq_dma_data(struct iwl_trans *trans, int queue,
|
||||
struct iwl_trans_rxq_dma_data *data)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (queue >= trans->num_rx_queues || !trans_pcie->rxq)
|
||||
return -EINVAL;
|
||||
|
||||
data->fr_bd_cb = trans_pcie->rxq[queue].bd_dma;
|
||||
data->urbd_stts_wrptr = trans_pcie->rxq[queue].rb_stts_dma;
|
||||
data->ur_bd_cb = trans_pcie->rxq[queue].used_bd_dma;
|
||||
data->fr_bd_wid = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
@ -2522,10 +2539,11 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
|
|||
pos += scnprintf(buf + pos, bufsz - pos, "\tfree_count: %u\n",
|
||||
rxq->free_count);
|
||||
if (rxq->rb_stts) {
|
||||
u32 r = __le16_to_cpu(iwl_get_closed_rb_stts(trans,
|
||||
rxq));
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tclosed_rb_num: %u\n",
|
||||
le16_to_cpu(rxq->rb_stts->closed_rb_num) &
|
||||
0x0FFF);
|
||||
r & 0x0FFF);
|
||||
} else {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tclosed_rb_num: Not Allocated\n");
|
||||
|
@ -2731,7 +2749,7 @@ static u32 iwl_trans_pcie_dump_rbs(struct iwl_trans *trans,
|
|||
|
||||
spin_lock(&rxq->lock);
|
||||
|
||||
r = le16_to_cpu(READ_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF;
|
||||
r = le16_to_cpu(iwl_get_closed_rb_stts(trans, rxq)) & 0x0FFF;
|
||||
|
||||
for (i = rxq->read, j = 0;
|
||||
i != r && j < allocated_rb_nums;
|
||||
|
@ -2934,11 +2952,12 @@ static struct iwl_trans_dump_data
|
|||
struct iwl_txq *cmdq = trans_pcie->txq[trans_pcie->cmd_queue];
|
||||
struct iwl_fw_error_dump_txcmd *txcmd;
|
||||
struct iwl_trans_dump_data *dump_data;
|
||||
u32 len, num_rbs;
|
||||
u32 len, num_rbs = 0;
|
||||
u32 monitor_len;
|
||||
int i, ptr;
|
||||
bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) &&
|
||||
!trans->cfg->mq_rx_supported;
|
||||
!trans->cfg->mq_rx_supported &&
|
||||
trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RB);
|
||||
|
||||
/* transport dump header */
|
||||
len = sizeof(*dump_data);
|
||||
|
@ -2990,6 +3009,10 @@ static struct iwl_trans_dump_data
|
|||
}
|
||||
|
||||
if (trigger && (trigger->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY)) {
|
||||
if (!(trans->dbg_dump_mask &
|
||||
BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)))
|
||||
return NULL;
|
||||
|
||||
dump_data = vzalloc(len);
|
||||
if (!dump_data)
|
||||
return NULL;
|
||||
|
@ -3002,22 +3025,28 @@ static struct iwl_trans_dump_data
|
|||
}
|
||||
|
||||
/* CSR registers */
|
||||
len += sizeof(*data) + IWL_CSR_TO_DUMP;
|
||||
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR))
|
||||
len += sizeof(*data) + IWL_CSR_TO_DUMP;
|
||||
|
||||
/* FH registers */
|
||||
if (trans->cfg->gen2)
|
||||
len += sizeof(*data) +
|
||||
(FH_MEM_UPPER_BOUND_GEN2 - FH_MEM_LOWER_BOUND_GEN2);
|
||||
else
|
||||
len += sizeof(*data) +
|
||||
(FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
|
||||
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) {
|
||||
if (trans->cfg->gen2)
|
||||
len += sizeof(*data) +
|
||||
(FH_MEM_UPPER_BOUND_GEN2 -
|
||||
FH_MEM_LOWER_BOUND_GEN2);
|
||||
else
|
||||
len += sizeof(*data) +
|
||||
(FH_MEM_UPPER_BOUND -
|
||||
FH_MEM_LOWER_BOUND);
|
||||
}
|
||||
|
||||
if (dump_rbs) {
|
||||
/* Dump RBs is supported only for pre-9000 devices (1 queue) */
|
||||
struct iwl_rxq *rxq = &trans_pcie->rxq[0];
|
||||
/* RBs */
|
||||
num_rbs = le16_to_cpu(READ_ONCE(rxq->rb_stts->closed_rb_num))
|
||||
& 0x0FFF;
|
||||
num_rbs =
|
||||
le16_to_cpu(iwl_get_closed_rb_stts(trans, rxq))
|
||||
& 0x0FFF;
|
||||
num_rbs = (num_rbs - rxq->read) & RX_QUEUE_MASK;
|
||||
len += num_rbs * (sizeof(*data) +
|
||||
sizeof(struct iwl_fw_error_dump_rb) +
|
||||
|
@ -3025,7 +3054,8 @@ static struct iwl_trans_dump_data
|
|||
}
|
||||
|
||||
/* Paged memory for gen2 HW */
|
||||
if (trans->cfg->gen2)
|
||||
if (trans->cfg->gen2 &&
|
||||
trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING))
|
||||
for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++)
|
||||
len += sizeof(*data) +
|
||||
sizeof(struct iwl_fw_error_dump_paging) +
|
||||
|
@ -3037,41 +3067,51 @@ static struct iwl_trans_dump_data
|
|||
|
||||
len = 0;
|
||||
data = (void *)dump_data->data;
|
||||
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
|
||||
txcmd = (void *)data->data;
|
||||
spin_lock_bh(&cmdq->lock);
|
||||
ptr = cmdq->write_ptr;
|
||||
for (i = 0; i < cmdq->n_window; i++) {
|
||||
u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr);
|
||||
u32 caplen, cmdlen;
|
||||
|
||||
cmdlen = iwl_trans_pcie_get_cmdlen(trans, cmdq->tfds +
|
||||
trans_pcie->tfd_size * ptr);
|
||||
caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen);
|
||||
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD)) {
|
||||
u16 tfd_size = trans_pcie->tfd_size;
|
||||
|
||||
if (cmdlen) {
|
||||
len += sizeof(*txcmd) + caplen;
|
||||
txcmd->cmdlen = cpu_to_le32(cmdlen);
|
||||
txcmd->caplen = cpu_to_le32(caplen);
|
||||
memcpy(txcmd->data, cmdq->entries[idx].cmd, caplen);
|
||||
txcmd = (void *)((u8 *)txcmd->data + caplen);
|
||||
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
|
||||
txcmd = (void *)data->data;
|
||||
spin_lock_bh(&cmdq->lock);
|
||||
ptr = cmdq->write_ptr;
|
||||
for (i = 0; i < cmdq->n_window; i++) {
|
||||
u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr);
|
||||
u32 caplen, cmdlen;
|
||||
|
||||
cmdlen = iwl_trans_pcie_get_cmdlen(trans,
|
||||
cmdq->tfds +
|
||||
tfd_size * ptr);
|
||||
caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen);
|
||||
|
||||
if (cmdlen) {
|
||||
len += sizeof(*txcmd) + caplen;
|
||||
txcmd->cmdlen = cpu_to_le32(cmdlen);
|
||||
txcmd->caplen = cpu_to_le32(caplen);
|
||||
memcpy(txcmd->data, cmdq->entries[idx].cmd,
|
||||
caplen);
|
||||
txcmd = (void *)((u8 *)txcmd->data + caplen);
|
||||
}
|
||||
|
||||
ptr = iwl_queue_dec_wrap(trans, ptr);
|
||||
}
|
||||
spin_unlock_bh(&cmdq->lock);
|
||||
|
||||
ptr = iwl_queue_dec_wrap(ptr);
|
||||
data->len = cpu_to_le32(len);
|
||||
len += sizeof(*data);
|
||||
data = iwl_fw_error_next_data(data);
|
||||
}
|
||||
spin_unlock_bh(&cmdq->lock);
|
||||
|
||||
data->len = cpu_to_le32(len);
|
||||
len += sizeof(*data);
|
||||
data = iwl_fw_error_next_data(data);
|
||||
|
||||
len += iwl_trans_pcie_dump_csr(trans, &data);
|
||||
len += iwl_trans_pcie_fh_regs_dump(trans, &data);
|
||||
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR))
|
||||
len += iwl_trans_pcie_dump_csr(trans, &data);
|
||||
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS))
|
||||
len += iwl_trans_pcie_fh_regs_dump(trans, &data);
|
||||
if (dump_rbs)
|
||||
len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs);
|
||||
|
||||
/* Paged memory for gen2 HW */
|
||||
if (trans->cfg->gen2) {
|
||||
if (trans->cfg->gen2 &&
|
||||
trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) {
|
||||
for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) {
|
||||
struct iwl_fw_error_dump_paging *paging;
|
||||
dma_addr_t addr =
|
||||
|
@ -3091,8 +3131,8 @@ static struct iwl_trans_dump_data
|
|||
len += sizeof(*data) + sizeof(*paging) + page_len;
|
||||
}
|
||||
}
|
||||
|
||||
len += iwl_trans_pcie_dump_monitor(trans, &data, monitor_len);
|
||||
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR))
|
||||
len += iwl_trans_pcie_dump_monitor(trans, &data, monitor_len);
|
||||
|
||||
dump_data->len = len;
|
||||
|
||||
|
@ -3187,6 +3227,7 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
|
|||
.txq_alloc = iwl_trans_pcie_dyn_txq_alloc,
|
||||
.txq_free = iwl_trans_pcie_dyn_txq_free,
|
||||
.wait_txq_empty = iwl_trans_pcie_wait_txq_empty,
|
||||
.rxq_dma_data = iwl_trans_pcie_rxq_dma_data,
|
||||
};
|
||||
|
||||
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
|
@ -3349,14 +3390,26 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
|
||||
#if IS_ENABLED(CONFIG_IWLMVM)
|
||||
trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID);
|
||||
if (trans->hw_rf_id == CSR_HW_RF_ID_TYPE_HR) {
|
||||
|
||||
if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
||||
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) {
|
||||
u32 hw_status;
|
||||
|
||||
hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS);
|
||||
if (hw_status & UMAG_GEN_HW_IS_FPGA)
|
||||
trans->cfg = &iwl22000_2ax_cfg_qnj_hr_f0;
|
||||
else
|
||||
if (CSR_HW_RF_STEP(trans->hw_rf_id) == SILICON_B_STEP)
|
||||
/*
|
||||
* b step fw is the same for physical card and fpga
|
||||
*/
|
||||
trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
|
||||
else if ((hw_status & UMAG_GEN_HW_IS_FPGA) &&
|
||||
CSR_HW_RF_STEP(trans->hw_rf_id) == SILICON_A_STEP) {
|
||||
trans->cfg = &iwl22000_2ax_cfg_qnj_hr_a0_f0;
|
||||
} else {
|
||||
/*
|
||||
* a step no FPGA
|
||||
*/
|
||||
trans->cfg = &iwl22000_2ac_cfg_hr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue