diff options
Diffstat (limited to 'drivers/net/wireless/ath/wcn36xx')
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/dxe.c | 57 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/hal.h | 222 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/main.c | 288 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/pmc.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/smd.c | 757 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/smd.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/txrx.c | 279 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 18 |
8 files changed, 1264 insertions, 376 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index bab30f7a443c..63079231e48e 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -334,6 +334,7 @@ void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) spin_lock_irqsave(&wcn->dxe_lock, flags); skb = wcn->tx_ack_skb; wcn->tx_ack_skb = NULL; + del_timer(&wcn->tx_ack_timer); spin_unlock_irqrestore(&wcn->dxe_lock, flags); if (!skb) { @@ -345,6 +346,8 @@ void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) if (status == 1) info->flags |= IEEE80211_TX_STAT_ACK; + else + info->flags &= ~IEEE80211_TX_STAT_ACK; wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status); @@ -352,6 +355,32 @@ void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) ieee80211_wake_queues(wcn->hw); } +static void wcn36xx_dxe_tx_timer(struct timer_list *t) +{ + struct wcn36xx *wcn = from_timer(wcn, t, tx_ack_timer); + struct ieee80211_tx_info *info; + unsigned long flags; + struct sk_buff *skb; + + /* TX Timeout */ + wcn36xx_dbg(WCN36XX_DBG_DXE, "TX timeout\n"); + + spin_lock_irqsave(&wcn->dxe_lock, flags); + skb = wcn->tx_ack_skb; + wcn->tx_ack_skb = NULL; + spin_unlock_irqrestore(&wcn->dxe_lock, flags); + + if (!skb) + return; + + info = IEEE80211_SKB_CB(skb); + info->flags &= ~IEEE80211_TX_STAT_ACK; + info->flags &= ~IEEE80211_TX_STAT_NOACK_TRANSMITTED; + + ieee80211_tx_status_irqsafe(wcn->hw, skb); + ieee80211_wake_queues(wcn->hw); +} + static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) { struct wcn36xx_dxe_ctl *ctl; @@ -397,6 +426,7 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) { struct wcn36xx *wcn = (struct wcn36xx *)dev; int int_src, int_reason; + bool transmitted = false; wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); @@ -434,8 +464,10 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) int_reason); if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | - WCN36XX_CH_STAT_INT_ED_MASK)) + WCN36XX_CH_STAT_INT_ED_MASK)) { reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); + transmitted = true; + } } if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) { @@ -473,9 +505,27 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) int_reason); if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | - WCN36XX_CH_STAT_INT_ED_MASK)) + WCN36XX_CH_STAT_INT_ED_MASK)) { reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); + transmitted = true; + } + } + + spin_lock(&wcn->dxe_lock); + if (wcn->tx_ack_skb && transmitted) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(wcn->tx_ack_skb); + + /* TX complete, no need to wait for 802.11 ack indication */ + if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS && + info->flags & IEEE80211_TX_CTL_NO_ACK) { + info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; + del_timer(&wcn->tx_ack_timer); + ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb); + wcn->tx_ack_skb = NULL; + ieee80211_wake_queues(wcn->hw); + } } + spin_unlock(&wcn->dxe_lock); return IRQ_HANDLED; } @@ -916,6 +966,8 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) if (ret < 0) goto out_err_irq; + timer_setup(&wcn->tx_ack_timer, wcn36xx_dxe_tx_timer, 0); + return 0; out_err_irq: @@ -934,6 +986,7 @@ void wcn36xx_dxe_deinit(struct wcn36xx *wcn) { free_irq(wcn->tx_irq, wcn); free_irq(wcn->rx_irq, wcn); + del_timer(&wcn->tx_ack_timer); if (wcn->tx_ack_skb) { ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb); diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index aab5a58616fc..65ef893f2736 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -726,7 +726,137 @@ enum pe_stats_mask { #define WCN36XX_HAL_CFG_AP_LINK_MONITOR_TIMEOUT 102 #define WCN36XX_HAL_CFG_BTC_DWELL_TIME_MULTIPLIER 103 #define WCN36XX_HAL_CFG_ENABLE_TDLS_OXYGEN_MODE 104 -#define WCN36XX_HAL_CFG_MAX_PARAMS 105 +#define WCN36XX_HAL_CFG_ENABLE_NAT_KEEP_ALIVE_FILTER 105 +#define WCN36XX_HAL_CFG_ENABLE_SAP_OBSS_PROT 106 +#define WCN36XX_HAL_CFG_PSPOLL_DATA_RECEP_TIMEOUT 107 +#define WCN36XX_HAL_CFG_TDLS_PUAPSD_BUFFER_STA_CAPABLE 108 +#define WCN36XX_HAL_CFG_TDLS_PUAPSD_MASK 109 +#define WCN36XX_HAL_CFG_TDLS_PUAPSD_INACTIVITY_TIME 110 +#define WCN36XX_HAL_CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD 111 +#define WCN36XX_HAL_CFG_ANTENNA_DIVERSITY 112 +#define WCN36XX_HAL_CFG_ATH_DISABLE 113 +#define WCN36XX_HAL_CFG_FLEXCONNECT_POWER_FACTOR 114 +#define WCN36XX_HAL_CFG_ENABLE_ADAPTIVE_RX_DRAIN 115 +#define WCN36XX_HAL_CFG_TDLS_OFF_CHANNEL_CAPABLE 116 +#define WCN36XX_HAL_CFG_MWS_COEX_V1_WAN_FREQ 117 +#define WCN36XX_HAL_CFG_MWS_COEX_V1_WLAN_FREQ 118 +#define WCN36XX_HAL_CFG_MWS_COEX_V1_CONFIG 119 +#define WCN36XX_HAL_CFG_MWS_COEX_V1_CONFIG2 120 +#define WCN36XX_HAL_CFG_MWS_COEX_V2_WAN_FREQ 121 +#define WCN36XX_HAL_CFG_MWS_COEX_V2_WLAN_FREQ 122 +#define WCN36XX_HAL_CFG_MWS_COEX_V2_CONFIG 123 +#define WCN36XX_HAL_CFG_MWS_COEX_V2_CONFIG2 124 +#define WCN36XX_HAL_CFG_MWS_COEX_V3_WAN_FREQ 125 +#define WCN36XX_HAL_CFG_MWS_COEX_V3_WLAN_FREQ 126 +#define WCN36XX_HAL_CFG_MWS_COEX_V3_CONFIG 127 +#define WCN36XX_HAL_CFG_MWS_COEX_V3_CONFIG2 128 +#define WCN36XX_HAL_CFG_MWS_COEX_V4_WAN_FREQ 129 +#define WCN36XX_HAL_CFG_MWS_COEX_V4_WLAN_FREQ 130 +#define WCN36XX_HAL_CFG_MWS_COEX_V4_CONFIG 131 +#define WCN36XX_HAL_CFG_MWS_COEX_V4_CONFIG2 132 +#define WCN36XX_HAL_CFG_MWS_COEX_V5_WAN_FREQ 133 +#define WCN36XX_HAL_CFG_MWS_COEX_V5_WLAN_FREQ 134 +#define WCN36XX_HAL_CFG_MWS_COEX_V5_CONFIG 135 +#define WCN36XX_HAL_CFG_MWS_COEX_V5_CONFIG2 136 +#define WCN36XX_HAL_CFG_MWS_COEX_V6_WAN_FREQ 137 +#define WCN36XX_HAL_CFG_MWS_COEX_V6_WLAN_FREQ 138 +#define WCN36XX_HAL_CFG_MWS_COEX_V6_CONFIG 139 +#define WCN36XX_HAL_CFG_MWS_COEX_V6_CONFIG2 140 +#define WCN36XX_HAL_CFG_MWS_COEX_V7_WAN_FREQ 141 +#define WCN36XX_HAL_CFG_MWS_COEX_V7_WLAN_FREQ 142 +#define WCN36XX_HAL_CFG_MWS_COEX_V7_CONFIG 143 +#define WCN36XX_HAL_CFG_MWS_COEX_V7_CONFIG2 144 +#define WCN36XX_HAL_CFG_MWS_COEX_V8_WAN_FREQ 145 +#define WCN36XX_HAL_CFG_MWS_COEX_V8_WLAN_FREQ 146 +#define WCN36XX_HAL_CFG_MWS_COEX_V8_CONFIG 147 +#define WCN36XX_HAL_CFG_MWS_COEX_V8_CONFIG2 148 +#define WCN36XX_HAL_CFG_MWS_COEX_V9_WAN_FREQ 149 +#define WCN36XX_HAL_CFG_MWS_COEX_V9_WLAN_FREQ 150 +#define WCN36XX_HAL_CFG_MWS_COEX_V9_CONFIG 151 +#define WCN36XX_HAL_CFG_MWS_COEX_V9_CONFIG2 152 +#define WCN36XX_HAL_CFG_MWS_COEX_V10_WAN_FREQ 153 +#define WCN36XX_HAL_CFG_MWS_COEX_V10_WLAN_FREQ 154 +#define WCN36XX_HAL_CFG_MWS_COEX_V10_CONFIG 155 +#define WCN36XX_HAL_CFG_MWS_COEX_V10_CONFIG2 156 +#define WCN36XX_HAL_CFG_MWS_COEX_MODEM_BACKOFF 157 +#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG1 158 +#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG2 159 +#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG3 160 +#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG4 161 +#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG5 162 +#define WCN36XX_HAL_CFG_MWS_COEX_CONFIG6 163 +#define WCN36XX_HAL_CFG_SAR_POWER_BACKOFF 164 +#define WCN36XX_HAL_CFG_GO_LINK_MONITOR_TIMEOUT 165 +#define WCN36XX_HAL_CFG_BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN 166 +#define WCN36XX_HAL_CFG_BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN 167 +#define WCN36XX_HAL_CFG_BTC_SAP_STATIC_OPP_ACTIVE_WLAN_LEN 168 +#define WCN36XX_HAL_CFG_BTC_SAP_STATIC_OPP_ACTIVE_BT_LEN 169 +#define WCN36XX_HAL_CFG_RMC_FIXED_RATE 170 +#define WCN36XX_HAL_CFG_ASD_PROBE_INTERVAL 171 +#define WCN36XX_HAL_CFG_ASD_TRIGGER_THRESHOLD 172 +#define WCN36XX_HAL_CFG_ASD_RTT_RSSI_HYST_THRESHOLD 173 +#define WCN36XX_HAL_CFG_BTC_CTS2S_ON_STA_DURING_SCO 174 +#define WCN36XX_HAL_CFG_SHORT_PREAMBLE 175 +#define WCN36XX_HAL_CFG_SHORT_SLOT_TIME 176 +#define WCN36XX_HAL_CFG_DELAYED_BA 177 +#define WCN36XX_HAL_CFG_IMMEDIATE_BA 178 +#define WCN36XX_HAL_CFG_DOT11_MODE 179 +#define WCN36XX_HAL_CFG_HT_CAPS 180 +#define WCN36XX_HAL_CFG_AMPDU_PARAMS 181 +#define WCN36XX_HAL_CFG_TX_BF_INFO 182 +#define WCN36XX_HAL_CFG_ASC_CAP_INFO 183 +#define WCN36XX_HAL_CFG_EXT_HT_CAPS 184 +#define WCN36XX_HAL_CFG_QOS_ENABLED 185 +#define WCN36XX_HAL_CFG_WME_ENABLED 186 +#define WCN36XX_HAL_CFG_WSM_ENABLED 187 +#define WCN36XX_HAL_CFG_WMM_ENABLED 188 +#define WCN36XX_HAL_CFG_UAPSD_PER_AC_BITMASK 189 +#define WCN36XX_HAL_CFG_MCS_RATES 190 +#define WCN36XX_HAL_CFG_VHT_CAPS 191 +#define WCN36XX_HAL_CFG_VHT_RX_SUPP_MCS 192 +#define WCN36XX_HAL_CFG_VHT_TX_SUPP_MCS 193 +#define WCN36XX_HAL_CFG_RA_FILTER_ENABLE 194 +#define WCN36XX_HAL_CFG_RA_RATE_LIMIT_INTERVAL 195 +#define WCN36XX_HAL_CFG_BTC_FATAL_HID_NSNIFF_BLK 196 +#define WCN36XX_HAL_CFG_BTC_CRITICAL_HID_NSNIFF_BLK 197 +#define WCN36XX_HAL_CFG_BTC_DYN_A2DP_TX_QUEUE_THOLD 198 +#define WCN36XX_HAL_CFG_BTC_DYN_OPP_TX_QUEUE_THOLD 199 +#define WCN36XX_HAL_CFG_LINK_FAIL_TIMEOUT 200 +#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_SP 201 +#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_RX_CNT 202 +#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_TX_CNT 203 +#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_RX_CNT_MEAS_WINDOW 204 +#define WCN36XX_HAL_CFG_MAX_UAPSD_CONSEC_TX_CNT_MEAS_WINDOW 205 +#define WCN36XX_HAL_CFG_MAX_PSPOLL_IN_WMM_UAPSD_PS_MODE 206 +#define WCN36XX_HAL_CFG_MAX_UAPSD_INACTIVITY_INTERVALS 207 +#define WCN36XX_HAL_CFG_ENABLE_DYNAMIC_WMMPS 208 +#define WCN36XX_HAL_CFG_BURST_MODE_BE_TXOP_VALUE 209 +#define WCN36XX_HAL_CFG_ENABLE_DYNAMIC_RA_START_RATE 210 +#define WCN36XX_HAL_CFG_BTC_FAST_WLAN_CONN_PREF 211 +#define WCN36XX_HAL_CFG_ENABLE_RTSCTS_HTVHT 212 +#define WCN36XX_HAL_CFG_BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN 213 +#define WCN36XX_HAL_CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN 214 +#define WCN36XX_HAL_CFG_LINK_FAIL_TX_CNT 215 +#define WCN36XX_HAL_CFG_TOGGLE_ARP_BDRATES 216 +#define WCN36XX_HAL_CFG_OPTIMIZE_CA_EVENT 217 +#define WCN36XX_HAL_CFG_EXT_SCAN_CONC_MODE 218 +#define WCN36XX_HAL_CFG_BAR_WAKEUP_HOST_DISABLE 219 +#define WCN36XX_HAL_CFG_SAR_BOFFSET_CORRECTION_ENABLE 220 +#define WCN36XX_HAL_CFG_UNITS_OF_BCN_WAIT_TIME 221 +#define WCN36XX_HAL_CFG_CONS_BCNMISS_COUNT 222 +#define WCN36XX_HAL_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL 223 +#define WCN36XX_HAL_CFG_DISABLE_SCAN_DURING_SCO 224 +#define WCN36XX_HAL_CFG_TRIGGER_NULLFRAME_BEFORE_HB 225 +#define WCN36XX_HAL_CFG_ENABLE_POWERSAVE_OFFLOAD 226 +#define WCN36XX_HAL_CFG_MAX_PARAMS 227 + +/* Specify the starting bitrate, 11B and 11A/G rates can be specified in + * multiples of 0.5 So for 5.5 mbps => 11. for MCS 0 - 7 rates, Bit 7 should + * set to 1 and Bit 0-6 represent the MCS index. so for MCS2 => 130. + * Any invalid non-zero value or unsupported rate will set the start rate + * to 6 mbps. + */ +#define WCN36XX_HAL_CFG_ENABLE_DYNAMIC_RA_START_RATE 210 /* Message definitons - All the messages below need to be packed */ @@ -1405,6 +1535,76 @@ struct wcn36xx_hal_config_sta_req_msg { struct wcn36xx_hal_config_sta_params sta_params; } __packed; +struct wcn36xx_hal_supported_rates_v1 { + /* For Self STA Entry: this represents Self Mode. + * For Peer Stations, this represents the mode of the peer. + * On Station: + * + * --this mode is updated when PE adds the Self Entry. + * + * -- OR when PE sends 'ADD_BSS' message and station context in BSS + * is used to indicate the mode of the AP. + * + * ON AP: + * + * -- this mode is updated when PE sends 'ADD_BSS' and Sta entry + * for that BSS is used to indicate the self mode of the AP. + * + * -- OR when a station is associated, PE sends 'ADD_STA' message + * with this mode updated. + */ + + enum sta_rate_mode op_rate_mode; + + /* 11b, 11a and aniLegacyRates are IE rates which gives rate in + * unit of 500Kbps + */ + u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES]; + u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES]; + u16 legacy_rates[WCN36XX_HAL_NUM_POLARIS_RATES]; + u16 reserved; + + /* Taurus only supports 26 Titan Rates(no ESF/concat Rates will be + * supported) First 26 bits are reserved for those Titan rates and + * the last 4 bits(bit28-31) for Taurus, 2(bit26-27) bits are + * reserved + * Titan and Taurus Rates + */ + u32 enhanced_rate_bitmap; + + /* 0-76 bits used, remaining reserved + * bits 0-15 and 32 should be set. + */ + u8 supported_mcs_set[WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET]; + + /* RX Highest Supported Data Rate defines the highest data + * rate that the STA is able to receive, in unites of 1Mbps. + * This value is derived from "Supported MCS Set field" inside + * the HT capability element. + */ + u16 rx_highest_data_rate; + + /* Indicates the Maximum MCS that can be received for each spatial + * stream. + */ + u16 vht_rx_mcs_map; + + /* Indicates the highest VHT data rate that the STA is able to + * receive. + */ + u16 vht_rx_highest_data_rate; + + /* Indicates the Maximum MCS that can be transmitted for each spatial + * stream. + */ + u16 vht_tx_mcs_map; + + /* Indicates the highest VHT data rate that the STA is able to + * transmit. + */ + u16 vht_tx_highest_data_rate; +} __packed; + struct wcn36xx_hal_config_sta_params_v1 { /* BSSID of STA */ u8 bssid[ETH_ALEN]; @@ -1507,12 +1707,22 @@ struct wcn36xx_hal_config_sta_params_v1 { u8 p2p; /* Reserved to align next field on a dword boundary */ - u8 reserved; + u8 ht_ldpc_enabled:1; + u8 vht_ldpc_enabled:1; + u8 vht_tx_bf_enabled:1; + u8 vht_tx_mu_beamformee_capable:1; + u8 reserved:4; /* These rates are the intersection of peer and self capabilities. */ - struct wcn36xx_hal_supported_rates supported_rates; + struct wcn36xx_hal_supported_rates_v1 supported_rates; + + u8 vht_capable; + u8 vht_tx_channel_width_set; + } __packed; +#define WCN36XX_DIFF_STA_PARAMS_V1_NOVHT 10 + struct wcn36xx_hal_config_sta_req_msg_v1 { struct wcn36xx_hal_msg_header header; struct wcn36xx_hal_config_sta_params_v1 sta_params; @@ -1933,8 +2143,14 @@ struct wcn36xx_hal_config_bss_params_v1 { * "STA context" */ struct wcn36xx_hal_config_sta_params_v1 sta; + + u8 vht_capable; + u8 vht_tx_channel_width_set; + } __packed; +#define WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT (WCN36XX_DIFF_STA_PARAMS_V1_NOVHT + 2) + struct wcn36xx_hal_config_bss_req_msg_v1 { struct wcn36xx_hal_msg_header header; struct wcn36xx_hal_config_bss_params_v1 bss_params; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 702b689c06df..706728fba72d 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -39,10 +39,10 @@ MODULE_PARM_DESC(debug_mask, "Debugging mask"); .max_power = 25, \ } -#define CHAN5G(_freq, _idx) { \ +#define CHAN5G(_freq, _idx, _phy_val) { \ .band = NL80211_BAND_5GHZ, \ .center_freq = (_freq), \ - .hw_value = (_idx), \ + .hw_value = (_phy_val) << HW_VALUE_PHY_SHIFT | HW_VALUE_CHANNEL(_idx), \ .max_power = 25, \ } @@ -67,29 +67,29 @@ static struct ieee80211_channel wcn_2ghz_channels[] = { }; static struct ieee80211_channel wcn_5ghz_channels[] = { - CHAN5G(5180, 36), - CHAN5G(5200, 40), - CHAN5G(5220, 44), - CHAN5G(5240, 48), - CHAN5G(5260, 52), - CHAN5G(5280, 56), - CHAN5G(5300, 60), - CHAN5G(5320, 64), - CHAN5G(5500, 100), - CHAN5G(5520, 104), - CHAN5G(5540, 108), - CHAN5G(5560, 112), - CHAN5G(5580, 116), - CHAN5G(5600, 120), - CHAN5G(5620, 124), - CHAN5G(5640, 128), - CHAN5G(5660, 132), - CHAN5G(5700, 140), - CHAN5G(5745, 149), - CHAN5G(5765, 153), - CHAN5G(5785, 157), - CHAN5G(5805, 161), - CHAN5G(5825, 165) + CHAN5G(5180, 36, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5200, 40, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5220, 44, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5240, 48, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5260, 52, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5280, 56, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5300, 60, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5320, 64, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5500, 100, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5520, 104, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5540, 108, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5560, 112, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5580, 116, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5600, 120, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5620, 124, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5640, 128, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5660, 132, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5700, 140, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5745, 149, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5765, 153, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5785, 157, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5805, 161, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5825, 165, 0) }; #define RATE(_bitrate, _hw_rate, _flags) { \ @@ -163,7 +163,7 @@ static struct ieee80211_supported_band wcn_band_5ghz = { .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, .mcs = { .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - .rx_highest = cpu_to_le16(72), + .rx_highest = cpu_to_le16(150), .tx_params = IEEE80211_HT_MCS_TX_DEFINED, } } @@ -354,8 +354,6 @@ static void wcn36xx_stop(struct ieee80211_hw *hw) wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); - cancel_work_sync(&wcn->scan_work); - mutex_lock(&wcn->scan_lock); if (wcn->scan_req) { struct cfg80211_scan_info scan_info = { @@ -378,12 +376,37 @@ static void wcn36xx_stop(struct ieee80211_hw *hw) kfree(wcn->hal_buf); } -static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) +static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable) { - struct wcn36xx *wcn = hw->priv; struct ieee80211_vif *vif = NULL; struct wcn36xx_vif *tmp; + list_for_each_entry(tmp, &wcn->vif_list, list) { + vif = wcn36xx_priv_to_vif(tmp); + if (enable && !wcn->sw_scan) { + if (vif->bss_conf.ps) /* ps allowed ? */ + wcn36xx_pmc_enter_bmps_state(wcn, vif); + } else { + wcn36xx_pmc_exit_bmps_state(wcn, vif); + } + } +} + +static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch) +{ + struct ieee80211_vif *vif = NULL; + struct wcn36xx_vif *tmp; + + list_for_each_entry(tmp, &wcn->vif_list, list) { + vif = wcn36xx_priv_to_vif(tmp); + wcn36xx_smd_switch_channel(wcn, vif, ch); + } +} + +static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) +{ + struct wcn36xx *wcn = hw->priv; + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); mutex_lock(&wcn->conf_mutex); @@ -392,24 +415,29 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) int ch = WCN36XX_HW_CHANNEL(wcn); wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", ch); - list_for_each_entry(tmp, &wcn->vif_list, list) { - vif = wcn36xx_priv_to_vif(tmp); - wcn36xx_smd_switch_channel(wcn, vif, ch); - } - } - if (changed & IEEE80211_CONF_CHANGE_PS) { - list_for_each_entry(tmp, &wcn->vif_list, list) { - vif = wcn36xx_priv_to_vif(tmp); - if (hw->conf.flags & IEEE80211_CONF_PS) { - if (vif->bss_conf.ps) /* ps allowed ? */ - wcn36xx_pmc_enter_bmps_state(wcn, vif); - } else { - wcn36xx_pmc_exit_bmps_state(wcn, vif); - } + if (wcn->sw_scan_opchannel == ch) { + /* If channel is the initial operating channel, we may + * want to receive/transmit regular data packets, then + * simply stop the scan session and exit PS mode. + */ + wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, + wcn->sw_scan_vif); + } else if (wcn->sw_scan) { + /* A scan is ongoing, do not change the operating + * channel, but start a scan session on the channel. + */ + wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN, + wcn->sw_scan_vif); + wcn36xx_smd_start_scan(wcn, ch); + } else { + wcn36xx_change_opchannel(wcn, ch); } } + if (changed & IEEE80211_CONF_CHANGE_PS) + wcn36xx_change_ps(wcn, hw->conf.flags & IEEE80211_CONF_PS); + mutex_unlock(&wcn->conf_mutex); return 0; @@ -582,6 +610,15 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } } } + /* FIXME: Only enable bmps support when encryption is enabled. + * For any reasons, when connected to open/no-security BSS, + * the wcn36xx controller in bmps mode does not forward + * 'wake-up' beacons despite AP sends DTIM with station AID. + * It could be due to a firmware issue or to the way driver + * configure the station. + */ + if (vif->type == NL80211_IFTYPE_STATION) + vif_priv->allow_bmps = true; break; case DISABLE_KEY: if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { @@ -614,55 +651,26 @@ out: return ret; } -static void wcn36xx_hw_scan_worker(struct work_struct *work) +static int wcn36xx_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req) { - struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work); - struct cfg80211_scan_request *req = wcn->scan_req; - u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX]; - struct cfg80211_scan_info scan_info = {}; - bool aborted = false; + struct wcn36xx *wcn = hw->priv; int i; - wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", req->n_channels); - - for (i = 0; i < req->n_channels; i++) - channels[i] = req->channels[i]->hw_value; - - wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels); - - wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); - for (i = 0; i < req->n_channels; i++) { - mutex_lock(&wcn->scan_lock); - aborted = wcn->scan_aborted; - mutex_unlock(&wcn->scan_lock); - - if (aborted) - break; - - wcn->scan_freq = req->channels[i]->center_freq; - wcn->scan_band = req->channels[i]->band; - - wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value); - msleep(30); - wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value); - - wcn->scan_freq = 0; + if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) { + /* fallback to mac80211 software scan */ + return 1; } - wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); - - scan_info.aborted = aborted; - ieee80211_scan_completed(wcn->hw, &scan_info); - mutex_lock(&wcn->scan_lock); - wcn->scan_req = NULL; - mutex_unlock(&wcn->scan_lock); -} + /* For unknown reason, the hardware offloaded scan only works with + * 2.4Ghz channels, fallback to software scan in other cases. + */ + for (i = 0; i < hw_req->req.n_channels; i++) { + if (hw_req->req.channels[i]->band != NL80211_BAND_2GHZ) + return 1; + } -static int wcn36xx_hw_scan(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_scan_request *hw_req) -{ - struct wcn36xx *wcn = hw->priv; mutex_lock(&wcn->scan_lock); if (wcn->scan_req) { mutex_unlock(&wcn->scan_lock); @@ -674,12 +682,6 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw, mutex_unlock(&wcn->scan_lock); - if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) { - /* legacy manual/sw scan */ - schedule_work(&wcn->scan_work); - return 0; - } - return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req); } @@ -696,16 +698,35 @@ static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw, /* ieee80211_scan_completed will be called on FW scan * indication */ wcn36xx_smd_stop_hw_scan(wcn); - } else { - struct cfg80211_scan_info scan_info = { - .aborted = true, - }; - - cancel_work_sync(&wcn->scan_work); - ieee80211_scan_completed(wcn->hw, &scan_info); } } +static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) +{ + struct wcn36xx *wcn = hw->priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); + + wcn->sw_scan = true; + wcn->sw_scan_vif = vif; + if (vif_priv->sta_assoc) + wcn->sw_scan_opchannel = WCN36XX_HW_CHANNEL(wcn); + else + wcn->sw_scan_opchannel = 0; +} + +static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct wcn36xx *wcn = hw->priv; + + /* ensure that any scan session is finished */ + wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, wcn->sw_scan_vif); + wcn->sw_scan = false; + wcn->sw_scan_opchannel = 0; +} + static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, enum nl80211_band band) { @@ -745,7 +766,16 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, sta->ht_cap.mcs.rx_mask, sizeof(sta->ht_cap.mcs.rx_mask)); } + + if (sta->vht_cap.vht_supported) { + sta_priv->supported_rates.op_rate_mode = STA_11ac; + sta_priv->supported_rates.vht_rx_mcs_map = + sta->vht_cap.vht_mcs.rx_mcs_map; + sta_priv->supported_rates.vht_tx_mcs_map = + sta->vht_cap.vht_mcs.tx_mcs_map; + } } + void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) { u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { @@ -772,6 +802,14 @@ void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); rates->supported_mcs_set[0] = 0xFF; } + +void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates) +{ + rates->op_rate_mode = STA_11ac; + rates->vht_rx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9; + rates->vht_tx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9; +} + static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -879,6 +917,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, vif->addr, bss_conf->aid); vif_priv->sta_assoc = false; + vif_priv->allow_bmps = false; wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr, @@ -1083,6 +1122,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, u16 tid = params->tid; u16 *ssn = ¶ms->ssn; int ret = 0; + u8 session; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", action, tid); @@ -1092,10 +1132,11 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: sta_priv->tid = tid; - wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, - get_sta_index(vif, sta_priv)); - wcn36xx_smd_add_ba(wcn); - wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); + session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, + get_sta_index(vif, sta_priv)); + wcn36xx_smd_add_ba(wcn, session); + wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid, + session); break; case IEEE80211_AMPDU_RX_STOP: wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); @@ -1149,6 +1190,8 @@ static const struct ieee80211_ops wcn36xx_ops = { .set_key = wcn36xx_set_key, .hw_scan = wcn36xx_hw_scan, .cancel_hw_scan = wcn36xx_cancel_hw_scan, + .sw_scan_start = wcn36xx_sw_scan_start, + .sw_scan_complete = wcn36xx_sw_scan_complete, .bss_info_changed = wcn36xx_bss_info_changed, .set_rts_threshold = wcn36xx_set_rts_threshold, .sta_add = wcn36xx_sta_add, @@ -1158,6 +1201,35 @@ static const struct ieee80211_ops wcn36xx_ops = { CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd) }; +static void +wcn36xx_set_ieee80211_vht_caps(struct ieee80211_sta_vht_cap *vht_cap) +{ + vht_cap->vht_supported = true; + + vht_cap->cap = (IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | + IEEE80211_VHT_CAP_SHORT_GI_80 | + IEEE80211_VHT_CAP_RXSTBC_1 | + IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | + 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT | + 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); + + vht_cap->vht_mcs.rx_mcs_map = + cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); + + vht_cap->vht_mcs.rx_highest = cpu_to_le16(433); + vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest; + + vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; +} + static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) { static const u32 cipher_suites[] = { @@ -1173,6 +1245,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) ieee80211_hw_set(wcn->hw, SIGNAL_DBM); ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL); ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS); + ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS); wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | @@ -1183,6 +1256,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) if (wcn->rf_id != RF_IRIS_WCN3620) wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz; + if (wcn->rf_id == RF_IRIS_WCN3680) + wcn36xx_set_ieee80211_vht_caps(&wcn_band_5ghz.vht_cap); + wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS; wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN; @@ -1280,6 +1356,8 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, if (iris_node) { if (of_device_is_compatible(iris_node, "qcom,wcn3620")) wcn->rf_id = RF_IRIS_WCN3620; + if (of_device_is_compatible(iris_node, "qcom,wcn3680")) + wcn->rf_id = RF_IRIS_WCN3680; of_node_put(iris_node); } @@ -1326,8 +1404,6 @@ static int wcn36xx_probe(struct platform_device *pdev) goto out_wq; } - INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker); - wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw); if (IS_ERR(wcn->smd_channel)) { wcn36xx_err("failed to open WLAN_CTRL channel\n"); diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c index 1976b80c235f..2d0780fefd47 100644 --- a/drivers/net/wireless/ath/wcn36xx/pmc.c +++ b/drivers/net/wireless/ath/wcn36xx/pmc.c @@ -23,11 +23,15 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, { int ret = 0; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - /* TODO: Make sure the TX chain clean */ + + if (!vif_priv->allow_bmps) + return -ENOTSUPP; + ret = wcn36xx_smd_enter_bmps(wcn, vif); if (!ret) { wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n"); vif_priv->pw_state = WCN36XX_BMPS; + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; } else { /* * One of the reasons why HW will not enter BMPS is because @@ -52,6 +56,7 @@ int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, } wcn36xx_smd_exit_bmps(wcn, vif); vif_priv->pw_state = WCN36XX_FULL_POWER; + vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; return 0; } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 77269ac7f352..766400f7b61c 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -45,8 +45,8 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = { WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000), WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64), WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347), - WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 6), - WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 6), + WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15), + WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15), WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000), WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5), WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10), @@ -77,6 +77,103 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = { WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000), WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10), WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0), + WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 133), /* MCS 5 */ +}; + +static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = { + WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1), + WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1), + WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0), + WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785), + WCN36XX_CFG_VAL(CAL_PERIOD, 5), + WCN36XX_CFG_VAL(CAL_CONTROL, 1), + WCN36XX_CFG_VAL(PROXIMITY, 0), + WCN36XX_CFG_VAL(NETWORK_DENSITY, 3), + WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 4096), + WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64), + WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347), + WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15), + WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15), + WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000), + WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5), + WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10), + WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15), + WCN36XX_CFG_VAL(FIXED_RATE, 0), + WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4), + WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0), + WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0), + WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5), + WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1), + WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5), + WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_24GHZ, 1), + WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5), + WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40), + WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200), + WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1), + WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1), + WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20), + WCN36XX_CFG_VAL(STATS_PERIOD, 10), + WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000), + WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0), + WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128), + WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560), + WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0), + WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1), + WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1), + WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000), + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000), + WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10), + WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0), + WCN36XX_CFG_VAL(TDLS_PUAPSD_MASK, 0), + WCN36XX_CFG_VAL(TDLS_PUAPSD_BUFFER_STA_CAPABLE, 1), + WCN36XX_CFG_VAL(TDLS_PUAPSD_INACTIVITY_TIME, 0), + WCN36XX_CFG_VAL(TDLS_PUAPSD_RX_FRAME_THRESHOLD, 10), + WCN36XX_CFG_VAL(TDLS_OFF_CHANNEL_CAPABLE, 1), + WCN36XX_CFG_VAL(ENABLE_ADAPTIVE_RX_DRAIN, 1), + WCN36XX_CFG_VAL(FLEXCONNECT_POWER_FACTOR, 0), + WCN36XX_CFG_VAL(ANTENNA_DIVERSITY, 3), + WCN36XX_CFG_VAL(ATH_DISABLE, 0), + WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN, 60000), + WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN, 90000), + WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_WLAN_LEN, 30000), + WCN36XX_CFG_VAL(BTC_SAP_STATIC_OPP_ACTIVE_BT_LEN, 30000), + WCN36XX_CFG_VAL(ASD_PROBE_INTERVAL, 50), + WCN36XX_CFG_VAL(ASD_TRIGGER_THRESHOLD, -60), + WCN36XX_CFG_VAL(ASD_RTT_RSSI_HYST_THRESHOLD, 3), + WCN36XX_CFG_VAL(BTC_CTS2S_ON_STA_DURING_SCO, 0), + WCN36XX_CFG_VAL(RA_FILTER_ENABLE, 0), + WCN36XX_CFG_VAL(RA_RATE_LIMIT_INTERVAL, 60), + WCN36XX_CFG_VAL(BTC_FATAL_HID_NSNIFF_BLK, 2), + WCN36XX_CFG_VAL(BTC_CRITICAL_HID_NSNIFF_BLK, 1), + WCN36XX_CFG_VAL(BTC_DYN_A2DP_TX_QUEUE_THOLD, 0), + WCN36XX_CFG_VAL(BTC_DYN_OPP_TX_QUEUE_THOLD, 1), + WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_SP, 10), + WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT, 50), + WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT, 50), + WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_TX_CNT_MEAS_WINDOW, 500), + WCN36XX_CFG_VAL(MAX_UAPSD_CONSEC_RX_CNT_MEAS_WINDOW, 500), + WCN36XX_CFG_VAL(MAX_PSPOLL_IN_WMM_UAPSD_PS_MODE, 0), + WCN36XX_CFG_VAL(MAX_UAPSD_INACTIVITY_INTERVALS, 10), + WCN36XX_CFG_VAL(ENABLE_DYNAMIC_WMMPS, 1), + WCN36XX_CFG_VAL(BURST_MODE_BE_TXOP_VALUE, 0), + WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 136), + WCN36XX_CFG_VAL(BTC_FAST_WLAN_CONN_PREF, 1), + WCN36XX_CFG_VAL(ENABLE_RTSCTS_HTVHT, 0), + WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN, 30000), + WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_BT_LEN, 120000), + WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 200), + WCN36XX_CFG_VAL(TOGGLE_ARP_BDRATES, 0), + WCN36XX_CFG_VAL(OPTIMIZE_CA_EVENT, 0), + WCN36XX_CFG_VAL(EXT_SCAN_CONC_MODE, 0), + WCN36XX_CFG_VAL(BAR_WAKEUP_HOST_DISABLE, 0), + WCN36XX_CFG_VAL(SAR_BOFFSET_CORRECTION_ENABLE, 0), + WCN36XX_CFG_VAL(BTC_DISABLE_WLAN_LINK_CRITICAL, 5), + WCN36XX_CFG_VAL(DISABLE_SCAN_DURING_SCO, 2), + WCN36XX_CFG_VAL(CONS_BCNMISS_COUNT, 0), + WCN36XX_CFG_VAL(UNITS_OF_BCN_WAIT_TIME, 0), + WCN36XX_CFG_VAL(TRIGGER_NULLFRAME_BEFORE_HB, 0), + WCN36XX_CFG_VAL(ENABLE_POWERSAVE_OFFLOAD, 0), }; static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value) @@ -121,6 +218,7 @@ static inline u8 is_cap_supported(unsigned long caps, unsigned long flag) { return caps & flag ? 1 : 0; } + static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct wcn36xx_hal_config_bss_params *bss_params) @@ -145,6 +243,15 @@ static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif, } } +static void +wcn36xx_smd_set_bss_vht_params(struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct wcn36xx_hal_config_bss_params_v1 *bss) +{ + if (sta && sta->vht_cap.vht_supported) + bss->vht_capable = 1; +} + static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta, struct wcn36xx_hal_config_sta_params *sta_params) { @@ -173,6 +280,37 @@ static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta, } } +static void wcn36xx_smd_set_sta_vht_params(struct wcn36xx *wcn, + struct ieee80211_sta *sta, + struct wcn36xx_hal_config_sta_params_v1 *sta_params) +{ + if (sta->vht_cap.vht_supported) { + unsigned long caps = sta->vht_cap.cap; + + sta_params->vht_capable = sta->vht_cap.vht_supported; + sta_params->vht_ldpc_enabled = + is_cap_supported(caps, IEEE80211_VHT_CAP_RXLDPC); + if (get_feat_caps(wcn->fw_feat_caps, MU_MIMO)) { + sta_params->vht_tx_mu_beamformee_capable = + is_cap_supported(caps, IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE); + if (sta_params->vht_tx_mu_beamformee_capable) + sta_params->vht_tx_bf_enabled = 1; + } else { + sta_params->vht_tx_mu_beamformee_capable = 0; + } + sta_params->vht_tx_channel_width_set = 0; + } +} + +static void wcn36xx_smd_set_sta_ht_ldpc_params(struct ieee80211_sta *sta, + struct wcn36xx_hal_config_sta_params_v1 *sta_params) +{ + if (sta->ht_cap.ht_supported) { + sta_params->ht_ldpc_enabled = + is_cap_supported(sta->ht_cap.cap, IEEE80211_HT_CAP_LDPC_CODING); + } +} + static void wcn36xx_smd_set_sta_default_ht_params( struct wcn36xx_hal_config_sta_params *sta_params) { @@ -189,6 +327,31 @@ static void wcn36xx_smd_set_sta_default_ht_params( sta_params->dsss_cck_mode_40mhz = 1; } +static void wcn36xx_smd_set_sta_default_vht_params(struct wcn36xx *wcn, + struct wcn36xx_hal_config_sta_params_v1 *sta_params) +{ + if (wcn->rf_id == RF_IRIS_WCN3680) { + sta_params->vht_capable = 1; + sta_params->vht_tx_mu_beamformee_capable = 1; + } else { + sta_params->vht_capable = 0; + sta_params->vht_tx_mu_beamformee_capable = 0; + } + + sta_params->vht_ldpc_enabled = 0; + sta_params->vht_tx_channel_width_set = 0; + sta_params->vht_tx_bf_enabled = 0; +} + +static void wcn36xx_smd_set_sta_default_ht_ldpc_params(struct wcn36xx *wcn, + struct wcn36xx_hal_config_sta_params_v1 *sta_params) +{ + if (wcn->rf_id == RF_IRIS_WCN3680) + sta_params->ht_ldpc_enabled = 1; + else + sta_params->ht_ldpc_enabled = 0; +} + static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -241,9 +404,10 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, sta_params->aid = sta_priv->aid; wcn36xx_smd_set_sta_ht_params(sta, sta_params); memcpy(&sta_params->supported_rates, &sta_priv->supported_rates, - sizeof(sta_priv->supported_rates)); + sizeof(struct wcn36xx_hal_supported_rates)); } else { - wcn36xx_set_default_rates(&sta_params->supported_rates); + wcn36xx_set_default_rates((struct wcn36xx_hal_supported_rates *) + &sta_params->supported_rates); wcn36xx_smd_set_sta_default_ht_params(sta_params); } } @@ -290,14 +454,20 @@ static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr, hdr->len = msg_size + sizeof(*hdr); } -#define INIT_HAL_MSG(msg_body, type) \ +#define __INIT_HAL_MSG(msg_body, type, version) \ do { \ memset(&msg_body, 0, sizeof(msg_body)); \ msg_body.header.msg_type = type; \ - msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ + msg_body.header.msg_version = version; \ msg_body.header.len = sizeof(msg_body); \ } while (0) \ +#define INIT_HAL_MSG(msg_body, type) \ + __INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION0) + +#define INIT_HAL_MSG_V1(msg_body, type) \ + __INIT_HAL_MSG(msg_body, type, WCN36XX_HAL_MSG_VERSION1) + #define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \ do { \ memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \ @@ -449,6 +619,8 @@ int wcn36xx_smd_start(struct wcn36xx *wcn) int ret; int i; size_t len; + int cfg_elements; + static struct wcn36xx_cfg_val *cfg_vals; mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ); @@ -461,9 +633,17 @@ int wcn36xx_smd_start(struct wcn36xx *wcn) body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf; len = body->header.len; - for (i = 0; i < ARRAY_SIZE(wcn36xx_cfg_vals); i++) { - ret = put_cfg_tlv_u32(wcn, &len, wcn36xx_cfg_vals[i].cfg_id, - wcn36xx_cfg_vals[i].value); + if (wcn->rf_id == RF_IRIS_WCN3680) { + cfg_vals = wcn3680_cfg_vals; + cfg_elements = ARRAY_SIZE(wcn3680_cfg_vals); + } else { + cfg_vals = wcn36xx_cfg_vals; + cfg_elements = ARRAY_SIZE(wcn36xx_cfg_vals); + } + + for (i = 0; i < cfg_elements; i++) { + ret = put_cfg_tlv_u32(wcn, &len, cfg_vals[i].cfg_id, + cfg_vals[i].value); if (ret) goto out; } @@ -517,8 +697,10 @@ out: return ret; } -int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode) +int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode, + struct ieee80211_vif *vif) { + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_hal_init_scan_req_msg msg_body; int ret; @@ -526,6 +708,13 @@ int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode) INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ); msg_body.mode = mode; + if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) { + /* Notify BSSID with null DATA packet */ + msg_body.frame_type = 2; + msg_body.notify = 1; + msg_body.scan_entry.bss_index[0] = vif_priv->bss_index; + msg_body.scan_entry.active_bss_count = 1; + } PREPARE_HAL_BUF(wcn->hal_buf, msg_body); @@ -607,8 +796,10 @@ out: } int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, - enum wcn36xx_hal_sys_mode mode) + enum wcn36xx_hal_sys_mode mode, + struct ieee80211_vif *vif) { + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); struct wcn36xx_hal_finish_scan_req_msg msg_body; int ret; @@ -616,6 +807,14 @@ int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ); msg_body.mode = mode; + msg_body.oper_channel = WCN36XX_HW_CHANNEL(wcn); + if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX) { + /* Notify BSSID with null data packet */ + msg_body.notify = 1; + msg_body.frame_type = 2; + msg_body.scan_entry.bss_index[0] = vif_priv->bss_index; + msg_body.scan_entry.active_bss_count = 1; + } PREPARE_HAL_BUF(wcn->hal_buf, msg_body); @@ -674,8 +873,10 @@ int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif, msg_body->num_channel = min_t(u8, req->n_channels, sizeof(msg_body->channels)); - for (i = 0; i < msg_body->num_channel; i++) - msg_body->channels[i] = req->channels[i]->hw_value; + for (i = 0; i < msg_body->num_channel; i++) { + msg_body->channels[i] = + HW_VALUE_CHANNEL(req->channels[i]->hw_value); + } msg_body->header.len -= WCN36XX_MAX_SCAN_IE_LEN; @@ -1163,6 +1364,31 @@ static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn, v1->p2p = orig->p2p; } +static void +wcn36xx_smd_set_sta_params_v1(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct wcn36xx_hal_config_sta_params_v1 *sta_par) +{ + struct wcn36xx_sta *sta_priv = NULL; + struct wcn36xx_hal_config_sta_params sta_par_v0; + + wcn36xx_smd_set_sta_params(wcn, vif, sta, &sta_par_v0); + wcn36xx_smd_convert_sta_to_v1(wcn, &sta_par_v0, sta_par); + + if (sta) { + sta_priv = wcn36xx_sta_to_priv(sta); + wcn36xx_smd_set_sta_vht_params(wcn, sta, sta_par); + wcn36xx_smd_set_sta_ht_ldpc_params(sta, sta_par); + memcpy(&sta_par->supported_rates, &sta_priv->supported_rates, + sizeof(sta_par->supported_rates)); + } else { + wcn36xx_set_default_rates_v1(&sta_par->supported_rates); + wcn36xx_smd_set_sta_default_vht_params(wcn, sta_par); + wcn36xx_smd_set_sta_default_ht_ldpc_params(wcn, sta_par); + } +} + static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, struct ieee80211_sta *sta, void *buf, @@ -1197,53 +1423,69 @@ static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, } static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn, - const struct wcn36xx_hal_config_sta_req_msg *orig) + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct wcn36xx_hal_config_sta_req_msg_v1 msg_body; - struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params; + struct wcn36xx_hal_config_sta_params_v1 *sta_params; - INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); + if (wcn->rf_id == RF_IRIS_WCN3680) { + INIT_HAL_MSG_V1(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); + } else { + INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); + msg_body.header.len -= WCN36XX_DIFF_STA_PARAMS_V1_NOVHT; + } - wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params, - &msg_body.sta_params); + sta_params = &msg_body.sta_params; + + wcn36xx_smd_set_sta_params_v1(wcn, vif, sta, sta_params); PREPARE_HAL_BUF(wcn->hal_buf, msg_body); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", - sta->action, sta->sta_index, sta->bssid_index, - sta->bssid, sta->type, sta->mac, sta->aid); + sta_params->action, sta_params->sta_index, sta_params->bssid_index, + sta_params->bssid, sta_params->type, sta_params->mac, sta_params->aid); return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); } -int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static int wcn36xx_smd_config_sta_v0(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct wcn36xx_hal_config_sta_req_msg msg; struct wcn36xx_hal_config_sta_params *sta_params; - int ret; - mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ); sta_params = &msg.sta_params; wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); - if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { - ret = wcn36xx_smd_config_sta_v1(wcn, &msg); - } else { - PREPARE_HAL_BUF(wcn->hal_buf, msg); + PREPARE_HAL_BUF(wcn->hal_buf, msg); - wcn36xx_dbg(WCN36XX_DBG_HAL, - "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", - sta_params->action, sta_params->sta_index, - sta_params->bssid_index, sta_params->bssid, - sta_params->type, sta_params->mac, sta_params->aid); + wcn36xx_dbg(WCN36XX_DBG_HAL, + "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", + sta_params->action, sta_params->sta_index, + sta_params->bssid_index, sta_params->bssid, + sta_params->type, sta_params->mac, sta_params->aid); + + return wcn36xx_smd_send_and_wait(wcn, msg.header.len); +} + +int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + int ret; + + mutex_lock(&wcn->hal_mutex); + + if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) + ret = wcn36xx_smd_config_sta_v1(wcn, vif, sta); + else + ret = wcn36xx_smd_config_sta_v0(wcn, vif, sta); - ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); - } if (ret) { wcn36xx_err("Sending hal_config_sta failed\n"); goto out; @@ -1261,189 +1503,14 @@ out: return ret; } -static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, - const struct wcn36xx_hal_config_bss_req_msg *orig) -{ - struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body; - struct wcn36xx_hal_config_bss_params_v1 *bss; - struct wcn36xx_hal_config_sta_params_v1 *sta; - int ret; - - msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL); - if (!msg_body) - return -ENOMEM; - - INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ); - - bss = &msg_body->bss_params; - sta = &bss->sta; - - /* convert orig to v1 */ - memcpy(&msg_body->bss_params.bssid, - &orig->bss_params.bssid, ETH_ALEN); - memcpy(&msg_body->bss_params.self_mac_addr, - &orig->bss_params.self_mac_addr, ETH_ALEN); - - msg_body->bss_params.bss_type = orig->bss_params.bss_type; - msg_body->bss_params.oper_mode = orig->bss_params.oper_mode; - msg_body->bss_params.nw_type = orig->bss_params.nw_type; - - msg_body->bss_params.short_slot_time_supported = - orig->bss_params.short_slot_time_supported; - msg_body->bss_params.lla_coexist = orig->bss_params.lla_coexist; - msg_body->bss_params.llb_coexist = orig->bss_params.llb_coexist; - msg_body->bss_params.llg_coexist = orig->bss_params.llg_coexist; - msg_body->bss_params.ht20_coexist = orig->bss_params.ht20_coexist; - msg_body->bss_params.lln_non_gf_coexist = - orig->bss_params.lln_non_gf_coexist; - - msg_body->bss_params.lsig_tx_op_protection_full_support = - orig->bss_params.lsig_tx_op_protection_full_support; - msg_body->bss_params.rifs_mode = orig->bss_params.rifs_mode; - msg_body->bss_params.beacon_interval = orig->bss_params.beacon_interval; - msg_body->bss_params.dtim_period = orig->bss_params.dtim_period; - msg_body->bss_params.tx_channel_width_set = - orig->bss_params.tx_channel_width_set; - msg_body->bss_params.oper_channel = orig->bss_params.oper_channel; - msg_body->bss_params.ext_channel = orig->bss_params.ext_channel; - - msg_body->bss_params.reserved = orig->bss_params.reserved; - - memcpy(&msg_body->bss_params.ssid, - &orig->bss_params.ssid, - sizeof(orig->bss_params.ssid)); - - msg_body->bss_params.action = orig->bss_params.action; - msg_body->bss_params.rateset = orig->bss_params.rateset; - msg_body->bss_params.ht = orig->bss_params.ht; - msg_body->bss_params.obss_prot_enabled = - orig->bss_params.obss_prot_enabled; - msg_body->bss_params.rmf = orig->bss_params.rmf; - msg_body->bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode; - msg_body->bss_params.dual_cts_protection = - orig->bss_params.dual_cts_protection; - - msg_body->bss_params.max_probe_resp_retry_limit = - orig->bss_params.max_probe_resp_retry_limit; - msg_body->bss_params.hidden_ssid = orig->bss_params.hidden_ssid; - msg_body->bss_params.proxy_probe_resp = - orig->bss_params.proxy_probe_resp; - msg_body->bss_params.edca_params_valid = - orig->bss_params.edca_params_valid; - - memcpy(&msg_body->bss_params.acbe, - &orig->bss_params.acbe, - sizeof(orig->bss_params.acbe)); - memcpy(&msg_body->bss_params.acbk, - &orig->bss_params.acbk, - sizeof(orig->bss_params.acbk)); - memcpy(&msg_body->bss_params.acvi, - &orig->bss_params.acvi, - sizeof(orig->bss_params.acvi)); - memcpy(&msg_body->bss_params.acvo, - &orig->bss_params.acvo, - sizeof(orig->bss_params.acvo)); - - msg_body->bss_params.ext_set_sta_key_param_valid = - orig->bss_params.ext_set_sta_key_param_valid; - - memcpy(&msg_body->bss_params.ext_set_sta_key_param, - &orig->bss_params.ext_set_sta_key_param, - sizeof(orig->bss_params.acvo)); - - msg_body->bss_params.wcn36xx_hal_persona = - orig->bss_params.wcn36xx_hal_persona; - msg_body->bss_params.spectrum_mgt_enable = - orig->bss_params.spectrum_mgt_enable; - msg_body->bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power; - msg_body->bss_params.max_tx_power = orig->bss_params.max_tx_power; - - wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, - &msg_body->bss_params.sta); - - PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body)); - - wcn36xx_dbg(WCN36XX_DBG_HAL, - "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", - bss->bssid, bss->self_mac_addr, bss->bss_type, - bss->oper_mode, bss->nw_type); - - wcn36xx_dbg(WCN36XX_DBG_HAL, - "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", - sta->bssid, sta->action, sta->sta_index, - sta->bssid_index, sta->aid, sta->type, sta->mac); - - ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len); - kfree(msg_body); - - return ret; -} - - -static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - void *buf, - size_t len) -{ - struct wcn36xx_hal_config_bss_rsp_msg *rsp; - struct wcn36xx_hal_config_bss_rsp_params *params; - struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - - if (len < sizeof(*rsp)) - return -EINVAL; - - rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf; - params = &rsp->bss_rsp_params; - - if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { - wcn36xx_warn("hal config bss response failure: %d\n", - params->status); - return -EIO; - } - - wcn36xx_dbg(WCN36XX_DBG_HAL, - "hal config bss rsp status %d bss_idx %d dpu_desc_index %d" - " sta_idx %d self_idx %d bcast_idx %d mac %pM" - " power %d ucast_dpu_signature %d\n", - params->status, params->bss_index, params->dpu_desc_index, - params->bss_sta_index, params->bss_self_sta_index, - params->bss_bcast_sta_idx, params->mac, - params->tx_mgmt_power, params->ucast_dpu_signature); - - vif_priv->bss_index = params->bss_index; - - if (sta) { - struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); - sta_priv->bss_sta_index = params->bss_sta_index; - sta_priv->bss_dpu_desc_index = params->dpu_desc_index; - } - - vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature; - - return 0; -} - -int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, const u8 *bssid, - bool update) +static void wcn36xx_smd_set_bss_params(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + const u8 *bssid, + bool update, + struct wcn36xx_hal_config_bss_params *bss) { - struct wcn36xx_hal_config_bss_req_msg *msg; - struct wcn36xx_hal_config_bss_params *bss; - struct wcn36xx_hal_config_sta_params *sta_params; struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); - int ret; - - mutex_lock(&wcn->hal_mutex); - msg = kzalloc(sizeof(*msg), GFP_KERNEL); - if (!msg) { - ret = -ENOMEM; - goto out; - } - INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ); - - bss = &msg->bss_params; - sta_params = &bss->sta; WARN_ON(is_zero_ether_addr(bssid)); @@ -1498,7 +1565,6 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE; bss->reserved = 0; - wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); /* wcn->ssid is only valid in AP and IBSS mode */ bss->ssid.length = vif_priv->ssid.length; @@ -1523,6 +1589,154 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, bss->action = update; vif_priv->bss_type = bss->bss_type; +} + +static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta_80211, + const u8 *bssid, + bool update) +{ + struct wcn36xx_hal_config_bss_req_msg_v1 *msg_body; + struct wcn36xx_hal_config_bss_params_v1 *bss; + struct wcn36xx_hal_config_bss_params bss_v0; + struct wcn36xx_hal_config_sta_params_v1 *sta; + struct cfg80211_chan_def *chandef; + int ret; + + msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL); + if (!msg_body) + return -ENOMEM; + + if (wcn->rf_id == RF_IRIS_WCN3680) { + INIT_HAL_MSG_V1((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ); + } else { + INIT_HAL_MSG((*msg_body), WCN36XX_HAL_CONFIG_BSS_REQ); + msg_body->header.len -= WCN36XX_DIFF_BSS_PARAMS_V1_NOVHT; + } + + bss = &msg_body->bss_params; + sta = &bss->sta; + + memset(&bss_v0, 0x00, sizeof(bss_v0)); + wcn36xx_smd_set_bss_params(wcn, vif, sta_80211, bssid, update, &bss_v0); + wcn36xx_smd_set_sta_params_v1(wcn, vif, sta_80211, sta); + + /* convert orig to v1 */ + memcpy(bss->bssid, &bss_v0.bssid, ETH_ALEN); + memcpy(bss->self_mac_addr, &bss_v0.self_mac_addr, ETH_ALEN); + + bss->bss_type = bss_v0.bss_type; + bss->oper_mode = bss_v0.oper_mode; + bss->nw_type = bss_v0.nw_type; + + bss->short_slot_time_supported = + bss_v0.short_slot_time_supported; + bss->lla_coexist = bss_v0.lla_coexist; + bss->llb_coexist = bss_v0.llb_coexist; + bss->llg_coexist = bss_v0.llg_coexist; + bss->ht20_coexist = bss_v0.ht20_coexist; + bss->lln_non_gf_coexist = bss_v0.lln_non_gf_coexist; + + bss->lsig_tx_op_protection_full_support = + bss_v0.lsig_tx_op_protection_full_support; + bss->rifs_mode = bss_v0.rifs_mode; + bss->beacon_interval = bss_v0.beacon_interval; + bss->dtim_period = bss_v0.dtim_period; + bss->tx_channel_width_set = bss_v0.tx_channel_width_set; + bss->oper_channel = bss_v0.oper_channel; + + if (wcn->hw->conf.chandef.width == NL80211_CHAN_WIDTH_80) { + chandef = &wcn->hw->conf.chandef; + bss->ext_channel = HW_VALUE_PHY(chandef->chan->hw_value); + } else { + bss->ext_channel = bss_v0.ext_channel; + } + + bss->reserved = bss_v0.reserved; + + memcpy(&bss->ssid, &bss_v0.ssid, + sizeof(bss_v0.ssid)); + + bss->action = bss_v0.action; + bss->rateset = bss_v0.rateset; + bss->ht = bss_v0.ht; + bss->obss_prot_enabled = bss_v0.obss_prot_enabled; + bss->rmf = bss_v0.rmf; + bss->ht_oper_mode = bss_v0.ht_oper_mode; + bss->dual_cts_protection = bss_v0.dual_cts_protection; + + bss->max_probe_resp_retry_limit = + bss_v0.max_probe_resp_retry_limit; + bss->hidden_ssid = bss_v0.hidden_ssid; + bss->proxy_probe_resp = bss_v0.proxy_probe_resp; + bss->edca_params_valid = bss_v0.edca_params_valid; + + memcpy(&bss->acbe, &bss_v0.acbe, + sizeof(bss_v0.acbe)); + memcpy(&bss->acbk, &bss_v0.acbk, + sizeof(bss_v0.acbk)); + memcpy(&bss->acvi, &bss_v0.acvi, + sizeof(bss_v0.acvi)); + memcpy(&bss->acvo, &bss_v0.acvo, + sizeof(bss_v0.acvo)); + + bss->ext_set_sta_key_param_valid = + bss_v0.ext_set_sta_key_param_valid; + + memcpy(&bss->ext_set_sta_key_param, + &bss_v0.ext_set_sta_key_param, + sizeof(bss_v0.acvo)); + + bss->wcn36xx_hal_persona = bss_v0.wcn36xx_hal_persona; + bss->spectrum_mgt_enable = bss_v0.spectrum_mgt_enable; + bss->tx_mgmt_power = bss_v0.tx_mgmt_power; + bss->max_tx_power = bss_v0.max_tx_power; + + wcn36xx_smd_set_bss_vht_params(vif, sta_80211, bss); + + PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body)); + + wcn36xx_dbg(WCN36XX_DBG_HAL, + "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", + bss->bssid, bss->self_mac_addr, bss->bss_type, + bss->oper_mode, bss->nw_type); + + wcn36xx_dbg(WCN36XX_DBG_HAL, + "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", + sta->bssid, sta->action, sta->sta_index, + sta->bssid_index, sta->aid, sta->type, sta->mac); + + ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len); + kfree(msg_body); + + return ret; +} + +static int wcn36xx_smd_config_bss_v0(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + const u8 *bssid, + bool update) +{ + struct wcn36xx_hal_config_bss_req_msg *msg; + struct wcn36xx_hal_config_bss_params *bss; + struct wcn36xx_hal_config_sta_params *sta_params; + int ret; + + msg = kzalloc(sizeof(*msg), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + INIT_HAL_MSG((*msg), WCN36XX_HAL_CONFIG_BSS_REQ); + + bss = &msg->bss_params; + sta_params = &bss->sta; + + wcn36xx_smd_set_bss_params(wcn, vif, sta, bssid, update, bss); + wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); + + PREPARE_HAL_BUF(wcn->hal_buf, (*msg)); wcn36xx_dbg(WCN36XX_DBG_HAL, "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", @@ -1536,13 +1750,69 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, sta_params->aid, sta_params->type, sta_params->mac); - if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { - ret = wcn36xx_smd_config_bss_v1(wcn, msg); - } else { - PREPARE_HAL_BUF(wcn->hal_buf, (*msg)); + ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len); + kfree(msg); + + return ret; +} + +static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + void *buf, + size_t len) +{ + struct wcn36xx_hal_config_bss_rsp_msg *rsp; + struct wcn36xx_hal_config_bss_rsp_params *params; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); + + if (len < sizeof(*rsp)) + return -EINVAL; + + rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf; + params = &rsp->bss_rsp_params; + + if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { + wcn36xx_warn("hal config bss response failure: %d\n", + params->status); + return -EIO; + } + + wcn36xx_dbg(WCN36XX_DBG_HAL, + "hal config bss rsp status %d bss_idx %d dpu_desc_index %d" + " sta_idx %d self_idx %d bcast_idx %d mac %pM" + " power %d ucast_dpu_signature %d\n", + params->status, params->bss_index, params->dpu_desc_index, + params->bss_sta_index, params->bss_self_sta_index, + params->bss_bcast_sta_idx, params->mac, + params->tx_mgmt_power, params->ucast_dpu_signature); - ret = wcn36xx_smd_send_and_wait(wcn, msg->header.len); + vif_priv->bss_index = params->bss_index; + + if (sta) { + struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta); + sta_priv->bss_sta_index = params->bss_sta_index; + sta_priv->bss_dpu_desc_index = params->dpu_desc_index; } + + vif_priv->self_ucast_dpu_sign = params->ucast_dpu_signature; + + return 0; +} + +int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, const u8 *bssid, + bool update) +{ + int ret; + + mutex_lock(&wcn->hal_mutex); + + if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) + ret = wcn36xx_smd_config_bss_v1(wcn, vif, sta, bssid, update); + else + ret = wcn36xx_smd_config_bss_v0(wcn, vif, sta, bssid, update); + if (ret) { wcn36xx_err("Sending hal_config_bss failed\n"); goto out; @@ -1552,12 +1822,10 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, sta, wcn->hal_buf, wcn->hal_rsp_len); - if (ret) { + if (ret) wcn36xx_err("hal_config_bss response failed err=%d\n", ret); - goto out; - } + out: - kfree(msg); mutex_unlock(&wcn->hal_mutex); return ret; } @@ -1924,6 +2192,7 @@ out: mutex_unlock(&wcn->hal_mutex); return ret; } + int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim) { struct wcn36xx_hal_set_power_params_req_msg msg_body; @@ -1953,6 +2222,7 @@ out: mutex_unlock(&wcn->hal_mutex); return ret; } + /* Notice: This function should be called after associated, or else it * will be invalid */ @@ -2080,6 +2350,8 @@ int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn) INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ); set_feat_caps(msg_body.feat_caps, STA_POWERSAVE); + if (wcn->rf_id == RF_IRIS_WCN3680) + set_feat_caps(msg_body.feat_caps, DOT11AC); PREPARE_HAL_BUF(wcn->hal_buf, msg_body); @@ -2102,6 +2374,22 @@ out: return ret; } +static int wcn36xx_smd_add_ba_session_rsp(void *buf, int len, u8 *session) +{ + struct wcn36xx_hal_add_ba_session_rsp_msg *rsp; + + if (len < sizeof(*rsp)) + return -EINVAL; + + rsp = (struct wcn36xx_hal_add_ba_session_rsp_msg *)buf; + if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) + return rsp->status; + + *session = rsp->ba_session_id; + + return 0; +} + int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, struct ieee80211_sta *sta, u16 tid, @@ -2110,6 +2398,7 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, u8 sta_index) { struct wcn36xx_hal_add_ba_session_req_msg msg_body; + u8 session_id; int ret; mutex_lock(&wcn->hal_mutex); @@ -2135,17 +2424,20 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, wcn36xx_err("Sending hal_add_ba_session failed\n"); goto out; } - ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); + ret = wcn36xx_smd_add_ba_session_rsp(wcn->hal_buf, wcn->hal_rsp_len, + &session_id); if (ret) { wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret); goto out; } + + ret = session_id; out: mutex_unlock(&wcn->hal_mutex); return ret; } -int wcn36xx_smd_add_ba(struct wcn36xx *wcn) +int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id) { struct wcn36xx_hal_add_ba_req_msg msg_body; int ret; @@ -2153,7 +2445,7 @@ int wcn36xx_smd_add_ba(struct wcn36xx *wcn) mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ); - msg_body.session_id = 0; + msg_body.session_id = session_id; msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); @@ -2212,7 +2504,7 @@ static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len) return rsp->status; } -int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) +int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u8 session_id) { struct wcn36xx_hal_trigger_ba_req_msg msg_body; struct wcn36xx_hal_trigger_ba_req_candidate *candidate; @@ -2221,7 +2513,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ); - msg_body.session_id = 0; + msg_body.session_id = session_id; msg_body.candidate_cnt = 1; msg_body.header.len += sizeof(*candidate); PREPARE_HAL_BUF(wcn->hal_buf, msg_body); @@ -2229,7 +2521,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *) (wcn->hal_buf + sizeof(msg_body)); candidate->sta_index = sta_index; - candidate->tid_bitmap = 1; + candidate->tid_bitmap = 1 << tid; ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); if (ret) { @@ -2610,6 +2902,7 @@ static void wcn36xx_ind_smd_work(struct work_struct *work) kfree(hal_ind_msg); } } + int wcn36xx_smd_open(struct wcn36xx *wcn) { wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind"); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index ff15df8ab56f..b1d8083d9d9d 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -59,11 +59,13 @@ void wcn36xx_smd_close(struct wcn36xx *wcn); int wcn36xx_smd_load_nv(struct wcn36xx *wcn); int wcn36xx_smd_start(struct wcn36xx *wcn); int wcn36xx_smd_stop(struct wcn36xx *wcn); -int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode); int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel); int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel); -int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, - enum wcn36xx_hal_sys_mode mode); +int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode, + struct ieee80211_vif *vif); +int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode, + struct ieee80211_vif *vif); + int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t channel_count); int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif, struct cfg80211_scan_request *req); @@ -132,9 +134,9 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, u16 *ssn, u8 direction, u8 sta_index); -int wcn36xx_smd_add_ba(struct wcn36xx *wcn); +int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id); int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); -int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); +int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u8 session_id); int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index a6902371e89c..1b831157ede1 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -23,11 +23,214 @@ static inline int get_rssi0(struct wcn36xx_rx_bd *bd) return 100 - ((bd->phy_stat0 >> 24) & 0xff); } +struct wcn36xx_rate { + u16 bitrate; + u16 mcs_or_legacy_index; + enum mac80211_rx_encoding encoding; + enum mac80211_rx_encoding_flags encoding_flags; + enum rate_info_bw bw; +}; + +static const struct wcn36xx_rate wcn36xx_rate_table[] = { + /* 11b rates */ + { 10, 0, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 20, 1, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 55, 2, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 110, 3, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + + /* 11b SP (short preamble) */ + { 10, 0, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 }, + { 20, 1, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 }, + { 55, 2, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 }, + { 110, 3, RX_ENC_LEGACY, RX_ENC_FLAG_SHORTPRE, RATE_INFO_BW_20 }, + + /* 11ag */ + { 60, 4, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 90, 5, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 120, 6, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 180, 7, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 240, 8, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 360, 9, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 480, 10, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + { 540, 11, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, + + /* 11n */ + { 65, 0, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 130, 1, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 195, 2, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 260, 3, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 390, 4, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 520, 5, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 585, 6, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 650, 7, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + + /* 11n SGI */ + { 72, 0, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + { 144, 1, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + { 217, 2, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + { 289, 3, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + { 434, 4, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + { 578, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + { 650, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + { 722, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + + /* 11n GF (greenfield) */ + { 65, 0, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, + { 130, 1, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, + { 195, 2, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, + { 260, 3, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, + { 390, 4, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, + { 520, 5, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, + { 585, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, + { 650, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_20 }, + + /* 11n CB (channel bonding) */ + { 135, 0, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 270, 1, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 405, 2, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 540, 3, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 810, 4, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 1080, 5, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 1215, 6, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + + /* 11n CB + SGI */ + { 150, 0, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 300, 1, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 450, 2, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 600, 3, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 900, 4, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1200, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1500, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11n GF + CB */ + { 135, 0, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, + { 270, 1, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, + { 405, 2, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, + { 540, 3, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, + { 810, 4, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, + { 1080, 5, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, + { 1215, 6, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, + { 1350, 7, RX_ENC_HT, RX_ENC_FLAG_HT_GF, RATE_INFO_BW_40 }, + + /* 11ac reserved indices */ + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac 20 MHz 800ns GI MCS 0-8 */ + { 65, 0, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 130, 1, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 195, 2, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 260, 3, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 390, 4, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 520, 5, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 585, 6, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 650, 7, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + { 780, 8, RX_ENC_HT, 0, RATE_INFO_BW_20 }, + + /* 11ac reserved indices */ + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac 20 MHz 400ns SGI MCS 6-8 */ + { 655, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + { 722, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + { 866, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_20 }, + + /* 11ac reserved indices */ + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac 40 MHz 800ns GI MCS 0-9 */ + { 135, 0, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 270, 1, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 405, 2, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 540, 3, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 810, 4, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 1080, 5, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 1215, 6, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 1350, 7, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 1620, 8, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + { 1800, 9, RX_ENC_HT, 0, RATE_INFO_BW_40 }, + + /* 11ac reserved indices */ + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac 40 MHz 400ns SGI MCS 5-7 */ + { 1200, 5, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1500, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac reserved index */ + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac 40 MHz 400ns SGI MCS 5-7 */ + { 1800, 8, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 2000, 9, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac reserved index */ + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac 80 MHz 800ns GI MCS 0-7 */ + { 292, 0, RX_ENC_HT, 0, RATE_INFO_BW_80}, + { 585, 1, RX_ENC_HT, 0, RATE_INFO_BW_80}, + { 877, 2, RX_ENC_HT, 0, RATE_INFO_BW_80}, + { 1170, 3, RX_ENC_HT, 0, RATE_INFO_BW_80}, + { 1755, 4, RX_ENC_HT, 0, RATE_INFO_BW_80}, + { 2340, 5, RX_ENC_HT, 0, RATE_INFO_BW_80}, + { 2632, 6, RX_ENC_HT, 0, RATE_INFO_BW_80}, + { 2925, 7, RX_ENC_HT, 0, RATE_INFO_BW_80}, + + /* 11 ac reserved index */ + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac 80 MHz 800 ns GI MCS 8-9 */ + { 3510, 8, RX_ENC_HT, 0, RATE_INFO_BW_80}, + { 3900, 9, RX_ENC_HT, 0, RATE_INFO_BW_80}, + + /* 11 ac reserved indices */ + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac 80 MHz 400 ns SGI MCS 6-7 */ + { 2925, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 }, + { 3250, 7, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 }, + + /* 11ac reserved index */ + { 1350, 6, RX_ENC_HT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_40 }, + + /* 11ac 80 MHz 400ns SGI MCS 8-9 */ + { 3900, 8, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 }, + { 4333, 9, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 }, +}; + int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) { struct ieee80211_rx_status status; + const struct wcn36xx_rate *rate; struct ieee80211_hdr *hdr; struct wcn36xx_rx_bd *bd; + struct ieee80211_supported_band *sband; u16 fc, sn; /* @@ -49,19 +252,11 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) fc = __le16_to_cpu(hdr->frame_control); sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); - /* When scanning associate beacons to this */ - if (ieee80211_is_beacon(hdr->frame_control) && wcn->scan_freq) { - status.freq = wcn->scan_freq; - status.band = wcn->scan_band; - } else { - status.freq = WCN36XX_CENTER_FREQ(wcn); - status.band = WCN36XX_BAND(wcn); - } - + status.freq = WCN36XX_CENTER_FREQ(wcn); + status.band = WCN36XX_BAND(wcn); status.mactime = 10; status.signal = -get_rssi0(bd); status.antenna = 1; - status.rate_idx = 1; status.flag = 0; status.rx_flags = 0; status.flag |= RX_FLAG_IV_STRIPPED | @@ -70,6 +265,28 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag); + if (bd->rate_id < ARRAY_SIZE(wcn36xx_rate_table)) { + rate = &wcn36xx_rate_table[bd->rate_id]; + status.encoding = rate->encoding; + status.enc_flags = rate->encoding_flags; + status.bw = rate->bw; + status.rate_idx = rate->mcs_or_legacy_index; + sband = wcn->hw->wiphy->bands[status.band]; + status.nss = 1; + + if (status.band == NL80211_BAND_5GHZ && + status.encoding == RX_ENC_LEGACY && + status.rate_idx >= sband->n_bitrates) { + /* no dsss rates in 5Ghz rates table */ + status.rate_idx -= 4; + } + } else { + status.encoding = 0; + status.bw = 0; + status.enc_flags = 0; + status.rate_idx = 0; + } + memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); if (ieee80211_is_beacon(hdr->frame_control)) { @@ -100,7 +317,8 @@ static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd, bd->pdu.mpdu_header_off; bd->pdu.mpdu_len = len; bd->pdu.tid = tid; - bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS; + /* Use seq number generated by mac80211 */ + bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST; } static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, @@ -160,9 +378,11 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, bool bcast) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = NULL; struct wcn36xx_vif *__vif_priv = NULL; - bool is_data_qos; + bool is_data_qos = ieee80211_is_data_qos(hdr->frame_control); + u16 tid = 0; bd->bd_rate = WCN36XX_BD_RATE_DATA; @@ -191,9 +411,21 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, bd->dpu_sign = __vif_priv->self_ucast_dpu_sign; } - if (ieee80211_is_nullfunc(hdr->frame_control) || - (sta_priv && !sta_priv->is_data_encrypted)) + if (is_data_qos) { + tid = ieee80211_get_tid(hdr); + /* TID->QID is one-to-one mapping */ + bd->queue_id = tid; + } + + if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT || + (sta_priv && !sta_priv->is_data_encrypted)) { bd->dpu_ne = 1; + } + + if (ieee80211_is_any_nullfunc(hdr->frame_control)) { + /* Don't use a regular queue for null packet (no ampdu) */ + bd->queue_id = WCN36XX_TX_U_WQ_ID; + } if (bcast) { bd->ub = 1; @@ -201,13 +433,11 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, } *vif_priv = __vif_priv; - is_data_qos = ieee80211_is_data_qos(hdr->frame_control); - wcn36xx_set_tx_pdu(bd, is_data_qos ? sizeof(struct ieee80211_qos_hdr) : sizeof(struct ieee80211_hdr_3addr), - skb->len, sta_priv ? sta_priv->tid : 0); + skb->len, tid); if (sta_priv && is_data_qos) wcn36xx_tx_start_ampdu(wcn, sta_priv, skb); @@ -287,9 +517,9 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, bd.dpu_rf = WCN36XX_BMU_WQ_TX; - bd.tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS); - if (bd.tx_comp) { + if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); + spin_lock_irqsave(&wcn->dxe_lock, flags); if (wcn->tx_ack_skb) { spin_unlock_irqrestore(&wcn->dxe_lock, flags); @@ -302,10 +532,15 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, /* Only one at a time is supported by fw. Stop the TX queues * until the ack status gets back. - * - * TODO: Add watchdog in case FW does not answer */ ieee80211_stop_queues(wcn->hw); + + /* TX watchdog if no TX irq or ack indication received */ + mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10); + + /* Request ack indication from the firmware */ + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) + bd.tx_comp = 1; } /* Data frames served first*/ @@ -319,7 +554,7 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, bd.tx_bd_sign = 0xbdbdbdbd; ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low); - if (ret && bd.tx_comp) { + if (ret && (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { /* If the skb has not been transmitted, * don't keep a reference to it. */ diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index a58f313983b9..71fa9992b118 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -83,7 +83,11 @@ enum wcn36xx_ampdu_state { WCN36XX_AMPDU_OPERATIONAL, }; -#define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value) +#define HW_VALUE_PHY_SHIFT 8 +#define HW_VALUE_PHY(hw_value) ((hw_value) >> HW_VALUE_PHY_SHIFT) +#define HW_VALUE_CHANNEL(hw_value) ((hw_value) & 0xFF) +#define WCN36XX_HW_CHANNEL(__wcn)\ + HW_VALUE_CHANNEL(__wcn->hw->conf.chandef.chan->hw_value) #define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band) #define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq) #define WCN36XX_LISTEN_INTERVAL(__wcn) (__wcn->hw->conf.listen_interval) @@ -92,6 +96,7 @@ enum wcn36xx_ampdu_state { #define RF_UNKNOWN 0x0000 #define RF_IRIS_WCN3620 0x3620 +#define RF_IRIS_WCN3680 0x3680 static inline void buff_to_be(u32 *buf, size_t len) { @@ -122,6 +127,7 @@ struct wcn36xx_vif { enum wcn36xx_hal_bss_type bss_type; /* Power management */ + bool allow_bmps; enum wcn36xx_power_state pw_state; u8 bss_index; @@ -167,7 +173,7 @@ struct wcn36xx_sta { u8 bss_dpu_desc_index; bool is_data_encrypted; /* Rates */ - struct wcn36xx_hal_supported_rates supported_rates; + struct wcn36xx_hal_supported_rates_v1 supported_rates; spinlock_t ampdu_lock; /* protects next two fields */ enum wcn36xx_ampdu_state ampdu_state[16]; @@ -223,10 +229,10 @@ struct wcn36xx { spinlock_t hal_ind_lock; struct list_head hal_ind_queue; - struct work_struct scan_work; struct cfg80211_scan_request *scan_req; - int scan_freq; - int scan_band; + bool sw_scan; + u8 sw_scan_opchannel; + struct ieee80211_vif *sw_scan_vif; struct mutex scan_lock; bool scan_aborted; @@ -245,6 +251,7 @@ struct wcn36xx { struct wcn36xx_dxe_mem_pool data_mem_pool; struct sk_buff *tx_ack_skb; + struct timer_list tx_ack_timer; /* RF module */ unsigned rf_id; @@ -268,6 +275,7 @@ static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn, wcn->fw_revision == revision); } void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates); +void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates); static inline struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv) |