^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * drivers/net/wireless/mwl8k.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Marvell TOPDOG 802.11 Wireless cards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2008, 2009, 2010 Marvell Semiconductor Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <net/mac80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MWL8K_NAME KBUILD_MODNAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MWL8K_VERSION "0.13"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* Module parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static bool ap_mode_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) module_param(ap_mode_default, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_PARM_DESC(ap_mode_default,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) "Set to 1 to make ap mode the default instead of sta mode");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MWL8K_HIU_GEN_PTR 0x00000c10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define MWL8K_MODE_STA 0x0000005a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MWL8K_MODE_AP 0x000000a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define MWL8K_HIU_INT_CODE 0x00000c14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MWL8K_FWSTA_READY 0xf0f1f2f4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MWL8K_FWAP_READY 0xf1f2f4a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define MWL8K_INT_CODE_CMD_FINISHED 0x00000005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MWL8K_HIU_SCRATCH 0x00000c40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* Host->device communications */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MWL8K_HIU_H2A_INTERRUPT_EVENTS 0x00000c18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MWL8K_HIU_H2A_INTERRUPT_STATUS 0x00000c1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define MWL8K_H2A_INT_DUMMY (1 << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define MWL8K_H2A_INT_RESET (1 << 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define MWL8K_H2A_INT_DOORBELL (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define MWL8K_H2A_INT_PPA_READY (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Device->host communications */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define MWL8K_HIU_A2H_INTERRUPT_STATUS 0x00000c30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define MWL8K_A2H_INT_DUMMY (1 << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define MWL8K_A2H_INT_BA_WATCHDOG (1 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define MWL8K_A2H_INT_RADAR_DETECT (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define MWL8K_A2H_INT_RADIO_ON (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define MWL8K_A2H_INT_RADIO_OFF (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define MWL8K_A2H_INT_MAC_EVENT (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define MWL8K_A2H_INT_OPC_DONE (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define MWL8K_A2H_INT_RX_READY (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define MWL8K_A2H_INT_TX_DONE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* HW micro second timer register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * located at offset 0xA600. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * will be used to timestamp tx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define MWL8K_HW_TIMER_REGISTER 0x0000a600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define BBU_RXRDY_CNT_REG 0x0000a860
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define NOK_CCA_CNT_REG 0x0000a6a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define BBU_AVG_NOISE_VAL 0x67
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) MWL8K_A2H_INT_CHNL_SWITCHED | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) MWL8K_A2H_INT_QUEUE_EMPTY | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) MWL8K_A2H_INT_RADAR_DETECT | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) MWL8K_A2H_INT_RADIO_ON | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) MWL8K_A2H_INT_RADIO_OFF | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) MWL8K_A2H_INT_MAC_EVENT | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) MWL8K_A2H_INT_OPC_DONE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) MWL8K_A2H_INT_RX_READY | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) MWL8K_A2H_INT_TX_DONE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) MWL8K_A2H_INT_BA_WATCHDOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define MWL8K_RX_QUEUES 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define MWL8K_TX_WMM_QUEUES 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define MWL8K_MAX_AMPDU_QUEUES 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define MWL8K_MAX_TX_QUEUES (MWL8K_TX_WMM_QUEUES + MWL8K_MAX_AMPDU_QUEUES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define mwl8k_tx_queues(priv) (MWL8K_TX_WMM_QUEUES + (priv)->num_ampdu_queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* txpriorities are mapped with hw queues.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * Each hw queue has a txpriority.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define TOTAL_HW_TX_QUEUES 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Each HW queue can have one AMPDU stream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * But, because one of the hw queue is reserved,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * maximum AMPDU queues that can be created are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * one short of total tx queues.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define MWL8K_NUM_AMPDU_STREAMS (TOTAL_HW_TX_QUEUES - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define MWL8K_NUM_CHANS 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct rxd_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int rxd_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) void (*rxd_refill)(void *rxd, dma_addr_t addr, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) __le16 *qos, s8 *noise);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct mwl8k_device_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) char *part_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) char *helper_image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) char *fw_image_sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) char *fw_image_ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct rxd_ops *ap_rxd_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 fw_api_ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct mwl8k_rx_queue {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int rxd_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* hw receives here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* refill descs here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) void *rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) dma_addr_t rxd_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) DEFINE_DMA_UNMAP_ADDR(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) } *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct mwl8k_tx_queue {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* hw transmits here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* sw appends here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct mwl8k_tx_desc *txd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) dma_addr_t txd_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct sk_buff **skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) AMPDU_NO_STREAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) AMPDU_STREAM_NEW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) AMPDU_STREAM_IN_PROGRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) AMPDU_STREAM_ACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct mwl8k_ampdu_stream {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct ieee80211_sta *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) u8 tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u8 state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) u8 idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct mwl8k_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct ieee80211_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct mwl8k_device_info *device_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) void __iomem *sram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) const struct firmware *fw_helper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) const struct firmware *fw_ucode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* hardware/firmware parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) bool ap_fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct rxd_ops *rxd_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct ieee80211_supported_band band_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct ieee80211_channel channels_24[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct ieee80211_rate rates_24[13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct ieee80211_supported_band band_50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct ieee80211_channel channels_50[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct ieee80211_rate rates_50[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u32 ap_macids_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u32 sta_macids_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* Ampdu stream information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u8 num_ampdu_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) spinlock_t stream_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct mwl8k_ampdu_stream ampdu[MWL8K_MAX_AMPDU_QUEUES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct work_struct watchdog_ba_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* firmware access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct mutex fw_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct task_struct *fw_mutex_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct task_struct *hw_restart_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int fw_mutex_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct completion *hostcmd_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) atomic_t watchdog_event_pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* lock held over TX and TX reap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) spinlock_t tx_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* TX quiesce completion, protected by fw_mutex and tx_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct completion *tx_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* List of interfaces. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u32 macids_used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct list_head vif_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* power management status cookie from firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u32 *cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) dma_addr_t cookie_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u16 num_mcaddrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u8 hw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) u32 fw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) u32 caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * Running count of TX packets in flight, to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * iterating over the transmit rings each time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int pending_tx_pkts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct mwl8k_tx_queue txq[MWL8K_MAX_TX_QUEUES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) u32 txq_offset[MWL8K_MAX_TX_QUEUES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) bool radio_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) bool radio_short_preamble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) bool sniffer_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) bool wmm_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* XXX need to convert this to handle multiple interfaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) bool capture_beacon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u8 capture_bssid[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct sk_buff *beacon_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * This FJ worker has to be global as it is scheduled from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * RX handler. At this point we don't know which interface it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * belongs to until the list of bssids waiting to complete join
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * is checked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct work_struct finalize_join_worker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Tasklet to perform TX reclaim. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct tasklet_struct poll_tx_task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* Tasklet to perform RX. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct tasklet_struct poll_rx_task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* Most recently reported noise in dBm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) s8 noise;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * preserve the queue configurations so they can be restored if/when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * the firmware image is swapped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_WMM_QUEUES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /* To perform the task of reloading the firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct work_struct fw_reload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) bool hw_restart_in_progress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* async firmware loading state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) unsigned fw_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) char *fw_pref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) char *fw_alt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) bool is_8764;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct completion firmware_loading_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* bitmap of running BSSes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) u32 running_bsses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* ACS related */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) bool sw_scan_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct ieee80211_channel *acs_chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) unsigned long channel_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct survey_info survey[MWL8K_NUM_CHANS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) #define MAX_WEP_KEY_LEN 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) #define NUM_WEP_KEYS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* Per interface specific private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct mwl8k_vif {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct ieee80211_vif *vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* Firmware macid for this vif. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int macid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* Non AMPDU sequence number assigned by driver. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) u16 seqno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /* Saved WEP keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) u8 enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) } wep_key_conf[NUM_WEP_KEYS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /* BSSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u8 bssid[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* A flag to indicate is HW crypto is enabled for this bssid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) bool is_hw_crypto_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) #define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct tx_traffic_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) u32 start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) u32 pkts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) #define MWL8K_MAX_TID 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct mwl8k_sta {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* Index into station database. Returned by UPDATE_STADB. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u8 peer_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) u8 is_ampdu_allowed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct tx_traffic_info tx_stats[MWL8K_MAX_TID];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static const struct ieee80211_channel mwl8k_channels_24[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) { .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) { .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) { .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) { .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) { .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) { .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) { .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) { .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) { .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) { .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) { .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) { .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) { .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) { .band = NL80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static const struct ieee80211_rate mwl8k_rates_24[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) { .bitrate = 10, .hw_value = 2, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) { .bitrate = 20, .hw_value = 4, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) { .bitrate = 55, .hw_value = 11, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) { .bitrate = 110, .hw_value = 22, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) { .bitrate = 220, .hw_value = 44, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) { .bitrate = 60, .hw_value = 12, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) { .bitrate = 90, .hw_value = 18, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) { .bitrate = 120, .hw_value = 24, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) { .bitrate = 180, .hw_value = 36, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) { .bitrate = 240, .hw_value = 48, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) { .bitrate = 360, .hw_value = 72, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) { .bitrate = 480, .hw_value = 96, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) { .bitrate = 540, .hw_value = 108, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static const struct ieee80211_channel mwl8k_channels_50[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) { .band = NL80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) { .band = NL80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) { .band = NL80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) { .band = NL80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) { .band = NL80211_BAND_5GHZ, .center_freq = 5745, .hw_value = 149, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) { .band = NL80211_BAND_5GHZ, .center_freq = 5765, .hw_value = 153, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) { .band = NL80211_BAND_5GHZ, .center_freq = 5785, .hw_value = 157, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) { .band = NL80211_BAND_5GHZ, .center_freq = 5805, .hw_value = 161, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) { .band = NL80211_BAND_5GHZ, .center_freq = 5825, .hw_value = 165, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static const struct ieee80211_rate mwl8k_rates_50[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) { .bitrate = 60, .hw_value = 12, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) { .bitrate = 90, .hw_value = 18, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) { .bitrate = 120, .hw_value = 24, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) { .bitrate = 180, .hw_value = 36, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) { .bitrate = 240, .hw_value = 48, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) { .bitrate = 360, .hw_value = 72, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) { .bitrate = 480, .hw_value = 96, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) { .bitrate = 540, .hw_value = 108, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* Set or get info from Firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) #define MWL8K_CMD_GET 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) #define MWL8K_CMD_SET 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) #define MWL8K_CMD_SET_LIST 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* Firmware command codes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) #define MWL8K_CMD_CODE_DNLD 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) #define MWL8K_CMD_GET_HW_SPEC 0x0003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #define MWL8K_CMD_SET_HW_SPEC 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) #define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) #define MWL8K_CMD_GET_STAT 0x0014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) #define MWL8K_CMD_BBP_REG_ACCESS 0x001a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) #define MWL8K_CMD_RADIO_CONTROL 0x001c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) #define MWL8K_CMD_RF_TX_POWER 0x001e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) #define MWL8K_CMD_TX_POWER 0x001f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) #define MWL8K_CMD_RF_ANTENNA 0x0020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) #define MWL8K_CMD_SET_BEACON 0x0100 /* per-vif */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) #define MWL8K_CMD_SET_PRE_SCAN 0x0107
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) #define MWL8K_CMD_SET_POST_SCAN 0x0108
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) #define MWL8K_CMD_SET_RF_CHANNEL 0x010a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) #define MWL8K_CMD_SET_AID 0x010d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) #define MWL8K_CMD_SET_RATE 0x0110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) #define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) #define MWL8K_CMD_RTS_THRESHOLD 0x0113
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) #define MWL8K_CMD_SET_SLOT 0x0114
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) #define MWL8K_CMD_SET_EDCA_PARAMS 0x0115
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) #define MWL8K_CMD_SET_WMM_MODE 0x0123
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) #define MWL8K_CMD_MIMO_CONFIG 0x0125
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) #define MWL8K_CMD_USE_FIXED_RATE 0x0126
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) #define MWL8K_CMD_ENABLE_SNIFFER 0x0150
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) #define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) #define MWL8K_CMD_GET_WATCHDOG_BITMAP 0x0205
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) #define MWL8K_CMD_DEL_MAC_ADDR 0x0206 /* per-vif */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) #define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) #define MWL8K_CMD_UPDATE_STADB 0x1123
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) #define MWL8K_CMD_BASTREAM 0x1125
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) #define MWL8K_LEGACY_5G_RATE_OFFSET \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) (ARRAY_SIZE(mwl8k_rates_24) - ARRAY_SIZE(mwl8k_rates_50))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) u16 command = le16_to_cpu(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) #define MWL8K_CMDNAME(x) case MWL8K_CMD_##x: do {\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) snprintf(buf, bufsize, "%s", #x);\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return buf;\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) switch (command & ~0x8000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) MWL8K_CMDNAME(CODE_DNLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) MWL8K_CMDNAME(GET_HW_SPEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) MWL8K_CMDNAME(SET_HW_SPEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) MWL8K_CMDNAME(MAC_MULTICAST_ADR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) MWL8K_CMDNAME(GET_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) MWL8K_CMDNAME(RADIO_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) MWL8K_CMDNAME(RF_TX_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) MWL8K_CMDNAME(TX_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) MWL8K_CMDNAME(RF_ANTENNA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) MWL8K_CMDNAME(SET_BEACON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) MWL8K_CMDNAME(SET_PRE_SCAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) MWL8K_CMDNAME(SET_POST_SCAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) MWL8K_CMDNAME(SET_RF_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) MWL8K_CMDNAME(SET_AID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) MWL8K_CMDNAME(SET_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) MWL8K_CMDNAME(SET_FINALIZE_JOIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) MWL8K_CMDNAME(RTS_THRESHOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) MWL8K_CMDNAME(SET_SLOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) MWL8K_CMDNAME(SET_EDCA_PARAMS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) MWL8K_CMDNAME(SET_WMM_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) MWL8K_CMDNAME(MIMO_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) MWL8K_CMDNAME(USE_FIXED_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) MWL8K_CMDNAME(ENABLE_SNIFFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) MWL8K_CMDNAME(SET_MAC_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) MWL8K_CMDNAME(SET_RATEADAPT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) MWL8K_CMDNAME(BSS_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) MWL8K_CMDNAME(SET_NEW_STN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) MWL8K_CMDNAME(UPDATE_ENCRYPTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) MWL8K_CMDNAME(UPDATE_STADB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) MWL8K_CMDNAME(BASTREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) MWL8K_CMDNAME(GET_WATCHDOG_BITMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) snprintf(buf, bufsize, "0x%x", cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) #undef MWL8K_CMDNAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* Hardware and firmware reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static void mwl8k_hw_reset(struct mwl8k_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) iowrite32(MWL8K_H2A_INT_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) iowrite32(MWL8K_H2A_INT_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* Release fw image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static void mwl8k_release_fw(const struct firmware **fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (*fw == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) release_firmware(*fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) *fw = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static void mwl8k_release_firmware(struct mwl8k_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) mwl8k_release_fw(&priv->fw_ucode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) mwl8k_release_fw(&priv->fw_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /* states for asynchronous f/w loading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static void mwl8k_fw_state_machine(const struct firmware *fw, void *context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) FW_STATE_INIT = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) FW_STATE_LOADING_PREF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) FW_STATE_LOADING_ALT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) FW_STATE_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* Request fw image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int mwl8k_request_fw(struct mwl8k_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) const char *fname, const struct firmware **fw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) bool nowait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* release current image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (*fw != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) mwl8k_release_fw(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (nowait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return request_firmware_nowait(THIS_MODULE, 1, fname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) &priv->pdev->dev, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) priv, mwl8k_fw_state_machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return request_firmware(fw, fname, &priv->pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static int mwl8k_request_firmware(struct mwl8k_priv *priv, char *fw_image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) bool nowait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct mwl8k_device_info *di = priv->device_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (di->helper_image != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (nowait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) rc = mwl8k_request_fw(priv, di->helper_image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) &priv->fw_helper, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) rc = mwl8k_request_fw(priv, di->helper_image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) &priv->fw_helper, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) printk(KERN_ERR "%s: Error requesting helper fw %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) pci_name(priv->pdev), di->helper_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (rc || nowait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (nowait) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * if we get here, no helper image is needed. Skip the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * FW_STATE_INIT state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) priv->fw_state = FW_STATE_LOADING_PREF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) rc = mwl8k_request_fw(priv, fw_image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) &priv->fw_ucode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) rc = mwl8k_request_fw(priv, fw_image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) &priv->fw_ucode, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) printk(KERN_ERR "%s: Error requesting firmware file %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) pci_name(priv->pdev), fw_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) mwl8k_release_fw(&priv->fw_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct mwl8k_cmd_pkt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) __le16 code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) __le16 length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) __u8 seq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) __u8 macid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) __le16 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) char payload[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * Firmware loading.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) void __iomem *regs = priv->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) dma_addr_t dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) int loops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (pci_dma_mapping_error(priv->pdev, dma_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) iowrite32(0, regs + MWL8K_HIU_INT_CODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) iowrite32(MWL8K_H2A_INT_DOORBELL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) iowrite32(MWL8K_H2A_INT_DUMMY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) loops = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) u32 int_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (priv->is_8764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) int_code = ioread32(regs +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) MWL8K_HIU_H2A_INTERRUPT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (int_code == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) int_code = ioread32(regs + MWL8K_HIU_INT_CODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (int_code == MWL8K_INT_CODE_CMD_FINISHED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) iowrite32(0, regs + MWL8K_HIU_INT_CODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) } while (--loops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return loops ? 0 : -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static int mwl8k_load_fw_image(struct mwl8k_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) const u8 *data, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct mwl8k_cmd_pkt *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) cmd = kmalloc(sizeof(*cmd) + 256, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) cmd->seq_num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) cmd->macid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) cmd->result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) while (length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) int block_size = length > 256 ? 256 : length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) memcpy(cmd->payload, data + done, block_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) cmd->length = cpu_to_le16(block_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) rc = mwl8k_send_fw_load_cmd(priv, cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) sizeof(*cmd) + block_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) done += block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) length -= block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) cmd->length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) rc = mwl8k_send_fw_load_cmd(priv, cmd, sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static int mwl8k_feed_fw_image(struct mwl8k_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) const u8 *data, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) unsigned char *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) int may_continue, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) u32 done, prev_block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) buffer = kmalloc(1024, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (buffer == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) prev_block_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) may_continue = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) while (may_continue > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) u32 block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) block_size = ioread32(priv->regs + MWL8K_HIU_SCRATCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (block_size & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) block_size &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) may_continue--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) done += prev_block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) length -= prev_block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (block_size > 1024 || block_size > length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) rc = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (length == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (block_size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) rc = -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) may_continue--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) prev_block_size = block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) memcpy(buffer, data + done, block_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) rc = mwl8k_send_fw_load_cmd(priv, buffer, block_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (!rc && length != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) rc = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) static int mwl8k_load_firmware(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) const struct firmware *fw = priv->fw_ucode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) int loops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (!memcmp(fw->data, "\x01\x00\x00\x00", 4) && !priv->is_8764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) const struct firmware *helper = priv->fw_helper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (helper == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) printk(KERN_ERR "%s: helper image needed but none "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) "given\n", pci_name(priv->pdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) rc = mwl8k_load_fw_image(priv, helper->data, helper->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) printk(KERN_ERR "%s: unable to load firmware "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) "helper image\n", pci_name(priv->pdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (priv->is_8764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) rc = mwl8k_load_fw_image(priv, fw->data, fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) printk(KERN_ERR "%s: unable to load firmware image\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) pci_name(priv->pdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) loops = 500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) u32 ready_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) ready_code = ioread32(priv->regs + MWL8K_HIU_INT_CODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (ready_code == MWL8K_FWAP_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) priv->ap_fw = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) } else if (ready_code == MWL8K_FWSTA_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) priv->ap_fw = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) } while (--loops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return loops ? 0 : -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /* DMA header used by firmware and hardware. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) struct mwl8k_dma_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) __le16 fwlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) struct ieee80211_hdr wh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) char data[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) /* Routines to add/remove DMA header from skb. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct mwl8k_dma_data *tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) int hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) tr = (struct mwl8k_dma_data *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (hdrlen != sizeof(tr->wh)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (ieee80211_is_data_qos(tr->wh.frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) *((__le16 *)(tr->data - 2)) = qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) memmove(tr->data - hdrlen, &tr->wh, hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (hdrlen != sizeof(*tr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) skb_pull(skb, sizeof(*tr) - hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) #define REDUCED_TX_HEADROOM 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) int head_pad, int tail_pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct ieee80211_hdr *wh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) int reqd_hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct mwl8k_dma_data *tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * Add a firmware DMA header; the firmware requires that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * present a 2-byte payload length followed by a 4-address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * header (without QoS field), followed (optionally) by any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * WEP/ExtIV header (but only filled in for CCMP).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) wh = (struct ieee80211_hdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) hdrlen = ieee80211_hdrlen(wh->frame_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * Check if skb_resize is required because of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * tx_headroom adjustment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (priv->ap_fw && (hdrlen < (sizeof(struct ieee80211_cts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) + REDUCED_TX_HEADROOM))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (pskb_expand_head(skb, REDUCED_TX_HEADROOM, 0, GFP_ATOMIC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) wiphy_err(priv->hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) "Failed to reallocate TX buffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) skb->truesize += REDUCED_TX_HEADROOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) reqd_hdrlen = sizeof(*tr) + head_pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (hdrlen != reqd_hdrlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) skb_push(skb, reqd_hdrlen - hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (ieee80211_is_data_qos(wh->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) hdrlen -= IEEE80211_QOS_CTL_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) tr = (struct mwl8k_dma_data *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (wh != &tr->wh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) memmove(&tr->wh, wh, hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (hdrlen != sizeof(tr->wh))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) * Firmware length is the length of the fully formed "802.11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * payload". That is, everything except for the 802.11 header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * This includes all crypto material including the MIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct ieee80211_hdr *wh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) struct ieee80211_tx_info *tx_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) struct ieee80211_key_conf *key_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) int data_pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) int head_pad = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) wh = (struct ieee80211_hdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) tx_info = IEEE80211_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) key_conf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (ieee80211_is_data(wh->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) key_conf = tx_info->control.hw_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * Make sure the packet header is in the DMA header format (4-address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * without QoS), and add head & tail padding when HW crypto is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * We have the following trailer padding requirements:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * - WEP: 4 trailer bytes (ICV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * - TKIP: 12 trailer bytes (8 MIC + 4 ICV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * - CCMP: 8 trailer bytes (MIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) data_pad = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (key_conf != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) head_pad = key_conf->iv_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) switch (key_conf->cipher) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) case WLAN_CIPHER_SUITE_WEP40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) case WLAN_CIPHER_SUITE_WEP104:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) data_pad = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) case WLAN_CIPHER_SUITE_TKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) data_pad = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) case WLAN_CIPHER_SUITE_CCMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) data_pad = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) mwl8k_add_dma_header(priv, skb, head_pad, data_pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) * Packet reception for 88w8366/88w8764 AP firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct mwl8k_rxd_ap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) __le16 pkt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) __u8 sq2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) __u8 rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) __le32 pkt_phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) __le32 next_rxd_phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) __le16 qos_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) __le16 htsig2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) __le32 hw_rssi_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) __le32 hw_noise_floor_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) __u8 noise_floor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) __u8 pad0[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) __u8 rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) __u8 rx_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) __u8 channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) __u8 rx_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) #define MWL8K_AP_RATE_INFO_MCS_FORMAT 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) #define MWL8K_AP_RATE_INFO_40MHZ 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) #define MWL8K_AP_RATE_INFO_RATEID(x) ((x) & 0x3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) #define MWL8K_AP_RX_CTRL_OWNED_BY_HOST 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /* 8366/8764 AP rx_status bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) #define MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) #define MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) #define MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) #define MWL8K_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) #define MWL8K_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) static void mwl8k_rxd_ap_init(void *_rxd, dma_addr_t next_dma_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) struct mwl8k_rxd_ap *rxd = _rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) rxd->rx_ctrl = MWL8K_AP_RX_CTRL_OWNED_BY_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) static void mwl8k_rxd_ap_refill(void *_rxd, dma_addr_t addr, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) struct mwl8k_rxd_ap *rxd = _rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) rxd->pkt_len = cpu_to_le16(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) rxd->pkt_phys_addr = cpu_to_le32(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) rxd->rx_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) __le16 *qos, s8 *noise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct mwl8k_rxd_ap *rxd = _rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (!(rxd->rx_ctrl & MWL8K_AP_RX_CTRL_OWNED_BY_HOST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) rmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) memset(status, 0, sizeof(*status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) status->signal = -rxd->rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) *noise = -rxd->noise_floor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (rxd->rate & MWL8K_AP_RATE_INFO_MCS_FORMAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) status->encoding = RX_ENC_HT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (rxd->rate & MWL8K_AP_RATE_INFO_40MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) status->bw = RATE_INFO_BW_40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) status->rate_idx = MWL8K_AP_RATE_INFO_RATEID(rxd->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) for (i = 0; i < ARRAY_SIZE(mwl8k_rates_24); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (mwl8k_rates_24[i].hw_value == rxd->rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) status->rate_idx = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (rxd->channel > 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) status->band = NL80211_BAND_5GHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (!(status->encoding == RX_ENC_HT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) status->band = NL80211_BAND_2GHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) status->freq = ieee80211_channel_to_frequency(rxd->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) status->band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) *qos = rxd->qos_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if ((rxd->rx_status != MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) (rxd->rx_status & MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) (rxd->rx_status & MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) status->flag |= RX_FLAG_MMIC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return le16_to_cpu(rxd->pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) static struct rxd_ops rxd_ap_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) .rxd_size = sizeof(struct mwl8k_rxd_ap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) .rxd_init = mwl8k_rxd_ap_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) .rxd_refill = mwl8k_rxd_ap_refill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) .rxd_process = mwl8k_rxd_ap_process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) * Packet reception for STA firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) struct mwl8k_rxd_sta {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) __le16 pkt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) __u8 link_quality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) __u8 noise_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) __le32 pkt_phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) __le32 next_rxd_phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) __le16 qos_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) __le16 rate_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) __le32 pad0[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) __u8 rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) __u8 channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) __le16 pad1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) __u8 rx_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) __u8 rx_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) __u8 pad2[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) #define MWL8K_STA_RATE_INFO_SHORTPRE 0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) #define MWL8K_STA_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) #define MWL8K_STA_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) #define MWL8K_STA_RATE_INFO_40MHZ 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) #define MWL8K_STA_RATE_INFO_SHORTGI 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) #define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) #define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) #define MWL8K_STA_RX_CTRL_DECRYPT_ERROR 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) /* ICV=0 or MIC=1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) #define MWL8K_STA_RX_CTRL_DEC_ERR_TYPE 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /* Key is uploaded only in failure case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) #define MWL8K_STA_RX_CTRL_KEY_INDEX 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct mwl8k_rxd_sta *rxd = _rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) rxd->rx_ctrl = MWL8K_STA_RX_CTRL_OWNED_BY_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) struct mwl8k_rxd_sta *rxd = _rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) rxd->pkt_len = cpu_to_le16(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) rxd->pkt_phys_addr = cpu_to_le32(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) rxd->rx_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) __le16 *qos, s8 *noise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) struct mwl8k_rxd_sta *rxd = _rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) u16 rate_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (!(rxd->rx_ctrl & MWL8K_STA_RX_CTRL_OWNED_BY_HOST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) rmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) rate_info = le16_to_cpu(rxd->rate_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) memset(status, 0, sizeof(*status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) status->signal = -rxd->rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) *noise = -rxd->noise_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (rate_info & MWL8K_STA_RATE_INFO_SHORTPRE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (rate_info & MWL8K_STA_RATE_INFO_40MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) status->bw = RATE_INFO_BW_40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (rate_info & MWL8K_STA_RATE_INFO_SHORTGI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (rate_info & MWL8K_STA_RATE_INFO_MCS_FORMAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) status->encoding = RX_ENC_HT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (rxd->channel > 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) status->band = NL80211_BAND_5GHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (!(status->encoding == RX_ENC_HT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) status->rate_idx >= MWL8K_LEGACY_5G_RATE_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) status->rate_idx -= MWL8K_LEGACY_5G_RATE_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) status->band = NL80211_BAND_2GHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) status->freq = ieee80211_channel_to_frequency(rxd->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) status->band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) *qos = rxd->qos_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) (rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DEC_ERR_TYPE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) status->flag |= RX_FLAG_MMIC_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return le16_to_cpu(rxd->pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) static struct rxd_ops rxd_sta_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) .rxd_size = sizeof(struct mwl8k_rxd_sta),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) .rxd_init = mwl8k_rxd_sta_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) .rxd_refill = mwl8k_rxd_sta_refill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) .rxd_process = mwl8k_rxd_sta_process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) #define MWL8K_RX_DESCS 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) #define MWL8K_RX_MAXSZ 3800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) struct mwl8k_rx_queue *rxq = priv->rxq + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) rxq->rxd_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) rxq->head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) rxq->tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) rxq->rxd = pci_zalloc_consistent(priv->pdev, size, &rxq->rxd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (rxq->rxd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) wiphy_err(hw->wiphy, "failed to alloc RX descriptors\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (rxq->buf == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) for (i = 0; i < MWL8K_RX_DESCS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) int desc_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) void *rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) int nexti;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) dma_addr_t next_dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) desc_size = priv->rxd_ops->rxd_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) rxd = rxq->rxd + (i * priv->rxd_ops->rxd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) nexti = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (nexti == MWL8K_RX_DESCS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) nexti = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) next_dma_addr = rxq->rxd_dma + (nexti * desc_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) priv->rxd_ops->rxd_init(rxd, next_dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) static int rxq_refill(struct ieee80211_hw *hw, int index, int limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) struct mwl8k_rx_queue *rxq = priv->rxq + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) int refilled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) refilled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) while (rxq->rxd_count < MWL8K_RX_DESCS && limit--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) dma_addr_t addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) int rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) void *rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) skb = dev_alloc_skb(MWL8K_RX_MAXSZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) addr = pci_map_single(priv->pdev, skb->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) MWL8K_RX_MAXSZ, DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) rxq->rxd_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) rx = rxq->tail++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (rxq->tail == MWL8K_RX_DESCS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) rxq->tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) rxq->buf[rx].skb = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) dma_unmap_addr_set(&rxq->buf[rx], dma, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) refilled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return refilled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) /* Must be called only when the card's reception is completely halted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) struct mwl8k_rx_queue *rxq = priv->rxq + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (rxq->rxd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) for (i = 0; i < MWL8K_RX_DESCS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (rxq->buf[i].skb != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) pci_unmap_single(priv->pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) dma_unmap_addr(&rxq->buf[i], dma),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) dma_unmap_addr_set(&rxq->buf[i], dma, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) kfree_skb(rxq->buf[i].skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) rxq->buf[i].skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) kfree(rxq->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) rxq->buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) pci_free_consistent(priv->pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) MWL8K_RX_DESCS * priv->rxd_ops->rxd_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) rxq->rxd, rxq->rxd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) rxq->rxd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) * Scan a list of BSSIDs to process for finalize join.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * Allows for extension to process multiple BSSIDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) return priv->capture_beacon &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) ieee80211_is_beacon(wh->frame_control) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) ether_addr_equal_64bits(wh->addr3, priv->capture_bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) static inline void mwl8k_save_beacon(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) priv->capture_beacon = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) eth_zero_addr(priv->capture_bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) * Use GFP_ATOMIC as rxq_process is called from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) * the primary interrupt handler, memory allocation call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) * must not sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) priv->beacon_skb = skb_copy(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (priv->beacon_skb != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) ieee80211_queue_work(hw, &priv->finalize_join_worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) static inline struct mwl8k_vif *mwl8k_find_vif_bss(struct list_head *vif_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) u8 *bssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) struct mwl8k_vif *mwl8k_vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) list_for_each_entry(mwl8k_vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) vif_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (memcmp(bssid, mwl8k_vif->bssid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) ETH_ALEN) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) return mwl8k_vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) struct mwl8k_vif *mwl8k_vif = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) struct mwl8k_rx_queue *rxq = priv->rxq + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) int processed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) processed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) while (rxq->rxd_count && limit--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) void *rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) int pkt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) struct ieee80211_rx_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) struct ieee80211_hdr *wh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) __le16 qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) skb = rxq->buf[rxq->head].skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) &priv->noise);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (pkt_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) rxq->buf[rxq->head].skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) pci_unmap_single(priv->pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) dma_unmap_addr(&rxq->buf[rxq->head], dma),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) dma_unmap_addr_set(&rxq->buf[rxq->head], dma, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) rxq->head++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (rxq->head == MWL8K_RX_DESCS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) rxq->head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) rxq->rxd_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) wh = &((struct mwl8k_dma_data *)skb->data)->wh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * Check for a pending join operation. Save a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) * copy of the beacon and schedule a tasklet to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) * send a FINALIZE_JOIN command to the firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (mwl8k_capture_bssid(priv, (void *)skb->data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) mwl8k_save_beacon(hw, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (ieee80211_has_protected(wh->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /* Check if hw crypto has been enabled for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) * this bss. If yes, set the status flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) mwl8k_vif = mwl8k_find_vif_bss(&priv->vif_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) wh->addr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) if (mwl8k_vif != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) mwl8k_vif->is_hw_crypto_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * When MMIC ERROR is encountered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * by the firmware, payload is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * dropped and only 32 bytes of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * mwl8k Firmware header is sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * to the host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) * We need to add four bytes of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) * key information. In it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * MAC80211 expects keyidx set to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) * 0 for triggering Counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) * Measure of MMIC failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (status.flag & RX_FLAG_MMIC_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) struct mwl8k_dma_data *tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) tr = (struct mwl8k_dma_data *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) memset((void *)&(tr->data), 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) pkt_len += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (!ieee80211_is_auth(wh->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) status.flag |= RX_FLAG_IV_STRIPPED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) RX_FLAG_DECRYPTED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) RX_FLAG_MMIC_STRIPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) skb_put(skb, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) mwl8k_remove_dma_header(skb, qos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) ieee80211_rx_irqsafe(hw, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) processed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) return processed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) * Packet transmission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) #define MWL8K_TXD_STATUS_OK 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) #define MWL8K_QOS_QLEN_UNSPEC 0xff00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) #define MWL8K_QOS_ACK_POLICY_MASK 0x0060
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) #define MWL8K_QOS_ACK_POLICY_NORMAL 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) #define MWL8K_QOS_ACK_POLICY_BLOCKACK 0x0060
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) #define MWL8K_QOS_EOSP 0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) struct mwl8k_tx_desc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) __le32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) __u8 data_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) __u8 tx_priority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) __le16 qos_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) __le32 pkt_phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) __le16 pkt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) __u8 dest_MAC_addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) __le32 next_txd_phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) __le32 timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) __le16 rate_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) __u8 peer_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) __u8 tx_frag_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) #define MWL8K_TX_DESCS 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) struct mwl8k_tx_queue *txq = priv->txq + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) txq->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) txq->head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) txq->tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) txq->txd = pci_zalloc_consistent(priv->pdev, size, &txq->txd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if (txq->txd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) wiphy_err(hw->wiphy, "failed to alloc TX descriptors\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (txq->skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) txq->txd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) for (i = 0; i < MWL8K_TX_DESCS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) struct mwl8k_tx_desc *tx_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) int nexti;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) tx_desc = txq->txd + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) nexti = (i + 1) % MWL8K_TX_DESCS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) tx_desc->status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) tx_desc->next_txd_phys_addr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) cpu_to_le32(txq->txd_dma + nexti * sizeof(*tx_desc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) static inline void mwl8k_tx_start(struct mwl8k_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) iowrite32(MWL8K_H2A_INT_PPA_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) iowrite32(MWL8K_H2A_INT_DUMMY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) ioread32(priv->regs + MWL8K_HIU_INT_CODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) for (i = 0; i < mwl8k_tx_queues(priv); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) struct mwl8k_tx_queue *txq = priv->txq + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) int fw_owned = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) int drv_owned = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) int unused = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) int desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) for (desc = 0; desc < MWL8K_TX_DESCS; desc++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) struct mwl8k_tx_desc *tx_desc = txq->txd + desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) status = le32_to_cpu(tx_desc->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (status & MWL8K_TXD_STATUS_FW_OWNED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) fw_owned++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) drv_owned++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) if (tx_desc->pkt_len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) unused++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) wiphy_err(hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) "txq[%d] len=%d head=%d tail=%d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) "fw_owned=%d drv_owned=%d unused=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) txq->len, txq->head, txq->tail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) fw_owned, drv_owned, unused);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) * Must be called with priv->fw_mutex held and tx queues stopped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) #define MWL8K_TX_WAIT_TIMEOUT_MS 5000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) DECLARE_COMPLETION_ONSTACK(tx_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) int retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) might_sleep();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) /* Since fw restart is in progress, allow only the firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) * commands from the restart code and block the other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) * commands since they are going to fail in any case since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) * the firmware has crashed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (priv->hw_restart_in_progress) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) if (priv->hw_restart_owner == current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) if (atomic_read(&priv->watchdog_event_pending))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) * The TX queues are stopped at this point, so this test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) * doesn't need to take ->tx_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) if (!priv->pending_tx_pkts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) retry = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) spin_lock_bh(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) priv->tx_wait = &tx_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) while (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) int oldcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) oldcount = priv->pending_tx_pkts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) spin_unlock_bh(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) timeout = wait_for_completion_timeout(&tx_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) msecs_to_jiffies(MWL8K_TX_WAIT_TIMEOUT_MS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) if (atomic_read(&priv->watchdog_event_pending)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) spin_lock_bh(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) priv->tx_wait = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) spin_unlock_bh(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) spin_lock_bh(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) if (timeout || !priv->pending_tx_pkts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) WARN_ON(priv->pending_tx_pkts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) if (retry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) wiphy_notice(hw->wiphy, "tx rings drained\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) if (retry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) mwl8k_tx_start(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) retry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) if (priv->pending_tx_pkts < oldcount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) wiphy_notice(hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) "waiting for tx rings to drain (%d -> %d pkts)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) oldcount, priv->pending_tx_pkts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) retry = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) priv->tx_wait = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) wiphy_err(hw->wiphy, "tx rings stuck for %d ms\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) MWL8K_TX_WAIT_TIMEOUT_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) mwl8k_dump_tx_rings(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) priv->hw_restart_in_progress = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) ieee80211_queue_work(hw, &priv->fw_reload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) rc = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) priv->tx_wait = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) spin_unlock_bh(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) #define MWL8K_TXD_SUCCESS(status) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) ((status) & (MWL8K_TXD_STATUS_OK | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) MWL8K_TXD_STATUS_OK_RETRY | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) MWL8K_TXD_STATUS_OK_MORE_RETRY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) static int mwl8k_tid_queue_mapping(u8 tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) BUG_ON(tid > 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) switch (tid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) return IEEE80211_AC_BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) return IEEE80211_AC_BK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return IEEE80211_AC_VI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) return IEEE80211_AC_VO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) /* The firmware will fill in the rate information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) * for each packet that gets queued in the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) * and these macros will interpret that info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) #define RI_FORMAT(a) (a & 0x0001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) #define RI_RATE_ID_MCS(a) ((a & 0x01f8) >> 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) struct mwl8k_tx_queue *txq = priv->txq + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) int processed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) processed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) while (txq->len > 0 && limit--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) int tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) struct mwl8k_tx_desc *tx_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) struct ieee80211_tx_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) struct ieee80211_sta *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) struct mwl8k_sta *sta_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) u16 rate_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) struct ieee80211_hdr *wh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) tx = txq->head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) tx_desc = txq->txd + tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) status = le32_to_cpu(tx_desc->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) if (status & MWL8K_TXD_STATUS_FW_OWNED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) if (!force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) tx_desc->status &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) ~cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) txq->head = (tx + 1) % MWL8K_TX_DESCS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) BUG_ON(txq->len == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) txq->len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) priv->pending_tx_pkts--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) addr = le32_to_cpu(tx_desc->pkt_phys_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) size = le16_to_cpu(tx_desc->pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) skb = txq->skb[tx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) txq->skb[tx] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) BUG_ON(skb == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) mwl8k_remove_dma_header(skb, tx_desc->qos_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) wh = (struct ieee80211_hdr *) skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) /* Mark descriptor as unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) tx_desc->pkt_phys_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) tx_desc->pkt_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) info = IEEE80211_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) if (ieee80211_is_data(wh->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) sta = ieee80211_find_sta_by_ifaddr(hw, wh->addr1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) wh->addr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) if (sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) sta_info = MWL8K_STA(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) BUG_ON(sta_info == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) rate_info = le16_to_cpu(tx_desc->rate_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) /* If rate is < 6.5 Mpbs for an ht station
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) * do not form an ampdu. If the station is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) * legacy station (format = 0), do not form an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) * ampdu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (RI_RATE_ID_MCS(rate_info) < 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) RI_FORMAT(rate_info) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) sta_info->is_ampdu_allowed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) sta_info->is_ampdu_allowed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) ieee80211_tx_info_clear_status(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) /* Rate control is happening in the firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) * Ensure no tx rate is being reported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) info->status.rates[0].idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) info->status.rates[0].count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) if (MWL8K_TXD_SUCCESS(status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) info->flags |= IEEE80211_TX_STAT_ACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) ieee80211_tx_status_irqsafe(hw, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) processed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) return processed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) /* must be called only when the card's transmit is completely halted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) struct mwl8k_tx_queue *txq = priv->txq + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) if (txq->txd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) mwl8k_txq_reclaim(hw, index, INT_MAX, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) kfree(txq->skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) txq->skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) pci_free_consistent(priv->pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) txq->txd, txq->txd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) txq->txd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) /* caller must hold priv->stream_lock when calling the stream functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) static struct mwl8k_ampdu_stream *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) struct mwl8k_ampdu_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) for (i = 0; i < MWL8K_NUM_AMPDU_STREAMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) stream = &priv->ampdu[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) if (stream->state == AMPDU_NO_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) stream->sta = sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) stream->state = AMPDU_STREAM_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) stream->tid = tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) stream->idx = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) wiphy_debug(hw->wiphy, "Added a new stream for %pM %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) sta->addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) return stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) mwl8k_start_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) /* if the stream has already been started, don't start it again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) if (stream->state != AMPDU_STREAM_NEW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) ret = ieee80211_start_tx_ba_session(stream->sta, stream->tid, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) wiphy_debug(hw->wiphy, "Failed to start stream for %pM %d: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) "%d\n", stream->sta->addr, stream->tid, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) wiphy_debug(hw->wiphy, "Started stream for %pM %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) stream->sta->addr, stream->tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) mwl8k_remove_stream(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) wiphy_debug(hw->wiphy, "Remove stream for %pM %d\n", stream->sta->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) stream->tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) memset(stream, 0, sizeof(*stream));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) static struct mwl8k_ampdu_stream *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) for (i = 0; i < MWL8K_NUM_AMPDU_STREAMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) struct mwl8k_ampdu_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) stream = &priv->ampdu[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) if (stream->state == AMPDU_NO_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) if (!memcmp(stream->sta->addr, addr, ETH_ALEN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) stream->tid == tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) return stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) #define MWL8K_AMPDU_PACKET_THRESHOLD 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) static inline bool mwl8k_ampdu_allowed(struct ieee80211_sta *sta, u8 tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) struct mwl8k_sta *sta_info = MWL8K_STA(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) struct tx_traffic_info *tx_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) BUG_ON(tid >= MWL8K_MAX_TID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) tx_stats = &sta_info->tx_stats[tid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) return sta_info->is_ampdu_allowed &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) tx_stats->pkts > MWL8K_AMPDU_PACKET_THRESHOLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) static inline void mwl8k_tx_count_packet(struct ieee80211_sta *sta, u8 tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) struct mwl8k_sta *sta_info = MWL8K_STA(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) struct tx_traffic_info *tx_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) BUG_ON(tid >= MWL8K_MAX_TID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) tx_stats = &sta_info->tx_stats[tid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) if (tx_stats->start_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) tx_stats->start_time = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) /* reset the packet count after each second elapses. If the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) * packets ever exceeds the ampdu_min_traffic threshold, we will allow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) * an ampdu stream to be started.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) if (jiffies - tx_stats->start_time > HZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) tx_stats->pkts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) tx_stats->start_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) tx_stats->pkts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) /* The hardware ampdu queues start from 5.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) * txpriorities for ampdu queues are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) * 5 6 7 0 1 2 3 4 ie., queue 5 is highest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) * and queue 3 is lowest (queue 4 is reserved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) #define BA_QUEUE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) mwl8k_txq_xmit(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) struct ieee80211_sta *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) struct ieee80211_tx_info *tx_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) struct mwl8k_vif *mwl8k_vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) struct ieee80211_hdr *wh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) struct mwl8k_tx_queue *txq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) struct mwl8k_tx_desc *tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) dma_addr_t dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) u32 txstatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) u8 txdatarate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) u16 qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) int txpriority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) u8 tid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) struct mwl8k_ampdu_stream *stream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) bool start_ba_session = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) bool mgmtframe = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) bool eapol_frame = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) wh = (struct ieee80211_hdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) if (ieee80211_is_data_qos(wh->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) qos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) if (skb->protocol == cpu_to_be16(ETH_P_PAE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) eapol_frame = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) if (ieee80211_is_mgmt(wh->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) mgmtframe = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) if (priv->ap_fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) mwl8k_encapsulate_tx_frame(priv, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) mwl8k_add_dma_header(priv, skb, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) wh = &((struct mwl8k_dma_data *)skb->data)->wh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) tx_info = IEEE80211_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) wh->seq_ctrl |= cpu_to_le16(mwl8k_vif->seqno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) mwl8k_vif->seqno += 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) /* Setup firmware control bit fields for each frame type. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) txstatus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) txdatarate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) if (ieee80211_is_mgmt(wh->frame_control) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) ieee80211_is_ctl(wh->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) txdatarate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) qos |= MWL8K_QOS_QLEN_UNSPEC | MWL8K_QOS_EOSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) } else if (ieee80211_is_data(wh->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) txdatarate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) if (is_multicast_ether_addr(wh->addr1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) qos &= ~MWL8K_QOS_ACK_POLICY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) qos |= MWL8K_QOS_ACK_POLICY_BLOCKACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) qos |= MWL8K_QOS_ACK_POLICY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) /* Queue ADDBA request in the respective data queue. While setting up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) * the ampdu stream, mac80211 queues further packets for that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) * particular ra/tid pair. However, packets piled up in the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) * for that ra/tid pair will still go out. ADDBA request and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) * related data packets going out from different queues asynchronously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) * will cause a shift in the receiver window which might result in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) * ampdu packets getting dropped at the receiver after the stream has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) * been setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) if (unlikely(ieee80211_is_action(wh->frame_control) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) mgmt->u.action.category == WLAN_CATEGORY_BACK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) priv->ap_fw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) u16 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) index = mwl8k_tid_queue_mapping(tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) txpriority = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) if (priv->ap_fw && sta && sta->ht_cap.ht_supported && !eapol_frame &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) ieee80211_is_data_qos(wh->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) tid = qos & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) mwl8k_tx_count_packet(sta, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) stream = mwl8k_lookup_stream(hw, sta->addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) if (stream != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) if (stream->state == AMPDU_STREAM_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) WARN_ON(!(qos & MWL8K_QOS_ACK_POLICY_BLOCKACK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) txpriority = (BA_QUEUE + stream->idx) %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) TOTAL_HW_TX_QUEUES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) if (stream->idx <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) index = stream->idx +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) MWL8K_TX_WMM_QUEUES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) } else if (stream->state == AMPDU_STREAM_NEW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) /* We get here if the driver sends us packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) * after we've initiated a stream, but before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) * our ampdu_action routine has been called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) * with IEEE80211_AMPDU_TX_START to get the SSN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) * for the ADDBA request. So this packet can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) * go out with no risk of sequence number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) * mismatch. No special handling is required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) /* Drop packets that would go out after the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) * ADDBA request was sent but before the ADDBA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) * response is received. If we don't do this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) * the recipient would probably receive it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) * after the ADDBA request with SSN 0. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) * will cause the recipient's BA receive window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) * to shift, which would cause the subsequent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) * packets in the BA stream to be discarded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) * mac80211 queues our packets for us in this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) * case, so this is really just a safety check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) wiphy_warn(hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) "Cannot send packet while ADDBA "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) "dialog is underway.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) /* Defer calling mwl8k_start_stream so that the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) * skb can go out before the ADDBA request. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) * prevents sequence number mismatch at the recepient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) * as described above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) if (mwl8k_ampdu_allowed(sta, tid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) stream = mwl8k_add_stream(hw, sta, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) if (stream != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) start_ba_session = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) qos &= ~MWL8K_QOS_ACK_POLICY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) qos |= MWL8K_QOS_ACK_POLICY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) dma = pci_map_single(priv->pdev, skb->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) skb->len, PCI_DMA_TODEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) if (pci_dma_mapping_error(priv->pdev, dma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) wiphy_debug(hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) "failed to dma map skb, dropping TX frame.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) if (start_ba_session) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) mwl8k_remove_stream(hw, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) spin_lock_bh(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) txq = priv->txq + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) /* Mgmt frames that go out frequently are probe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) * responses. Other mgmt frames got out relatively
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) * infrequently. Hence reserve 2 buffers so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) * other mgmt frames do not get dropped due to an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) * already queued probe response in one of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) * reserved buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) if (txq->len >= MWL8K_TX_DESCS - 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) if (!mgmtframe || txq->len == MWL8K_TX_DESCS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) if (start_ba_session) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) mwl8k_remove_stream(hw, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) mwl8k_tx_start(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) spin_unlock_bh(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) pci_unmap_single(priv->pdev, dma, skb->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) PCI_DMA_TODEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) BUG_ON(txq->skb[txq->tail] != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) txq->skb[txq->tail] = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) tx = txq->txd + txq->tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) tx->data_rate = txdatarate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) tx->tx_priority = txpriority;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) tx->qos_control = cpu_to_le16(qos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) tx->pkt_phys_addr = cpu_to_le32(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) tx->pkt_len = cpu_to_le16(skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) tx->rate_info = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) if (!priv->ap_fw && sta != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) tx->peer_id = MWL8K_STA(sta)->peer_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) tx->peer_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) if (priv->ap_fw && ieee80211_is_data(wh->frame_control) && !eapol_frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) tx->timestamp = cpu_to_le32(ioread32(priv->regs +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) MWL8K_HW_TIMER_REGISTER));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) tx->timestamp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) txq->len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) priv->pending_tx_pkts++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) txq->tail++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) if (txq->tail == MWL8K_TX_DESCS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) txq->tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) mwl8k_tx_start(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) spin_unlock_bh(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) /* Initiate the ampdu session here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) if (start_ba_session) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) if (mwl8k_start_stream(hw, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) mwl8k_remove_stream(hw, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) * Firmware access.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) * We have the following requirements for issuing firmware commands:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) * - Some commands require that the packet transmit path is idle when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) * the command is issued. (For simplicity, we'll just quiesce the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) * transmit path for every command.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) * - There are certain sequences of commands that need to be issued to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) * the hardware sequentially, with no other intervening commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) * This leads to an implementation of a "firmware lock" as a mutex that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) * can be taken recursively, and which is taken by both the low-level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) * command submission function (mwl8k_post_cmd) as well as any users of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) * that function that require issuing of an atomic sequence of commands,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) * and quiesces the transmit path whenever it's taken.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) static int mwl8k_fw_lock(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) if (priv->fw_mutex_owner != current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) mutex_lock(&priv->fw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) ieee80211_stop_queues(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) rc = mwl8k_tx_wait_empty(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) if (!priv->hw_restart_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) ieee80211_wake_queues(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) mutex_unlock(&priv->fw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) priv->fw_mutex_owner = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) priv->fw_mutex_depth++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) static void mwl8k_fw_unlock(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) if (!--priv->fw_mutex_depth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) if (!priv->hw_restart_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) ieee80211_wake_queues(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) priv->fw_mutex_owner = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) mutex_unlock(&priv->fw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) static void mwl8k_enable_bsses(struct ieee80211_hw *hw, bool enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) u32 bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) * Command processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) /* Timeout firmware commands after 10s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) #define MWL8K_CMD_TIMEOUT_MS 10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) DECLARE_COMPLETION_ONSTACK(cmd_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) void __iomem *regs = priv->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) dma_addr_t dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) unsigned int dma_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) unsigned long timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) u8 buf[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) u32 bitmap = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) wiphy_dbg(hw->wiphy, "Posting %s [%d]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), cmd->macid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) /* Before posting firmware commands that could change the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) * characteristics, make sure that all BSSes are stopped temporary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) * Enable these stopped BSSes after completion of the commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) rc = mwl8k_fw_lock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) if (priv->ap_fw && priv->running_bsses) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) switch (le16_to_cpu(cmd->code)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) case MWL8K_CMD_SET_RF_CHANNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) case MWL8K_CMD_RADIO_CONTROL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) case MWL8K_CMD_RF_TX_POWER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) case MWL8K_CMD_TX_POWER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) case MWL8K_CMD_RF_ANTENNA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) case MWL8K_CMD_RTS_THRESHOLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) case MWL8K_CMD_MIMO_CONFIG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) bitmap = priv->running_bsses;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) mwl8k_enable_bsses(hw, false, bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) cmd->result = (__force __le16) 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) dma_size = le16_to_cpu(cmd->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) dma_addr = pci_map_single(priv->pdev, cmd, dma_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) PCI_DMA_BIDIRECTIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) if (pci_dma_mapping_error(priv->pdev, dma_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) priv->hostcmd_wait = &cmd_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) iowrite32(MWL8K_H2A_INT_DOORBELL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) iowrite32(MWL8K_H2A_INT_DUMMY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) timeout = wait_for_completion_timeout(&cmd_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) priv->hostcmd_wait = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) pci_unmap_single(priv->pdev, dma_addr, dma_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) PCI_DMA_BIDIRECTIONAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) wiphy_err(hw->wiphy, "Command %s timeout after %u ms\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) MWL8K_CMD_TIMEOUT_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) rc = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) int ms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) ms = MWL8K_CMD_TIMEOUT_MS - jiffies_to_msecs(timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) rc = cmd->result ? -EINVAL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) wiphy_err(hw->wiphy, "Command %s error 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) le16_to_cpu(cmd->result));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) else if (ms > 2000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) wiphy_notice(hw->wiphy, "Command %s took %d ms\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) mwl8k_cmd_name(cmd->code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) buf, sizeof(buf)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) if (bitmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) mwl8k_enable_bsses(hw, true, bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) static int mwl8k_post_pervif_cmd(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) struct mwl8k_cmd_pkt *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) if (vif != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) cmd->macid = MWL8K_VIF(vif)->macid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) return mwl8k_post_cmd(hw, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) * Setup code shared between STA and AP firmware images.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) static void mwl8k_setup_2ghz_band(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) BUILD_BUG_ON(sizeof(priv->channels_24) != sizeof(mwl8k_channels_24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) memcpy(priv->channels_24, mwl8k_channels_24, sizeof(mwl8k_channels_24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl8k_rates_24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) memcpy(priv->rates_24, mwl8k_rates_24, sizeof(mwl8k_rates_24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) priv->band_24.band = NL80211_BAND_2GHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) priv->band_24.channels = priv->channels_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) priv->band_24.n_channels = ARRAY_SIZE(mwl8k_channels_24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) priv->band_24.bitrates = priv->rates_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) priv->band_24.n_bitrates = ARRAY_SIZE(mwl8k_rates_24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) hw->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) static void mwl8k_setup_5ghz_band(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) BUILD_BUG_ON(sizeof(priv->channels_50) != sizeof(mwl8k_channels_50));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) memcpy(priv->channels_50, mwl8k_channels_50, sizeof(mwl8k_channels_50));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl8k_rates_50));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) memcpy(priv->rates_50, mwl8k_rates_50, sizeof(mwl8k_rates_50));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) priv->band_50.band = NL80211_BAND_5GHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) priv->band_50.channels = priv->channels_50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) priv->band_50.n_channels = ARRAY_SIZE(mwl8k_channels_50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) priv->band_50.bitrates = priv->rates_50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) priv->band_50.n_bitrates = ARRAY_SIZE(mwl8k_rates_50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) hw->wiphy->bands[NL80211_BAND_5GHZ] = &priv->band_50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) * CMD_GET_HW_SPEC (STA version).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) struct mwl8k_cmd_get_hw_spec_sta {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) __u8 hw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) __u8 host_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) __le16 num_mcaddrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) __u8 perm_addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) __le16 region_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) __le32 fw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) __le32 ps_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) __le32 caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) __u8 mcs_bitmap[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) __le32 rx_queue_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) __le32 num_tx_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) __le32 tx_queue_ptrs[MWL8K_TX_WMM_QUEUES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) __le32 caps2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) __le32 num_tx_desc_per_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) __le32 total_rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) #define MWL8K_CAP_MAX_AMSDU 0x20000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) #define MWL8K_CAP_GREENFIELD 0x08000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) #define MWL8K_CAP_AMPDU 0x04000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) #define MWL8K_CAP_RX_STBC 0x01000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) #define MWL8K_CAP_TX_STBC 0x00800000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) #define MWL8K_CAP_SHORTGI_40MHZ 0x00400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) #define MWL8K_CAP_SHORTGI_20MHZ 0x00200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) #define MWL8K_CAP_RX_ANTENNA_MASK 0x000e0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) #define MWL8K_CAP_TX_ANTENNA_MASK 0x0001c000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) #define MWL8K_CAP_DELAY_BA 0x00003000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) #define MWL8K_CAP_MIMO 0x00000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) #define MWL8K_CAP_40MHZ 0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) #define MWL8K_CAP_BAND_MASK 0x00000007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) #define MWL8K_CAP_5GHZ 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) #define MWL8K_CAP_2GHZ4 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) mwl8k_set_ht_caps(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) struct ieee80211_supported_band *band, u32 cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) int rx_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) int tx_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) band->ht_cap.ht_supported = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) if (cap & MWL8K_CAP_MAX_AMSDU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) band->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) if (cap & MWL8K_CAP_GREENFIELD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) band->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) if (cap & MWL8K_CAP_AMPDU) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) ieee80211_hw_set(hw, AMPDU_AGGREGATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) if (cap & MWL8K_CAP_RX_STBC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) band->ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) if (cap & MWL8K_CAP_TX_STBC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) band->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) if (cap & MWL8K_CAP_SHORTGI_40MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) if (cap & MWL8K_CAP_SHORTGI_20MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) if (cap & MWL8K_CAP_DELAY_BA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) band->ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) if (cap & MWL8K_CAP_40MHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) rx_streams = hweight32(cap & MWL8K_CAP_RX_ANTENNA_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) tx_streams = hweight32(cap & MWL8K_CAP_TX_ANTENNA_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) band->ht_cap.mcs.rx_mask[0] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) if (rx_streams >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) band->ht_cap.mcs.rx_mask[1] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) if (rx_streams >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) band->ht_cap.mcs.rx_mask[2] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) band->ht_cap.mcs.rx_mask[4] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) if (rx_streams != tx_streams) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) band->ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) band->ht_cap.mcs.tx_params |= (tx_streams - 1) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) if (priv->caps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) mwl8k_setup_2ghz_band(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) if (caps & MWL8K_CAP_MIMO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) mwl8k_set_ht_caps(hw, &priv->band_24, caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) if (caps & MWL8K_CAP_5GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) mwl8k_setup_5ghz_band(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) if (caps & MWL8K_CAP_MIMO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) mwl8k_set_ht_caps(hw, &priv->band_50, caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) priv->caps = caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) struct mwl8k_cmd_get_hw_spec_sta *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) for (i = 0; i < mwl8k_tx_queues(priv); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) priv->fw_rev = le32_to_cpu(cmd->fw_rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) priv->hw_rev = cmd->hw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) mwl8k_set_caps(hw, le32_to_cpu(cmd->caps));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) priv->ap_macids_supported = 0x00000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) priv->sta_macids_supported = 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) * CMD_GET_HW_SPEC (AP version).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) struct mwl8k_cmd_get_hw_spec_ap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) __u8 hw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) __u8 host_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) __le16 num_wcb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) __le16 num_mcaddrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) __u8 perm_addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) __le16 region_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) __le16 num_antenna;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) __le32 fw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) __le32 wcbbase0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) __le32 rxwrptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) __le32 rxrdptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) __le32 ps_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) __le32 wcbbase1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) __le32 wcbbase2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) __le32 wcbbase3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) __le32 fw_api_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) __le32 caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) __le32 num_of_ampdu_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) __le32 wcbbase_ampdu[MWL8K_MAX_AMPDU_QUEUES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) struct mwl8k_cmd_get_hw_spec_ap *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) u32 api_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) int off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) api_version = le32_to_cpu(cmd->fw_api_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) if (priv->device_info->fw_api_ap != api_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) printk(KERN_ERR "%s: Unsupported fw API version for %s."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) " Expected %d got %d.\n", MWL8K_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) priv->device_info->part_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) priv->device_info->fw_api_ap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) api_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) priv->fw_rev = le32_to_cpu(cmd->fw_rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) priv->hw_rev = cmd->hw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) mwl8k_set_caps(hw, le32_to_cpu(cmd->caps));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) priv->ap_macids_supported = 0x000000ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) priv->sta_macids_supported = 0x00000100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) priv->num_ampdu_queues = le32_to_cpu(cmd->num_of_ampdu_queues);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) if (priv->num_ampdu_queues > MWL8K_MAX_AMPDU_QUEUES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) wiphy_warn(hw->wiphy, "fw reported %d ampdu queues"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) " but we only support %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) priv->num_ampdu_queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) MWL8K_MAX_AMPDU_QUEUES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) priv->num_ampdu_queues = MWL8K_MAX_AMPDU_QUEUES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) off = le32_to_cpu(cmd->rxwrptr) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) iowrite32(priv->rxq[0].rxd_dma, priv->sram + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) off = le32_to_cpu(cmd->rxrdptr) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) iowrite32(priv->rxq[0].rxd_dma, priv->sram + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) priv->txq_offset[0] = le32_to_cpu(cmd->wcbbase0) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) for (i = 0; i < priv->num_ampdu_queues; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) priv->txq_offset[i + MWL8K_TX_WMM_QUEUES] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) le32_to_cpu(cmd->wcbbase_ampdu[i]) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) * CMD_SET_HW_SPEC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) struct mwl8k_cmd_set_hw_spec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) __u8 hw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) __u8 host_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) __le16 num_mcaddrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) __u8 perm_addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) __le16 region_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) __le32 fw_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) __le32 ps_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) __le32 caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) __le32 rx_queue_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) __le32 num_tx_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) __le32 tx_queue_ptrs[MWL8K_MAX_TX_QUEUES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) __le32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) __le32 num_tx_desc_per_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) __le32 total_rxd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) /* If enabled, MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY will cause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) * packets to expire 500 ms after the timestamp in the tx descriptor. That is,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) * the packets that are queued for more than 500ms, will be dropped in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) * hardware. This helps minimizing the issues caused due to head-of-line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) * blocking where a slow client can hog the bandwidth and affect traffic to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) * faster client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) #define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) #define MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR 0x00000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) struct mwl8k_cmd_set_hw_spec *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_HW_SPEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) * Mac80211 stack has Q0 as highest priority and Q3 as lowest in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) * that order. Firmware has Q3 as highest priority and Q0 as lowest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) * in that order. Map Q3 of mac80211 to Q0 of firmware so that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) * priority is interpreted the right way in firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) for (i = 0; i < mwl8k_tx_queues(priv); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) int j = mwl8k_tx_queues(priv) - 1 - i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[j].txd_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) * CMD_MAC_MULTICAST_ADR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) struct mwl8k_cmd_mac_multicast_adr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) __le16 numaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) __u8 addr[][ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) #define MWL8K_ENABLE_RX_DIRECTED 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) #define MWL8K_ENABLE_RX_MULTICAST 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) #define MWL8K_ENABLE_RX_ALL_MULTICAST 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) #define MWL8K_ENABLE_RX_BROADCAST 0x0008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) static struct mwl8k_cmd_pkt *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) struct netdev_hw_addr_list *mc_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) struct mwl8k_cmd_mac_multicast_adr *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) int mc_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) if (mc_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) mc_count = netdev_hw_addr_list_count(mc_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) if (allmulti || mc_count > priv->num_mcaddrs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) allmulti = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) mc_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) size = sizeof(*cmd) + mc_count * ETH_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) cmd = kzalloc(size, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) cmd->header.length = cpu_to_le16(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_DIRECTED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) MWL8K_ENABLE_RX_BROADCAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) if (allmulti) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_ALL_MULTICAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) } else if (mc_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) struct netdev_hw_addr *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) cmd->numaddr = cpu_to_le16(mc_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) netdev_hw_addr_list_for_each(ha, mc_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) memcpy(cmd->addr[i], ha->addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) return &cmd->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) * CMD_GET_STAT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) struct mwl8k_cmd_get_stat {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) __le32 stats[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) #define MWL8K_STAT_ACK_FAILURE 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) #define MWL8K_STAT_RTS_FAILURE 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) #define MWL8K_STAT_FCS_ERROR 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) #define MWL8K_STAT_RTS_SUCCESS 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) struct ieee80211_low_level_stats *stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) struct mwl8k_cmd_get_stat *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) stats->dot11ACKFailureCount =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) le32_to_cpu(cmd->stats[MWL8K_STAT_ACK_FAILURE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) stats->dot11RTSFailureCount =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_FAILURE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) stats->dot11FCSErrorCount =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) le32_to_cpu(cmd->stats[MWL8K_STAT_FCS_ERROR]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) stats->dot11RTSSuccessCount =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_SUCCESS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) * CMD_RADIO_CONTROL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) struct mwl8k_cmd_radio_control {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) __le16 control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) __le16 radio_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) struct mwl8k_cmd_radio_control *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) if (enable == priv->radio_on && !force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) cmd->action = cpu_to_le16(MWL8K_CMD_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) cmd->control = cpu_to_le16(priv->radio_short_preamble ? 3 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) priv->radio_on = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) static int mwl8k_cmd_radio_disable(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) return mwl8k_cmd_radio_control(hw, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) static int mwl8k_cmd_radio_enable(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) return mwl8k_cmd_radio_control(hw, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) priv->radio_short_preamble = short_preamble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) return mwl8k_cmd_radio_control(hw, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) * CMD_RF_TX_POWER.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) #define MWL8K_RF_TX_POWER_LEVEL_TOTAL 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) struct mwl8k_cmd_rf_tx_power {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) __le16 support_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) __le16 current_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) __le16 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) __le16 power_level_list[MWL8K_RF_TX_POWER_LEVEL_TOTAL];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) struct mwl8k_cmd_rf_tx_power *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_TX_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) cmd->action = cpu_to_le16(MWL8K_CMD_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) cmd->support_level = cpu_to_le16(dBm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) * CMD_TX_POWER.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) #define MWL8K_TX_POWER_LEVEL_TOTAL 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) struct mwl8k_cmd_tx_power {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) __le16 band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) __le16 channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) __le16 bw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) __le16 sub_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) struct ieee80211_conf *conf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) unsigned short pwr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) struct ieee80211_channel *channel = conf->chandef.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) enum nl80211_channel_type channel_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) cfg80211_get_chandef_type(&conf->chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) struct mwl8k_cmd_tx_power *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) cmd->header.code = cpu_to_le16(MWL8K_CMD_TX_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) cmd->action = cpu_to_le16(MWL8K_CMD_SET_LIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) if (channel->band == NL80211_BAND_2GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) cmd->band = cpu_to_le16(0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) else if (channel->band == NL80211_BAND_5GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) cmd->band = cpu_to_le16(0x4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) cmd->channel = cpu_to_le16(channel->hw_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) if (channel_type == NL80211_CHAN_NO_HT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) channel_type == NL80211_CHAN_HT20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) cmd->bw = cpu_to_le16(0x2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) cmd->bw = cpu_to_le16(0x4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) if (channel_type == NL80211_CHAN_HT40MINUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) cmd->sub_ch = cpu_to_le16(0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) else if (channel_type == NL80211_CHAN_HT40PLUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) cmd->sub_ch = cpu_to_le16(0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) for (i = 0; i < MWL8K_TX_POWER_LEVEL_TOTAL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) cmd->power_level_list[i] = cpu_to_le16(pwr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) * CMD_RF_ANTENNA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) struct mwl8k_cmd_rf_antenna {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) __le16 antenna;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) __le16 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) #define MWL8K_RF_ANTENNA_RX 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) #define MWL8K_RF_ANTENNA_TX 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) struct mwl8k_cmd_rf_antenna *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_ANTENNA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) cmd->antenna = cpu_to_le16(antenna);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) cmd->mode = cpu_to_le16(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) * CMD_SET_BEACON.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) struct mwl8k_cmd_set_beacon {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) __le16 beacon_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) __u8 beacon[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) struct ieee80211_vif *vif, u8 *beacon, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) struct mwl8k_cmd_set_beacon *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) cmd->header.length = cpu_to_le16(sizeof(*cmd) + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) cmd->beacon_len = cpu_to_le16(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) memcpy(cmd->beacon, beacon, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) * CMD_SET_PRE_SCAN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) struct mwl8k_cmd_set_pre_scan {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) struct mwl8k_cmd_set_pre_scan *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_PRE_SCAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) * CMD_BBP_REG_ACCESS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) struct mwl8k_cmd_bbp_reg_access {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) __le16 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) u8 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) u8 rsrv[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) mwl8k_cmd_bbp_reg_access(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) u16 action,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) u8 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) struct mwl8k_cmd_bbp_reg_access *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) cmd->header.code = cpu_to_le16(MWL8K_CMD_BBP_REG_ACCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) cmd->action = cpu_to_le16(action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) cmd->offset = cpu_to_le16(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) *value = cmd->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) *value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) * CMD_SET_POST_SCAN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) struct mwl8k_cmd_set_post_scan {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) __le32 isibss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) __u8 bssid[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, const __u8 *mac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) struct mwl8k_cmd_set_post_scan *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) cmd->isibss = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) memcpy(cmd->bssid, mac, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) static int freq_to_idx(struct mwl8k_priv *priv, int freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) int band, ch, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) sband = priv->hw->wiphy->bands[band];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) for (ch = 0; ch < sband->n_channels; ch++, idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) if (sband->channels[ch].center_freq == freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) return idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) static void mwl8k_update_survey(struct mwl8k_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) struct ieee80211_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) u32 cca_cnt, rx_rdy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) s8 nf = 0, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) struct survey_info *survey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) idx = freq_to_idx(priv, priv->acs_chan->center_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) if (idx >= MWL8K_NUM_CHANS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) wiphy_err(priv->hw->wiphy, "Failed to update survey\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) survey = &priv->survey[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) cca_cnt = ioread32(priv->regs + NOK_CCA_CNT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) cca_cnt /= 1000; /* uSecs to mSecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) survey->time_busy = (u64) cca_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) rx_rdy = ioread32(priv->regs + BBU_RXRDY_CNT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) rx_rdy /= 1000; /* uSecs to mSecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) survey->time_rx = (u64) rx_rdy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) priv->channel_time = jiffies - priv->channel_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) survey->time = jiffies_to_msecs(priv->channel_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) survey->channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) mwl8k_cmd_bbp_reg_access(priv->hw, 0, BBU_AVG_NOISE_VAL, &nf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) /* Make sure sign is negative else ACS at hostapd fails */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) survey->noise = nf * -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) survey->filled = SURVEY_INFO_NOISE_DBM |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) SURVEY_INFO_TIME |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) SURVEY_INFO_TIME_BUSY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) SURVEY_INFO_TIME_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) * CMD_SET_RF_CHANNEL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) struct mwl8k_cmd_set_rf_channel {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) __u8 current_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) __le32 channel_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) struct ieee80211_conf *conf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) struct ieee80211_channel *channel = conf->chandef.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) enum nl80211_channel_type channel_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) cfg80211_get_chandef_type(&conf->chandef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) struct mwl8k_cmd_set_rf_channel *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RF_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) cmd->action = cpu_to_le16(MWL8K_CMD_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) cmd->current_channel = channel->hw_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) if (channel->band == NL80211_BAND_2GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) cmd->channel_flags |= cpu_to_le32(0x00000001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) else if (channel->band == NL80211_BAND_5GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) cmd->channel_flags |= cpu_to_le32(0x00000004);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) if (!priv->sw_scan_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) if (channel_type == NL80211_CHAN_NO_HT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) channel_type == NL80211_CHAN_HT20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) cmd->channel_flags |= cpu_to_le32(0x00000080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) else if (channel_type == NL80211_CHAN_HT40MINUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) cmd->channel_flags |= cpu_to_le32(0x000001900);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) else if (channel_type == NL80211_CHAN_HT40PLUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) cmd->channel_flags |= cpu_to_le32(0x000000900);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) cmd->channel_flags |= cpu_to_le32(0x00000080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) if (priv->sw_scan_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) /* Store current channel stats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) * before switching to newer one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) * This will be processed only for AP fw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) if (priv->channel_time != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) mwl8k_update_survey(priv, priv->acs_chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) priv->channel_time = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) priv->acs_chan = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) * CMD_SET_AID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) #define MWL8K_FRAME_PROT_DISABLED 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) #define MWL8K_FRAME_PROT_11G 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) struct mwl8k_cmd_update_set_aid {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) __le16 aid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) /* AP's MAC address (BSSID) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) __u8 bssid[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) __le16 protection_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) __u8 supp_rates[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) static void legacy_rate_mask_to_array(u8 *rates, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) * Clear nonstandard rate 4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) mask &= 0x1fef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) for (i = 0, j = 0; i < 13; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) if (mask & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) rates[j++] = mwl8k_rates_24[i].hw_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) struct ieee80211_vif *vif, u32 legacy_rate_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) struct mwl8k_cmd_update_set_aid *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) u16 prot_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) cmd->aid = cpu_to_le16(vif->bss_conf.aid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) if (vif->bss_conf.use_cts_prot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) prot_mode = MWL8K_FRAME_PROT_11G;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) switch (vif->bss_conf.ht_operation_mode &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) IEEE80211_HT_OP_MODE_PROTECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) prot_mode = MWL8K_FRAME_PROT_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) cmd->protection_mode = cpu_to_le16(prot_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) legacy_rate_mask_to_array(cmd->supp_rates, legacy_rate_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) * CMD_SET_RATE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) struct mwl8k_cmd_set_rate {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) __u8 legacy_rates[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) /* Bitmap for supported MCS codes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) __u8 mcs_set[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) __u8 reserved[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) u32 legacy_rate_mask, u8 *mcs_rates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) struct mwl8k_cmd_set_rate *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) memcpy(cmd->mcs_set, mcs_rates, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) * CMD_FINALIZE_JOIN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) #define MWL8K_FJ_BEACON_MAXLEN 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) struct mwl8k_cmd_finalize_join {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) __le32 sleep_interval; /* Number of beacon periods to sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) int framelen, int dtim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) struct mwl8k_cmd_finalize_join *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) struct ieee80211_mgmt *payload = frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) int payload_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) payload_len = framelen - ieee80211_hdrlen(payload->frame_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) if (payload_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) payload_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) else if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) payload_len = MWL8K_FJ_BEACON_MAXLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) * CMD_SET_RTS_THRESHOLD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) struct mwl8k_cmd_set_rts_threshold {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) __le16 threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, int rts_thresh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) struct mwl8k_cmd_set_rts_threshold *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) cmd->action = cpu_to_le16(MWL8K_CMD_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) cmd->threshold = cpu_to_le16(rts_thresh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) * CMD_SET_SLOT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) struct mwl8k_cmd_set_slot {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) __u8 short_slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) struct mwl8k_cmd_set_slot *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) cmd->action = cpu_to_le16(MWL8K_CMD_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) cmd->short_slot = short_slot_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) * CMD_SET_EDCA_PARAMS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) struct mwl8k_cmd_set_edca_params {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) /* See MWL8K_SET_EDCA_XXX below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) /* TX opportunity in units of 32 us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) __le16 txop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) /* Log exponent of max contention period: 0...15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) __le32 log_cw_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) /* Log exponent of min contention period: 0...15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) __le32 log_cw_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) /* Adaptive interframe spacing in units of 32us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) __u8 aifs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) /* TX queue to configure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) __u8 txq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) } ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) /* Log exponent of max contention period: 0...15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) __u8 log_cw_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) /* Log exponent of min contention period: 0...15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) __u8 log_cw_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) /* Adaptive interframe spacing in units of 32us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) __u8 aifs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) /* TX queue to configure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) __u8 txq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) } sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) #define MWL8K_SET_EDCA_CW 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) #define MWL8K_SET_EDCA_TXOP 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) #define MWL8K_SET_EDCA_AIFS 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) #define MWL8K_SET_EDCA_ALL (MWL8K_SET_EDCA_CW | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) MWL8K_SET_EDCA_TXOP | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) MWL8K_SET_EDCA_AIFS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) __u16 cw_min, __u16 cw_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) __u8 aifs, __u16 txop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) struct mwl8k_cmd_set_edca_params *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) cmd->txop = cpu_to_le16(txop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) if (priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) cmd->ap.log_cw_max = cpu_to_le32(ilog2(cw_max + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) cmd->ap.log_cw_min = cpu_to_le32(ilog2(cw_min + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) cmd->ap.aifs = aifs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) cmd->ap.txq = qnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) cmd->sta.log_cw_max = (u8)ilog2(cw_max + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) cmd->sta.log_cw_min = (u8)ilog2(cw_min + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) cmd->sta.aifs = aifs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) cmd->sta.txq = qnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) * CMD_SET_WMM_MODE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) struct mwl8k_cmd_set_wmm_mode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) struct mwl8k_cmd_set_wmm_mode *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) cmd->action = cpu_to_le16(!!enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) priv->wmm_enabled = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) * CMD_MIMO_CONFIG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) struct mwl8k_cmd_mimo_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) __le32 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) __u8 rx_antenna_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) __u8 tx_antenna_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) struct mwl8k_cmd_mimo_config *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) cmd->rx_antenna_map = rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) cmd->tx_antenna_map = tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) * CMD_USE_FIXED_RATE (STA version).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) struct mwl8k_cmd_use_fixed_rate_sta {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) __le32 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) __le32 allow_rate_drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) __le32 num_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) __le32 is_ht_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) __le32 enable_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) __le32 rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) __le32 retry_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) } rate_entry[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) __le32 rate_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) __le32 reserved1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) __le32 reserved2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) #define MWL8K_USE_AUTO_RATE 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) #define MWL8K_UCAST_RATE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) static int mwl8k_cmd_use_fixed_rate_sta(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) struct mwl8k_cmd_use_fixed_rate_sta *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) cmd->rate_type = cpu_to_le32(MWL8K_UCAST_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) * CMD_USE_FIXED_RATE (AP version).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) struct mwl8k_cmd_use_fixed_rate_ap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) __le32 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) __le32 allow_rate_drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) __le32 num_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) struct mwl8k_rate_entry_ap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) __le32 is_ht_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) __le32 enable_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) __le32 rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) __le32 retry_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) } rate_entry[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) u8 multicast_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) u8 multicast_rate_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) u8 management_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) mwl8k_cmd_use_fixed_rate_ap(struct ieee80211_hw *hw, int mcast, int mgmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) struct mwl8k_cmd_use_fixed_rate_ap *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) cmd->multicast_rate = mcast;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) cmd->management_rate = mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) * CMD_ENABLE_SNIFFER.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) struct mwl8k_cmd_enable_sniffer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) __le32 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) struct mwl8k_cmd_enable_sniffer *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) cmd->action = cpu_to_le32(!!enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) struct mwl8k_cmd_update_mac_addr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) __le16 mac_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) __u8 mac_addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) } mbss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) __u8 mac_addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) #define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) #define MWL8K_MAC_TYPE_SECONDARY_CLIENT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) #define MWL8K_MAC_TYPE_PRIMARY_AP 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) #define MWL8K_MAC_TYPE_SECONDARY_AP 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) static int mwl8k_cmd_update_mac_addr(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) struct ieee80211_vif *vif, u8 *mac, bool set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) struct mwl8k_cmd_update_mac_addr *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) int mac_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) mac_type = MWL8K_MAC_TYPE_PRIMARY_AP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) if (vif != NULL && vif->type == NL80211_IFTYPE_STATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) if (mwl8k_vif->macid + 1 == ffs(priv->sta_macids_supported))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) if (priv->ap_fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) mac_type = MWL8K_MAC_TYPE_SECONDARY_CLIENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) mac_type = MWL8K_MAC_TYPE_PRIMARY_CLIENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) mac_type = MWL8K_MAC_TYPE_SECONDARY_CLIENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) } else if (vif != NULL && vif->type == NL80211_IFTYPE_AP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) if (mwl8k_vif->macid + 1 == ffs(priv->ap_macids_supported))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) mac_type = MWL8K_MAC_TYPE_PRIMARY_AP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) mac_type = MWL8K_MAC_TYPE_SECONDARY_AP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) if (set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) cmd->header.code = cpu_to_le16(MWL8K_CMD_DEL_MAC_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) if (priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) cmd->mbss.mac_type = cpu_to_le16(mac_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) memcpy(cmd->mac_addr, mac, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) * MWL8K_CMD_SET_MAC_ADDR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) static inline int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) struct ieee80211_vif *vif, u8 *mac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) return mwl8k_cmd_update_mac_addr(hw, vif, mac, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) * MWL8K_CMD_DEL_MAC_ADDR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) static inline int mwl8k_cmd_del_mac_addr(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) struct ieee80211_vif *vif, u8 *mac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) return mwl8k_cmd_update_mac_addr(hw, vif, mac, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) * CMD_SET_RATEADAPT_MODE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) struct mwl8k_cmd_set_rate_adapt_mode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) __le16 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) struct mwl8k_cmd_set_rate_adapt_mode *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) cmd->action = cpu_to_le16(MWL8K_CMD_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) cmd->mode = cpu_to_le16(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) * CMD_GET_WATCHDOG_BITMAP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) struct mwl8k_cmd_get_watchdog_bitmap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) u8 bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) static int mwl8k_cmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) struct mwl8k_cmd_get_watchdog_bitmap *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_WATCHDOG_BITMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) *bitmap = cmd->bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) #define MWL8K_WMM_QUEUE_NUMBER 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) static void mwl8k_destroy_ba(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) u8 idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) static void mwl8k_watchdog_ba_events(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) u8 bitmap = 0, stream_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) struct mwl8k_ampdu_stream *streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) struct mwl8k_priv *priv =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) container_of(work, struct mwl8k_priv, watchdog_ba_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) struct ieee80211_hw *hw = priv->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) u32 status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) mwl8k_fw_lock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) rc = mwl8k_cmd_get_watchdog_bitmap(priv->hw, &bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) /* the bitmap is the hw queue number. Map it to the ampdu queue. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) for (i = 0; i < TOTAL_HW_TX_QUEUES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) if (bitmap & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) stream_index = (i + MWL8K_WMM_QUEUE_NUMBER) %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) TOTAL_HW_TX_QUEUES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) streams = &priv->ampdu[stream_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) if (streams->state == AMPDU_STREAM_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) ieee80211_stop_tx_ba_session(streams->sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) streams->tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) mwl8k_destroy_ba(hw, stream_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) atomic_dec(&priv->watchdog_event_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) iowrite32((status | MWL8K_A2H_INT_BA_WATCHDOG),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) * CMD_BSS_START.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) struct mwl8k_cmd_bss_start {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) __le32 enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) struct ieee80211_vif *vif, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) struct mwl8k_cmd_bss_start *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) if (enable && (priv->running_bsses & (1 << mwl8k_vif->macid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) if (!enable && !(priv->running_bsses & (1 << mwl8k_vif->macid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) cmd->header.code = cpu_to_le16(MWL8K_CMD_BSS_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) cmd->enable = cpu_to_le32(enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) priv->running_bsses |= (1 << mwl8k_vif->macid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) priv->running_bsses &= ~(1 << mwl8k_vif->macid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) static void mwl8k_enable_bsses(struct ieee80211_hw *hw, bool enable, u32 bitmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) struct mwl8k_vif *mwl8k_vif, *tmp_vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) struct ieee80211_vif *vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) list_for_each_entry_safe(mwl8k_vif, tmp_vif, &priv->vif_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909) vif = mwl8k_vif->vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) if (!(bitmap & (1 << mwl8k_vif->macid)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) if (vif->type == NL80211_IFTYPE_AP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) mwl8k_cmd_bss_start(hw, vif, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) * CMD_BASTREAM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) * UPSTREAM is tx direction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) #define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) #define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) enum ba_stream_action_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) MWL8K_BA_CREATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) MWL8K_BA_UPDATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) MWL8K_BA_DESTROY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) MWL8K_BA_FLUSH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) MWL8K_BA_CHECK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) struct mwl8k_create_ba_stream {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) __le32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) __le32 idle_thrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) __le32 bar_thrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) __le32 window_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) u8 peer_mac_addr[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) u8 dialog_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) u8 tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) u8 queue_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) u8 param_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) __le32 ba_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) u8 reset_seq_no_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) __le16 curr_seq_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) u8 sta_src_mac_addr[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) struct mwl8k_destroy_ba_stream {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) __le32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) __le32 ba_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) struct mwl8k_cmd_bastream {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) __le32 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) struct mwl8k_create_ba_stream create_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) struct mwl8k_destroy_ba_stream destroy_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) struct ieee80211_vif *vif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) struct mwl8k_cmd_bastream *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) cmd->action = cpu_to_le32(MWL8K_BA_CHECK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) cmd->create_params.queue_id = stream->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984) memcpy(&cmd->create_params.peer_mac_addr[0], stream->sta->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) cmd->create_params.tid = stream->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) cmd->create_params.flags =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) cpu_to_le32(BASTREAM_FLAG_DIRECTION_UPSTREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) u8 buf_size, struct ieee80211_vif *vif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) struct mwl8k_cmd_bastream *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) cmd->action = cpu_to_le32(MWL8K_BA_CREATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) cmd->create_params.bar_thrs = cpu_to_le32((u32)buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) cmd->create_params.window_size = cpu_to_le32((u32)buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) cmd->create_params.queue_id = stream->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) memcpy(cmd->create_params.peer_mac_addr, stream->sta->addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) cmd->create_params.tid = stream->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) cmd->create_params.curr_seq_no = cpu_to_le16(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) cmd->create_params.reset_seq_no_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) cmd->create_params.param_info =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) (stream->sta->ht_cap.ampdu_factor &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) IEEE80211_HT_AMPDU_PARM_FACTOR) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) ((stream->sta->ht_cap.ampdu_density << 2) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) IEEE80211_HT_AMPDU_PARM_DENSITY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) cmd->create_params.flags =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) BASTREAM_FLAG_DIRECTION_UPSTREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037) wiphy_debug(hw->wiphy, "Created a BA stream for %pM : tid %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) stream->sta->addr, stream->tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) static void mwl8k_destroy_ba(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) u8 idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) struct mwl8k_cmd_bastream *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) cmd->action = cpu_to_le32(MWL8K_BA_DESTROY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) cmd->destroy_params.ba_context = cpu_to_le32(idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) wiphy_debug(hw->wiphy, "Deleted BA stream index %d\n", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) * CMD_SET_NEW_STN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068) struct mwl8k_cmd_set_new_stn {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) __le16 aid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) __u8 mac_addr[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) __le16 stn_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) __le16 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) __le16 rsvd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) __le32 legacy_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) __u8 ht_rates[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077) __le16 cap_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) __le16 ht_capabilities_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) __u8 mac_ht_param_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) __u8 rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) __u8 control_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) __u8 add_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) __le16 op_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) __le16 stbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) __u8 add_qos_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) __u8 is_qos_sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087) __le32 fw_sta_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) #define MWL8K_STA_ACTION_ADD 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) #define MWL8K_STA_ACTION_REMOVE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) struct ieee80211_sta *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) struct mwl8k_cmd_set_new_stn *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098) u32 rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) cmd->aid = cpu_to_le16(sta->aid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108) memcpy(cmd->mac_addr, sta->addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) cmd->stn_id = cpu_to_le16(sta->aid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110) cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) rates = sta->supp_rates[NL80211_BAND_2GHZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) rates = sta->supp_rates[NL80211_BAND_5GHZ] << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) cmd->legacy_rates = cpu_to_le32(rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) if (sta->ht_cap.ht_supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) cmd->ht_rates[0] = sta->ht_cap.mcs.rx_mask[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) cmd->ht_rates[1] = sta->ht_cap.mcs.rx_mask[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) cmd->ht_rates[2] = sta->ht_cap.mcs.rx_mask[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) cmd->ht_rates[3] = sta->ht_cap.mcs.rx_mask[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) cmd->ht_capabilities_info = cpu_to_le16(sta->ht_cap.cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) cmd->mac_ht_param_info = (sta->ht_cap.ampdu_factor & 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) ((sta->ht_cap.ampdu_density & 7) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) cmd->is_qos_sta = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) static int mwl8k_cmd_set_new_stn_add_self(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) struct ieee80211_vif *vif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) struct mwl8k_cmd_set_new_stn *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) memcpy(cmd->mac_addr, vif->addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) struct ieee80211_vif *vif, u8 *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156) struct mwl8k_cmd_set_new_stn *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) int rc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159) u8 idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162) /* Destroy any active ampdu streams for this sta */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) for (i = 0; i < MWL8K_NUM_AMPDU_STREAMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) struct mwl8k_ampdu_stream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) s = &priv->ampdu[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) if (s->state != AMPDU_NO_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) if (memcmp(s->sta->addr, addr, ETH_ALEN) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) if (s->state == AMPDU_STREAM_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) idx = s->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) mwl8k_destroy_ba(hw, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) } else if (s->state == AMPDU_STREAM_NEW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) mwl8k_remove_stream(hw, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) memcpy(cmd->mac_addr, addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) cmd->action = cpu_to_le16(MWL8K_STA_ACTION_REMOVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) * CMD_UPDATE_ENCRYPTION.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) #define MAX_ENCR_KEY_LENGTH 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) #define MIC_KEY_LENGTH 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204) struct mwl8k_cmd_update_encryption {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207) __le32 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) __le32 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) __u8 mac_addr[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210) __u8 encr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) struct mwl8k_cmd_set_key {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) __le32 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) __le32 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) __le16 length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) __le16 key_type_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221) __le32 key_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) __le32 key_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) __le16 key_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224) __u8 key_material[MAX_ENCR_KEY_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) __u8 tkip_tx_mic_key[MIC_KEY_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) __u8 tkip_rx_mic_key[MIC_KEY_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) __le16 tkip_rsc_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228) __le32 tkip_rsc_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) __le16 tkip_tsc_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) __le32 tkip_tsc_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) __u8 mac_addr[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235) MWL8K_ENCR_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236) MWL8K_ENCR_SET_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) MWL8K_ENCR_REMOVE_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) MWL8K_ENCR_SET_GROUP_KEY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241) #define MWL8K_UPDATE_ENCRYPTION_TYPE_WEP 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) #define MWL8K_UPDATE_ENCRYPTION_TYPE_DISABLE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243) #define MWL8K_UPDATE_ENCRYPTION_TYPE_TKIP 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) #define MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) #define MWL8K_UPDATE_ENCRYPTION_TYPE_AES 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) MWL8K_ALG_WEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) MWL8K_ALG_TKIP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) MWL8K_ALG_CCMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) #define MWL8K_KEY_FLAG_TXGROUPKEY 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) #define MWL8K_KEY_FLAG_PAIRWISE 0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255) #define MWL8K_KEY_FLAG_TSC_VALID 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) #define MWL8K_KEY_FLAG_WEP_TXKEY 0x01000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) #define MWL8K_KEY_FLAG_MICKEY_VALID 0x02000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) static int mwl8k_cmd_update_encryption_enable(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) u8 encr_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) struct mwl8k_cmd_update_encryption *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) cmd->action = cpu_to_le32(MWL8K_ENCR_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274) memcpy(cmd->mac_addr, addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) cmd->encr_type = encr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) static int mwl8k_encryption_set_cmd_info(struct mwl8k_cmd_set_key *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) struct ieee80211_key_conf *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289) cmd->length = cpu_to_le16(sizeof(*cmd) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) offsetof(struct mwl8k_cmd_set_key, length));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291) cmd->key_id = cpu_to_le32(key->keyidx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292) cmd->key_len = cpu_to_le16(key->keylen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) memcpy(cmd->mac_addr, addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295) switch (key->cipher) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) case WLAN_CIPHER_SUITE_WEP40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) case WLAN_CIPHER_SUITE_WEP104:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) cmd->key_type_id = cpu_to_le16(MWL8K_ALG_WEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) if (key->keyidx == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300) cmd->key_info = cpu_to_le32(MWL8K_KEY_FLAG_WEP_TXKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) case WLAN_CIPHER_SUITE_TKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304) cmd->key_type_id = cpu_to_le16(MWL8K_ALG_TKIP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305) cmd->key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) ? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) : cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308) cmd->key_info |= cpu_to_le32(MWL8K_KEY_FLAG_MICKEY_VALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) | MWL8K_KEY_FLAG_TSC_VALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) case WLAN_CIPHER_SUITE_CCMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312) cmd->key_type_id = cpu_to_le16(MWL8K_ALG_CCMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) cmd->key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314) ? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315) : cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4324) static int mwl8k_cmd_encryption_set_key(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4325) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4326) u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4327) struct ieee80211_key_conf *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4329) struct mwl8k_cmd_set_key *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4330) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4331) int keymlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4332) u32 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4333) u8 idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4334) struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4336) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4337) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4338) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4340) rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4341) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4342) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4344) idx = key->keyidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4346) if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4347) action = MWL8K_ENCR_SET_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4348) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4349) action = MWL8K_ENCR_SET_GROUP_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4351) switch (key->cipher) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4352) case WLAN_CIPHER_SUITE_WEP40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4353) case WLAN_CIPHER_SUITE_WEP104:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4354) if (!mwl8k_vif->wep_key_conf[idx].enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4355) memcpy(mwl8k_vif->wep_key_conf[idx].key, key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4356) sizeof(*key) + key->keylen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4357) mwl8k_vif->wep_key_conf[idx].enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4360) keymlen = key->keylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4361) action = MWL8K_ENCR_SET_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4362) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4363) case WLAN_CIPHER_SUITE_TKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4364) keymlen = MAX_ENCR_KEY_LENGTH + 2 * MIC_KEY_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4366) case WLAN_CIPHER_SUITE_CCMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4367) keymlen = key->keylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4369) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4370) rc = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4371) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4374) memcpy(cmd->key_material, key->key, keymlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4375) cmd->action = cpu_to_le32(action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4377) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4378) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4379) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4381) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4384) static int mwl8k_cmd_encryption_remove_key(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4385) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4386) u8 *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4387) struct ieee80211_key_conf *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4389) struct mwl8k_cmd_set_key *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4390) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4391) struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4393) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4394) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4395) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4397) rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4398) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4399) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4401) if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4402) key->cipher == WLAN_CIPHER_SUITE_WEP104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4403) mwl8k_vif->wep_key_conf[key->keyidx].enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4405) cmd->action = cpu_to_le32(MWL8K_ENCR_REMOVE_KEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4407) rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4408) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4409) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4411) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4414) static int mwl8k_set_key(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4415) enum set_key_cmd cmd_param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4416) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4417) struct ieee80211_sta *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4418) struct ieee80211_key_conf *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4420) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4421) u8 encr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4422) u8 *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4423) struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4424) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4426) if (vif->type == NL80211_IFTYPE_STATION && !priv->ap_fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4427) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4429) if (sta == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4430) addr = vif->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4431) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4432) addr = sta->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4434) if (cmd_param == SET_KEY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4435) rc = mwl8k_cmd_encryption_set_key(hw, vif, addr, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4436) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4437) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4439) if ((key->cipher == WLAN_CIPHER_SUITE_WEP40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4440) || (key->cipher == WLAN_CIPHER_SUITE_WEP104))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4441) encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_WEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4442) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4443) encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4445) rc = mwl8k_cmd_update_encryption_enable(hw, vif, addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4446) encr_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4447) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4448) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4450) mwl8k_vif->is_hw_crypto_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4452) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4453) rc = mwl8k_cmd_encryption_remove_key(hw, vif, addr, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4455) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4456) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4458) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4459) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4462) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4463) * CMD_UPDATE_STADB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4464) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4465) struct ewc_ht_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4466) __le16 control1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4467) __le16 control2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4468) __le16 control3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4469) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4471) struct peer_capability_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4472) /* Peer type - AP vs. STA. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4473) __u8 peer_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4475) /* Basic 802.11 capabilities from assoc resp. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4476) __le16 basic_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4478) /* Set if peer supports 802.11n high throughput (HT). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4479) __u8 ht_support;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4481) /* Valid if HT is supported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4482) __le16 ht_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4483) __u8 extended_ht_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4484) struct ewc_ht_info ewc_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4486) /* Legacy rate table. Intersection of our rates and peer rates. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4487) __u8 legacy_rates[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4489) /* HT rate table. Intersection of our rates and peer rates. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4490) __u8 ht_rates[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4491) __u8 pad[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4493) /* If set, interoperability mode, no proprietary extensions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4494) __u8 interop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4495) __u8 pad2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4496) __u8 station_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4497) __le16 amsdu_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4498) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4500) struct mwl8k_cmd_update_stadb {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4501) struct mwl8k_cmd_pkt header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4503) /* See STADB_ACTION_TYPE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4504) __le32 action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4506) /* Peer MAC address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4507) __u8 peer_addr[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4509) __le32 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4511) /* Peer info - valid during add/update. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4512) struct peer_capability_info peer_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4513) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4515) #define MWL8K_STA_DB_MODIFY_ENTRY 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4516) #define MWL8K_STA_DB_DEL_ENTRY 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4518) /* Peer Entry flags - used to define the type of the peer node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4519) #define MWL8K_PEER_TYPE_ACCESSPOINT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4521) static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4522) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4523) struct ieee80211_sta *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4525) struct mwl8k_cmd_update_stadb *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4526) struct peer_capability_info *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4527) u32 rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4528) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4530) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4531) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4532) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4534) cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4535) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4536) cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4537) memcpy(cmd->peer_addr, sta->addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4539) p = &cmd->peer_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4540) p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4541) p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4542) p->ht_support = sta->ht_cap.ht_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4543) p->ht_caps = cpu_to_le16(sta->ht_cap.cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4544) p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4545) ((sta->ht_cap.ampdu_density & 7) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4546) if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4547) rates = sta->supp_rates[NL80211_BAND_2GHZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4548) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4549) rates = sta->supp_rates[NL80211_BAND_5GHZ] << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4550) legacy_rate_mask_to_array(p->legacy_rates, rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4551) memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4552) p->interop = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4553) p->amsdu_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4555) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4556) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4557) rc = p->station_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4558) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4560) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4563) static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4564) struct ieee80211_vif *vif, u8 *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4566) struct mwl8k_cmd_update_stadb *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4567) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4569) cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4570) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4571) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4573) cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4574) cmd->header.length = cpu_to_le16(sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4575) cmd->action = cpu_to_le32(MWL8K_STA_DB_DEL_ENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4576) memcpy(cmd->peer_addr, addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4578) rc = mwl8k_post_cmd(hw, &cmd->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4579) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4581) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4585) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4586) * Interrupt handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4587) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4588) static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4590) struct ieee80211_hw *hw = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4591) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4592) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4594) status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4595) if (!status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4596) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4598) if (status & MWL8K_A2H_INT_TX_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4599) status &= ~MWL8K_A2H_INT_TX_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4600) tasklet_schedule(&priv->poll_tx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4603) if (status & MWL8K_A2H_INT_RX_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4604) status &= ~MWL8K_A2H_INT_RX_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4605) tasklet_schedule(&priv->poll_rx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4608) if (status & MWL8K_A2H_INT_BA_WATCHDOG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4609) iowrite32(~MWL8K_A2H_INT_BA_WATCHDOG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4610) priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4612) atomic_inc(&priv->watchdog_event_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4613) status &= ~MWL8K_A2H_INT_BA_WATCHDOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4614) ieee80211_queue_work(hw, &priv->watchdog_ba_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4617) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4618) iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4620) if (status & MWL8K_A2H_INT_OPC_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4621) if (priv->hostcmd_wait != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4622) complete(priv->hostcmd_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4625) if (status & MWL8K_A2H_INT_QUEUE_EMPTY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4626) if (!mutex_is_locked(&priv->fw_mutex) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4627) priv->radio_on && priv->pending_tx_pkts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4628) mwl8k_tx_start(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4631) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4634) static void mwl8k_tx_poll(struct tasklet_struct *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4636) struct mwl8k_priv *priv = from_tasklet(priv, t, poll_tx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4637) struct ieee80211_hw *hw = pci_get_drvdata(priv->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4638) int limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4639) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4641) limit = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4643) spin_lock(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4645) for (i = 0; i < mwl8k_tx_queues(priv); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4646) limit -= mwl8k_txq_reclaim(hw, i, limit, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4648) if (!priv->pending_tx_pkts && priv->tx_wait != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4649) complete(priv->tx_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4650) priv->tx_wait = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4653) spin_unlock(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4655) if (limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4656) writel(~MWL8K_A2H_INT_TX_DONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4657) priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4658) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4659) tasklet_schedule(&priv->poll_tx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4663) static void mwl8k_rx_poll(struct tasklet_struct *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4665) struct mwl8k_priv *priv = from_tasklet(priv, t, poll_rx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4666) struct ieee80211_hw *hw = pci_get_drvdata(priv->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4667) int limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4669) limit = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4670) limit -= rxq_process(hw, 0, limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4671) limit -= rxq_refill(hw, 0, limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4673) if (limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4674) writel(~MWL8K_A2H_INT_RX_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4675) priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4676) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4677) tasklet_schedule(&priv->poll_rx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4682) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4683) * Core driver operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4684) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4685) static void mwl8k_tx(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4686) struct ieee80211_tx_control *control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4687) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4689) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4690) int index = skb_get_queue_mapping(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4692) if (!priv->radio_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4693) wiphy_debug(hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4694) "dropped TX frame since radio disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4695) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4696) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4699) mwl8k_txq_xmit(hw, index, control->sta, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4702) static int mwl8k_start(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4704) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4705) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4707) rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4708) IRQF_SHARED, MWL8K_NAME, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4709) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4710) priv->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4711) wiphy_err(hw->wiphy, "failed to register IRQ handler\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4712) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4714) priv->irq = priv->pdev->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4716) /* Enable TX reclaim and RX tasklets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4717) tasklet_enable(&priv->poll_tx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4718) tasklet_enable(&priv->poll_rx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4720) /* Enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4721) iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4722) iowrite32(MWL8K_A2H_EVENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4723) priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4725) rc = mwl8k_fw_lock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4726) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4727) rc = mwl8k_cmd_radio_enable(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4729) if (!priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4730) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4731) rc = mwl8k_cmd_enable_sniffer(hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4733) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4734) rc = mwl8k_cmd_set_pre_scan(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4736) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4737) rc = mwl8k_cmd_set_post_scan(hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4738) "\x00\x00\x00\x00\x00\x00");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4741) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4742) rc = mwl8k_cmd_set_rateadapt_mode(hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4744) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4745) rc = mwl8k_cmd_set_wmm_mode(hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4747) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4750) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4751) iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4752) free_irq(priv->pdev->irq, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4753) priv->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4754) tasklet_disable(&priv->poll_tx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4755) tasklet_disable(&priv->poll_rx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4756) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4757) ieee80211_wake_queues(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4760) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4763) static void mwl8k_stop(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4765) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4766) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4768) if (!priv->hw_restart_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4769) mwl8k_cmd_radio_disable(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4771) ieee80211_stop_queues(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4773) /* Disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4774) iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4775) if (priv->irq != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4776) free_irq(priv->pdev->irq, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4777) priv->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4780) /* Stop finalize join worker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4781) cancel_work_sync(&priv->finalize_join_worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4782) cancel_work_sync(&priv->watchdog_ba_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4783) if (priv->beacon_skb != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4784) dev_kfree_skb(priv->beacon_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4786) /* Stop TX reclaim and RX tasklets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4787) tasklet_disable(&priv->poll_tx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4788) tasklet_disable(&priv->poll_rx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4790) /* Return all skbs to mac80211 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4791) for (i = 0; i < mwl8k_tx_queues(priv); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4792) mwl8k_txq_reclaim(hw, i, INT_MAX, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4795) static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4797) static int mwl8k_add_interface(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4798) struct ieee80211_vif *vif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4800) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4801) struct mwl8k_vif *mwl8k_vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4802) u32 macids_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4803) int macid, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4804) struct mwl8k_device_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4806) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4807) * Reject interface creation if sniffer mode is active, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4808) * STA operation is mutually exclusive with hardware sniffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4809) * mode. (Sniffer mode is only used on STA firmware.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4810) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4811) if (priv->sniffer_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4812) wiphy_info(hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4813) "unable to create STA interface because sniffer mode is enabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4814) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4817) di = priv->device_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4818) switch (vif->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4819) case NL80211_IFTYPE_AP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4820) if (!priv->ap_fw && di->fw_image_ap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4821) /* we must load the ap fw to meet this request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4822) if (!list_empty(&priv->vif_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4823) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4824) rc = mwl8k_reload_firmware(hw, di->fw_image_ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4825) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4826) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4828) macids_supported = priv->ap_macids_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4829) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4830) case NL80211_IFTYPE_STATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4831) if (priv->ap_fw && di->fw_image_sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4832) if (!list_empty(&priv->vif_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4833) wiphy_warn(hw->wiphy, "AP interface is running.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4834) "Adding STA interface for WDS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4835) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4836) /* we must load the sta fw to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4837) * meet this request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4838) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4839) rc = mwl8k_reload_firmware(hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4840) di->fw_image_sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4841) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4842) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4845) macids_supported = priv->sta_macids_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4846) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4847) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4848) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4851) macid = ffs(macids_supported & ~priv->macids_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4852) if (!macid--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4853) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4855) /* Setup driver private area. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4856) mwl8k_vif = MWL8K_VIF(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4857) memset(mwl8k_vif, 0, sizeof(*mwl8k_vif));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4858) mwl8k_vif->vif = vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4859) mwl8k_vif->macid = macid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4860) mwl8k_vif->seqno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4861) memcpy(mwl8k_vif->bssid, vif->addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4862) mwl8k_vif->is_hw_crypto_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4864) /* Set the mac address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4865) mwl8k_cmd_set_mac_addr(hw, vif, vif->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4867) if (vif->type == NL80211_IFTYPE_AP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4868) mwl8k_cmd_set_new_stn_add_self(hw, vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4870) priv->macids_used |= 1 << mwl8k_vif->macid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4871) list_add_tail(&mwl8k_vif->list, &priv->vif_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4873) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4876) static void mwl8k_remove_vif(struct mwl8k_priv *priv, struct mwl8k_vif *vif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4878) /* Has ieee80211_restart_hw re-added the removed interfaces? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4879) if (!priv->macids_used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4880) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4882) priv->macids_used &= ~(1 << vif->macid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4883) list_del(&vif->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4886) static void mwl8k_remove_interface(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4887) struct ieee80211_vif *vif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4889) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4890) struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4892) if (vif->type == NL80211_IFTYPE_AP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4893) mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4895) mwl8k_cmd_del_mac_addr(hw, vif, vif->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4897) mwl8k_remove_vif(priv, mwl8k_vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4900) static void mwl8k_hw_restart_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4901) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4902) struct mwl8k_priv *priv =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4903) container_of(work, struct mwl8k_priv, fw_reload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4904) struct ieee80211_hw *hw = priv->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4905) struct mwl8k_device_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4906) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4908) /* If some command is waiting for a response, clear it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4909) if (priv->hostcmd_wait != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4910) complete(priv->hostcmd_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4911) priv->hostcmd_wait = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4914) priv->hw_restart_owner = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4915) di = priv->device_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4916) mwl8k_fw_lock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4918) if (priv->ap_fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4919) rc = mwl8k_reload_firmware(hw, di->fw_image_ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4920) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4921) rc = mwl8k_reload_firmware(hw, di->fw_image_sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4923) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4924) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4926) priv->hw_restart_owner = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4927) priv->hw_restart_in_progress = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4929) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4930) * This unlock will wake up the queues and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4931) * also opens the command path for other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4932) * commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4933) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4934) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4936) ieee80211_restart_hw(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4938) wiphy_err(hw->wiphy, "Firmware restarted successfully\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4940) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4941) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4942) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4944) wiphy_err(hw->wiphy, "Firmware restart failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4947) static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4949) struct ieee80211_conf *conf = &hw->conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4950) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4951) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4953) rc = mwl8k_fw_lock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4954) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4955) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4957) if (conf->flags & IEEE80211_CONF_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4958) rc = mwl8k_cmd_radio_disable(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4959) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4960) rc = mwl8k_cmd_radio_enable(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4961) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4962) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4964) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4965) rc = mwl8k_cmd_set_rf_channel(hw, conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4966) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4967) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4970) if (conf->power_level > 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4971) conf->power_level = 18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4973) if (priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4975) if (conf->flags & IEEE80211_CONF_CHANGE_POWER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4976) rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4977) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4978) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4982) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4983) rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4984) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4985) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4986) rc = mwl8k_cmd_mimo_config(hw, 0x7, 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4989) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4990) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4992) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4995) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4996) mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4997) struct ieee80211_bss_conf *info, u32 changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4999) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5000) u32 ap_legacy_rates = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5001) u8 ap_mcs_rates[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5002) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5004) if (mwl8k_fw_lock(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5005) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5007) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5008) * No need to capture a beacon if we're no longer associated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5009) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5010) if ((changed & BSS_CHANGED_ASSOC) && !vif->bss_conf.assoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5011) priv->capture_beacon = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5013) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5014) * Get the AP's legacy and MCS rates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5015) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5016) if (vif->bss_conf.assoc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5017) struct ieee80211_sta *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5019) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5021) ap = ieee80211_find_sta(vif, vif->bss_conf.bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5022) if (ap == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5023) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5024) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5027) if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5028) ap_legacy_rates = ap->supp_rates[NL80211_BAND_2GHZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5029) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5030) ap_legacy_rates =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5031) ap->supp_rates[NL80211_BAND_5GHZ] << 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5033) memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5035) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5037) if (changed & BSS_CHANGED_ASSOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5038) if (!priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5039) rc = mwl8k_cmd_set_rate(hw, vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5040) ap_legacy_rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5041) ap_mcs_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5042) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5043) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5045) rc = mwl8k_cmd_use_fixed_rate_sta(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5046) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5047) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5048) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5049) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5050) int rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5052) /* Use AP firmware specific rate command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5053) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5054) idx = ffs(vif->bss_conf.basic_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5055) if (idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5056) idx--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5058) if (hw->conf.chandef.chan->band ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5059) NL80211_BAND_2GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5060) rate = mwl8k_rates_24[idx].hw_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5061) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5062) rate = mwl8k_rates_50[idx].hw_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5064) mwl8k_cmd_use_fixed_rate_ap(hw, rate, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5069) if (changed & BSS_CHANGED_ERP_PREAMBLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5070) rc = mwl8k_set_radio_preamble(hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5071) vif->bss_conf.use_short_preamble);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5072) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5073) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5076) if ((changed & BSS_CHANGED_ERP_SLOT) && !priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5077) rc = mwl8k_cmd_set_slot(hw, vif->bss_conf.use_short_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5078) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5079) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5082) if (vif->bss_conf.assoc && !priv->ap_fw &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5083) (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_CTS_PROT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5084) BSS_CHANGED_HT))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5085) rc = mwl8k_cmd_set_aid(hw, vif, ap_legacy_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5086) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5087) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5090) if (vif->bss_conf.assoc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5091) (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INT))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5092) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5093) * Finalize the join. Tell rx handler to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5094) * next beacon from our BSSID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5095) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5096) memcpy(priv->capture_bssid, vif->bss_conf.bssid, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5097) priv->capture_beacon = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5100) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5101) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5104) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5105) mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5106) struct ieee80211_bss_conf *info, u32 changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5108) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5110) if (mwl8k_fw_lock(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5111) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5113) if (changed & BSS_CHANGED_ERP_PREAMBLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5114) rc = mwl8k_set_radio_preamble(hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5115) vif->bss_conf.use_short_preamble);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5116) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5117) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5120) if (changed & BSS_CHANGED_BASIC_RATES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5121) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5122) int rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5125) * Use lowest supported basic rate for multicasts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5126) * and management frames (such as probe responses --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5127) * beacons will always go out at 1 Mb/s).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5129) idx = ffs(vif->bss_conf.basic_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5130) if (idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5131) idx--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5133) if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5134) rate = mwl8k_rates_24[idx].hw_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5135) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5136) rate = mwl8k_rates_50[idx].hw_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5138) mwl8k_cmd_use_fixed_rate_ap(hw, rate, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5141) if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5142) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5144) skb = ieee80211_beacon_get(hw, vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5145) if (skb != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5146) mwl8k_cmd_set_beacon(hw, vif, skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5147) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5151) if (changed & BSS_CHANGED_BEACON_ENABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5152) mwl8k_cmd_bss_start(hw, vif, info->enable_beacon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5154) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5155) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5158) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5159) mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5160) struct ieee80211_bss_conf *info, u32 changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5162) if (vif->type == NL80211_IFTYPE_STATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5163) mwl8k_bss_info_changed_sta(hw, vif, info, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5164) if (vif->type == NL80211_IFTYPE_AP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5165) mwl8k_bss_info_changed_ap(hw, vif, info, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5168) static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5169) struct netdev_hw_addr_list *mc_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5171) struct mwl8k_cmd_pkt *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5173) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5174) * Synthesize and return a command packet that programs the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5175) * hardware multicast address filter. At this point we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5176) * know whether FIF_ALLMULTI is being requested, but if it is,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5177) * we'll end up throwing this packet away and creating a new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5178) * one in mwl8k_configure_filter().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5180) cmd = __mwl8k_cmd_mac_multicast_adr(hw, 0, mc_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5182) return (unsigned long)cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5185) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5186) mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5187) unsigned int changed_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5188) unsigned int *total_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5190) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5193) * Hardware sniffer mode is mutually exclusive with STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5194) * operation, so refuse to enable sniffer mode if a STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5195) * interface is active.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5197) if (!list_empty(&priv->vif_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5198) if (net_ratelimit())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5199) wiphy_info(hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5200) "not enabling sniffer mode because STA interface is active\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5201) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5204) if (!priv->sniffer_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5205) if (mwl8k_cmd_enable_sniffer(hw, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5206) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5207) priv->sniffer_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5210) *total_flags &= FIF_ALLMULTI |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5211) FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5212) FIF_OTHER_BSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5214) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5217) static struct mwl8k_vif *mwl8k_first_vif(struct mwl8k_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5219) if (!list_empty(&priv->vif_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5220) return list_entry(priv->vif_list.next, struct mwl8k_vif, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5222) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5225) static void mwl8k_configure_filter(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5226) unsigned int changed_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5227) unsigned int *total_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5228) u64 multicast)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5230) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5231) struct mwl8k_cmd_pkt *cmd = (void *)(unsigned long)multicast;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5233) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5234) * AP firmware doesn't allow fine-grained control over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5235) * the receive filter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5236) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5237) if (priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5238) *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5239) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5240) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5243) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5244) * Enable hardware sniffer mode if FIF_CONTROL or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5245) * FIF_OTHER_BSS is requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5247) if (*total_flags & (FIF_CONTROL | FIF_OTHER_BSS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5248) mwl8k_configure_filter_sniffer(hw, changed_flags, total_flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5249) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5250) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5253) /* Clear unsupported feature flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5254) *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5256) if (mwl8k_fw_lock(hw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5257) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5258) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5261) if (priv->sniffer_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5262) mwl8k_cmd_enable_sniffer(hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5263) priv->sniffer_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5266) if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5267) if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5268) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5269) * Disable the BSS filter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5271) mwl8k_cmd_set_pre_scan(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5272) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5273) struct mwl8k_vif *mwl8k_vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5274) const u8 *bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5276) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5277) * Enable the BSS filter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5278) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5279) * If there is an active STA interface, use that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5280) * interface's BSSID, otherwise use a dummy one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5281) * (where the OUI part needs to be nonzero for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5282) * the BSSID to be accepted by POST_SCAN).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5284) mwl8k_vif = mwl8k_first_vif(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5285) if (mwl8k_vif != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5286) bssid = mwl8k_vif->vif->bss_conf.bssid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5287) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5288) bssid = "\x01\x00\x00\x00\x00\x00";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5290) mwl8k_cmd_set_post_scan(hw, bssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5294) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5295) * If FIF_ALLMULTI is being requested, throw away the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5296) * packet that ->prepare_multicast() built and replace it with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5297) * a command packet that enables reception of all multicast
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5298) * packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5300) if (*total_flags & FIF_ALLMULTI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5301) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5302) cmd = __mwl8k_cmd_mac_multicast_adr(hw, 1, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5305) if (cmd != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5306) mwl8k_post_cmd(hw, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5307) kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5310) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5313) static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5315) return mwl8k_cmd_set_rts_threshold(hw, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5318) static int mwl8k_sta_remove(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5319) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5320) struct ieee80211_sta *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5322) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5324) if (priv->ap_fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5325) return mwl8k_cmd_set_new_stn_del(hw, vif, sta->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5326) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5327) return mwl8k_cmd_update_stadb_del(hw, vif, sta->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5330) static int mwl8k_sta_add(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5331) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5332) struct ieee80211_sta *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5334) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5335) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5336) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5337) struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5338) struct ieee80211_key_conf *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5340) if (!priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5341) ret = mwl8k_cmd_update_stadb_add(hw, vif, sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5342) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5343) MWL8K_STA(sta)->peer_id = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5344) if (sta->ht_cap.ht_supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5345) MWL8K_STA(sta)->is_ampdu_allowed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5346) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5349) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5350) ret = mwl8k_cmd_set_new_stn_add(hw, vif, sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5353) for (i = 0; i < NUM_WEP_KEYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5354) key = IEEE80211_KEY_CONF(mwl8k_vif->wep_key_conf[i].key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5355) if (mwl8k_vif->wep_key_conf[i].enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5356) mwl8k_set_key(hw, SET_KEY, vif, sta, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5358) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5361) static int mwl8k_conf_tx(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5362) struct ieee80211_vif *vif, u16 queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5363) const struct ieee80211_tx_queue_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5365) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5366) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5368) rc = mwl8k_fw_lock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5369) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5370) BUG_ON(queue > MWL8K_TX_WMM_QUEUES - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5371) memcpy(&priv->wmm_params[queue], params, sizeof(*params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5373) if (!priv->wmm_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5374) rc = mwl8k_cmd_set_wmm_mode(hw, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5376) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5377) int q = MWL8K_TX_WMM_QUEUES - 1 - queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5378) rc = mwl8k_cmd_set_edca_params(hw, q,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5379) params->cw_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5380) params->cw_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5381) params->aifs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5382) params->txop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5385) mwl8k_fw_unlock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5388) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5391) static int mwl8k_get_stats(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5392) struct ieee80211_low_level_stats *stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5394) return mwl8k_cmd_get_stat(hw, stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5397) static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5398) struct survey_info *survey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5400) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5401) struct ieee80211_conf *conf = &hw->conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5402) struct ieee80211_supported_band *sband;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5404) if (priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5405) sband = hw->wiphy->bands[NL80211_BAND_2GHZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5407) if (sband && idx >= sband->n_channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5408) idx -= sband->n_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5409) sband = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5412) if (!sband)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5413) sband = hw->wiphy->bands[NL80211_BAND_5GHZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5415) if (!sband || idx >= sband->n_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5416) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5418) memcpy(survey, &priv->survey[idx], sizeof(*survey));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5419) survey->channel = &sband->channels[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5421) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5424) if (idx != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5425) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5427) survey->channel = conf->chandef.chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5428) survey->filled = SURVEY_INFO_NOISE_DBM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5429) survey->noise = priv->noise;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5431) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5434) #define MAX_AMPDU_ATTEMPTS 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5436) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5437) mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5438) struct ieee80211_ampdu_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5440) struct ieee80211_sta *sta = params->sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5441) enum ieee80211_ampdu_mlme_action action = params->action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5442) u16 tid = params->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5443) u16 *ssn = ¶ms->ssn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5444) u8 buf_size = params->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5445) int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5446) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5447) struct mwl8k_ampdu_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5448) u8 *addr = sta->addr, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5449) struct mwl8k_sta *sta_info = MWL8K_STA(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5451) if (!ieee80211_hw_check(hw, AMPDU_AGGREGATION))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5452) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5454) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5455) stream = mwl8k_lookup_stream(hw, addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5457) switch (action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5458) case IEEE80211_AMPDU_RX_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5459) case IEEE80211_AMPDU_RX_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5460) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5461) case IEEE80211_AMPDU_TX_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5462) /* By the time we get here the hw queues may contain outgoing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5463) * packets for this RA/TID that are not part of this BA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5464) * session. The hw will assign sequence numbers to these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5465) * packets as they go out. So if we query the hw for its next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5466) * sequence number and use that for the SSN here, it may end up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5467) * being wrong, which will lead to sequence number mismatch at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5468) * the recipient. To avoid this, we reset the sequence number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5469) * to O for the first MPDU in this BA stream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5470) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5471) *ssn = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5472) if (stream == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5473) /* This means that somebody outside this driver called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5474) * ieee80211_start_tx_ba_session. This is unexpected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5475) * because we do our own rate control. Just warn and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5476) * move on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5478) wiphy_warn(hw->wiphy, "Unexpected call to %s. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5479) "Proceeding anyway.\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5480) stream = mwl8k_add_stream(hw, sta, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5482) if (stream == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5483) wiphy_debug(hw->wiphy, "no free AMPDU streams\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5484) rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5485) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5487) stream->state = AMPDU_STREAM_IN_PROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5489) /* Release the lock before we do the time consuming stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5490) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5491) for (i = 0; i < MAX_AMPDU_ATTEMPTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5493) /* Check if link is still valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5494) if (!sta_info->is_ampdu_allowed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5495) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5496) mwl8k_remove_stream(hw, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5497) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5498) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5501) rc = mwl8k_check_ba(hw, stream, vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5503) /* If HW restart is in progress mwl8k_post_cmd will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5504) * return -EBUSY. Avoid retrying mwl8k_check_ba in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5505) * such cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5506) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5507) if (!rc || rc == -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5508) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5509) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5510) * HW queues take time to be flushed, give them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5511) * sufficient time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5514) msleep(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5516) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5517) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5518) wiphy_err(hw->wiphy, "Stream for tid %d busy after %d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5519) " attempts\n", tid, MAX_AMPDU_ATTEMPTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5520) mwl8k_remove_stream(hw, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5521) rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5522) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5524) rc = IEEE80211_AMPDU_TX_START_IMMEDIATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5525) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5526) case IEEE80211_AMPDU_TX_STOP_CONT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5527) case IEEE80211_AMPDU_TX_STOP_FLUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5528) case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5529) if (stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5530) if (stream->state == AMPDU_STREAM_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5531) idx = stream->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5532) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5533) mwl8k_destroy_ba(hw, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5534) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5536) mwl8k_remove_stream(hw, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5538) ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5539) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5540) case IEEE80211_AMPDU_TX_OPERATIONAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5541) BUG_ON(stream == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5542) BUG_ON(stream->state != AMPDU_STREAM_IN_PROGRESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5543) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5544) rc = mwl8k_create_ba(hw, stream, buf_size, vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5545) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5546) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5547) stream->state = AMPDU_STREAM_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5548) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5549) idx = stream->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5550) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5551) mwl8k_destroy_ba(hw, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5552) spin_lock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5553) wiphy_debug(hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5554) "Failed adding stream for sta %pM tid %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5555) addr, tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5556) mwl8k_remove_stream(hw, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5558) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5560) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5561) rc = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5564) spin_unlock(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5565) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5568) static void mwl8k_sw_scan_start(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5569) struct ieee80211_vif *vif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5570) const u8 *mac_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5572) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5573) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5575) if (!priv->ap_fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5576) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5578) /* clear all stats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5579) priv->channel_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5580) ioread32(priv->regs + BBU_RXRDY_CNT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5581) ioread32(priv->regs + NOK_CCA_CNT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5582) mwl8k_cmd_bbp_reg_access(priv->hw, 0, BBU_AVG_NOISE_VAL, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5584) priv->sw_scan_start = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5587) static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5588) struct ieee80211_vif *vif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5590) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5591) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5593) if (!priv->ap_fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5594) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5596) priv->sw_scan_start = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5598) /* clear all stats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5599) priv->channel_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5600) ioread32(priv->regs + BBU_RXRDY_CNT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5601) ioread32(priv->regs + NOK_CCA_CNT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5602) mwl8k_cmd_bbp_reg_access(priv->hw, 0, BBU_AVG_NOISE_VAL, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5605) static const struct ieee80211_ops mwl8k_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5606) .tx = mwl8k_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5607) .start = mwl8k_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5608) .stop = mwl8k_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5609) .add_interface = mwl8k_add_interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5610) .remove_interface = mwl8k_remove_interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5611) .config = mwl8k_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5612) .bss_info_changed = mwl8k_bss_info_changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5613) .prepare_multicast = mwl8k_prepare_multicast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5614) .configure_filter = mwl8k_configure_filter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5615) .set_key = mwl8k_set_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5616) .set_rts_threshold = mwl8k_set_rts_threshold,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5617) .sta_add = mwl8k_sta_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5618) .sta_remove = mwl8k_sta_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5619) .conf_tx = mwl8k_conf_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5620) .get_stats = mwl8k_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5621) .get_survey = mwl8k_get_survey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5622) .ampdu_action = mwl8k_ampdu_action,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5623) .sw_scan_start = mwl8k_sw_scan_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5624) .sw_scan_complete = mwl8k_sw_scan_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5625) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5627) static void mwl8k_finalize_join_worker(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5629) struct mwl8k_priv *priv =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5630) container_of(work, struct mwl8k_priv, finalize_join_worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5631) struct sk_buff *skb = priv->beacon_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5632) struct ieee80211_mgmt *mgmt = (void *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5633) int len = skb->len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5634) const u8 *tim = cfg80211_find_ie(WLAN_EID_TIM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5635) mgmt->u.beacon.variable, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5636) int dtim_period = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5638) if (tim && tim[1] >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5639) dtim_period = tim[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5641) mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, dtim_period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5643) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5644) priv->beacon_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5647) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5648) MWL8363 = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5649) MWL8687,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5650) MWL8366,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5651) MWL8764,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5652) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5654) #define MWL8K_8366_AP_FW_API 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5655) #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5656) #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5658) #define MWL8K_8764_AP_FW_API 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5659) #define _MWL8K_8764_AP_FW(api) "mwl8k/fmimage_8764_ap-" #api ".fw"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5660) #define MWL8K_8764_AP_FW(api) _MWL8K_8764_AP_FW(api)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5662) static struct mwl8k_device_info mwl8k_info_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5663) [MWL8363] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5664) .part_name = "88w8363",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5665) .helper_image = "mwl8k/helper_8363.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5666) .fw_image_sta = "mwl8k/fmimage_8363.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5667) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5668) [MWL8687] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5669) .part_name = "88w8687",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5670) .helper_image = "mwl8k/helper_8687.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5671) .fw_image_sta = "mwl8k/fmimage_8687.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5672) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5673) [MWL8366] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5674) .part_name = "88w8366",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5675) .helper_image = "mwl8k/helper_8366.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5676) .fw_image_sta = "mwl8k/fmimage_8366.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5677) .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5678) .fw_api_ap = MWL8K_8366_AP_FW_API,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5679) .ap_rxd_ops = &rxd_ap_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5680) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5681) [MWL8764] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5682) .part_name = "88w8764",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5683) .fw_image_ap = MWL8K_8764_AP_FW(MWL8K_8764_AP_FW_API),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5684) .fw_api_ap = MWL8K_8764_AP_FW_API,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5685) .ap_rxd_ops = &rxd_ap_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5686) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5687) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5689) MODULE_FIRMWARE("mwl8k/helper_8363.fw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5690) MODULE_FIRMWARE("mwl8k/fmimage_8363.fw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5691) MODULE_FIRMWARE("mwl8k/helper_8687.fw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5692) MODULE_FIRMWARE("mwl8k/fmimage_8687.fw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5693) MODULE_FIRMWARE("mwl8k/helper_8366.fw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5694) MODULE_FIRMWARE("mwl8k/fmimage_8366.fw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5695) MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5697) static const struct pci_device_id mwl8k_pci_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5698) { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5699) { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5700) { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5701) { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5702) { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5703) { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5704) { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5705) { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5706) { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5707) { PCI_VDEVICE(MARVELL, 0x2b36), .driver_data = MWL8764, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5708) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5709) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5710) MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5712) static int mwl8k_request_alt_fw(struct mwl8k_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5714) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5715) printk(KERN_ERR "%s: Error requesting preferred fw %s.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5716) "Trying alternative firmware %s\n", pci_name(priv->pdev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5717) priv->fw_pref, priv->fw_alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5718) rc = mwl8k_request_fw(priv, priv->fw_alt, &priv->fw_ucode, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5719) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5720) printk(KERN_ERR "%s: Error requesting alt fw %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5721) pci_name(priv->pdev), priv->fw_alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5722) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5724) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5727) static int mwl8k_firmware_load_success(struct mwl8k_priv *priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5728) static void mwl8k_fw_state_machine(const struct firmware *fw, void *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5730) struct mwl8k_priv *priv = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5731) struct mwl8k_device_info *di = priv->device_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5732) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5734) switch (priv->fw_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5735) case FW_STATE_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5736) if (!fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5737) printk(KERN_ERR "%s: Error requesting helper fw %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5738) pci_name(priv->pdev), di->helper_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5739) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5741) priv->fw_helper = fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5742) rc = mwl8k_request_fw(priv, priv->fw_pref, &priv->fw_ucode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5743) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5744) if (rc && priv->fw_alt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5745) rc = mwl8k_request_alt_fw(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5746) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5747) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5748) priv->fw_state = FW_STATE_LOADING_ALT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5749) } else if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5750) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5751) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5752) priv->fw_state = FW_STATE_LOADING_PREF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5753) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5755) case FW_STATE_LOADING_PREF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5756) if (!fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5757) if (priv->fw_alt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5758) rc = mwl8k_request_alt_fw(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5759) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5760) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5761) priv->fw_state = FW_STATE_LOADING_ALT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5762) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5763) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5764) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5765) priv->fw_ucode = fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5766) rc = mwl8k_firmware_load_success(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5767) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5768) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5769) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5770) complete(&priv->firmware_loading_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5772) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5774) case FW_STATE_LOADING_ALT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5775) if (!fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5776) printk(KERN_ERR "%s: Error requesting alt fw %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5777) pci_name(priv->pdev), di->helper_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5778) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5780) priv->fw_ucode = fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5781) rc = mwl8k_firmware_load_success(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5782) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5783) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5784) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5785) complete(&priv->firmware_loading_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5788) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5789) printk(KERN_ERR "%s: Unexpected firmware loading state: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5790) MWL8K_NAME, priv->fw_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5791) BUG_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5794) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5796) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5797) priv->fw_state = FW_STATE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5798) complete(&priv->firmware_loading_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5799) mwl8k_release_firmware(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5800) device_release_driver(&priv->pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5803) #define MAX_RESTART_ATTEMPTS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5804) static int mwl8k_init_firmware(struct ieee80211_hw *hw, char *fw_image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5805) bool nowait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5807) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5808) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5809) int count = MAX_RESTART_ATTEMPTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5811) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5812) /* Reset firmware and hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5813) mwl8k_hw_reset(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5815) /* Ask userland hotplug daemon for the device firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5816) rc = mwl8k_request_firmware(priv, fw_image, nowait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5817) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5818) wiphy_err(hw->wiphy, "Firmware files not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5819) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5822) if (nowait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5823) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5825) /* Load firmware into hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5826) rc = mwl8k_load_firmware(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5827) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5828) wiphy_err(hw->wiphy, "Cannot start firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5830) /* Reclaim memory once firmware is successfully loaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5831) mwl8k_release_firmware(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5833) if (rc && count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5834) /* FW did not start successfully;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5835) * lets try one more time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5836) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5837) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5838) wiphy_err(hw->wiphy, "Trying to reload the firmware again\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5839) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5840) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5843) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5846) static int mwl8k_init_txqs(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5848) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5849) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5850) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5852) for (i = 0; i < mwl8k_tx_queues(priv); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5853) rc = mwl8k_txq_init(hw, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5854) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5855) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5856) if (priv->ap_fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5857) iowrite32(priv->txq[i].txd_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5858) priv->sram + priv->txq_offset[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5860) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5863) /* initialize hw after successfully loading a firmware image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5864) static int mwl8k_probe_hw(struct ieee80211_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5866) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5867) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5868) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5870) if (priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5871) priv->rxd_ops = priv->device_info->ap_rxd_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5872) if (priv->rxd_ops == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5873) wiphy_err(hw->wiphy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5874) "Driver does not have AP firmware image support for this hardware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5875) rc = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5876) goto err_stop_firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5878) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5879) priv->rxd_ops = &rxd_sta_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5882) priv->sniffer_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5883) priv->wmm_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5884) priv->pending_tx_pkts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5885) atomic_set(&priv->watchdog_event_pending, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5887) rc = mwl8k_rxq_init(hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5888) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5889) goto err_stop_firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5890) rxq_refill(hw, 0, INT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5892) /* For the sta firmware, we need to know the dma addresses of tx queues
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5893) * before sending MWL8K_CMD_GET_HW_SPEC. So we must initialize them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5894) * prior to issuing this command. But for the AP case, we learn the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5895) * total number of queues from the result CMD_GET_HW_SPEC, so for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5896) * case we must initialize the tx queues after.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5897) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5898) priv->num_ampdu_queues = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5899) if (!priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5900) rc = mwl8k_init_txqs(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5901) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5902) goto err_free_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5905) iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5906) iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5907) iowrite32(MWL8K_A2H_INT_TX_DONE|MWL8K_A2H_INT_RX_READY|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5908) MWL8K_A2H_INT_BA_WATCHDOG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5909) priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5910) iowrite32(MWL8K_A2H_INT_OPC_DONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5911) priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5913) rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5914) IRQF_SHARED, MWL8K_NAME, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5915) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5916) wiphy_err(hw->wiphy, "failed to register IRQ handler\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5917) goto err_free_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5920) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5921) * When hw restart is requested,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5922) * mac80211 will take care of clearing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5923) * the ampdu streams, so do not clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5924) * the ampdu state here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5925) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5926) if (!priv->hw_restart_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5927) memset(priv->ampdu, 0, sizeof(priv->ampdu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5929) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5930) * Temporarily enable interrupts. Initial firmware host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5931) * commands use interrupts and avoid polling. Disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5932) * interrupts when done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5933) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5934) iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5936) /* Get config data, mac addrs etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5937) if (priv->ap_fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5938) rc = mwl8k_cmd_get_hw_spec_ap(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5939) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5940) rc = mwl8k_init_txqs(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5941) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5942) rc = mwl8k_cmd_set_hw_spec(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5943) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5944) rc = mwl8k_cmd_get_hw_spec_sta(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5946) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5947) wiphy_err(hw->wiphy, "Cannot initialise firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5948) goto err_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5951) /* Turn radio off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5952) rc = mwl8k_cmd_radio_disable(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5953) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5954) wiphy_err(hw->wiphy, "Cannot disable\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5955) goto err_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5958) /* Clear MAC address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5959) rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5960) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5961) wiphy_err(hw->wiphy, "Cannot clear MAC address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5962) goto err_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5965) /* Configure Antennas */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5966) rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5967) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5968) wiphy_warn(hw->wiphy, "failed to set # of RX antennas");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5969) rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5970) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5971) wiphy_warn(hw->wiphy, "failed to set # of TX antennas");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5974) /* Disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5975) iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5976) free_irq(priv->pdev->irq, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5978) wiphy_info(hw->wiphy, "%s v%d, %pm, %s firmware %u.%u.%u.%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5979) priv->device_info->part_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5980) priv->hw_rev, hw->wiphy->perm_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5981) priv->ap_fw ? "AP" : "STA",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5982) (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5983) (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5985) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5987) err_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5988) iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5989) free_irq(priv->pdev->irq, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5991) err_free_queues:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5992) for (i = 0; i < mwl8k_tx_queues(priv); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5993) mwl8k_txq_deinit(hw, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5994) mwl8k_rxq_deinit(hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5996) err_stop_firmware:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5997) mwl8k_hw_reset(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5999) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6002) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6003) * invoke mwl8k_reload_firmware to change the firmware image after the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6004) * has already been registered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6005) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6006) static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6008) int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6009) struct mwl8k_priv *priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6010) struct mwl8k_vif *vif, *tmp_vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6012) mwl8k_stop(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6013) mwl8k_rxq_deinit(hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6015) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6016) * All the existing interfaces are re-added by the ieee80211_reconfig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6017) * which means driver should remove existing interfaces before calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6018) * ieee80211_restart_hw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6019) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6020) if (priv->hw_restart_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6021) list_for_each_entry_safe(vif, tmp_vif, &priv->vif_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6022) mwl8k_remove_vif(priv, vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6024) for (i = 0; i < mwl8k_tx_queues(priv); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6025) mwl8k_txq_deinit(hw, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6027) rc = mwl8k_init_firmware(hw, fw_image, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6028) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6029) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6031) rc = mwl8k_probe_hw(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6032) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6033) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6035) if (priv->hw_restart_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6036) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6038) rc = mwl8k_start(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6039) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6040) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6042) rc = mwl8k_config(hw, ~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6043) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6044) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6046) for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6047) rc = mwl8k_conf_tx(hw, NULL, i, &priv->wmm_params[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6048) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6049) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6052) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6054) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6055) printk(KERN_WARNING "mwl8k: Failed to reload firmware image.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6056) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6059) static const struct ieee80211_iface_limit ap_if_limits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6060) { .max = 8, .types = BIT(NL80211_IFTYPE_AP) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6061) { .max = 1, .types = BIT(NL80211_IFTYPE_STATION) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6062) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6064) static const struct ieee80211_iface_combination ap_if_comb = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6065) .limits = ap_if_limits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6066) .n_limits = ARRAY_SIZE(ap_if_limits),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6067) .max_interfaces = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6068) .num_different_channels = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6069) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6072) static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6074) struct ieee80211_hw *hw = priv->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6075) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6077) rc = mwl8k_load_firmware(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6078) mwl8k_release_firmware(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6079) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6080) wiphy_err(hw->wiphy, "Cannot start firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6081) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6084) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6085) * Extra headroom is the size of the required DMA header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6086) * minus the size of the smallest 802.11 frame (CTS frame).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6087) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6088) hw->extra_tx_headroom =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6089) sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6091) hw->extra_tx_headroom -= priv->ap_fw ? REDUCED_TX_HEADROOM : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6093) hw->queues = MWL8K_TX_WMM_QUEUES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6095) /* Set rssi values to dBm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6096) ieee80211_hw_set(hw, SIGNAL_DBM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6097) ieee80211_hw_set(hw, HAS_RATE_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6099) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6100) * Ask mac80211 to not to trigger PS mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6101) * based on PM bit of incoming frames.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6103) if (priv->ap_fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6104) ieee80211_hw_set(hw, AP_LINK_PS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6106) hw->vif_data_size = sizeof(struct mwl8k_vif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6107) hw->sta_data_size = sizeof(struct mwl8k_sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6109) priv->macids_used = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6110) INIT_LIST_HEAD(&priv->vif_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6112) /* Set default radio state and preamble */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6113) priv->radio_on = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6114) priv->radio_short_preamble = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6116) /* Finalize join worker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6117) INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6118) /* Handle watchdog ba events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6119) INIT_WORK(&priv->watchdog_ba_handle, mwl8k_watchdog_ba_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6120) /* To reload the firmware if it crashes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6121) INIT_WORK(&priv->fw_reload, mwl8k_hw_restart_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6123) /* TX reclaim and RX tasklets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6124) tasklet_setup(&priv->poll_tx_task, mwl8k_tx_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6125) tasklet_disable(&priv->poll_tx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6126) tasklet_setup(&priv->poll_rx_task, mwl8k_rx_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6127) tasklet_disable(&priv->poll_rx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6129) /* Power management cookie */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6130) priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6131) if (priv->cookie == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6132) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6134) mutex_init(&priv->fw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6135) priv->fw_mutex_owner = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6136) priv->fw_mutex_depth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6137) priv->hostcmd_wait = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6139) spin_lock_init(&priv->tx_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6141) spin_lock_init(&priv->stream_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6143) priv->tx_wait = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6145) rc = mwl8k_probe_hw(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6146) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6147) goto err_free_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6149) hw->wiphy->interface_modes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6151) if (priv->ap_macids_supported || priv->device_info->fw_image_ap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6152) hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6153) hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6154) hw->wiphy->iface_combinations = &ap_if_comb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6155) hw->wiphy->n_iface_combinations = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6158) if (priv->sta_macids_supported || priv->device_info->fw_image_sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6159) hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6161) wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6163) rc = ieee80211_register_hw(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6164) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6165) wiphy_err(hw->wiphy, "Cannot register device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6166) goto err_unprobe_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6171) err_unprobe_hw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6172) for (i = 0; i < mwl8k_tx_queues(priv); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6173) mwl8k_txq_deinit(hw, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6174) mwl8k_rxq_deinit(hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6176) err_free_cookie:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6177) if (priv->cookie != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6178) pci_free_consistent(priv->pdev, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6179) priv->cookie, priv->cookie_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6181) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6183) static int mwl8k_probe(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6184) const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6186) static int printed_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6187) struct ieee80211_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6188) struct mwl8k_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6189) struct mwl8k_device_info *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6190) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6192) if (!printed_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6193) printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6194) printed_version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6198) rc = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6199) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6200) printk(KERN_ERR "%s: Cannot enable new PCI device\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6201) MWL8K_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6202) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6205) rc = pci_request_regions(pdev, MWL8K_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6206) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6207) printk(KERN_ERR "%s: Cannot obtain PCI resources\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6208) MWL8K_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6209) goto err_disable_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6212) pci_set_master(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6215) hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6216) if (hw == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6217) printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6218) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6219) goto err_free_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6222) SET_IEEE80211_DEV(hw, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6223) pci_set_drvdata(pdev, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6225) priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6226) priv->hw = hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6227) priv->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6228) priv->device_info = &mwl8k_info_tbl[id->driver_data];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6230) if (id->driver_data == MWL8764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6231) priv->is_8764 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6233) priv->sram = pci_iomap(pdev, 0, 0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6234) if (priv->sram == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6235) wiphy_err(hw->wiphy, "Cannot map device SRAM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6236) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6237) goto err_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6241) * If BAR0 is a 32 bit BAR, the register BAR will be BAR1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6242) * If BAR0 is a 64 bit BAR, the register BAR will be BAR2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6244) priv->regs = pci_iomap(pdev, 1, 0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6245) if (priv->regs == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6246) priv->regs = pci_iomap(pdev, 2, 0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6247) if (priv->regs == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6248) wiphy_err(hw->wiphy, "Cannot map device registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6249) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6250) goto err_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6255) * Choose the initial fw image depending on user input. If a second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6256) * image is available, make it the alternative image that will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6257) * loaded if the first one fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6259) init_completion(&priv->firmware_loading_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6260) di = priv->device_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6261) if (ap_mode_default && di->fw_image_ap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6262) priv->fw_pref = di->fw_image_ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6263) priv->fw_alt = di->fw_image_sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6264) } else if (!ap_mode_default && di->fw_image_sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6265) priv->fw_pref = di->fw_image_sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6266) priv->fw_alt = di->fw_image_ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6267) } else if (ap_mode_default && !di->fw_image_ap && di->fw_image_sta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6268) printk(KERN_WARNING "AP fw is unavailable. Using STA fw.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6269) priv->fw_pref = di->fw_image_sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6270) } else if (!ap_mode_default && !di->fw_image_sta && di->fw_image_ap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6271) printk(KERN_WARNING "STA fw is unavailable. Using AP fw.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6272) priv->fw_pref = di->fw_image_ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6274) rc = mwl8k_init_firmware(hw, priv->fw_pref, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6275) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6276) goto err_stop_firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6278) priv->hw_restart_in_progress = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6280) priv->running_bsses = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6282) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6284) err_stop_firmware:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6285) mwl8k_hw_reset(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6287) err_iounmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6288) if (priv->regs != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6289) pci_iounmap(pdev, priv->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6291) if (priv->sram != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6292) pci_iounmap(pdev, priv->sram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6294) ieee80211_free_hw(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6296) err_free_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6297) pci_release_regions(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6299) err_disable_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6300) pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6302) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6305) static void mwl8k_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6307) struct ieee80211_hw *hw = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6308) struct mwl8k_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6309) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6311) if (hw == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6312) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6313) priv = hw->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6315) wait_for_completion(&priv->firmware_loading_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6317) if (priv->fw_state == FW_STATE_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6318) mwl8k_hw_reset(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6319) goto unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6322) ieee80211_stop_queues(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6324) ieee80211_unregister_hw(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6326) /* Remove TX reclaim and RX tasklets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6327) tasklet_kill(&priv->poll_tx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6328) tasklet_kill(&priv->poll_rx_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6330) /* Stop hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6331) mwl8k_hw_reset(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6333) /* Return all skbs to mac80211 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6334) for (i = 0; i < mwl8k_tx_queues(priv); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6335) mwl8k_txq_reclaim(hw, i, INT_MAX, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6337) for (i = 0; i < mwl8k_tx_queues(priv); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6338) mwl8k_txq_deinit(hw, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6340) mwl8k_rxq_deinit(hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6342) pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6344) unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6345) pci_iounmap(pdev, priv->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6346) pci_iounmap(pdev, priv->sram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6347) ieee80211_free_hw(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6348) pci_release_regions(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6349) pci_disable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6352) static struct pci_driver mwl8k_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6353) .name = MWL8K_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6354) .id_table = mwl8k_pci_id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6355) .probe = mwl8k_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6356) .remove = mwl8k_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6357) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6359) module_pci_driver(mwl8k_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6361) MODULE_DESCRIPTION(MWL8K_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6362) MODULE_VERSION(MWL8K_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6363) MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6364) MODULE_LICENSE("GPL");