diff options
Diffstat (limited to 'drivers/net/wireless')
86 files changed, 3948 insertions, 1769 deletions
diff --git a/drivers/net/wireless/admtek/adm8211.h b/drivers/net/wireless/admtek/adm8211.h index 2c55c629de28..095625ecb8ff 100644 --- a/drivers/net/wireless/admtek/adm8211.h +++ b/drivers/net/wireless/admtek/adm8211.h @@ -531,7 +531,7 @@ struct adm8211_eeprom { u8 lpf_cutoff[14]; /* 0x62 */ u8 lnags_threshold[14]; /* 0x70 */ __le16 checksum; /* 0x7E */ - u8 cis_data[0]; /* 0x80, 384 bytes */ + u8 cis_data[]; /* 0x80, 384 bytes */ } __packed; struct adm8211_priv { diff --git a/drivers/net/wireless/atmel/at76c50x-usb.h b/drivers/net/wireless/atmel/at76c50x-usb.h index f56863403b05..746e64dfd8aa 100644 --- a/drivers/net/wireless/atmel/at76c50x-usb.h +++ b/drivers/net/wireless/atmel/at76c50x-usb.h @@ -151,7 +151,7 @@ struct at76_command { u8 cmd; u8 reserved; __le16 size; - u8 data[0]; + u8 data[]; } __packed; /* Length of Atmel-specific Rx header before 802.11 frame */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index a2328d3eee03..2ba165330038 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -2953,7 +2953,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) { bphy_err(drvr, "Bss info is larger than buffer. Discarding\n"); - return 0; + return -EINVAL; } if (!bi->ctl_ch) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h index 3347439543bb..46c66415b4a6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h @@ -60,7 +60,7 @@ struct brcmf_fw_request { u16 bus_nr; u32 n_items; const char *board_type; - struct brcmf_fw_item items[0]; + struct brcmf_fw_item items[]; }; struct brcmf_fw_name { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index 79c8a858b6d6..a5cced2c89ac 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c @@ -32,7 +32,7 @@ struct brcmf_fweh_queue_item { u8 ifaddr[ETH_ALEN]; struct brcmf_event_msg_be emsg; u32 datalen; - u8 data[0]; + u8 data[]; }; /** diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index 5e1a11c07551..8cc52935fd41 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -404,7 +404,7 @@ struct brcmf_fws_mac_descriptor { u8 traffic_lastreported_bmp; }; -#define BRCMF_FWS_HANGER_MAXITEMS 1024 +#define BRCMF_FWS_HANGER_MAXITEMS 3072 /** * enum brcmf_fws_hanger_item_state - state of hanger item. @@ -2145,8 +2145,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); brcmf_fws_schedule_deq(fws); } else { - bphy_err(drvr, "drop skb: no hanger slot\n"); - brcmf_txfinalize(ifp, skb, false); + bphy_err(drvr, "no hanger slot available\n"); rc = -ENOMEM; } brcmf_fws_unlock(fws); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 575ed19e9195..ac5463838fcf 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -164,7 +164,6 @@ struct brcmf_usbdev_info { struct urb *bulk_urb; /* used for FW download */ - bool wowl_enabled; struct brcmf_mp_device *settings; }; @@ -312,27 +311,43 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len) int err = 0; int timeout = 0; struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); + struct usb_interface *intf = to_usb_interface(dev); brcmf_dbg(USB, "Enter\n"); - if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) - return -EIO; - if (test_and_set_bit(0, &devinfo->ctl_op)) - return -EIO; + err = usb_autopm_get_interface(intf); + if (err) + goto out; + + if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { + err = -EIO; + goto fail; + } + + if (test_and_set_bit(0, &devinfo->ctl_op)) { + err = -EIO; + goto fail; + } devinfo->ctl_completed = false; err = brcmf_usb_send_ctl(devinfo, buf, len); if (err) { brcmf_err("fail %d bytes: %d\n", err, len); clear_bit(0, &devinfo->ctl_op); - return err; + goto fail; } timeout = brcmf_usb_ioctl_resp_wait(devinfo); - clear_bit(0, &devinfo->ctl_op); if (!timeout) { brcmf_err("Txctl wait timed out\n"); + usb_kill_urb(devinfo->ctl_urb); err = -EIO; + goto fail; } + clear_bit(0, &devinfo->ctl_op); + +fail: + usb_autopm_put_interface(intf); +out: return err; } @@ -341,32 +356,46 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len) int err = 0; int timeout = 0; struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); + struct usb_interface *intf = to_usb_interface(dev); brcmf_dbg(USB, "Enter\n"); - if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) - return -EIO; - if (test_and_set_bit(0, &devinfo->ctl_op)) - return -EIO; + err = usb_autopm_get_interface(intf); + if (err) + goto out; + + if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { + err = -EIO; + goto fail; + } + + if (test_and_set_bit(0, &devinfo->ctl_op)) { + err = -EIO; + goto fail; + } devinfo->ctl_completed = false; err = brcmf_usb_recv_ctl(devinfo, buf, len); if (err) { brcmf_err("fail %d bytes: %d\n", err, len); clear_bit(0, &devinfo->ctl_op); - return err; + goto fail; } timeout = brcmf_usb_ioctl_resp_wait(devinfo); err = devinfo->ctl_urb_status; - clear_bit(0, &devinfo->ctl_op); if (!timeout) { brcmf_err("rxctl wait timed out\n"); + usb_kill_urb(devinfo->ctl_urb); err = -EIO; + goto fail; } + clear_bit(0, &devinfo->ctl_op); +fail: + usb_autopm_put_interface(intf); if (!err) return devinfo->ctl_urb_actual_length; - else - return err; +out: + return err; } static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo, @@ -500,10 +529,12 @@ static void brcmf_usb_rx_complete(struct urb *urb) return; } - if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { + if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP || + devinfo->bus_pub.state == BRCMFMAC_USB_STATE_SLEEP) { skb_put(skb, urb->actual_length); brcmf_rx_frame(devinfo->dev, skb, true); brcmf_usb_rx_refill(devinfo, req); + usb_mark_last_busy(urb->dev); } else { brcmu_pkt_buf_free_skb(skb); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL); @@ -587,6 +618,11 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) struct brcmf_usbreq *req; int ret; unsigned long flags; + struct usb_interface *intf = to_usb_interface(dev); + + ret = usb_autopm_get_interface(intf); + if (ret) + goto out; brcmf_dbg(USB, "Enter, skb=%p\n", skb); if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { @@ -625,9 +661,10 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) devinfo->tx_flowblock = true; } spin_unlock_irqrestore(&devinfo->tx_flowblock_lock, flags); - return 0; fail: + usb_autopm_put_interface(intf); +out: return ret; } @@ -991,20 +1028,32 @@ static int brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo) { int err; + struct usb_interface *intf; brcmf_dbg(USB, "Enter\n"); - if (devinfo == NULL) - return -ENODEV; + if (!devinfo) { + err = -ENODEV; + goto out; + } if (!devinfo->image) { brcmf_err("No firmware!\n"); - return -ENOENT; + err = -ENOENT; + goto out; } + intf = to_usb_interface(devinfo->dev); + err = usb_autopm_get_interface(intf); + if (err) + goto out; + err = brcmf_usb_dlstart(devinfo, (u8 *)devinfo->image, devinfo->image_len); if (err == 0) err = brcmf_usb_dlrun(devinfo); + + usb_autopm_put_interface(intf); +out: return err; } @@ -1105,18 +1154,6 @@ error: return NULL; } -static void brcmf_usb_wowl_config(struct device *dev, bool enabled) -{ - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); - - brcmf_dbg(USB, "Configuring WOWL, enabled=%d\n", enabled); - devinfo->wowl_enabled = enabled; - if (enabled) - device_set_wakeup_enable(devinfo->dev, true); - else - device_set_wakeup_enable(devinfo->dev, false); -} - static int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name) { @@ -1143,7 +1180,6 @@ static const struct brcmf_bus_ops brcmf_usb_bus_ops = { .txdata = brcmf_usb_tx, .txctl = brcmf_usb_tx_ctlpkt, .rxctl = brcmf_usb_rx_ctlpkt, - .wowl_config = brcmf_usb_wowl_config, .get_fwname = brcmf_usb_get_fwname, }; @@ -1332,6 +1368,8 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) usb_set_intfdata(intf, devinfo); + intf->needs_remote_wakeup = 1; + /* Check that the device supports only one configuration */ if (usb->descriptor.bNumConfigurations != 1) { brcmf_err("Number of configurations: %d not supported\n", @@ -1445,12 +1483,8 @@ static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state) brcmf_dbg(USB, "Enter\n"); devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP; - if (devinfo->wowl_enabled) { - brcmf_cancel_all_urbs(devinfo); - } else { - brcmf_detach(&usb->dev); - brcmf_free(&usb->dev); - } + brcmf_cancel_all_urbs(devinfo); + device_set_wakeup_enable(devinfo->dev, true); return 0; } @@ -1463,22 +1497,10 @@ static int brcmf_usb_resume(struct usb_interface *intf) struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); brcmf_dbg(USB, "Enter\n"); - if (!devinfo->wowl_enabled) { - int err; - - err = brcmf_alloc(&usb->dev, devinfo->settings); - if (err) - return err; - - err = brcmf_attach(devinfo->dev); - if (err) { - brcmf_free(devinfo->dev); - return err; - } - } devinfo->bus_pub.state = BRCMFMAC_USB_STATE_UP; brcmf_usb_rx_fill_all(devinfo); + device_set_wakeup_enable(devinfo->dev, false); return 0; } @@ -1535,6 +1557,7 @@ static struct usb_driver brcmf_usbdrvr = { .suspend = brcmf_usb_suspend, .resume = brcmf_usb_resume, .reset_resume = brcmf_usb_reset_resume, + .supports_autosuspend = true, .disable_hub_initiated_lpm = 1, }; diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index a22a830019c0..53568bbcf214 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -246,6 +246,23 @@ static const struct iwl_ht_params iwl_22000_ht_params = { #define IWL_NUM_RBDS_22000_HE 2048 #define IWL_NUM_RBDS_AX210_HE 4096 +const struct iwl_cfg_trans_params iwl_ax200_trans_cfg = { + .device_family = IWL_DEVICE_FAMILY_22000, + .base_params = &iwl_22000_base_params, + .mq_rx_supported = true, + .use_tfh = true, + .rf_id = true, + .gen2 = true, + .bisr_workaround = 1, +}; + +const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz"; + +const char iwl_ax200_killer_1650w_name[] = + "Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)"; +const char iwl_ax200_killer_1650x_name[] = + "Killer(R) Wi-Fi 6 AX1650x 160MHz Wireless Network Adapter (200NGW)"; + const struct iwl_cfg iwl_ax101_cfg_qu_hr = { .name = "Intel(R) Wi-Fi 6 AX101", .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, @@ -352,35 +369,6 @@ const struct iwl_cfg iwl_ax1650i_cfg_quz_hr = { }; const struct iwl_cfg iwl_ax200_cfg_cc = { - .name = "Intel(R) Wi-Fi 6 AX200 160MHz", - .fw_name_pre = IWL_CC_A_FW_PRE, - IWL_DEVICE_22500, - /* - * This device doesn't support receiving BlockAck with a large bitmap - * so we need to restrict the size of transmitted aggregation to the - * HT size; mac80211 would otherwise pick the HE max (256) by default. - */ - .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, - .trans.bisr_workaround = 1, - .num_rbds = IWL_NUM_RBDS_22000_HE, -}; - -const struct iwl_cfg killer1650x_2ax_cfg = { - .name = "Killer(R) Wi-Fi 6 AX1650x 160MHz Wireless Network Adapter (200NGW)", - .fw_name_pre = IWL_CC_A_FW_PRE, - IWL_DEVICE_22500, - /* - * This device doesn't support receiving BlockAck with a large bitmap - * so we need to restrict the size of transmitted aggregation to the - * HT size; mac80211 would otherwise pick the HE max (256) by default. - */ - .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, - .trans.bisr_workaround = 1, - .num_rbds = IWL_NUM_RBDS_22000_HE, -}; - -const struct iwl_cfg killer1650w_2ax_cfg = { - .name = "Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)", .fw_name_pre = IWL_CC_A_FW_PRE, IWL_DEVICE_22500, /* @@ -389,7 +377,6 @@ const struct iwl_cfg killer1650w_2ax_cfg = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, - .trans.bisr_workaround = 1, .num_rbds = IWL_NUM_RBDS_22000_HE, }; diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 379ea788e424..d02936a8e11d 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -123,8 +123,6 @@ static const struct iwl_tt_params iwl9000_tt_params = { #define IWL_DEVICE_9000 \ .ucode_api_max = IWL9000_UCODE_API_MAX, \ .ucode_api_min = IWL9000_UCODE_API_MIN, \ - .trans.device_family = IWL_DEVICE_FAMILY_9000, \ - .trans.base_params = &iwl9000_base_params, \ .led_mode = IWL_LED_RF_STATE, \ .nvm_hw_section_num = 10, \ .non_shared_ant = ANT_B, \ @@ -137,11 +135,9 @@ static const struct iwl_tt_params iwl9000_tt_params = { .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \ .thermal_params = &iwl9000_tt_params, \ .apmg_not_supported = true, \ - .trans.mq_rx_supported = true, \ .num_rbds = 512, \ .vht_mu_mimo_supported = true, \ .mac_addr_from_csr = true, \ - .trans.rf_id = true, \ .nvm_type = IWL_NVM_EXT, \ .dbgc_supported = true, \ .min_umac_error_event_table = 0x800000, \ @@ -178,168 +174,45 @@ const struct iwl_cfg_trans_params iwl9000_trans_cfg = { .rf_id = true, }; -const struct iwl_cfg iwl9160_2ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC 9160", - .fw_name_pre = IWL9260_FW_PRE, - IWL_DEVICE_9000, -}; - const struct iwl_cfg iwl9260_2ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC 9260", .fw_name_pre = IWL9260_FW_PRE, IWL_DEVICE_9000, }; +const char iwl9162_name[] = "Intel(R) Wireless-AC 9162"; +const char iwl9260_name[] = "Intel(R) Wireless-AC 9260"; +const char iwl9260_1_name[] = "Intel(R) Wireless-AC 9260-1"; +const char iwl9270_name[] = "Intel(R) Wireless-AC 9270"; +const char iwl9461_name[] = "Intel(R) Wireless-AC 9461"; +const char iwl9462_name[] = "Intel(R) Wireless-AC 9462"; +const char iwl9560_name[] = "Intel(R) Wireless-AC 9560"; +const char iwl9162_160_name[] = "Intel(R) Wireless-AC 9162 160MHz"; const char iwl9260_160_name[] = "Intel(R) Wireless-AC 9260 160MHz"; +const char iwl9270_160_name[] = "Intel(R) Wireless-AC 9270 160MHz"; +const char iwl9461_160_name[] = "Intel(R) Wireless-AC 9461 160MHz"; +const char iwl9462_160_name[] = "Intel(R) Wireless-AC 9462 160MHz"; const char iwl9560_160_name[] = "Intel(R) Wireless-AC 9560 160MHz"; -const struct iwl_cfg iwl9260_2ac_160_cfg = { - .fw_name_pre = IWL9260_FW_PRE, - IWL_DEVICE_9000, -}; - -const struct iwl_cfg iwl9260_killer_2ac_cfg = { - .name = "Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW)", - .fw_name_pre = IWL9260_FW_PRE, - IWL_DEVICE_9000, -}; - -const struct iwl_cfg iwl9270_2ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC 9270", - .fw_name_pre = IWL9260_FW_PRE, - IWL_DEVICE_9000, -}; - -const struct iwl_cfg iwl9460_2ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC 9460", - .fw_name_pre = IWL9260_FW_PRE, - IWL_DEVICE_9000, -}; - -const struct iwl_cfg iwl9460_2ac_cfg_soc = { - .name = "Intel(R) Dual Band Wireless AC 9460", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, -}; - -const struct iwl_cfg iwl9461_2ac_cfg_soc = { - .name = "Intel(R) Dual Band Wireless AC 9461", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, -}; - -const struct iwl_cfg iwl9462_2ac_cfg_soc = { - .name = "Intel(R) Dual Band Wireless AC 9462", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, -}; +const char iwl9260_killer_1550_name[] = + "Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW)"; +const char iwl9560_killer_1550i_name[] = + "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)"; +const char iwl9560_killer_1550s_name[] = + "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)"; const struct iwl_cfg iwl9560_2ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC 9560", - .fw_name_pre = IWL9260_FW_PRE, - IWL_DEVICE_9000, -}; - -const struct iwl_cfg iwl9560_2ac_160_cfg = { - .name = "Intel(R) Wireless-AC 9560 160MHz", .fw_name_pre = IWL9260_FW_PRE, IWL_DEVICE_9000, }; const struct iwl_cfg iwl9560_2ac_cfg_soc = { - .name = "Intel(R) Dual Band Wireless AC 9560", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, -}; - -const struct iwl_cfg iwl9560_2ac_160_cfg_soc = { - .name = "Intel(R) Wireless-AC 9560 160MHz", .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, }; -const struct iwl_cfg iwl9560_killer_2ac_cfg_soc = { - .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, -}; - -const struct iwl_cfg iwl9560_killer_s_2ac_cfg_soc = { - .name = "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, -}; - -const struct iwl_cfg iwl9460_2ac_cfg_shared_clk = { - .name = "Intel(R) Dual Band Wireless AC 9460", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, - .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK -}; - -const struct iwl_cfg iwl9461_2ac_cfg_shared_clk = { - .name = "Intel(R) Dual Band Wireless AC 9461", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, - .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK -}; - -const struct iwl_cfg iwl9462_2ac_cfg_shared_clk = { - .name = "Intel(R) Dual Band Wireless AC 9462", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, - .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK -}; - const struct iwl_cfg iwl9560_2ac_cfg_shared_clk = { - .name = "Intel(R) Dual Band Wireless AC 9560", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, - .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK -}; - -const struct iwl_cfg iwl9560_2ac_160_cfg_shared_clk = { - .name = "Intel(R) Wireless-AC 9560 160MHz", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, - .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK -}; - -const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk = { - .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", - .fw_name_pre = IWL9000_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, - .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK -}; - -const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk = { - .name = "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)", .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index be6a2bf9ce74..dc32ccf95be5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -454,9 +454,40 @@ struct iwl_cfg { #define IWL_CFG_ANY (~0) +#define IWL_CFG_MAC_TYPE_PU 0x31 +#define IWL_CFG_MAC_TYPE_PNJ 0x32 +#define IWL_CFG_MAC_TYPE_TH 0x32 +#define IWL_CFG_MAC_TYPE_QU 0x33 + +#define IWL_CFG_RF_TYPE_TH 0x105 +#define IWL_CFG_RF_TYPE_TH1 0x108 +#define IWL_CFG_RF_TYPE_JF2 0x105 +#define IWL_CFG_RF_TYPE_JF1 0x108 + +#define IWL_CFG_RF_ID_TH 0x1 +#define IWL_CFG_RF_ID_TH1 0x1 +#define IWL_CFG_RF_ID_JF 0x3 +#define IWL_CFG_RF_ID_JF1 0x6 +#define IWL_CFG_RF_ID_JF1_DIV 0xA + +#define IWL_CFG_NO_160 0x0 +#define IWL_CFG_160 0x1 + +#define IWL_CFG_CORES_BT 0x0 +#define IWL_CFG_CORES_BT_GNSS 0x5 + +#define IWL_SUBDEVICE_RF_ID(subdevice) ((u16)((subdevice) & 0x00F0) >> 4) +#define IWL_SUBDEVICE_NO_160(subdevice) ((u16)((subdevice) & 0x0100) >> 9) +#define IWL_SUBDEVICE_CORES(subdevice) ((u16)((subdevice) & 0x1C00) >> 10) + struct iwl_dev_info { u16 device; u16 subdevice; + u16 mac_type; + u16 rf_type; + u8 rf_id; + u8 no_160; + u8 cores; const struct iwl_cfg *cfg; const char *name; }; @@ -465,8 +496,26 @@ struct iwl_dev_info { * This list declares the config structures for all devices. */ extern const struct iwl_cfg_trans_params iwl9000_trans_cfg; +extern const struct iwl_cfg_trans_params iwl_ax200_trans_cfg; +extern const char iwl9162_name[]; +extern const char iwl9260_name[]; +extern const char iwl9260_1_name[]; +extern const char iwl9270_name[]; +extern const char iwl9461_name[]; +extern const char iwl9462_name[]; +extern const char iwl9560_name[]; +extern const char iwl9162_160_name[]; extern const char iwl9260_160_name[]; +extern const char iwl9270_160_name[]; +extern const char iwl9461_160_name[]; +extern const char iwl9462_160_name[]; extern const char iwl9560_160_name[]; +extern const char iwl9260_killer_1550_name[]; +extern const char iwl9560_killer_1550i_name[]; +extern const char iwl9560_killer_1550s_name[]; +extern const char iwl_ax200_name[]; +extern const char iwl_ax200_killer_1650w_name[]; +extern const char iwl_ax200_killer_1650x_name[]; #if IS_ENABLED(CONFIG_IWLDVM) extern const struct iwl_cfg iwl5300_agn_cfg; @@ -533,28 +582,18 @@ extern const struct iwl_cfg iwl8260_2ac_cfg; extern const struct iwl_cfg iwl8265_2ac_cfg; extern const struct iwl_cfg iwl8275_2ac_cfg; extern const struct iwl_cfg iwl4165_2ac_cfg; -extern const struct iwl_cfg iwl9160_2ac_cfg; extern const struct iwl_cfg iwl9260_2ac_cfg; extern const struct iwl_cfg iwl9260_2ac_160_cfg; extern const struct iwl_cfg iwl9260_killer_2ac_cfg; extern const struct iwl_cfg iwl9270_2ac_cfg; -extern const struct iwl_cfg iwl9460_2ac_cfg; extern const struct iwl_cfg iwl9560_2ac_cfg; extern const struct iwl_cfg iwl9560_2ac_cfg_quz_a0_jf_b0_soc; -extern const struct iwl_cfg iwl9560_2ac_160_cfg; extern const struct iwl_cfg iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc; -extern const struct iwl_cfg iwl9460_2ac_cfg_soc; -extern const struct iwl_cfg iwl9461_2ac_cfg_soc; extern const struct iwl_cfg iwl9461_2ac_cfg_quz_a0_jf_b0_soc; -extern const struct iwl_cfg iwl9462_2ac_cfg_soc; extern const struct iwl_cfg iwl9462_2ac_cfg_quz_a0_jf_b0_soc; extern const struct iwl_cfg iwl9560_2ac_cfg_soc; -extern const struct iwl_cfg iwl9560_2ac_160_cfg_soc; -extern const struct iwl_cfg iwl9560_killer_2ac_cfg_soc; -extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_soc; extern const struct iwl_cfg iwl9560_killer_i_2ac_cfg_quz_a0_jf_b0_soc; extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_quz_a0_jf_b0_soc; -extern const struct iwl_cfg iwl9460_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl9461_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl9462_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl9560_2ac_cfg_shared_clk; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index 70b29bf16bb9..60296a754af2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -308,7 +308,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) } /* PHY_SKU section is mandatory in B0 */ - if (!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) { + if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT && + !mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) { IWL_ERR(mvm, "Can't parse phy_sku in B0, empty sections\n"); return NULL; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 97f227f3cbc3..5413e80f86bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -566,43 +566,13 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x06F0, 0x4234, iwl9560_2ac_cfg_quz_a0_jf_b0_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x42A4, iwl9462_2ac_cfg_quz_a0_jf_b0_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x0034, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0060, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x0064, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x00A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x00A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x0210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0214, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0230, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0234, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0238, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x023C, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0260, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x02A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x1010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x1030, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x1210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x1410, iwl9270_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x1420, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x1550, iwl9260_killer_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x1610, iwl9270_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, PCI_ANY_ID, iwl9000_trans_cfg)}, - - {IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)}, - {IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)}, - {IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)}, - {IWL_PCI_DEVICE(0x271B, 0x0214, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x271C, 0x0214, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x271B, PCI_ANY_ID, iwl9000_trans_cfg)}, + {IWL_PCI_DEVICE(0x271C, PCI_ANY_ID, iwl9000_trans_cfg)}, + {IWL_PCI_DEVICE(0x30DC, PCI_ANY_ID, iwl9000_trans_cfg)}, + {IWL_PCI_DEVICE(0x31DC, PCI_ANY_ID, iwl9000_trans_cfg)}, + {IWL_PCI_DEVICE(0x9DF0, PCI_ANY_ID, iwl9000_trans_cfg)}, + {IWL_PCI_DEVICE(0xA370, PCI_ANY_ID, iwl9000_trans_cfg)}, {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, @@ -630,64 +600,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2720, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x2720, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x30DC, 0x0030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0038, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x003C, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0060, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0064, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x00A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x00A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0230, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0238, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x023C, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0260, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x02A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x1010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x30DC, 0x1030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x1210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x30DC, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x2030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x2034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x4030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x4034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x40A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x4234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x42A4, iwl9462_2ac_cfg_soc)}, - - {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_160_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_160_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_160_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0060, iwl9460_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0064, iwl9461_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x00A0, iwl9462_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x00A4, iwl9462_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0230, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0234, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0238, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x023C, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0260, iwl9461_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0264, iwl9461_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x02A0, iwl9462_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x02A4, iwl9462_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x1010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x31DC, 0x1030, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x1210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x31DC, 0x1551, iwl9560_killer_s_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x1552, iwl9560_killer_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x2030, iwl9560_2ac_160_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x2034, iwl9560_2ac_160_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x4030, iwl9560_2ac_160_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x4034, iwl9560_2ac_160_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x40A4, iwl9462_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x4234, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x42A4, iwl9462_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x34F0, 0x0030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, @@ -768,46 +680,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x43F0, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x43F0, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0000, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0010, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0038, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x003C, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0060, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0064, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x00A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x00A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0210, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0230, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0238, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x023C, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0260, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x02A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0310, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0410, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0510, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0610, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0710, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0A10, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x1010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x9DF0, 0x1030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x1210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x9DF0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x2010, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x2030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x2034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x4030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x4034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x40A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x4234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0xA0F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, @@ -835,37 +707,11 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA0F0, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0xA0F0, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0xA370, 0x0030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0038, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x003C, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0060, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0064, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x00A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x00A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0230, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0238, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x023C, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0260, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x02A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x1010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0xA370, 0x1030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x1210, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0xA370, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x2030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x2034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x4030, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x4034, iwl9560_2ac_160_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x40A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x4234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_cfg_qnj_jf_b0)}, /* 22000 Series */ + {IWL_PCI_DEVICE(0x2723, PCI_ANY_ID, iwl_ax200_trans_cfg)}, + {IWL_PCI_DEVICE(0x02F0, 0x0070, iwl_ax201_cfg_quz_hr)}, {IWL_PCI_DEVICE(0x02F0, 0x0074, iwl_ax201_cfg_quz_hr)}, {IWL_PCI_DEVICE(0x02F0, 0x0078, iwl_ax201_cfg_quz_hr)}, @@ -940,16 +786,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA0F0, 0x4070, iwl_ax201_cfg_qu_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x4244, iwl_ax101_cfg_qu_hr)}, - {IWL_PCI_DEVICE(0x2723, 0x0080, iwl_ax200_cfg_cc)}, - {IWL_PCI_DEVICE(0x2723, 0x0084, iwl_ax200_cfg_cc)}, - {IWL_PCI_DEVICE(0x2723, 0x0088, iwl_ax200_cfg_cc)}, - {IWL_PCI_DEVICE(0x2723, 0x008C, iwl_ax200_cfg_cc)}, - {IWL_PCI_DEVICE(0x2723, 0x1653, killer1650w_2ax_cfg)}, - {IWL_PCI_DEVICE(0x2723, 0x1654, killer1650x_2ax_cfg)}, - {IWL_PCI_DEVICE(0x2723, 0x2080, iwl_ax200_cfg_cc)}, - {IWL_PCI_DEVICE(0x2723, 0x4080, iwl_ax200_cfg_cc)}, - {IWL_PCI_DEVICE(0x2723, 0x4088, iwl_ax200_cfg_cc)}, - {IWL_PCI_DEVICE(0x2725, 0x0090, iwlax211_2ax_cfg_so_gf_a0)}, {IWL_PCI_DEVICE(0x2725, 0x0020, iwlax210_2ax_cfg_ty_gf_a0)}, {IWL_PCI_DEVICE(0x2725, 0x0310, iwlax210_2ax_cfg_ty_gf_a0)}, @@ -971,28 +807,139 @@ static const struct pci_device_id iwl_hw_card_ids[] = { }; MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); -#define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \ - { .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \ - .name = _name } +#define _IWL_DEV_INFO(_device, _subdevice, _mac_type, _rf_type, _rf_id, \ + _no_160, _cores, _cfg, _name) \ + { .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \ + .name = _name, .mac_type = _mac_type, .rf_type = _rf_type, \ + .no_160 = _no_160, .cores = _cores, .rf_id = _rf_id, } + +#define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \ + _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \ + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, _cfg, _name) static const struct iwl_dev_info iwl_dev_info_table[] = { #if IS_ENABLED(CONFIG_IWLMVM) - IWL_DEV_INFO(0x2526, 0x0010, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0x0014, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0x0018, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0x001C, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0x6010, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0x6014, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0x8014, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0x8010, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0xA014, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0xE010, iwl9260_2ac_160_cfg, iwl9260_160_name), - IWL_DEV_INFO(0x2526, 0xE014, iwl9260_2ac_160_cfg, iwl9260_160_name), - - IWL_DEV_INFO(0x2526, 0x0030, iwl9560_2ac_160_cfg, iwl9560_160_name), - IWL_DEV_INFO(0x2526, 0x0038, iwl9560_2ac_160_cfg, iwl9560_160_name), - IWL_DEV_INFO(0x2526, 0x003C, iwl9560_2ac_160_cfg, iwl9560_160_name), - IWL_DEV_INFO(0x2526, 0x4030, iwl9560_2ac_160_cfg, iwl9560_160_name), +/* 9000 */ + IWL_DEV_INFO(0x2526, 0x1550, iwl9260_2ac_cfg, iwl9260_killer_1550_name), + IWL_DEV_INFO(0x2526, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name), + IWL_DEV_INFO(0x2526, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name), + IWL_DEV_INFO(0x30DC, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name), + IWL_DEV_INFO(0x30DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name), + IWL_DEV_INFO(0x31DC, 0x1551, iwl9560_2ac_cfg_shared_clk, iwl9560_killer_1550s_name), + IWL_DEV_INFO(0x31DC, 0x1552, iwl9560_2ac_cfg_shared_clk, iwl9560_killer_1550i_name), + + IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name), + + _IWL_DEV_INFO(0x31DC, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_shared_clk, iwl9461_160_name), + _IWL_DEV_INFO(0x31DC, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_shared_clk, iwl9461_name), + _IWL_DEV_INFO(0x31DC, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_shared_clk, iwl9462_160_name), + _IWL_DEV_INFO(0x31DC, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_shared_clk, iwl9462_name), + + _IWL_DEV_INFO(0x31DC, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_shared_clk, iwl9560_160_name), + _IWL_DEV_INFO(0x31DC, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_shared_clk, iwl9560_name), + + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_soc, iwl9461_160_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_soc, iwl9461_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_soc, iwl9462_160_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_soc, iwl9462_name), + + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_soc, iwl9560_160_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PU, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg_soc, iwl9560_name), + + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg, iwl9461_160_name), + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg, iwl9461_name), + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg, iwl9462_160_name), + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg, iwl9462_name), + + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg, iwl9560_160_name), + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9560_2ac_cfg, iwl9560_name), + + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_TH, IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, + iwl9260_2ac_cfg, iwl9270_160_name), + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_TH, IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT_GNSS, + iwl9260_2ac_cfg, iwl9270_name), + + _IWL_DEV_INFO(0x271B, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_TH, IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9260_2ac_cfg, iwl9162_160_name), + _IWL_DEV_INFO(0x271B, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_TH, IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9260_2ac_cfg, iwl9162_name), + + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_TH, IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_CORES_BT, + iwl9260_2ac_cfg, iwl9260_160_name), + _IWL_DEV_INFO(0x2526, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_TH, IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_CORES_BT, + iwl9260_2ac_cfg, iwl9260_name), + +/* AX200 */ + IWL_DEV_INFO(0x2723, 0x1653, iwl_ax200_cfg_cc, iwl_ax200_killer_1650w_name), + IWL_DEV_INFO(0x2723, 0x1654, iwl_ax200_cfg_cc, iwl_ax200_killer_1650x_name), + IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name), + #endif /* CONFIG_IWLMVM */ }; @@ -1028,13 +975,29 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* the trans_cfg should never change, so set it now */ iwl_trans->trans_cfg = trans; + iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID); + for (i = 0; i < ARRAY_SIZE(iwl_dev_info_table); i++) { const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i]; - - if ((dev_info->device == IWL_CFG_ANY || + if ((dev_info->device == (u16)IWL_CFG_ANY || dev_info->device == pdev->device) && - (dev_info->subdevice == IWL_CFG_ANY || - dev_info->subdevice == pdev->subsystem_device)) { + (dev_info->subdevice == (u16)IWL_CFG_ANY || + dev_info->subdevice == pdev->subsystem_device) && + (dev_info->mac_type == (u16)IWL_CFG_ANY || + dev_info->mac_type == + CSR_HW_REV_TYPE(iwl_trans->hw_rev)) && + (dev_info->rf_type == (u16)IWL_CFG_ANY || + dev_info->rf_type == + CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id)) && + (dev_info->rf_id == (u8)IWL_CFG_ANY || + dev_info->rf_id == + IWL_SUBDEVICE_RF_ID(pdev->subsystem_device)) && + (dev_info->no_160 == (u8)IWL_CFG_ANY || + dev_info->no_160 == + IWL_SUBDEVICE_NO_160(pdev->subsystem_device)) && + (dev_info->cores == (u8)IWL_CFG_ANY || + dev_info->cores == + IWL_SUBDEVICE_CORES(pdev->subsystem_device))) { iwl_trans->cfg = dev_info->cfg; iwl_trans->name = dev_info->name; goto found; @@ -1059,8 +1022,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D) iwl_trans->cfg = cfg_7265d; - iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID); - if (cfg == &iwlax210_2ax_cfg_so_hr_a0) { if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_TY) { iwl_trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0; diff --git a/drivers/net/wireless/intersil/hostap/hostap_common.h b/drivers/net/wireless/intersil/hostap/hostap_common.h index 22543538239b..dd29a8e8d349 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_common.h +++ b/drivers/net/wireless/intersil/hostap/hostap_common.h @@ -322,7 +322,7 @@ struct prism2_download_param { u32 addr; /* wlan card address */ u32 len; void __user *ptr; /* pointer to data in user space */ - } data[0]; + } data[]; }; #define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072 diff --git a/drivers/net/wireless/intersil/hostap/hostap_wlan.h b/drivers/net/wireless/intersil/hostap/hostap_wlan.h index 487883fbb58c..dd2603d9b5d3 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_wlan.h +++ b/drivers/net/wireless/intersil/hostap/hostap_wlan.h @@ -615,7 +615,7 @@ struct prism2_download_data { u32 addr; /* wlan card address */ u32 len; u8 *data; /* allocated data */ - } data[0]; + } data[]; }; diff --git a/drivers/net/wireless/intersil/orinoco/fw.c b/drivers/net/wireless/intersil/orinoco/fw.c index 400a35217644..015af782881b 100644 --- a/drivers/net/wireless/intersil/orinoco/fw.c +++ b/drivers/net/wireless/intersil/orinoco/fw.c @@ -49,7 +49,7 @@ struct orinoco_fw_header { __le32 pdr_offset; /* Offset to PDR data from eof header */ __le32 pri_offset; /* Offset to primary plug data */ __le32 compat_offset; /* Offset to compatibility data*/ - char signature[0]; /* FW signature length headersize-20 */ + char signature[]; /* FW signature length headersize-20 */ } __packed; /* Check the range of various header entries. Return a pointer to a diff --git a/drivers/net/wireless/intersil/orinoco/hermes.h b/drivers/net/wireless/intersil/orinoco/hermes.h index 121fdd8e5da2..9f668185b7d2 100644 --- a/drivers/net/wireless/intersil/orinoco/hermes.h +++ b/drivers/net/wireless/intersil/orinoco/hermes.h @@ -341,7 +341,7 @@ struct agere_ext_scan_info { __le64 timestamp; __le16 beacon_interval; __le16 capabilities; - u8 data[0]; + u8 data[]; } __packed; #define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000) diff --git a/drivers/net/wireless/intersil/orinoco/hermes_dld.c b/drivers/net/wireless/intersil/orinoco/hermes_dld.c index 4a10b7aca043..dbeadfcfefe2 100644 --- a/drivers/net/wireless/intersil/orinoco/hermes_dld.c +++ b/drivers/net/wireless/intersil/orinoco/hermes_dld.c @@ -64,7 +64,7 @@ struct dblock { __le32 addr; /* adapter address where to write the block */ __le16 len; /* length of the data only, in bytes */ - char data[0]; /* data to be written */ + char data[]; /* data to be written */ } __packed; /* @@ -76,7 +76,7 @@ struct pdr { __le32 id; /* record ID */ __le32 addr; /* adapter address where to write the data */ __le32 len; /* expected length of the data, in bytes */ - char next[0]; /* next PDR starts here */ + char next[]; /* next PDR starts here */ } __packed; /* @@ -87,7 +87,7 @@ struct pdr { struct pdi { __le16 len; /* length of ID and data, in words */ __le16 id; /* record ID */ - char data[0]; /* plug data */ + char data[]; /* plug data */ } __packed; /*** FW data block access functions ***/ diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c index e753f43e0162..a77bbcd544d6 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c @@ -202,7 +202,7 @@ struct ezusb_packet { __le16 crc; /* CRC up to here */ __le16 hermes_len; __le16 hermes_rid; - u8 data[0]; + u8 data[]; } __packed; /* Table of devices that work or may work with this driver */ diff --git a/drivers/net/wireless/intersil/p54/eeprom.h b/drivers/net/wireless/intersil/p54/eeprom.h index b8f46883a292..1d0aaf54389a 100644 --- a/drivers/net/wireless/intersil/p54/eeprom.h +++ b/drivers/net/wireless/intersil/p54/eeprom.h @@ -24,7 +24,7 @@ struct pda_entry { __le16 len; /* includes both code and data */ __le16 code; - u8 data[0]; + u8 data[]; } __packed; struct eeprom_pda_wrap { @@ -32,7 +32,7 @@ struct eeprom_pda_wrap { __le16 pad; __le16 len; __le32 arm_opcode; - u8 data[0]; + u8 data[]; } __packed; struct p54_iq_autocal_entry { @@ -87,7 +87,7 @@ struct pda_pa_curve_data { u8 channels; u8 points_per_channel; u8 padding; - u8 data[0]; + u8 data[]; } __packed; struct pda_rssi_cal_ext_entry { @@ -119,7 +119,7 @@ struct pda_custom_wrapper { __le16 entry_size; __le16 offset; __le16 len; - u8 data[0]; + u8 data[]; } __packed; /* diff --git a/drivers/net/wireless/intersil/p54/lmac.h b/drivers/net/wireless/intersil/p54/lmac.h index e00761536cfc..8adde6ba35ab 100644 --- a/drivers/net/wireless/intersil/p54/lmac.h +++ b/drivers/net/wireless/intersil/p54/lmac.h @@ -81,7 +81,7 @@ struct p54_hdr { __le16 type; /* enum p54_control_frame_types */ u8 rts_tries; u8 tries; - u8 data[0]; + u8 data[]; } __packed; #define GET_REQ_ID(skb) \ @@ -176,7 +176,7 @@ struct p54_rx_data { u8 rssi_raw; __le32 tsf32; __le32 unalloc0; - u8 align[0]; + u8 align[]; } __packed; enum p54_trap_type { @@ -267,7 +267,7 @@ struct p54_tx_data { } __packed normal; } __packed; u8 unalloc2[2]; - u8 align[0]; + u8 align[]; } __packed; /* unit is ms */ diff --git a/drivers/net/wireless/intersil/p54/p54.h b/drivers/net/wireless/intersil/p54/p54.h index 0a9c1a19380f..3356ea708d81 100644 --- a/drivers/net/wireless/intersil/p54/p54.h +++ b/drivers/net/wireless/intersil/p54/p54.h @@ -126,7 +126,7 @@ struct p54_cal_database { size_t entry_size; size_t offset; size_t len; - u8 data[0]; + u8 data[]; }; #define EEPROM_READBACK_LEN 0x3fc diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index da0a6b6c4771..7fe8207db6ae 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -4,7 +4,7 @@ * Copyright (c) 2008, Jouni Malinen <j@w1.fi> * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com> * Copyright (c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2020 Intel Corporation */ /* @@ -33,6 +33,9 @@ #include <net/netns/generic.h> #include <linux/rhashtable.h> #include <linux/nospec.h> +#include <linux/virtio.h> +#include <linux/virtio_ids.h> +#include <linux/virtio_config.h> #include "mac80211_hwsim.h" #define WARN_QUEUE 100 @@ -613,14 +616,14 @@ static const struct genl_multicast_group hwsim_mcgrps[] = { /* MAC80211_HWSIM netlink policy */ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { - [HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, - [HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, + [HWSIM_ATTR_ADDR_RECEIVER] = NLA_POLICY_ETH_ADDR_COMPAT, + [HWSIM_ATTR_ADDR_TRANSMITTER] = NLA_POLICY_ETH_ADDR_COMPAT, [HWSIM_ATTR_FRAME] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, [HWSIM_ATTR_FLAGS] = { .type = NLA_U32 }, [HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 }, [HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 }, - [HWSIM_ATTR_TX_INFO] = { .type = NLA_UNSPEC, + [HWSIM_ATTR_TX_INFO] = { .type = NLA_BINARY, .len = IEEE80211_TX_MAX_RATES * sizeof(struct hwsim_tx_rate)}, [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, @@ -630,15 +633,61 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, + [HWSIM_ATTR_USE_CHANCTX] = { .type = NLA_FLAG }, [HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG }, [HWSIM_ATTR_RADIO_NAME] = { .type = NLA_STRING }, [HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG }, [HWSIM_ATTR_FREQ] = { .type = NLA_U32 }, - [HWSIM_ATTR_PERM_ADDR] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, + [HWSIM_ATTR_TX_INFO_FLAGS] = { .type = NLA_BINARY }, + [HWSIM_ATTR_PERM_ADDR] = NLA_POLICY_ETH_ADDR_COMPAT, [HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 }, [HWSIM_ATTR_CIPHER_SUPPORT] = { .type = NLA_BINARY }, }; +#if IS_REACHABLE(CONFIG_VIRTIO) + +/* MAC80211_HWSIM virtio queues */ +static struct virtqueue *hwsim_vqs[HWSIM_NUM_VQS]; +static bool hwsim_virtio_enabled; +static spinlock_t hwsim_virtio_lock; + +static void hwsim_virtio_rx_work(struct work_struct *work); +static DECLARE_WORK(hwsim_virtio_rx, hwsim_virtio_rx_work); + +static int hwsim_tx_virtio(struct mac80211_hwsim_data *data, + struct sk_buff *skb) +{ + struct scatterlist sg[1]; + unsigned long flags; + int err; + + spin_lock_irqsave(&hwsim_virtio_lock, flags); + if (!hwsim_virtio_enabled) { + err = -ENODEV; + goto out_free; + } + + sg_init_one(sg, skb->head, skb_end_offset(skb)); + err = virtqueue_add_outbuf(hwsim_vqs[HWSIM_VQ_TX], sg, 1, skb, + GFP_ATOMIC); + if (err) + goto out_free; + virtqueue_kick(hwsim_vqs[HWSIM_VQ_TX]); + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); + return 0; + +out_free: + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); + nlmsg_free(skb); + return err; +} +#else +/* cause a linker error if this ends up being needed */ +extern int hwsim_tx_virtio(struct mac80211_hwsim_data *data, + struct sk_buff *skb); +#define hwsim_virtio_enabled false +#endif + static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_channel *chan); @@ -1138,8 +1187,14 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, goto nla_put_failure; genlmsg_end(skb, msg_head); - if (hwsim_unicast_netgroup(data, skb, dst_portid)) - goto err_free_txskb; + + if (hwsim_virtio_enabled) { + if (hwsim_tx_virtio(data, skb)) + goto err_free_txskb; + } else { + if (hwsim_unicast_netgroup(data, skb, dst_portid)) + goto err_free_txskb; + } /* Enqueue the packet */ skb_queue_tail(&data->pending, my_skb); @@ -1441,7 +1496,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, /* wmediumd mode check */ _portid = READ_ONCE(data->wmediumd); - if (_portid) + if (_portid || hwsim_virtio_enabled) return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); /* NO wmediumd detected, perfect medium simulation */ @@ -1547,7 +1602,7 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, mac80211_hwsim_monitor_rx(hw, skb, chan); - if (_pid) + if (_pid || hwsim_virtio_enabled) return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); mac80211_hwsim_tx_frame_no_nl(hw, skb, chan); @@ -3293,11 +3348,14 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, if (!data2) goto out; - if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup) - goto out; + if (!hwsim_virtio_enabled) { + if (hwsim_net_get_netgroup(genl_info_net(info)) != + data2->netgroup) + goto out; - if (info->snd_portid != data2->wmediumd) - goto out; + if (info->snd_portid != data2->wmediumd) + goto out; + } /* look for the skb matching the cookie passed back from user */ skb_queue_walk_safe(&data2->pending, skb, tmp) { @@ -3387,11 +3445,14 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, if (!data2) goto out; - if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup) - goto out; + if (!hwsim_virtio_enabled) { + if (hwsim_net_get_netgroup(genl_info_net(info)) != + data2->netgroup) + goto out; - if (info->snd_portid != data2->wmediumd) - goto out; + if (info->snd_portid != data2->wmediumd) + goto out; + } /* check if radio is configured properly */ @@ -3932,6 +3993,229 @@ static void hwsim_exit_netlink(void) genl_unregister_family(&hwsim_genl_family); } +#if IS_REACHABLE(CONFIG_VIRTIO) +static void hwsim_virtio_tx_done(struct virtqueue *vq) +{ + unsigned int len; + struct sk_buff *skb; + unsigned long flags; + + spin_lock_irqsave(&hwsim_virtio_lock, flags); + while ((skb = virtqueue_get_buf(vq, &len))) + nlmsg_free(skb); + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); +} + +static int hwsim_virtio_handle_cmd(struct sk_buff *skb) +{ + struct nlmsghdr *nlh; + struct genlmsghdr *gnlh; + struct nlattr *tb[HWSIM_ATTR_MAX + 1]; + struct genl_info info = {}; + int err; + + nlh = nlmsg_hdr(skb); + gnlh = nlmsg_data(nlh); + err = genlmsg_parse(nlh, &hwsim_genl_family, tb, HWSIM_ATTR_MAX, + hwsim_genl_policy, NULL); + if (err) { + pr_err_ratelimited("hwsim: genlmsg_parse returned %d\n", err); + return err; + } + + info.attrs = tb; + + switch (gnlh->cmd) { + case HWSIM_CMD_FRAME: + hwsim_cloned_frame_received_nl(skb, &info); + break; + case HWSIM_CMD_TX_INFO_FRAME: + hwsim_tx_info_frame_received_nl(skb, &info); + break; + default: + pr_err_ratelimited("hwsim: invalid cmd: %d\n", gnlh->cmd); + return -EPROTO; + } + return 0; +} + +static void hwsim_virtio_rx_work(struct work_struct *work) +{ + struct virtqueue *vq; + unsigned int len; + struct sk_buff *skb; + struct scatterlist sg[1]; + int err; + unsigned long flags; + + spin_lock_irqsave(&hwsim_virtio_lock, flags); + if (!hwsim_virtio_enabled) + goto out_unlock; + + skb = virtqueue_get_buf(hwsim_vqs[HWSIM_VQ_RX], &len); + if (!skb) + goto out_unlock; + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); + + skb->data = skb->head; + skb_set_tail_pointer(skb, len); + hwsim_virtio_handle_cmd(skb); + + spin_lock_irqsave(&hwsim_virtio_lock, flags); + if (!hwsim_virtio_enabled) { + nlmsg_free(skb); + goto out_unlock; + } + vq = hwsim_vqs[HWSIM_VQ_RX]; + sg_init_one(sg, skb->head, skb_end_offset(skb)); + err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL); + if (WARN(err, "virtqueue_add_inbuf returned %d\n", err)) + nlmsg_free(skb); + else + virtqueue_kick(vq); + schedule_work(&hwsim_virtio_rx); + +out_unlock: + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); +} + +static void hwsim_virtio_rx_done(struct virtqueue *vq) +{ + schedule_work(&hwsim_virtio_rx); +} + +static int init_vqs(struct virtio_device *vdev) +{ + vq_callback_t *callbacks[HWSIM_NUM_VQS] = { + [HWSIM_VQ_TX] = hwsim_virtio_tx_done, + [HWSIM_VQ_RX] = hwsim_virtio_rx_done, + }; + const char *names[HWSIM_NUM_VQS] = { + [HWSIM_VQ_TX] = "tx", + [HWSIM_VQ_RX] = "rx", + }; + + return virtio_find_vqs(vdev, HWSIM_NUM_VQS, + hwsim_vqs, callbacks, names, NULL); +} + +static int fill_vq(struct virtqueue *vq) +{ + int i, err; + struct sk_buff *skb; + struct scatterlist sg[1]; + + for (i = 0; i < virtqueue_get_vring_size(vq); i++) { + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + sg_init_one(sg, skb->head, skb_end_offset(skb)); + err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL); + if (err) { + nlmsg_free(skb); + return err; + } + } + virtqueue_kick(vq); + return 0; +} + +static void remove_vqs(struct virtio_device *vdev) +{ + int i; + + vdev->config->reset(vdev); + + for (i = 0; i < ARRAY_SIZE(hwsim_vqs); i++) { + struct virtqueue *vq = hwsim_vqs[i]; + struct sk_buff *skb; + + while ((skb = virtqueue_detach_unused_buf(vq))) + nlmsg_free(skb); + } + + vdev->config->del_vqs(vdev); +} + +static int hwsim_virtio_probe(struct virtio_device *vdev) +{ + int err; + unsigned long flags; + + spin_lock_irqsave(&hwsim_virtio_lock, flags); + if (hwsim_virtio_enabled) { + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); + return -EEXIST; + } + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); + + err = init_vqs(vdev); + if (err) + return err; + + err = fill_vq(hwsim_vqs[HWSIM_VQ_RX]); + if (err) + goto out_remove; + + spin_lock_irqsave(&hwsim_virtio_lock, flags); + hwsim_virtio_enabled = true; + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); + + schedule_work(&hwsim_virtio_rx); + return 0; + +out_remove: + remove_vqs(vdev); + return err; +} + +static void hwsim_virtio_remove(struct virtio_device *vdev) +{ + hwsim_virtio_enabled = false; + + cancel_work_sync(&hwsim_virtio_rx); + + remove_vqs(vdev); +} + +/* MAC80211_HWSIM virtio device id table */ +static const struct virtio_device_id id_table[] = { + { VIRTIO_ID_MAC80211_HWSIM, VIRTIO_DEV_ANY_ID }, + { 0 } +}; +MODULE_DEVICE_TABLE(virtio, id_table); + +static struct virtio_driver virtio_hwsim = { + .driver.name = KBUILD_MODNAME, + .driver.owner = THIS_MODULE, + .id_table = id_table, + .probe = hwsim_virtio_probe, + .remove = hwsim_virtio_remove, +}; + +static int hwsim_register_virtio_driver(void) +{ + spin_lock_init(&hwsim_virtio_lock); + + return register_virtio_driver(&virtio_hwsim); +} + +static void hwsim_unregister_virtio_driver(void) +{ + unregister_virtio_driver(&virtio_hwsim); +} +#else +static inline int hwsim_register_virtio_driver(void) +{ + return 0; +} + +static inline void hwsim_unregister_virtio_driver(void) +{ +} +#endif + static int __init init_mac80211_hwsim(void) { int i, err; @@ -3960,10 +4244,14 @@ static int __init init_mac80211_hwsim(void) if (err) goto out_unregister_driver; + err = hwsim_register_virtio_driver(); + if (err) + goto out_exit_netlink; + hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); if (IS_ERR(hwsim_class)) { err = PTR_ERR(hwsim_class); - goto out_exit_netlink; + goto out_exit_virtio; } for (i = 0; i < radios; i++) { @@ -4075,6 +4363,8 @@ out_free_mon: free_netdev(hwsim_mon); out_free_radios: mac80211_hwsim_free(); +out_exit_virtio: + hwsim_unregister_virtio_driver(); out_exit_netlink: hwsim_exit_netlink(); out_unregister_driver: @@ -4091,6 +4381,7 @@ static void __exit exit_mac80211_hwsim(void) { pr_debug("mac80211_hwsim: unregister radios\n"); + hwsim_unregister_virtio_driver(); hwsim_exit_netlink(); mac80211_hwsim_free(); diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index a85bc7c5c030..28ade92adcb4 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h @@ -3,6 +3,7 @@ * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211 * Copyright (c) 2008, Jouni Malinen <j@w1.fi> * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com> + * Copyright (C) 2020 Intel Corporation */ #ifndef __MAC80211_HWSIM_H @@ -245,4 +246,24 @@ struct hwsim_tx_rate_flag { s8 idx; u16 flags; } __packed; + +/** + * DOC: Frame transmission support over virtio + * + * Frame transmission is also supported over virtio to allow communication + * with external entities. + */ + +/** + * enum hwsim_vqs - queues for virtio frame transmission + * + * @HWSIM_VQ_TX: send frames to external entity + * @HWSIM_VQ_RX: receive frames and transmission info reports + * @HWSIM_NUM_VQS: enum limit + */ +enum { + HWSIM_VQ_TX, + HWSIM_VQ_RX, + HWSIM_NUM_VQS, +}; #endif /* __MAC80211_HWSIM_H */ diff --git a/drivers/net/wireless/marvell/libertas/host.h b/drivers/net/wireless/marvell/libertas/host.h index a4fc3f79bb17..dfa22468b14a 100644 --- a/drivers/net/wireless/marvell/libertas/host.h +++ b/drivers/net/wireless/marvell/libertas/host.h @@ -461,7 +461,7 @@ struct cmd_ds_802_11_scan { uint8_t bsstype; uint8_t bssid[ETH_ALEN]; - uint8_t tlvbuffer[0]; + uint8_t tlvbuffer[]; } __packed; struct cmd_ds_802_11_scan_rsp { @@ -469,7 +469,7 @@ struct cmd_ds_802_11_scan_rsp { __le16 bssdescriptsize; uint8_t nr_sets; - uint8_t bssdesc_and_tlvbuffer[0]; + uint8_t bssdesc_and_tlvbuffer[]; } __packed; struct cmd_ds_802_11_get_log { diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index 30f1025ecb9b..acf61b93b782 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -103,7 +103,7 @@ MODULE_FIRMWARE("sd8688.bin"); struct if_sdio_packet { struct if_sdio_packet *next; u16 nb; - u8 buffer[0] __attribute__((aligned(4))); + u8 buffer[] __aligned(4); }; struct if_sdio_card { diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c index 3c3f266bf116..cd9f8ecf171f 100644 --- a/drivers/net/wireless/marvell/libertas/if_spi.c +++ b/drivers/net/wireless/marvell/libertas/if_spi.c @@ -35,7 +35,7 @@ struct if_spi_packet { struct list_head list; u16 blen; - u8 buffer[0] __attribute__((aligned(4))); + u8 buffer[] __aligned(4); }; struct if_spi_card { diff --git a/drivers/net/wireless/marvell/libertas/if_usb.h b/drivers/net/wireless/marvell/libertas/if_usb.h index 8dc14bec3e16..7d0daeb33c3f 100644 --- a/drivers/net/wireless/marvell/libertas/if_usb.h +++ b/drivers/net/wireless/marvell/libertas/if_usb.h @@ -91,7 +91,7 @@ struct fwheader { struct fwdata { struct fwheader hdr; __le32 seqnum; - uint8_t data[0]; + uint8_t data[]; }; /* fwsyncheader */ diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.h b/drivers/net/wireless/marvell/libertas_tf/if_usb.h index 585ad36f9055..f6dd7373b09e 100644 --- a/drivers/net/wireless/marvell/libertas_tf/if_usb.h +++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.h @@ -81,7 +81,7 @@ struct fwheader { struct fwdata { struct fwheader hdr; __le32 seqnum; - uint8_t data[0]; + uint8_t data[]; }; /** fwsyncheader */ diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 4dfdf928f705..a415d73a73e6 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -846,7 +846,7 @@ struct mwifiex_ie_types_random_mac { struct mwifiex_ietypes_chanstats { struct mwifiex_ie_types_header header; - struct mwifiex_fw_chan_stats chanstats[0]; + struct mwifiex_fw_chan_stats chanstats[]; } __packed; struct mwifiex_ie_types_wildcard_ssid_params { @@ -1082,7 +1082,7 @@ struct host_cmd_ds_get_hw_spec { __le32 reserved_6; __le32 dot_11ac_dev_cap; __le32 dot_11ac_mcs_support; - u8 tlvs[0]; + u8 tlvs[]; } __packed; struct host_cmd_ds_802_11_rssi_info { @@ -1140,7 +1140,7 @@ struct ieee_types_assoc_rsp { __le16 cap_info_bitmap; __le16 status_code; __le16 a_id; - u8 ie_buffer[0]; + u8 ie_buffer[]; } __packed; struct host_cmd_ds_802_11_associate_rsp { @@ -1455,7 +1455,7 @@ struct host_cmd_ds_chan_rpt_event { __le32 result; __le64 start_tsf; __le32 duration; - u8 tlvbuf[0]; + u8 tlvbuf[]; } __packed; struct host_cmd_sdio_sp_rx_aggr_cfg { @@ -1625,7 +1625,7 @@ struct host_cmd_ds_802_11_bg_scan_config { __le32 reserved2; __le32 report_condition; __le16 reserved3; - u8 tlv[0]; + u8 tlv[]; } __packed; struct host_cmd_ds_802_11_bg_scan_query { @@ -1720,7 +1720,7 @@ struct mwifiex_ie_types_sta_info { struct host_cmd_ds_sta_list { __le16 sta_count; - u8 tlv[0]; + u8 tlv[]; } __packed; struct mwifiex_ie_types_pwr_capability { @@ -1743,7 +1743,7 @@ struct mwifiex_ie_types_wmm_param_set { struct mwifiex_ie_types_mgmt_frame { struct mwifiex_ie_types_header header; __le16 frame_control; - u8 frame_contents[0]; + u8 frame_contents[]; }; struct mwifiex_ie_types_wmm_queue_status { @@ -1861,7 +1861,7 @@ struct mwifiex_ie_types_2040bssco { struct mwifiex_ie_types_extcap { struct mwifiex_ie_types_header header; - u8 ext_capab[0]; + u8 ext_capab[]; } __packed; struct host_cmd_ds_mem_access { @@ -1918,12 +1918,12 @@ struct mwifiex_assoc_event { __le16 frame_control; __le16 cap_info; __le16 listen_interval; - u8 data[0]; + u8 data[]; } __packed; struct host_cmd_ds_sys_config { __le16 action; - u8 tlv[0]; + u8 tlv[]; }; struct host_cmd_11ac_vht_cfg { @@ -1956,7 +1956,7 @@ struct host_cmd_tlv_gwk_cipher { struct host_cmd_tlv_passphrase { struct mwifiex_ie_types_header header; - u8 passphrase[0]; + u8 passphrase[]; } __packed; struct host_cmd_tlv_wep_key { @@ -1978,12 +1978,12 @@ struct host_cmd_tlv_encrypt_protocol { struct host_cmd_tlv_ssid { struct mwifiex_ie_types_header header; - u8 ssid[0]; + u8 ssid[]; } __packed; struct host_cmd_tlv_rates { struct mwifiex_ie_types_header header; - u8 rates[0]; + u8 rates[]; } __packed; struct mwifiex_ie_types_bssid_list { @@ -2100,13 +2100,13 @@ struct mwifiex_fw_mef_entry { u8 mode; u8 action; __le16 exprsize; - u8 expr[0]; + u8 expr[]; } __packed; struct host_cmd_ds_mef_cfg { __le32 criteria; __le16 num_entries; - struct mwifiex_fw_mef_entry mef_entry[0]; + struct mwifiex_fw_mef_entry mef_entry[]; } __packed; #define CONNECTION_TYPE_INFRA 0 @@ -2169,7 +2169,7 @@ struct mwifiex_radar_det_event { struct mwifiex_ie_types_multi_chan_info { struct mwifiex_ie_types_header header; __le16 status; - u8 tlv_buffer[0]; + u8 tlv_buffer[]; } __packed; struct mwifiex_ie_types_mc_group_info { @@ -2185,7 +2185,7 @@ struct mwifiex_ie_types_mc_group_info { u8 usb_ep_num; } hid_num; u8 intf_num; - u8 bss_type_numlist[0]; + u8 bss_type_numlist[]; } __packed; struct meas_rpt_map { @@ -2250,13 +2250,13 @@ struct coalesce_receive_filt_rule { u8 num_of_fields; u8 pkt_type; __le16 max_coalescing_delay; - struct coalesce_filt_field_param params[0]; + struct coalesce_filt_field_param params[]; } __packed; struct host_cmd_ds_coalesce_cfg { __le16 action; __le16 num_of_rules; - struct coalesce_receive_filt_rule rule[0]; + struct coalesce_receive_filt_rule rule[]; } __packed; struct host_cmd_ds_multi_chan_policy { @@ -2295,7 +2295,7 @@ struct host_cmd_ds_pkt_aggr_ctrl { struct host_cmd_ds_sta_configure { __le16 action; - u8 tlv_buffer[0]; + u8 tlv_buffer[]; } __packed; struct host_cmd_ds_command { diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c index d55f229abeea..47fb4b3ea004 100644 --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c @@ -592,7 +592,7 @@ struct mwl8k_cmd_pkt { __u8 seq_num; __u8 macid; __le16 result; - char payload[0]; + char payload[]; } __packed; /* @@ -806,7 +806,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) struct mwl8k_dma_data { __le16 fwlen; struct ieee80211_hdr wh; - char data[0]; + char data[]; } __packed; /* Routines to add/remove DMA header from skb. */ @@ -2955,7 +2955,7 @@ mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask) struct mwl8k_cmd_set_beacon { struct mwl8k_cmd_pkt header; __le16 beacon_len; - __u8 beacon[0]; + __u8 beacon[]; }; static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index e5dd7080e88e..75e659774e07 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -467,10 +467,13 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data, struct page *page = virt_to_head_page(data); int offset = data - page_address(page); struct sk_buff *skb = q->rx_head; + struct skb_shared_info *shinfo = skb_shinfo(skb); - offset += q->buf_offset; - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, offset, len, - q->buf_size); + if (shinfo->nr_frags < ARRAY_SIZE(shinfo->frags)) { + offset += q->buf_offset; + skb_add_rx_frag(skb, shinfo->nr_frags, page, offset, len, + q->buf_size); + } if (more) return; diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index 633ad948c21d..4048f446e3ee 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -9,14 +9,16 @@ struct sk_buff * mt76_mcu_msg_alloc(const void *data, int head_len, int data_len, int tail_len) { + int length = head_len + data_len + tail_len; struct sk_buff *skb; - skb = alloc_skb(head_len + data_len + tail_len, - GFP_KERNEL); + skb = alloc_skb(length, GFP_KERNEL); if (!skb) return NULL; + memset(skb->head, 0, length); skb_reserve(skb, head_len); + if (data && data_len) skb_put_data(skb, data, data_len); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 2e57e7c6bd29..8e4759bc8f59 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -139,6 +139,8 @@ struct mt76_sw_queue { struct mt76_mcu_ops { int (*mcu_send_msg)(struct mt76_dev *dev, int cmd, const void *data, int len, bool wait_resp); + int (*mcu_skb_send_msg)(struct mt76_dev *dev, struct sk_buff *skb, + int cmd, bool wait_resp); int (*mcu_wr_rp)(struct mt76_dev *dev, u32 base, const struct mt76_reg_pair *rp, int len); int (*mcu_rd_rp)(struct mt76_dev *dev, u32 base, @@ -403,7 +405,6 @@ struct mt76_mcu { #define MCU_RESP_URB_SIZE 1024 struct mt76_usb { struct mutex usb_ctrl_mtx; - __le32 reg_val; u8 *data; u16 data_len; @@ -589,7 +590,9 @@ enum mt76_phy_type { #define mt76_rd_rp(dev, ...) (dev)->mt76.bus->rd_rp(&((dev)->mt76), __VA_ARGS__) #define mt76_mcu_send_msg(dev, ...) (dev)->mt76.mcu_ops->mcu_send_msg(&((dev)->mt76), __VA_ARGS__) + #define __mt76_mcu_send_msg(dev, ...) (dev)->mcu_ops->mcu_send_msg((dev), __VA_ARGS__) +#define __mt76_mcu_skb_send_msg(dev, ...) (dev)->mcu_ops->mcu_skb_send_msg((dev), __VA_ARGS__) #define mt76_mcu_restart(dev, ...) (dev)->mt76.mcu_ops->mcu_restart(&((dev)->mt76)) #define __mt76_mcu_restart(dev, ...) (dev)->mcu_ops->mcu_restart((dev)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c index 47c85a9fac28..cc7c788abedd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c @@ -121,4 +121,8 @@ void mt7603_init_debugfs(struct mt7603_dev *dev) mt7603_reset_read); debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, mt7603_radio_read); + debugfs_create_u8("sensitivity_limit", 0600, dir, + &dev->sensitivity_limit); + debugfs_create_bool("dynamic_sensitivity", 0600, dir, + &dev->dynamic_sensitivity); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 9e40e81bcc29..f641a8b56b39 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -540,6 +540,8 @@ int mt7603_register_device(struct mt7603_dev *dev) dev->mphy.antenna_mask = 1; dev->slottime = 9; + dev->sensitivity_limit = 28; + dev->dynamic_sensitivity = true; ret = mt7603_init_hardware(dev); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 8f5ca9283f7d..39b7c5d6e6cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1727,6 +1727,9 @@ mt7603_false_cca_check(struct mt7603_dev *dev) int min_signal; u32 val; + if (!dev->dynamic_sensitivity) + return; + val = mt76_rr(dev, MT_PHYCTRL_STAT_PD); pd_cck = FIELD_GET(MT_PHYCTRL_STAT_PD_CCK, val); pd_ofdm = FIELD_GET(MT_PHYCTRL_STAT_PD_OFDM, val); @@ -1750,7 +1753,8 @@ mt7603_false_cca_check(struct mt7603_dev *dev) min_signal -= 15; false_cca = dev->false_cca_ofdm + dev->false_cca_cck; - if (false_cca > 600) { + if (false_cca > 600 && + dev->sensitivity < -100 + dev->sensitivity_limit) { if (!dev->sensitivity) dev->sensitivity = -92; else diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index b466b3ab8a2c..77985d81c447 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -27,7 +27,6 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, seq = ++mdev->mcu.msg_seq & 0xf; txd = (struct mt7603_mcu_txd *)skb_push(skb, hdrlen); - memset(txd, 0, hdrlen); txd->len = cpu_to_le16(skb->len); if (cmd == -MCU_CMD_FW_SCATTER) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index ef374641fe80..7fadf094e9be 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -142,7 +142,9 @@ struct mt7603_dev { u8 ed_strict_mode; u8 ed_strong_signal; + bool dynamic_sensitivity; s8 sensitivity; + u8 sensitivity_limit; u8 beacon_check; u8 tx_hang_check; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 1bc71f5081ce..b19f208e3d54 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -101,8 +101,12 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, __le32 *rxd = (__le32 *)skb->data; __le32 *end = (__le32 *)&skb->data[skb->len]; enum rx_pkt_type type; + u16 flag; type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0])); + if (type == PKT_TYPE_RX_EVENT && flag == 0x1) + type = PKT_TYPE_NORMAL_MCU; switch (type) { case PKT_TYPE_TXS: @@ -116,6 +120,7 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, case PKT_TYPE_RX_EVENT: mt7615_mcu_rx_event(dev, skb); break; + case PKT_TYPE_NORMAL_MCU: case PKT_TYPE_NORMAL: if (!mt7615_mac_fill_rx(dev, skb)) { mt76_rx(&dev->mt76, q, skb); @@ -186,6 +191,41 @@ static void mt7622_dma_sched_init(struct mt7615_dev *dev) mt76_wr(dev, reg + MT_DMASHDL_SCHED_SET1, 0xedcba987); } +static void mt7663_dma_sched_init(struct mt7615_dev *dev) +{ + int i; + + mt76_rmw(dev, MT_DMA_SHDL(MT_DMASHDL_PKT_MAX_SIZE), + MT_DMASHDL_PKT_MAX_SIZE_PLE | MT_DMASHDL_PKT_MAX_SIZE_PSE, + FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PLE, 1) | + FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PSE, 8)); + + /* enable refill control group 0, 1, 2, 4, 5 */ + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_REFILL), 0xffc80000); + /* enable group 0, 1, 2, 4, 5, 15 */ + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_OPTIONAL), 0x70068037); + + /* each group min quota must larger then PLE_PKT_MAX_SIZE_NUM */ + for (i = 0; i < 5; i++) + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_GROUP_QUOTA(i)), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x40) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x800)); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_GROUP_QUOTA(5)), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x40) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x40)); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_GROUP_QUOTA(15)), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x20) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x20)); + + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(0)), 0x42104210); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(1)), 0x42104210); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(2)), 0x00050005); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(3)), 0); + /* ALTX0 and ALTX1 QID mapping to group 5 */ + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET0), 0x6012345f); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET1), 0xedcba987); +} + int mt7615_dma_init(struct mt7615_dev *dev) { int rx_ring_size = MT7615_RX_RING_SIZE; @@ -198,10 +238,6 @@ int mt7615_dma_init(struct mt7615_dev *dev) MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN | MT_WPDMA_GLO_CFG_OMIT_TX_INFO); - if (!is_mt7622(&dev->mt76)) - mt76_set(dev, MT_WPDMA_GLO_CFG, - MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY); - mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0, 0x1); @@ -215,6 +251,9 @@ int mt7615_dma_init(struct mt7615_dev *dev) MT_WPDMA_GLO_CFG_MULTI_DMA_EN, 0x3); if (is_mt7615(&dev->mt76)) { + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY); + mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1); mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000); mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000); @@ -271,6 +310,9 @@ int mt7615_dma_init(struct mt7615_dev *dev) if (is_mt7622(&dev->mt76)) mt7622_dma_sched_init(dev); + if (is_mt7663(&dev->mt76)) + mt7663_dma_sched_init(dev); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 5220c18e711f..dfa9a08b896d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -91,11 +91,23 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) } } -static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) +static void +mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) { - u8 *eeprom = dev->mt76.eeprom.data; - u8 tx_mask, max_nss; - u32 val; + u8 val, *eeprom = dev->mt76.eeprom.data; + + if (is_mt7663(&dev->mt76)) { + /* dual band */ + dev->mt76.cap.has_2ghz = true; + dev->mt76.cap.has_5ghz = true; + return; + } + + if (is_mt7622(&dev->mt76)) { + /* 2GHz only */ + dev->mt76.cap.has_2ghz = true; + return; + } val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, eeprom[MT_EE_WIFI_CONF]); @@ -111,18 +123,30 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) dev->mt76.cap.has_5ghz = true; break; } +} + +static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) +{ + u8 *eeprom = dev->mt76.eeprom.data; + u8 tx_mask; + + mt7615_eeprom_parse_hw_band_cap(dev); - if (is_mt7622(&dev->mt76)) - dev->mt76.cap.has_5ghz = false; + if (is_mt7663(&dev->mt76)) { + tx_mask = 2; + } else { + u8 max_nss; + u32 val; - /* read tx-rx mask from eeprom */ - val = mt76_rr(dev, MT_TOP_STRAP_STA); - max_nss = val & MT_TOP_3NSS ? 3 : 4; + /* read tx-rx mask from eeprom */ + val = mt76_rr(dev, MT_TOP_STRAP_STA); + max_nss = val & MT_TOP_3NSS ? 3 : 4; - tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK, - eeprom[MT_EE_NIC_CONF_0]); - if (!tx_mask || tx_mask > max_nss) - tx_mask = max_nss; + tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK, + eeprom[MT_EE_NIC_CONF_0]); + if (!tx_mask || tx_mask > max_nss) + tx_mask = max_nss; + } dev->chainmask = BIT(tx_mask) - 1; dev->mphy.antenna_mask = dev->chainmask; @@ -229,6 +253,18 @@ static void mt7622_apply_cal_free_data(struct mt7615_dev *dev) } } +static void mt7615_cal_free_data(struct mt7615_dev *dev) +{ + switch (mt76_chip(&dev->mt76)) { + case 0x7622: + mt7622_apply_cal_free_data(dev); + break; + case 0x7615: + mt7615_apply_cal_free_data(dev); + break; + } +} + int mt7615_eeprom_init(struct mt7615_dev *dev) { int ret; @@ -241,10 +277,8 @@ int mt7615_eeprom_init(struct mt7615_dev *dev) if (ret && dev->mt76.otp.data) memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, MT7615_EEPROM_SIZE); - else if (is_mt7622(&dev->mt76)) - mt7622_apply_cal_free_data(dev); else - mt7615_apply_cal_free_data(dev); + mt7615_cal_free_data(dev); mt7615_eeprom_parse_hw_cap(dev); memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index 18c7301521b7..8a2a64b7fcd3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -18,11 +18,13 @@ enum mt7615_eeprom_field { MT_EE_TX1_5G_G0_TARGET_POWER = 0x098, MT_EE_EXT_PA_2G_TARGET_POWER = 0x0f2, MT_EE_EXT_PA_5G_TARGET_POWER = 0x0f3, + MT7663_EE_TX0_2G_TARGET_POWER = 0x123, MT_EE_TX2_5G_G0_TARGET_POWER = 0x142, MT_EE_TX3_5G_G0_TARGET_POWER = 0x16a, MT7615_EE_MAX = 0x3bf, MT7622_EE_MAX = 0x3db, + MT7663_EE_MAX = 0x400, }; #define MT_EE_NIC_CONF_TX_MASK GENMASK(7, 4) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 889eb72ad6bd..03b1e56534d6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -4,6 +4,7 @@ * Author: Roy Luo <royluo@google.com> * Ryder Lee <ryder.lee@mediatek.com> * Felix Fietkau <nbd@nbd.name> + * Lorenzo Bianconi <lorenzo@kernel.org> */ #include <linux/etherdevice.h> @@ -18,27 +19,65 @@ static void mt7615_phy_init(struct mt7615_dev *dev) mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(1), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); } -static void mt7615_mac_init(struct mt7615_dev *dev) +static void +mt7615_init_mac_chain(struct mt7615_dev *dev, int chain) { u32 val, mask, set; - int i; + + if (!chain) + val = MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN; + else + val = MT_CFG_CCR_MAC_D1_1X_GC_EN | MT_CFG_CCR_MAC_D1_2X_GC_EN; /* enable band 0/1 clk */ - mt76_set(dev, MT_CFG_CCR, - MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN | - MT_CFG_CCR_MAC_D1_1X_GC_EN | MT_CFG_CCR_MAC_D1_2X_GC_EN); - - val = mt76_rmw(dev, MT_TMAC_TRCR(0), - MT_TMAC_TRCR_CCA_SEL | MT_TMAC_TRCR_SEC_CCA_SEL, - FIELD_PREP(MT_TMAC_TRCR_CCA_SEL, 2) | - FIELD_PREP(MT_TMAC_TRCR_SEC_CCA_SEL, 0)); - mt76_wr(dev, MT_TMAC_TRCR(1), val); - - val = MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE | - FIELD_PREP(MT_AGG_ACR_CFEND_RATE, MT7615_CFEND_RATE_DEFAULT) | - FIELD_PREP(MT_AGG_ACR_BAR_RATE, MT7615_BAR_RATE_DEFAULT); - mt76_wr(dev, MT_AGG_ACR(0), val); - mt76_wr(dev, MT_AGG_ACR(1), val); + mt76_set(dev, MT_CFG_CCR, val); + + mt76_rmw(dev, MT_TMAC_TRCR(chain), + MT_TMAC_TRCR_CCA_SEL | MT_TMAC_TRCR_SEC_CCA_SEL, + FIELD_PREP(MT_TMAC_TRCR_CCA_SEL, 2) | + FIELD_PREP(MT_TMAC_TRCR_SEC_CCA_SEL, 0)); + + mt76_wr(dev, MT_AGG_ACR(chain), + MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE | + FIELD_PREP(MT_AGG_ACR_CFEND_RATE, MT7615_CFEND_RATE_DEFAULT) | + FIELD_PREP(MT_AGG_ACR_BAR_RATE, MT7615_BAR_RATE_DEFAULT)); + + mt76_wr(dev, MT_AGG_ARUCR(chain), + FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1)); + + mt76_wr(dev, MT_AGG_ARDCR(chain), + FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1)); + + mask = MT_DMA_RCFR0_MCU_RX_MGMT | + MT_DMA_RCFR0_MCU_RX_CTL_NON_BAR | + MT_DMA_RCFR0_MCU_RX_CTL_BAR | + MT_DMA_RCFR0_MCU_RX_BYPASS | + MT_DMA_RCFR0_RX_DROPPED_UCAST | + MT_DMA_RCFR0_RX_DROPPED_MCAST; + set = FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_UCAST, 2) | + FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_MCAST, 2); + mt76_rmw(dev, MT_DMA_RCFR0(chain), mask, set); +} + +static void mt7615_mac_init(struct mt7615_dev *dev) +{ + int i; + + mt7615_init_mac_chain(dev, 0); mt76_rmw_field(dev, MT_TMAC_CTCR0, MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); @@ -56,47 +95,11 @@ static void mt7615_mac_init(struct mt7615_dev *dev) mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS, MT_AGG_SCR_NLNAV_MID_PTEC_DIS); - mt76_wr(dev, MT_DMA_DCR0, MT_DMA_DCR0_RX_VEC_DROP | - FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072)); - - val = FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1); - mt76_wr(dev, MT_AGG_ARUCR(0), val); - mt76_wr(dev, MT_AGG_ARUCR(1), val); - - val = FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1); - mt76_wr(dev, MT_AGG_ARDCR(0), val); - mt76_wr(dev, MT_AGG_ARDCR(1), val); - mt76_wr(dev, MT_AGG_ARCR, - (FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | - MT_AGG_ARCR_RATE_DOWN_RATIO_EN | - FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | - FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4))); - - mask = MT_DMA_RCFR0_MCU_RX_MGMT | - MT_DMA_RCFR0_MCU_RX_CTL_NON_BAR | - MT_DMA_RCFR0_MCU_RX_CTL_BAR | - MT_DMA_RCFR0_MCU_RX_BYPASS | - MT_DMA_RCFR0_RX_DROPPED_UCAST | - MT_DMA_RCFR0_RX_DROPPED_MCAST; - set = FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_UCAST, 2) | - FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_MCAST, 2); - mt76_rmw(dev, MT_DMA_RCFR0(0), mask, set); - mt76_rmw(dev, MT_DMA_RCFR0(1), mask, set); + FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | + MT_AGG_ARCR_RATE_DOWN_RATIO_EN | + FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | + FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4)); for (i = 0; i < MT7615_WTBL_SIZE; i++) mt7615_mac_wtbl_update(dev, i, @@ -104,6 +107,19 @@ static void mt7615_mac_init(struct mt7615_dev *dev) mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_EN); mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN); + + /* disable hdr translation and hw AMSDU */ + mt76_wr(dev, MT_DMA_DCR0, + FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) | + MT_DMA_DCR0_RX_VEC_DROP); + if (is_mt7663(&dev->mt76)) { + mt76_wr(dev, MT_CSR(0x010), 0x8208); + mt76_wr(dev, 0x44064, 0x2000000); + mt76_wr(dev, MT_WF_AGG(0x160), 0x5c341c02); + mt76_wr(dev, MT_WF_AGG(0x164), 0x70708040); + } else { + mt7615_init_mac_chain(dev, 1); + } } bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev) @@ -350,6 +366,8 @@ mt7615_cap_dbdc_enable(struct mt7615_dev *dev) else dev->mphy.antenna_mask = dev->chainmask >> 1; dev->phy.chainmask = dev->mphy.antenna_mask; + dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask; + dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask; mt76_set_stream_caps(&dev->mt76, true); } @@ -361,6 +379,8 @@ mt7615_cap_dbdc_disable(struct mt7615_dev *dev) IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; dev->mphy.antenna_mask = dev->chainmask; dev->phy.chainmask = dev->chainmask; + dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask; + dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask; mt76_set_stream_caps(&dev->mt76, true); } @@ -425,11 +445,9 @@ void mt7615_unregister_ext_phy(struct mt7615_dev *dev) ieee80211_free_hw(mphy->hw); } - -int mt7615_register_device(struct mt7615_dev *dev) +void mt7615_init_device(struct mt7615_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); - int ret; dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; @@ -440,14 +458,6 @@ int mt7615_register_device(struct mt7615_dev *dev) init_waitqueue_head(&dev->reset_wait); INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); - ret = mt7622_wmac_init(dev); - if (ret) - return ret; - - ret = mt7615_init_hardware(dev); - if (ret) - return ret; - mt7615_init_wiphy(hw); dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; @@ -456,6 +466,13 @@ int mt7615_register_device(struct mt7615_dev *dev) IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; mt7615_cap_dbdc_disable(dev); dev->phy.dfs_state = -1; +} + +int mt7615_register_device(struct mt7615_dev *dev) +{ + int ret; + + mt7615_init_device(dev); /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { @@ -463,6 +480,14 @@ int mt7615_register_device(struct mt7615_dev *dev) dev->mt76.led_cdev.blink_set = mt7615_led_set_blink; } + ret = mt7622_wmac_init(dev); + if (ret) + return ret; + + ret = mt7615_init_hardware(dev); + if (ret) + return ret; + ret = mt76_register_device(&dev->mt76, true, mt7615_rates, ARRAY_SIZE(mt7615_rates)); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 145366dbc39b..a27a6d164009 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -503,7 +503,7 @@ mt7615_mac_tx_rate_val(struct mt7615_dev *dev, int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int pid, - struct ieee80211_key_conf *key) + struct ieee80211_key_conf *key, bool beacon) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rate = &info->control.rates[0]; @@ -541,7 +541,7 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, q_idx = wmm_idx * MT7615_MAX_WMM_SETS + skb_get_queue_mapping(skb); p_fmt = MT_TX_TYPE_CT; - } else if (ieee80211_is_beacon(fc)) { + } else if (beacon) { if (ext_phy) q_idx = MT_LMAC_BCN1; else @@ -703,9 +703,9 @@ void mt7615_txp_skb_unmap(struct mt76_dev *dev, mt7615_txp_skb_unmap_hw(dev, &txp->hw); } -static u32 mt7615_mac_wtbl_addr(int wcid) +static u32 mt7615_mac_wtbl_addr(struct mt7615_dev *dev, int wcid) { - return MT_WTBL_BASE + wcid * MT_WTBL_ENTRY_SIZE; + return MT_WTBL_BASE(dev) + wcid * MT_WTBL_ENTRY_SIZE; } bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask) @@ -751,7 +751,7 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) list_del_init(&msta->poll_list); spin_unlock_bh(&dev->sta_poll_lock); - addr = mt7615_mac_wtbl_addr(msta->wcid.idx) + 19 * 4; + addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4; for (i = 0; i < 4; i++, addr += 8) { u32 tx_last = msta->airtime_ac[i]; @@ -801,7 +801,7 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct mt76_phy *mphy = phy->mt76; struct ieee80211_tx_rate *ref; int wcid = sta->wcid.idx; - u32 addr = mt7615_mac_wtbl_addr(wcid); + u32 addr = mt7615_mac_wtbl_addr(dev, wcid); bool stbc = false; int n_rates = sta->n_rates; u8 bw, bw_prev, bw_idx = 0; @@ -966,7 +966,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, enum mt7615_cipher_type cipher, enum set_key_cmd cmd) { - u32 addr = mt7615_mac_wtbl_addr(wcid->idx) + 30 * 4; + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; u8 data[32] = {}; if (key->keylen > sizeof(data)) @@ -1004,7 +1004,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, enum mt7615_cipher_type cipher, int keyidx, enum set_key_cmd cmd) { - u32 addr = mt7615_mac_wtbl_addr(wcid->idx), w0, w1; + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000)) return -ETIMEDOUT; @@ -1040,7 +1040,7 @@ mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, enum mt7615_cipher_type cipher, enum set_key_cmd cmd) { - u32 addr = mt7615_mac_wtbl_addr(wcid->idx); + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); if (cmd == SET_KEY) { if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) @@ -1208,7 +1208,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return id; mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, - pid, key); + pid, key, false); txp = txwi + MT_TXD_SIZE; memset(txp, 0, sizeof(struct mt7615_txp_common)); @@ -1524,6 +1524,9 @@ void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable) if (dev->scs_en == enable) goto out; + if (is_mt7663(&dev->mt76)) + goto out; + if (enable) { mt76_set(dev, MT_WF_PHY_MIN_PRI_PWR(0), MT_WF_PHY_PD_BLK(0)); @@ -1555,6 +1558,9 @@ void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy) { u32 rxtd; + if (is_mt7663(&dev->mt76)) + return; + if (ext_phy) rxtd = MT_WF_PHY_RXTD2(10); else @@ -1630,7 +1636,6 @@ mt7615_mac_adjust_sensitivity(struct mt7615_phy *phy, MT_WF_PHY_PD_OFDM(ext_phy, val)); } else { val = *sensitivity + 256; - if (!ext_phy) mt76_rmw(dev, MT_WF_PHY_RXTD_CCK_PD(ext_phy), MT_WF_PHY_PD_CCK_MASK(ext_phy), MT_WF_PHY_PD_CCK(ext_phy, val)); @@ -1823,8 +1828,9 @@ static void mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct ieee80211_hw *hw = priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); - mt7615_mcu_set_bcn(hw, vif, vif->bss_conf.enable_beacon); + mt7615_mcu_add_beacon(dev, hw, vif, vif->bss_conf.enable_beacon); } static void diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 6fa7e3dd6a3a..e0b89257db90 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -8,6 +8,7 @@ #define MT_CT_DMA_BUF_NUM 2 #define MT_RXD0_LENGTH GENMASK(15, 0) +#define MT_RXD0_PKT_FLAG GENMASK(19, 16) #define MT_RXD0_PKT_TYPE GENMASK(31, 29) #define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) @@ -26,7 +27,8 @@ enum rx_pkt_type { PKT_TYPE_RX_TMR, PKT_TYPE_RETRIEVE, PKT_TYPE_TXRX_NOTIFY, - PKT_TYPE_RX_EVENT + PKT_TYPE_RX_EVENT, + PKT_TYPE_NORMAL_MCU, }; #define MT_RXD1_NORMAL_BSSID GENMASK(31, 26) @@ -229,8 +231,15 @@ enum tx_phy_bandwidth { #define MT_TXD6_FIXED_BW BIT(2) #define MT_TXD6_BW GENMASK(1, 0) +/* MT7663 DW7 HW-AMSDU */ +#define MT_TXD7_HW_AMSDU_CAP BIT(30) #define MT_TXD7_TYPE GENMASK(21, 20) #define MT_TXD7_SUB_TYPE GENMASK(19, 16) +#define MT_TXD7_SPE_IDX GENMASK(15, 11) +#define MT_TXD7_SPE_IDX_SLE BIT(10) + +#define MT_TXD8_L_TYPE GENMASK(5, 4) +#define MT_TXD8_L_SUB_TYPE GENMASK(3, 0) #define MT_TX_RATE_STBC BIT(11) #define MT_TX_RATE_NSS GENMASK(10, 9) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 01194ed79869..6586176c29af 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -39,13 +39,13 @@ static int mt7615_start(struct ieee80211_hw *hw) running = mt7615_dev_running(dev); if (!running) { - mt7615_mcu_ctrl_pm_state(dev, 0, 0); + mt7615_mcu_set_pm(dev, 0, 0); mt7615_mcu_set_mac_enable(dev, 0, true); mt7615_mac_enable_nf(dev, 0); } if (phy != &dev->phy) { - mt7615_mcu_ctrl_pm_state(dev, 1, 0); + mt7615_mcu_set_pm(dev, 1, 0); mt7615_mcu_set_mac_enable(dev, 1, true); mt7615_mac_enable_nf(dev, 1); } @@ -78,14 +78,14 @@ static void mt7615_stop(struct ieee80211_hw *hw) clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); if (phy != &dev->phy) { - mt7615_mcu_ctrl_pm_state(dev, 1, 1); + mt7615_mcu_set_pm(dev, 1, 1); mt7615_mcu_set_mac_enable(dev, 1, false); } if (!mt7615_dev_running(dev)) { cancel_delayed_work_sync(&dev->mt76.mac_work); - mt7615_mcu_ctrl_pm_state(dev, 0, 1); + mt7615_mcu_set_pm(dev, 0, 1); mt7615_mcu_set_mac_enable(dev, 0, false); } @@ -157,7 +157,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, else mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS; - ret = mt7615_mcu_set_dev_info(dev, vif, 1); + ret = mt7615_mcu_add_dev_info(dev, vif, true); if (ret) goto out; @@ -200,7 +200,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, /* TODO: disable beacon for the bss */ - mt7615_mcu_set_dev_info(dev, vif, 0); + mt7615_mcu_add_dev_info(dev, vif, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); if (vif->txq) @@ -412,7 +412,7 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&dev->mt76.mutex); if (changed & BSS_CHANGED_ASSOC) - mt7615_mcu_set_bss_info(dev, vif, info->assoc); + mt7615_mcu_add_bss_info(dev, vif, info->assoc); if (changed & BSS_CHANGED_ERP_SLOT) { int slottime = info->use_short_slot ? 9 : 20; @@ -425,13 +425,13 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BEACON_ENABLED) { - mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon); - mt7615_mcu_set_bmc(dev, vif, info->enable_beacon); + mt7615_mcu_add_bss_info(dev, vif, info->enable_beacon); + mt7615_mcu_sta_add(dev, vif, NULL, info->enable_beacon); } if (changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) - mt7615_mcu_set_bcn(hw, vif, info->enable_beacon); + mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon); mutex_unlock(&dev->mt76.mutex); } @@ -444,7 +444,7 @@ mt7615_channel_switch_beacon(struct ieee80211_hw *hw, struct mt7615_dev *dev = mt7615_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mt7615_mcu_set_bcn(hw, vif, true); + mt7615_mcu_add_beacon(dev, hw, vif, true); mutex_unlock(&dev->mt76.mutex); } @@ -469,7 +469,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - mt7615_mcu_set_sta(dev, vif, sta, 1); + mt7615_mcu_sta_add(dev, vif, sta, true); return 0; } @@ -480,7 +480,7 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - mt7615_mcu_set_sta(dev, vif, sta, 0); + mt7615_mcu_sta_add(dev, vif, sta, false); mt7615_mac_wtbl_update(dev, msta->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -578,21 +578,21 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_RX_START: mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, params->buf_size); - mt7615_mcu_set_rx_ba(dev, params, 1); + mt7615_mcu_add_rx_ba(dev, params, true); break; case IEEE80211_AMPDU_RX_STOP: mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); - mt7615_mcu_set_rx_ba(dev, params, 0); + mt7615_mcu_add_rx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_OPERATIONAL: mtxq->aggr = true; mtxq->send_bar = false; - mt7615_mcu_set_tx_ba(dev, params, 1); + mt7615_mcu_add_tx_ba(dev, params, true); break; case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - mt7615_mcu_set_tx_ba(dev, params, 0); + mt7615_mcu_add_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn); @@ -600,7 +600,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - mt7615_mcu_set_tx_ba(dev, params, 0); + mt7615_mcu_add_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } @@ -686,7 +686,13 @@ mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) mutex_lock(&dev->mt76.mutex); phy->mt76->antenna_mask = tx_ant; - phy->chainmask = ext_phy ? tx_ant << 2 : tx_ant; + if (ext_phy) { + if (dev->chainmask == 0xf) + tx_ant <<= 2; + else + tx_ant <<= 1; + } + phy->chainmask = tx_ant; mt76_set_stream_caps(&dev->mt76, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 7218a3041ead..610cfa918c7b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -29,8 +29,37 @@ struct mt7615_fw_trailer { __le32 len; } __packed; +#define FW_V3_COMMON_TAILER_SIZE 36 +#define FW_V3_REGION_TAILER_SIZE 40 +#define FW_START_OVERRIDE BIT(0) +#define FW_START_DLYCAL BIT(1) +#define FW_START_WORKING_PDA_CR4 BIT(2) + +struct mt7663_fw_trailer { + u8 chip_id; + u8 eco_code; + u8 n_region; + u8 format_ver; + u8 format_flag; + u8 reserv[2]; + char fw_ver[10]; + char build_date[15]; + __le32 crc; +} __packed; + +struct mt7663_fw_buf { + __le32 crc; + __le32 d_img_size; + __le32 block_size; + u8 rsv[4]; + __le32 img_dest_addr; + __le32 img_size; + u8 feature_set; +}; + #define MT7615_PATCH_ADDRESS 0x80000 #define MT7622_PATCH_ADDRESS 0x9c000 +#define MT7663_PATCH_ADDRESS 0xdc000 #define N9_REGION_NUM 2 #define CR4_REGION_NUM 1 @@ -44,29 +73,32 @@ struct mt7615_fw_trailer { #define DL_MODE_KEY_IDX GENMASK(2, 1) #define DL_MODE_RESET_SEC_IV BIT(3) #define DL_MODE_WORKING_PDA_CR4 BIT(4) +#define DL_MODE_VALID_RAM_ENTRY BIT(5) #define DL_MODE_NEED_RSP BIT(31) #define FW_START_OVERRIDE BIT(0) #define FW_START_WORKING_PDA_CR4 BIT(2) -static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, int *wait_seq) +void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb, + int cmd, int *wait_seq) { + int txd_len, mcu_cmd = cmd & MCU_CMD_MASK; + struct mt7615_uni_txd *uni_txd; struct mt7615_mcu_txd *mcu_txd; u8 seq, q_idx, pkt_fmt; - enum mt76_txq_id qid; - u32 val; __le32 *txd; + u32 val; seq = ++dev->mt76.mcu.msg_seq & 0xf; if (!seq) seq = ++dev->mt76.mcu.msg_seq & 0xf; + if (wait_seq) + *wait_seq = seq; - mcu_txd = (struct mt7615_mcu_txd *)skb_push(skb, - sizeof(struct mt7615_mcu_txd)); - memset(mcu_txd, 0, sizeof(struct mt7615_mcu_txd)); + txd_len = cmd & MCU_UNI_PREFIX ? sizeof(*uni_txd) : sizeof(*mcu_txd); + txd = (__le32 *)skb_push(skb, txd_len); - if (cmd != -MCU_CMD_FW_SCATTER) { + if (cmd != MCU_CMD_FW_SCATTER) { q_idx = MT_TX_MCU_PORT_RX_Q0; pkt_fmt = MT_TX_TYPE_CMD; } else { @@ -74,8 +106,6 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, pkt_fmt = MT_TX_TYPE_FW; } - txd = mcu_txd->txd; - val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) | FIELD_PREP(MT_TXD0_P_IDX, MT_TX_PORT_IDX_MCU) | FIELD_PREP(MT_TXD0_Q_IDX, q_idx); @@ -86,25 +116,42 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, FIELD_PREP(MT_TXD1_PKT_FMT, pkt_fmt); txd[1] = cpu_to_le32(val); + if (cmd & MCU_UNI_PREFIX) { + uni_txd = (struct mt7615_uni_txd *)txd; + uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd)); + uni_txd->option = MCU_CMD_UNI_EXT_ACK; + uni_txd->cid = cpu_to_le16(mcu_cmd); + uni_txd->s2d_index = MCU_S2D_H2N; + uni_txd->pkt_type = MCU_PKT_ID; + uni_txd->seq = seq; + + return; + } + + mcu_txd = (struct mt7615_mcu_txd *)txd; mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd)); mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, q_idx)); + mcu_txd->s2d_index = MCU_S2D_H2N; mcu_txd->pkt_type = MCU_PKT_ID; mcu_txd->seq = seq; - if (cmd < 0) { + if (cmd & MCU_FW_PREFIX) { mcu_txd->set_query = MCU_Q_NA; - mcu_txd->cid = -cmd; + mcu_txd->cid = mcu_cmd; } else { mcu_txd->cid = MCU_CMD_EXT_CID; mcu_txd->set_query = MCU_Q_SET; mcu_txd->ext_cid = cmd; mcu_txd->ext_cid_ack = 1; } - mcu_txd->s2d_index = MCU_S2D_H2N; +} - if (wait_seq) - *wait_seq = seq; +static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, + int cmd, int *wait_seq) +{ + enum mt76_txq_id qid; + mt7615_mcu_fill_msg(dev, skb, cmd, wait_seq); if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) qid = MT_TXQ_MCU; else @@ -124,7 +171,7 @@ mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd, return -EAGAIN; switch (cmd) { - case -MCU_CMD_PATCH_SEM_CONTROL: + case MCU_CMD_PATCH_SEM_CONTROL: skb_pull(skb, sizeof(*rxd) - 4); ret = *skb->data; break; @@ -140,32 +187,18 @@ mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd, return ret; } -static int -mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, - int len, bool wait_resp) +int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq) { - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); unsigned long expires = jiffies + 20 * HZ; struct sk_buff *skb; - int ret, seq; - - skb = mt7615_mcu_msg_alloc(data, len); - if (!skb) - return -ENOMEM; - - mutex_lock(&mdev->mcu.mutex); - - ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); - if (ret) - goto out; + int ret = 0; - while (wait_resp) { - skb = mt76_mcu_get_response(mdev, expires); + while (true) { + skb = mt76_mcu_get_response(&dev->mt76, expires); if (!skb) { - dev_err(mdev->dev, "Message %d (seq %d) timeout\n", - cmd, seq); - ret = -ETIMEDOUT; - break; + dev_err(dev->mt76.dev, "Message %ld (seq %d) timeout\n", + cmd & MCU_CMD_MASK, seq); + return -ETIMEDOUT; } ret = mt7615_mcu_parse_response(dev, cmd, skb, seq); @@ -173,12 +206,44 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, break; } + return ret; +} + +static int +mt7615_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, + int cmd, bool wait_resp) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + int ret, seq; + + mutex_lock(&mdev->mcu.mutex); + + ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); + if (ret) + goto out; + + if (wait_resp) + ret = mt7615_mcu_wait_response(dev, cmd, seq); + out: mutex_unlock(&mdev->mcu.mutex); return ret; } +static int +mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, + int len, bool wait_resp) +{ + struct sk_buff *skb; + + skb = mt7615_mcu_msg_alloc(data, len); + if (!skb) + return -ENOMEM; + + return __mt76_mcu_skb_send_msg(mdev, skb, cmd, wait_resp); +} + static void mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { @@ -287,10 +352,1095 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, .mode = cpu_to_le32(mode), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_TARGET_ADDRESS_LEN_REQ, + &req, sizeof(req), true); +} + +static int +mt7615_mcu_add_dev(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct { + struct req_hdr { + u8 omac_idx; + u8 band_idx; + __le16 tlv_num; + u8 is_tlv_append; + u8 rsv[3]; + } __packed hdr; + struct req_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 band_idx; + u8 omac_addr[ETH_ALEN]; + } __packed tlv; + } data = { + .hdr = { + .omac_idx = mvif->omac_idx, + .band_idx = mvif->band_idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + }, + .tlv = { + .tag = cpu_to_le16(DEV_INFO_ACTIVE), + .len = cpu_to_le16(sizeof(struct req_tlv)), + .active = enable, + .band_idx = mvif->band_idx, + }, + }; + + memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, + &data, sizeof(data), true); +} + +static int +mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + struct ieee80211_mutable_offsets offs; + struct ieee80211_tx_info *info; + struct req { + u8 omac_idx; + u8 enable; + u8 wlan_idx; + u8 band_idx; + u8 pkt_type; + u8 need_pre_tbtt_int; + __le16 csa_ie_pos; + __le16 pkt_len; + __le16 tim_ie_pos; + u8 pkt[512]; + u8 csa_cnt; + /* bss color change */ + u8 bcc_cnt; + __le16 bcc_ie_pos; + } __packed req = { + .omac_idx = mvif->omac_idx, + .enable = enable, + .wlan_idx = wcid->idx, + .band_idx = mvif->band_idx, + }; + struct sk_buff *skb; + + skb = ieee80211_beacon_get_template(hw, vif, &offs); + if (!skb) + return -EINVAL; + + if (skb->len > 512 - MT_TXD_SIZE) { + dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + if (mvif->band_idx) { + info = IEEE80211_SKB_CB(skb); + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + } + + mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, + 0, NULL, true); + memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); + req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); + if (offs.csa_counter_offs[0]) { + u16 csa_offs; + + csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4; + req.csa_ie_pos = cpu_to_le16(csa_offs); + req.csa_cnt = skb->data[offs.csa_counter_offs[0]]; + } + dev_kfree_skb(skb); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, + &req, sizeof(req), true); +} + +static int +mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) +{ +#define ENTER_PM_STATE 1 +#define EXIT_PM_STATE 2 + struct { + u8 pm_number; + u8 pm_state; + u8 bssid[ETH_ALEN]; + u8 dtim_period; + u8 wlan_idx; + __le16 bcn_interval; + __le32 aid; + __le32 rx_filter; + u8 band_idx; + u8 rsv[3]; + __le32 feature; + u8 omac_idx; + u8 wmm_idx; + u8 bcn_loss_cnt; + u8 bcn_sp_duration; + } __packed req = { + .pm_number = 5, + .pm_state = state ? ENTER_PM_STATE : EXIT_PM_STATE, + .band_idx = band, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, &req, sizeof(req), true); } +static struct sk_buff * +mt7615_mcu_alloc_sta_req(struct mt7615_vif *mvif, struct mt7615_sta *msta) +{ + struct sta_req_hdr hdr = { + .bss_idx = mvif->idx, + .wlan_idx = msta ? msta->wcid.idx : 0, + .muar_idx = msta ? mvif->omac_idx : 0, + .is_tlv_append = 1, + }; + struct sk_buff *skb; + + skb = mt7615_mcu_msg_alloc(NULL, MT7615_STA_UPDATE_MAX_SIZE); + if (!skb) + return ERR_PTR(-ENOMEM); + + skb_put_data(skb, &hdr, sizeof(hdr)); + + return skb; +} + +static struct wtbl_req_hdr * +mt7615_mcu_alloc_wtbl_req(struct mt7615_sta *msta, int cmd, + void *sta_wtbl, struct sk_buff **skb) +{ + struct tlv *sta_hdr = sta_wtbl; + struct wtbl_req_hdr hdr = { + .wlan_idx = msta->wcid.idx, + .operation = cmd, + }; + struct sk_buff *nskb = *skb; + + if (!nskb) { + nskb = mt7615_mcu_msg_alloc(NULL, MT7615_WTBL_UPDATE_BA_SIZE); + if (!nskb) + return ERR_PTR(-ENOMEM); + + *skb = nskb; + } + + if (sta_hdr) + sta_hdr->len = cpu_to_le16(sizeof(hdr)); + + return skb_put_data(nskb, &hdr, sizeof(hdr)); +} + +static struct tlv * +mt7615_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, + void *sta_ntlv, void *sta_wtbl) +{ + struct sta_ntlv_hdr *ntlv_hdr = sta_ntlv; + struct tlv *sta_hdr = sta_wtbl; + struct tlv *ptlv, tlv = { + .tag = cpu_to_le16(tag), + .len = cpu_to_le16(len), + }; + u16 ntlv; + + ptlv = skb_put(skb, len); + memcpy(ptlv, &tlv, sizeof(tlv)); + + ntlv = le16_to_cpu(ntlv_hdr->tlv_num); + ntlv_hdr->tlv_num = cpu_to_le16(ntlv + 1); + + if (sta_hdr) { + u16 size = le16_to_cpu(sta_hdr->len); + + sta_hdr->len = cpu_to_le16(size + len); + } + + return ptlv; +} + +static struct tlv * +mt7615_mcu_add_tlv(struct sk_buff *skb, int tag, int len) +{ + return mt7615_mcu_add_nested_tlv(skb, tag, len, skb->data, NULL); +} + +static int +mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct bss_info_basic *bss; + u8 wlan_idx = mvif->sta.wcid.idx; + u32 type = NETWORK_INFRA; + struct tlv *tlv; + + tlv = mt7615_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + break; + case NL80211_IFTYPE_STATION: + /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ + if (enable) { + struct ieee80211_sta *sta; + struct mt7615_sta *msta; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (!sta) { + rcu_read_unlock(); + return -EINVAL; + } + + msta = (struct mt7615_sta *)sta->drv_priv; + wlan_idx = msta->wcid.idx; + rcu_read_unlock(); + } + break; + case NL80211_IFTYPE_ADHOC: + type = NETWORK_IBSS; + break; + default: + WARN_ON(1); + break; + } + + bss = (struct bss_info_basic *)tlv; + memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); + bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + bss->network_type = cpu_to_le32(type); + bss->dtim_period = vif->bss_conf.dtim_period; + bss->bmc_tx_wlan_idx = wlan_idx; + bss->wmm_idx = mvif->wmm_idx; + bss->active = enable; + + return 0; +} + +static void +mt7615_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct bss_info_omac *omac; + struct tlv *tlv; + u32 type = 0; + u8 idx; + + tlv = mt7615_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac)); + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + type = CONNECTION_INFRA_AP; + break; + case NL80211_IFTYPE_STATION: + type = CONNECTION_INFRA_STA; + break; + case NL80211_IFTYPE_ADHOC: + type = CONNECTION_IBSS_ADHOC; + break; + default: + WARN_ON(1); + break; + } + + omac = (struct bss_info_omac *)tlv; + idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; + omac->conn_type = cpu_to_le32(type); + omac->omac_idx = mvif->omac_idx; + omac->band_idx = mvif->band_idx; + omac->hw_bss_idx = idx; +} + +/* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ +#define BCN_TX_ESTIMATE_TIME (4096 + 20) +static void +mt7615_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt7615_vif *mvif) +{ + struct bss_info_ext_bss *ext; + int ext_bss_idx, tsf_offset; + struct tlv *tlv; + + ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; + if (ext_bss_idx < 0) + return; + + tlv = mt7615_mcu_add_tlv(skb, BSS_INFO_EXT_BSS, sizeof(*ext)); + + ext = (struct bss_info_ext_bss *)tlv; + tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; + ext->mbss_tsf_offset = cpu_to_le32(tsf_offset); +} + +static void +mt7615_mcu_sta_ba_tlv(struct sk_buff *skb, + struct ieee80211_ampdu_params *params, + bool enable, bool tx) +{ + struct sta_rec_ba *ba; + struct tlv *tlv; + + tlv = mt7615_mcu_add_tlv(skb, STA_REC_BA, sizeof(*ba)); + + ba = (struct sta_rec_ba *)tlv; + ba->ba_type = tx ? MT_BA_TYPE_ORIGINATOR : MT_BA_TYPE_RECIPIENT, + ba->winsize = cpu_to_le16(params->buf_size); + ba->ssn = cpu_to_le16(params->ssn); + ba->ba_en = enable << params->tid; + ba->amsdu = params->amsdu; + ba->tid = params->tid; +} + +static void +mt7615_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ + struct sta_rec_basic *basic; + struct tlv *tlv; + + tlv = mt7615_mcu_add_tlv(skb, STA_REC_BASIC, sizeof(*basic)); + + basic = (struct sta_rec_basic *)tlv; + basic->extra_info = cpu_to_le16(EXTRA_INFO_VER); + + if (enable) { + basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW); + basic->conn_state = CONN_STATE_PORT_SECURE; + } else { + basic->conn_state = CONN_STATE_DISCONNECT; + } + + if (!sta) { + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC); + eth_broadcast_addr(basic->peer_addr); + return; + } + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_STA); + break; + case NL80211_IFTYPE_STATION: + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_AP); + break; + case NL80211_IFTYPE_ADHOC: + basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); + break; + default: + WARN_ON(1); + break; + } + + memcpy(basic->peer_addr, sta->addr, ETH_ALEN); + basic->aid = cpu_to_le16(sta->aid); + basic->qos = sta->wme; +} + +static void +mt7615_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +{ + struct tlv *tlv; + + if (sta->ht_cap.ht_supported) { + struct sta_rec_ht *ht; + + tlv = mt7615_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); + ht = (struct sta_rec_ht *)tlv; + ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + } + if (sta->vht_cap.vht_supported) { + struct sta_rec_vht *vht; + + tlv = mt7615_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht)); + vht = (struct sta_rec_vht *)tlv; + vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; + vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; + vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); + } +} + +static void +mt7615_mcu_wtbl_ba_tlv(struct sk_buff *skb, + struct ieee80211_ampdu_params *params, + bool enable, bool tx, void *sta_wtbl, + void *wtbl_tlv) +{ + struct wtbl_ba *ba; + struct tlv *tlv; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_BA, sizeof(*ba), + wtbl_tlv, sta_wtbl); + + ba = (struct wtbl_ba *)tlv; + ba->tid = params->tid; + + if (tx) { + ba->ba_type = MT_BA_TYPE_ORIGINATOR; + ba->sn = enable ? cpu_to_le16(params->ssn) : 0; + ba->ba_winsize = cpu_to_le16(params->buf_size); + ba->ba_en = enable; + } else { + memcpy(ba->peer_addr, params->sta->addr, ETH_ALEN); + ba->ba_type = MT_BA_TYPE_RECIPIENT; + ba->rst_ba_tid = params->tid; + ba->rst_ba_sel = RST_BA_MAC_TID_MATCH; + ba->rst_ba_sb = 1; + } + + if (enable && tx) { + u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; + int i; + + for (i = 7; i > 0; i--) { + if (params->buf_size >= ba_range[i]) + break; + } + ba->ba_winsize_idx = i; + } +} + +static void +mt7615_mcu_wtbl_generic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, void *sta_wtbl, + void *wtbl_tlv) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct wtbl_generic *generic; + struct wtbl_rx *rx; + struct tlv *tlv; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_GENERIC, sizeof(*generic), + wtbl_tlv, sta_wtbl); + + generic = (struct wtbl_generic *)tlv; + + if (sta) { + memcpy(generic->peer_addr, sta->addr, ETH_ALEN); + generic->partial_aid = cpu_to_le16(sta->aid); + generic->muar_idx = mvif->omac_idx; + generic->qos = sta->wme; + } else { + eth_broadcast_addr(generic->peer_addr); + generic->muar_idx = 0xe; + } + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_RX, sizeof(*rx), + wtbl_tlv, sta_wtbl); + + rx = (struct wtbl_rx *)tlv; + rx->rca1 = sta ? vif->type != NL80211_IFTYPE_AP : 1; + rx->rca2 = 1; + rx->rv = 1; +} + +static void +mt7615_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, + void *sta_wtbl, void *wtbl_tlv) +{ + struct tlv *tlv; + u32 flags = 0; + + if (sta->ht_cap.ht_supported) { + struct wtbl_ht *ht; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), + wtbl_tlv, sta_wtbl); + ht = (struct wtbl_ht *)tlv; + ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; + ht->af = sta->ht_cap.ampdu_factor; + ht->mm = sta->ht_cap.ampdu_density; + ht->ht = 1; + + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + flags |= MT_WTBL_W5_SHORT_GI_20; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + flags |= MT_WTBL_W5_SHORT_GI_40; + } + + if (sta->vht_cap.vht_supported) { + struct wtbl_vht *vht; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_VHT, sizeof(*vht), + wtbl_tlv, sta_wtbl); + vht = (struct wtbl_vht *)tlv; + vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC, + vht->vht = 1; + + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + flags |= MT_WTBL_W5_SHORT_GI_80; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) + flags |= MT_WTBL_W5_SHORT_GI_160; + } + + /* wtbl smps */ + if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) { + struct wtbl_smps *smps; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_SMPS, sizeof(*smps), + wtbl_tlv, sta_wtbl); + smps = (struct wtbl_smps *)tlv; + smps->smps = 1; + } + + if (sta->ht_cap.ht_supported) { + /* sgi */ + u32 msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | + MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; + struct wtbl_raw *raw; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_RAW_DATA, + sizeof(*raw), wtbl_tlv, + sta_wtbl); + raw = (struct wtbl_raw *)tlv; + raw->val = cpu_to_le32(flags); + raw->msk = cpu_to_le32(~msk); + raw->wtbl_idx = 1; + raw->dw = 5; + } +} + +static int +mt7615_mcu_add_bss(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct sk_buff *skb; + + skb = mt7615_mcu_alloc_sta_req(mvif, NULL); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + if (enable) + mt7615_mcu_bss_omac_tlv(skb, vif); + + mt7615_mcu_bss_basic_tlv(skb, vif, enable); + + if (enable && mvif->omac_idx > EXT_BSSID_START) + mt7615_mcu_bss_ext_tlv(skb, mvif); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_BSS_INFO_UPDATE, true); +} + +static int +mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct sk_buff *skb = NULL; + int err; + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, NULL, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, true, NULL, wtbl_hdr); + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_WTBL_UPDATE, true); + if (err < 0) + return err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, true); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); +} + +static int +mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct sk_buff *skb; + int err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, false); + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); + if (err < 0 || !enable) + return err; + + skb = NULL; + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, NULL, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, false, NULL, wtbl_hdr); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_WTBL_UPDATE, true); +} + +static int +mt7615_mcu_wtbl_sta_add(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct sk_buff *skb, *sskb, *wskb = NULL; + struct wtbl_req_hdr *wtbl_hdr; + struct mt7615_sta *msta; + int cmd, err; + + msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; + + sskb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(sskb)) + return PTR_ERR(sskb); + + mt7615_mcu_sta_basic_tlv(sskb, vif, sta, enable); + if (enable && sta) + mt7615_mcu_sta_ht_tlv(sskb, sta); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_RESET_AND_SET, NULL, + &wskb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + if (enable) { + mt7615_mcu_wtbl_generic_tlv(wskb, vif, sta, NULL, wtbl_hdr); + if (sta) + mt7615_mcu_wtbl_ht_tlv(wskb, sta, NULL, wtbl_hdr); + } + + cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE; + skb = enable ? wskb : sskb; + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); + if (err < 0) + return err; + + cmd = enable ? MCU_EXT_CMD_STA_REC_UPDATE : MCU_EXT_CMD_WTBL_UPDATE; + skb = enable ? sskb : wskb; + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); +} + +static const struct mt7615_mcu_ops wtbl_update_ops = { + .add_beacon_offload = mt7615_mcu_add_beacon_offload, + .set_pm_state = mt7615_mcu_ctrl_pm_state, + .add_dev_info = mt7615_mcu_add_dev, + .add_bss_info = mt7615_mcu_add_bss, + .add_tx_ba = mt7615_mcu_wtbl_tx_ba, + .add_rx_ba = mt7615_mcu_wtbl_rx_ba, + .sta_add = mt7615_mcu_wtbl_sta_add, +}; + +static int +mt7615_mcu_sta_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable, bool tx) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, tx); + + sta_wtbl = mt7615_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, sta_wtbl, &skb); + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); +} + +static int +mt7615_mcu_sta_tx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + return mt7615_mcu_sta_ba(dev, params, enable, true); +} + +static int +mt7615_mcu_sta_rx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + return mt7615_mcu_sta_ba(dev, params, enable, false); +} + +static int +mt7615_mcu_add_sta_cmd(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable, int cmd) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct wtbl_req_hdr *wtbl_hdr; + struct mt7615_sta *msta; + struct tlv *sta_wtbl; + struct sk_buff *skb; + + msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_basic_tlv(skb, vif, sta, enable); + if (enable && sta) + mt7615_mcu_sta_ht_tlv(skb, sta); + + sta_wtbl = mt7615_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_RESET_AND_SET, + sta_wtbl, &skb); + if (enable) { + mt7615_mcu_wtbl_generic_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); + if (sta) + mt7615_mcu_wtbl_ht_tlv(skb, sta, sta_wtbl, wtbl_hdr); + } + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); +} + +static int +mt7615_mcu_add_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ + return mt7615_mcu_add_sta_cmd(dev, vif, sta, enable, + MCU_EXT_CMD_STA_REC_UPDATE); +} + +static const struct mt7615_mcu_ops sta_update_ops = { + .add_beacon_offload = mt7615_mcu_add_beacon_offload, + .set_pm_state = mt7615_mcu_ctrl_pm_state, + .add_dev_info = mt7615_mcu_add_dev, + .add_bss_info = mt7615_mcu_add_bss, + .add_tx_ba = mt7615_mcu_sta_tx_ba, + .add_rx_ba = mt7615_mcu_sta_rx_ba, + .sta_add = mt7615_mcu_add_sta, +}; + +static int +mt7615_mcu_uni_add_dev(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct { + struct req_hdr { + u8 omac_idx; + u8 band_idx; + __le16 pad; + } __packed hdr; + struct req_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 pad; + u8 omac_addr[ETH_ALEN]; + } __packed tlv; + } data = { + .hdr = { + .omac_idx = mvif->omac_idx, + .band_idx = mvif->band_idx, + }, + .tlv = { + .tag = cpu_to_le16(DEV_INFO_ACTIVE), + .len = cpu_to_le16(sizeof(struct req_tlv)), + .active = enable, + }, + }; + + memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_DEV_INFO_UPDATE, + &data, sizeof(data), true); +} + +static int +mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) +{ + return 0; +} + +static int +mt7615_mcu_uni_add_bss(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct { + struct req_hdr { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct basic_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 omac_idx; + u8 hw_bss_idx; + u8 band_idx; + __le32 conn_type; + u8 conn_state; + u8 wmm_idx; + u8 bssid[ETH_ALEN]; + __le16 bmc_tx_wlan_idx; + __le16 bcn_interval; + u8 dtim_period; + u8 phymode; + __le16 sta_idx; + u8 nonht_basic_phy; + u8 pad[3]; + } __packed basic; + } req = { + .hdr = { + .bss_idx = mvif->idx, + }, + .basic = { + .tag = cpu_to_le16(UNI_BSS_INFO_BASIC), + .len = cpu_to_le16(sizeof(struct basic_tlv)), + .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int), + .dtim_period = vif->bss_conf.dtim_period, + .omac_idx = mvif->omac_idx, + .band_idx = mvif->band_idx, + .wmm_idx = mvif->wmm_idx, + .active = enable, + }, + }; + u8 idx, tx_wlan_idx = 0; + + idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; + req.basic.hw_bss_idx = idx; + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP); + tx_wlan_idx = mvif->sta.wcid.idx; + break; + case NL80211_IFTYPE_STATION: + if (enable) { + struct ieee80211_sta *sta; + struct mt7615_sta *msta; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (!sta) { + rcu_read_unlock(); + return -EINVAL; + } + + msta = (struct mt7615_sta *)sta->drv_priv; + tx_wlan_idx = msta->wcid.idx; + rcu_read_unlock(); + } + req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_STA); + break; + default: + WARN_ON(1); + break; + } + + memcpy(req.basic.bssid, vif->bss_conf.bssid, ETH_ALEN); + req.basic.bmc_tx_wlan_idx = cpu_to_le16(tx_wlan_idx); + req.basic.sta_idx = cpu_to_le16(tx_wlan_idx); + req.basic.conn_state = !enable; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, + &req, sizeof(req), true); +} + +static int +mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + struct ieee80211_mutable_offsets offs; + struct { + struct req_hdr { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct bcn_content_tlv { + __le16 tag; + __le16 len; + __le16 tim_ie_pos; + __le16 csa_ie_pos; + __le16 bcc_ie_pos; + /* 0: enable beacon offload + * 1: disable beacon offload + * 2: update probe respond offload + */ + u8 enable; + /* 0: legacy format (TXD + payload) + * 1: only cap field IE + */ + u8 type; + __le16 pkt_len; + u8 pkt[512]; + } __packed beacon_tlv; + } req = { + .hdr = { + .bss_idx = mvif->idx, + }, + .beacon_tlv = { + .tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT), + .len = cpu_to_le16(sizeof(struct bcn_content_tlv)), + .enable = enable, + }, + }; + struct sk_buff *skb; + + skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs); + if (!skb) + return -EINVAL; + + if (skb->len > 512 - MT_TXD_SIZE) { + dev_err(dev->mt76.dev, "beacon size limit exceed\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + mt7615_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb, + wcid, NULL, 0, NULL, true); + memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len); + req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); + + if (offs.csa_counter_offs[0]) { + u16 csa_offs; + + csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4; + req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs); + } + dev_kfree_skb(skb); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, + &req, sizeof(req), true); +} + +static int +mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + int err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + sta_wtbl = mt7615_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, true, sta_wtbl, + wtbl_hdr); + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); + if (err < 0) + return err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, true); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); +} + +static int +mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + int err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, false); + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); + if (err < 0 || !enable) + return err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + sta_wtbl = mt7615_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, false, sta_wtbl, + wtbl_hdr); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); +} + +static int +mt7615_mcu_uni_add_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ + return mt7615_mcu_add_sta_cmd(dev, vif, sta, enable, + MCU_UNI_CMD_STA_REC_UPDATE); +} + +static const struct mt7615_mcu_ops uni_update_ops = { + .add_beacon_offload = mt7615_mcu_uni_add_beacon_offload, + .set_pm_state = mt7615_mcu_uni_ctrl_pm_state, + .add_dev_info = mt7615_mcu_uni_add_dev, + .add_bss_info = mt7615_mcu_uni_add_bss, + .add_tx_ba = mt7615_mcu_uni_tx_ba, + .add_rx_ba = mt7615_mcu_uni_rx_ba, + .sta_add = mt7615_mcu_uni_add_sta, +}; + static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, int len) { @@ -300,14 +1450,16 @@ static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, cur_len = min_t(int, 4096 - sizeof(struct mt7615_mcu_txd), len); - ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_SCATTER, data, cur_len, false); if (ret) break; data += cur_len; len -= cur_len; - mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + + if (mt76_is_mmio(&dev->mt76)) + mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); } return ret; @@ -324,13 +1476,13 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, .addr = cpu_to_le32(addr), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_START_REQ, &req, sizeof(req), true); } static int mt7615_mcu_restart(struct mt76_dev *dev) { - return __mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, NULL, + return __mt76_mcu_send_msg(dev, MCU_CMD_RESTART_DL_REQ, NULL, 0, true); } @@ -342,7 +1494,7 @@ static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_SEM_CONTROL, + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_SEM_CONTROL, &req, sizeof(req), true); } @@ -355,7 +1507,7 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) .check_crc = 0, }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_FINISH_REQ, + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_FINISH_REQ, &req, sizeof(req), true); } @@ -371,11 +1523,13 @@ static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) static int mt7615_driver_own(struct mt7615_dev *dev) { - mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_DRV_OWN); + u32 addr; + + addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; + mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN); mt7622_trigger_hif_int(dev, true); - if (!mt76_poll_msec(dev, MT_CFG_LPCR_HOST, - MT_CFG_LPCR_HOST_FW_OWN, 0, 3000)) { + if (!mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000)) { dev_err(dev->mt76.dev, "Timeout for driver own\n"); return -EIO; } @@ -386,9 +1540,12 @@ static int mt7615_driver_own(struct mt7615_dev *dev) static int mt7615_firmware_own(struct mt7615_dev *dev) { + u32 addr; + + addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; mt7622_trigger_hif_int(dev, true); - mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN); + mt76_wr(dev, addr, MT_CFG_LPCR_HOST_FW_OWN); if (is_mt7622(&dev->mt76) && !mt76_poll_msec(dev, MT_CFG_LPCR_HOST, @@ -551,10 +1708,13 @@ static int mt7615_load_n9(struct mt7615_dev *dev, const char *name) sizeof(dev->mt76.hw->wiphy->fw_version), "%.10s-%.15s", hdr->fw_ver, hdr->build_date); - if (!strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) + if (!strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) { dev->fw_ver = MT7615_FIRMWARE_V2; - else + dev->mcu_ops = &sta_update_ops; + } else { dev->fw_ver = MT7615_FIRMWARE_V1; + dev->mcu_ops = &wtbl_update_ops; + } out: release_firmware(fw); @@ -686,9 +1846,125 @@ int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl) &data, sizeof(data), true); } +static int mt7663_load_n9(struct mt7615_dev *dev, const char *name) +{ + u32 offset = 0, override_addr = 0, flag = 0; + const struct mt7663_fw_trailer *hdr; + const struct mt7663_fw_buf *buf; + const struct firmware *fw; + const u8 *base_addr; + int i, ret; + + ret = request_firmware(&fw, name, dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < FW_V3_COMMON_TAILER_SIZE) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const struct mt7663_fw_trailer *)(fw->data + fw->size - + FW_V3_COMMON_TAILER_SIZE); + + dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n", + hdr->fw_ver, hdr->build_date); + dev_info(dev->mt76.dev, "Region number: 0x%x\n", hdr->n_region); + + base_addr = fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE; + for (i = 0; i < hdr->n_region; i++) { + u32 shift = (hdr->n_region - i) * FW_V3_REGION_TAILER_SIZE; + u32 len, addr, mode; + + dev_info(dev->mt76.dev, "Parsing tailer Region: %d\n", i); + + buf = (const struct mt7663_fw_buf *)(base_addr - shift); + mode = mt7615_mcu_gen_dl_mode(buf->feature_set, false); + addr = le32_to_cpu(buf->img_dest_addr); + len = le32_to_cpu(buf->img_size); + + ret = mt7615_mcu_init_download(dev, addr, len, mode); + if (ret) { + dev_err(dev->mt76.dev, "Download request failed\n"); + goto out; + } + + ret = mt7615_mcu_send_firmware(dev, fw->data + offset, len); + if (ret) { + dev_err(dev->mt76.dev, "Failed to send firmware\n"); + goto out; + } + + offset += le32_to_cpu(buf->img_size); + if (buf->feature_set & DL_MODE_VALID_RAM_ENTRY) { + override_addr = le32_to_cpu(buf->img_dest_addr); + dev_info(dev->mt76.dev, "Region %d, override_addr = 0x%08x\n", + i, override_addr); + } + } + + if (is_mt7663(&dev->mt76)) { + flag |= FW_START_DLYCAL; + if (override_addr) + flag |= FW_START_OVERRIDE; + + dev_info(dev->mt76.dev, "override_addr = 0x%08x, option = %d\n", + override_addr, flag); + } + + ret = mt7615_mcu_start_firmware(dev, override_addr, flag); + if (ret) + dev_err(dev->mt76.dev, "Failed to start N9 firmware\n"); + +out: + release_firmware(fw); + + return ret; +} + +static int mt7663_load_firmware(struct mt7615_dev *dev) +{ + int ret; + + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); + + ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY); + if (ret) { + dev_dbg(dev->mt76.dev, "Firmware is already download\n"); + return -EIO; + } + + ret = mt7615_load_patch(dev, MT7663_PATCH_ADDRESS, MT7663_ROM_PATCH); + if (ret) + return ret; + + dev->fw_ver = MT7615_FIRMWARE_V3; + dev->mcu_ops = &uni_update_ops; + + ret = mt7663_load_n9(dev, MT7663_FIRMWARE_N9); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY, + MT_TOP_MISC2_FW_N9_RDY, 1500)) { + ret = mt76_get_field(dev, MT_CONN_ON_MISC, + MT7663_TOP_MISC2_FW_STATE); + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; + } + + mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); + + dev_dbg(dev->mt76.dev, "Firmware init done\n"); + + return 0; +} + int mt7615_mcu_init(struct mt7615_dev *dev) { static const struct mt76_mcu_ops mt7615_mcu_ops = { + .mcu_skb_send_msg = mt7615_mcu_send_message, .mcu_send_msg = mt7615_mcu_msg_send, .mcu_restart = mt7615_mcu_restart, }; @@ -700,10 +1976,17 @@ int mt7615_mcu_init(struct mt7615_dev *dev) if (ret) return ret; - if (is_mt7622(&dev->mt76)) + switch (mt76_chip(&dev->mt76)) { + case 0x7622: ret = mt7622_load_firmware(dev); - else + break; + case 0x7663: + ret = mt7663_load_firmware(dev); + break; + default: ret = mt7615_load_firmware(dev); + break; + } if (ret) return ret; @@ -726,33 +2009,42 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) { struct { u8 buffer_mode; - u8 pad; + u8 content_format; __le16 len; } __packed req_hdr = { .buffer_mode = 1, }; - int ret, len, eep_len; - u8 *req, *eep = (u8 *)dev->mt76.eeprom.data; + u8 *eep = (u8 *)dev->mt76.eeprom.data; + struct sk_buff *skb; + int eep_len, offset; - if (is_mt7622(&dev->mt76)) + switch (mt76_chip(&dev->mt76)) { + case 0x7622: eep_len = MT7622_EE_MAX - MT_EE_NIC_CONF_0; - else + offset = MT_EE_NIC_CONF_0; + break; + case 0x7663: + eep_len = MT7663_EE_MAX - MT_EE_CHIP_ID; + req_hdr.content_format = 1; + offset = MT_EE_CHIP_ID; + break; + default: eep_len = MT7615_EE_MAX - MT_EE_NIC_CONF_0; - - len = sizeof(req_hdr) + eep_len; - req = kzalloc(len, GFP_KERNEL); - if (!req) - return -ENOMEM; + offset = MT_EE_NIC_CONF_0; + break; + } req_hdr.len = cpu_to_le16(eep_len); - memcpy(req, &req_hdr, sizeof(req_hdr)); - memcpy(req + sizeof(req_hdr), eep + MT_EE_NIC_CONF_0, eep_len); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, - req, len, true); - kfree(req); + skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + eep_len); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, &req_hdr, sizeof(req_hdr)); + skb_put_data(skb, eep + offset, eep_len); - return ret; + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_EFUSE_BUFFER_MODE, true); } int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable) @@ -827,36 +2119,6 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, &req, sizeof(req), true); } -int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int enter) -{ -#define ENTER_PM_STATE 1 -#define EXIT_PM_STATE 2 - struct { - u8 pm_number; - u8 pm_state; - u8 bssid[ETH_ALEN]; - u8 dtim_period; - u8 wlan_idx; - __le16 bcn_interval; - __le32 aid; - __le32 rx_filter; - u8 band_idx; - u8 rsv[3]; - __le32 feature; - u8 omac_idx; - u8 wmm_idx; - u8 bcn_loss_cnt; - u8 bcn_sp_duration; - } __packed req = { - .pm_number = 5, - .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, - .band_idx = band, - }; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, - &req, sizeof(req), true); -} - int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) { struct mt7615_phy *ext_phy = mt7615_ext_phy(dev); @@ -916,202 +2178,6 @@ out: &req, sizeof(req), true); } -int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool enable) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct { - struct req_hdr { - u8 omac_idx; - u8 band_idx; - __le16 tlv_num; - u8 is_tlv_append; - u8 rsv[3]; - } __packed hdr; - struct req_tlv { - __le16 tag; - __le16 len; - u8 active; - u8 band_idx; - u8 omac_addr[ETH_ALEN]; - } __packed tlv; - } data = { - .hdr = { - .omac_idx = mvif->omac_idx, - .band_idx = mvif->band_idx, - .tlv_num = cpu_to_le16(1), - .is_tlv_append = 1, - }, - .tlv = { - .tag = cpu_to_le16(DEV_INFO_ACTIVE), - .len = cpu_to_le16(sizeof(struct req_tlv)), - .active = enable, - .band_idx = mvif->band_idx, - }, - }; - - memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, - &data, sizeof(data), true); -} - -static void -mt7615_mcu_bss_info_omac_header(struct mt7615_vif *mvif, u8 *data, - u32 conn_type) -{ - struct bss_info_omac *hdr = (struct bss_info_omac *)data; - u8 idx; - - idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; - hdr->tag = cpu_to_le16(BSS_INFO_OMAC); - hdr->len = cpu_to_le16(sizeof(struct bss_info_omac)); - hdr->hw_bss_idx = idx; - hdr->omac_idx = mvif->omac_idx; - hdr->band_idx = mvif->band_idx; - hdr->conn_type = cpu_to_le32(conn_type); -} - -static void -mt7615_mcu_bss_info_basic_header(struct ieee80211_vif *vif, u8 *data, - u32 net_type, u8 tx_wlan_idx, - bool enable) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct bss_info_basic *hdr = (struct bss_info_basic *)data; - - hdr->tag = cpu_to_le16(BSS_INFO_BASIC); - hdr->len = cpu_to_le16(sizeof(struct bss_info_basic)); - hdr->network_type = cpu_to_le32(net_type); - hdr->active = enable; - hdr->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); - memcpy(hdr->bssid, vif->bss_conf.bssid, ETH_ALEN); - hdr->wmm_idx = mvif->wmm_idx; - hdr->dtim_period = vif->bss_conf.dtim_period; - hdr->bmc_tx_wlan_idx = tx_wlan_idx; -} - -static void -mt7615_mcu_bss_info_ext_header(struct mt7615_vif *mvif, u8 *data) -{ -/* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ -#define BCN_TX_ESTIMATE_TIME (4096 + 20) - struct bss_info_ext_bss *hdr = (struct bss_info_ext_bss *)data; - int ext_bss_idx, tsf_offset; - - ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; - if (ext_bss_idx < 0) - return; - - hdr->tag = cpu_to_le16(BSS_INFO_EXT_BSS); - hdr->len = cpu_to_le16(sizeof(struct bss_info_ext_bss)); - tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; - hdr->mbss_tsf_offset = cpu_to_le32(tsf_offset); -} - -int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, - struct ieee80211_vif *vif, int en) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct req_hdr { - u8 bss_idx; - u8 rsv0; - __le16 tlv_num; - u8 is_tlv_append; - u8 rsv1[3]; - } __packed; - int len = sizeof(struct req_hdr) + sizeof(struct bss_info_basic); - int ret, i, features = BIT(BSS_INFO_BASIC), ntlv = 1; - u32 conn_type = 0, net_type = NETWORK_INFRA; - u8 *buf, *data, tx_wlan_idx = 0; - struct req_hdr *hdr; - - if (en) { - len += sizeof(struct bss_info_omac); - features |= BIT(BSS_INFO_OMAC); - if (mvif->omac_idx > EXT_BSSID_START) { - len += sizeof(struct bss_info_ext_bss); - features |= BIT(BSS_INFO_EXT_BSS); - ntlv++; - } - ntlv++; - } - - switch (vif->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - tx_wlan_idx = mvif->sta.wcid.idx; - conn_type = CONNECTION_INFRA_AP; - break; - case NL80211_IFTYPE_STATION: { - /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ - if (en) { - struct ieee80211_sta *sta; - struct mt7615_sta *msta; - - rcu_read_lock(); - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); - if (!sta) { - rcu_read_unlock(); - return -EINVAL; - } - - msta = (struct mt7615_sta *)sta->drv_priv; - tx_wlan_idx = msta->wcid.idx; - rcu_read_unlock(); - } - conn_type = CONNECTION_INFRA_STA; - break; - } - case NL80211_IFTYPE_ADHOC: - conn_type = CONNECTION_IBSS_ADHOC; - tx_wlan_idx = mvif->sta.wcid.idx; - net_type = NETWORK_IBSS; - break; - default: - WARN_ON(1); - break; - } - - buf = kzalloc(len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - hdr = (struct req_hdr *)buf; - hdr->bss_idx = mvif->idx; - hdr->tlv_num = cpu_to_le16(ntlv); - hdr->is_tlv_append = 1; - - data = buf + sizeof(*hdr); - for (i = 0; i < BSS_INFO_MAX_NUM; i++) { - int tag = ffs(features & BIT(i)) - 1; - - switch (tag) { - case BSS_INFO_OMAC: - mt7615_mcu_bss_info_omac_header(mvif, data, - conn_type); - data += sizeof(struct bss_info_omac); - break; - case BSS_INFO_BASIC: - mt7615_mcu_bss_info_basic_header(vif, data, net_type, - tx_wlan_idx, en); - data += sizeof(struct bss_info_basic); - break; - case BSS_INFO_EXT_BSS: - mt7615_mcu_bss_info_ext_header(mvif, data); - data += sizeof(struct bss_info_ext_bss); - break; - default: - break; - } - } - - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BSS_INFO_UPDATE, - buf, len, true); - kfree(buf); - - return ret; -} - int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) { struct wtbl_req_hdr req = { @@ -1122,377 +2188,6 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) &req, sizeof(req), true); } -static int -mt7615_mcu_send_sta_rec(struct mt7615_dev *dev, u8 *req, u8 *wreq, - u8 wlen, bool enable) -{ - bool is_v1 = (dev->fw_ver == MT7615_FIRMWARE_V1); - u32 slen = is_v1 ? wreq - req : wreq - req + wlen; - int ret; - - if (is_v1 && !enable) { - ret = __mt76_mcu_send_msg(&dev->mt76, - MCU_EXT_CMD_STA_REC_UPDATE, - req, slen, true); - if (ret) - return ret; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - wreq, wlen, true); - } - - if (is_v1) { - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - wreq, wlen, true); - if (ret) - return ret; - } - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - req, slen, true); -} - -int mt7615_mcu_set_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool en) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct { - struct sta_req_hdr hdr; - struct sta_rec_basic basic; - u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; - } __packed req = { - .hdr = { - .bss_idx = mvif->idx, - .wlan_idx = mvif->sta.wcid.idx, - .tlv_num = cpu_to_le16(1), - .is_tlv_append = 1, - .muar_idx = mvif->omac_idx, - }, - .basic = { - .tag = cpu_to_le16(STA_REC_BASIC), - .len = cpu_to_le16(sizeof(struct sta_rec_basic)), - .conn_type = cpu_to_le32(CONNECTION_INFRA_BC), - }, - }; - struct sta_rec_wtbl *wtbl = NULL; - struct wtbl_req_hdr *wtbl_hdr; - struct wtbl_generic *wtbl_g; - struct wtbl_rx *wtbl_rx; - u8 *buf = req.buf; - - eth_broadcast_addr(req.basic.peer_addr); - - if (dev->fw_ver > MT7615_FIRMWARE_V1) { - req.hdr.tlv_num = cpu_to_le16(2); - wtbl = (struct sta_rec_wtbl *)buf; - wtbl->tag = cpu_to_le16(STA_REC_WTBL); - buf += sizeof(*wtbl); - } - - wtbl_hdr = (struct wtbl_req_hdr *)buf; - buf += sizeof(*wtbl_hdr); - wtbl_hdr->wlan_idx = mvif->sta.wcid.idx; - wtbl_hdr->operation = WTBL_RESET_AND_SET; - - if (en) { - req.basic.conn_state = CONN_STATE_PORT_SECURE; - req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | - EXTRA_INFO_NEW); - } else { - req.basic.conn_state = CONN_STATE_DISCONNECT; - req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); - goto out; - } - - wtbl_g = (struct wtbl_generic *)buf; - buf += sizeof(*wtbl_g); - wtbl_g->tag = cpu_to_le16(WTBL_GENERIC); - wtbl_g->len = cpu_to_le16(sizeof(*wtbl_g)); - wtbl_g->muar_idx = 0xe; - eth_broadcast_addr(wtbl_g->peer_addr); - - wtbl_rx = (struct wtbl_rx *)buf; - buf += sizeof(*wtbl_rx); - wtbl_rx->tag = cpu_to_le16(WTBL_RX); - wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); - wtbl_rx->rv = 1; - wtbl_rx->rca1 = 1; - wtbl_rx->rca2 = 1; - - wtbl_hdr->tlv_num = cpu_to_le16(2); - -out: - if (wtbl) - wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); - - return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, - buf - (u8 *)wtbl_hdr, en); -} - -int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool en) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - - struct { - struct sta_req_hdr hdr; - struct sta_rec_basic basic; - u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; - } __packed req = { - .hdr = { - .bss_idx = mvif->idx, - .wlan_idx = msta->wcid.idx, - .is_tlv_append = 1, - .muar_idx = mvif->omac_idx, - }, - .basic = { - .tag = cpu_to_le16(STA_REC_BASIC), - .len = cpu_to_le16(sizeof(struct sta_rec_basic)), - .qos = sta->wme, - .aid = cpu_to_le16(sta->aid), - }, - }; - struct sta_rec_wtbl *wtbl = NULL; - struct wtbl_req_hdr *wtbl_hdr; - struct wtbl_generic *wtbl_g; - struct wtbl_rx *wtbl_rx; - u8 *buf = req.buf; - u8 wtlv = 0, stlv = 1; - - memcpy(req.basic.peer_addr, sta->addr, ETH_ALEN); - - switch (vif->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_STA); - break; - case NL80211_IFTYPE_STATION: - req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP); - break; - case NL80211_IFTYPE_ADHOC: - req.basic.conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); - break; - default: - WARN_ON(1); - break; - } - - if (en) { - req.basic.conn_state = CONN_STATE_PORT_SECURE; - req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | - EXTRA_INFO_NEW); - - /* sta_rec ht */ - if (sta->ht_cap.ht_supported) { - struct sta_rec_ht *sta_ht; - - sta_ht = (struct sta_rec_ht *)buf; - buf += sizeof(*sta_ht); - sta_ht->tag = cpu_to_le16(STA_REC_HT); - sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); - sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); - stlv++; - - /* sta_rec vht */ - if (sta->vht_cap.vht_supported) { - struct sta_rec_vht *sta_vht; - - sta_vht = (struct sta_rec_vht *)buf; - buf += sizeof(*sta_vht); - sta_vht->tag = cpu_to_le16(STA_REC_VHT); - sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); - sta_vht->vht_cap = - cpu_to_le32(sta->vht_cap.cap); - sta_vht->vht_rx_mcs_map = - sta->vht_cap.vht_mcs.rx_mcs_map; - sta_vht->vht_tx_mcs_map = - sta->vht_cap.vht_mcs.tx_mcs_map; - stlv++; - } - } - } else { - req.basic.conn_state = CONN_STATE_DISCONNECT; - req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); - } - - /* wtbl */ - if (dev->fw_ver > MT7615_FIRMWARE_V1) { - wtbl = (struct sta_rec_wtbl *)buf; - wtbl->tag = cpu_to_le16(STA_REC_WTBL); - buf += sizeof(*wtbl); - stlv++; - } - - wtbl_hdr = (struct wtbl_req_hdr *)buf; - buf += sizeof(*wtbl_hdr); - wtbl_hdr->wlan_idx = msta->wcid.idx; - wtbl_hdr->operation = WTBL_RESET_AND_SET; - - if (!en) - goto out; - - wtbl_g = (struct wtbl_generic *)buf; - buf += sizeof(*wtbl_g); - wtbl_g->tag = cpu_to_le16(WTBL_GENERIC); - wtbl_g->len = cpu_to_le16(sizeof(*wtbl_g)); - wtbl_g->muar_idx = mvif->omac_idx; - wtbl_g->qos = sta->wme; - wtbl_g->partial_aid = cpu_to_le16(sta->aid); - memcpy(wtbl_g->peer_addr, sta->addr, ETH_ALEN); - wtlv++; - - wtbl_rx = (struct wtbl_rx *)buf; - buf += sizeof(*wtbl_rx); - wtbl_rx->tag = cpu_to_le16(WTBL_RX); - wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); - wtbl_rx->rv = 1; - wtbl_rx->rca1 = vif->type != NL80211_IFTYPE_AP; - wtbl_rx->rca2 = 1; - wtlv++; - - /* wtbl ht */ - if (sta->ht_cap.ht_supported) { - struct wtbl_ht *wtbl_ht; - struct wtbl_raw *wtbl_raw; - u32 val = 0, msk; - - wtbl_ht = (struct wtbl_ht *)buf; - buf += sizeof(*wtbl_ht); - wtbl_ht->tag = cpu_to_le16(WTBL_HT); - wtbl_ht->len = cpu_to_le16(sizeof(*wtbl_ht)); - wtbl_ht->ht = 1; - wtbl_ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; - wtbl_ht->af = sta->ht_cap.ampdu_factor; - wtbl_ht->mm = sta->ht_cap.ampdu_density; - wtlv++; - - /* wtbl vht */ - if (sta->vht_cap.vht_supported) { - struct wtbl_vht *wtbl_vht; - - wtbl_vht = (struct wtbl_vht *)buf; - buf += sizeof(*wtbl_vht); - wtbl_vht->tag = cpu_to_le16(WTBL_VHT); - wtbl_vht->len = cpu_to_le16(sizeof(*wtbl_vht)); - wtbl_vht->vht = 1; - wtbl_vht->ldpc = sta->vht_cap.cap & - IEEE80211_VHT_CAP_RXLDPC; - wtlv++; - - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) - val |= MT_WTBL_W5_SHORT_GI_80; - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) - val |= MT_WTBL_W5_SHORT_GI_160; - } - - /* wtbl smps */ - if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) { - struct wtbl_smps *wtbl_smps; - - wtbl_smps = (struct wtbl_smps *)buf; - buf += sizeof(*wtbl_smps); - wtbl_smps->tag = cpu_to_le16(WTBL_SMPS); - wtbl_smps->len = cpu_to_le16(sizeof(*wtbl_smps)); - wtbl_smps->smps = 1; - wtlv++; - } - - /* sgi */ - msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | - MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; - - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) - val |= MT_WTBL_W5_SHORT_GI_20; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) - val |= MT_WTBL_W5_SHORT_GI_40; - - wtbl_raw = (struct wtbl_raw *)buf; - buf += sizeof(*wtbl_raw); - wtbl_raw->tag = cpu_to_le16(WTBL_RAW_DATA); - wtbl_raw->len = cpu_to_le16(sizeof(*wtbl_raw)); - wtbl_raw->wtbl_idx = 1; - wtbl_raw->dw = 5; - wtbl_raw->msk = cpu_to_le32(~msk); - wtbl_raw->val = cpu_to_le32(val); - wtlv++; - } - -out: - if (wtbl) - wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); - - wtbl_hdr->tlv_num = cpu_to_le16(wtlv); - req.hdr.tlv_num = cpu_to_le16(stlv); - - return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, - buf - (u8 *)wtbl_hdr, en); -} - -int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - int en) -{ - struct mt7615_dev *dev = mt7615_hw_dev(hw); - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt76_wcid *wcid = &dev->mt76.global_wcid; - struct ieee80211_mutable_offsets offs; - struct ieee80211_tx_info *info; - struct req { - u8 omac_idx; - u8 enable; - u8 wlan_idx; - u8 band_idx; - u8 pkt_type; - u8 need_pre_tbtt_int; - __le16 csa_ie_pos; - __le16 pkt_len; - __le16 tim_ie_pos; - u8 pkt[512]; - u8 csa_cnt; - /* bss color change */ - u8 bcc_cnt; - __le16 bcc_ie_pos; - } __packed req = { - .omac_idx = mvif->omac_idx, - .enable = en, - .wlan_idx = wcid->idx, - .band_idx = mvif->band_idx, - }; - struct sk_buff *skb; - - skb = ieee80211_beacon_get_template(hw, vif, &offs); - if (!skb) - return -EINVAL; - - if (skb->len > 512 - MT_TXD_SIZE) { - dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); - dev_kfree_skb(skb); - return -EINVAL; - } - - if (mvif->band_idx) { - info = IEEE80211_SKB_CB(skb); - info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; - } - - mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, - 0, NULL); - memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); - req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); - req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); - if (offs.csa_counter_offs[0]) { - u16 csa_offs; - - csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4; - req.csa_ie_pos = cpu_to_le16(csa_offs); - req.csa_cnt = skb->data[offs.csa_counter_offs[0]]; - } - dev_kfree_skb(skb); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, - &req, sizeof(req), true); -} - int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, enum mt7615_rdd_cmd cmd, u8 index, u8 rx_sel, u8 val) @@ -1690,146 +2385,6 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } -int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, - struct ieee80211_ampdu_params *params, - bool add) -{ - struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; - struct mt7615_vif *mvif = msta->vif; - struct { - struct sta_req_hdr hdr; - struct sta_rec_ba ba; - u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; - } __packed req = { - .hdr = { - .bss_idx = mvif->idx, - .wlan_idx = msta->wcid.idx, - .tlv_num = cpu_to_le16(1), - .is_tlv_append = 1, - .muar_idx = mvif->omac_idx, - }, - .ba = { - .tag = cpu_to_le16(STA_REC_BA), - .len = cpu_to_le16(sizeof(struct sta_rec_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_ORIGINATOR, - .amsdu = params->amsdu, - .ba_en = add << params->tid, - .ssn = cpu_to_le16(params->ssn), - .winsize = cpu_to_le16(params->buf_size), - }, - }; - struct sta_rec_wtbl *wtbl = NULL; - struct wtbl_req_hdr *wtbl_hdr; - struct wtbl_ba *wtbl_ba; - u8 *buf = req.buf; - - if (dev->fw_ver > MT7615_FIRMWARE_V1) { - req.hdr.tlv_num = cpu_to_le16(2); - wtbl = (struct sta_rec_wtbl *)buf; - wtbl->tag = cpu_to_le16(STA_REC_WTBL); - buf += sizeof(*wtbl); - } - - wtbl_hdr = (struct wtbl_req_hdr *)buf; - buf += sizeof(*wtbl_hdr); - wtbl_hdr->wlan_idx = msta->wcid.idx; - wtbl_hdr->operation = WTBL_SET; - wtbl_hdr->tlv_num = cpu_to_le16(1); - - wtbl_ba = (struct wtbl_ba *)buf; - buf += sizeof(*wtbl_ba); - wtbl_ba->tag = cpu_to_le16(WTBL_BA); - wtbl_ba->len = cpu_to_le16(sizeof(*wtbl_ba)); - wtbl_ba->tid = params->tid; - wtbl_ba->ba_type = MT_BA_TYPE_ORIGINATOR; - wtbl_ba->sn = add ? cpu_to_le16(params->ssn) : 0; - wtbl_ba->ba_en = add; - - if (add) { - u8 idx, ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; - - for (idx = 7; idx > 0; idx--) { - if (params->buf_size >= ba_range[idx]) - break; - } - - wtbl_ba->ba_winsize_idx = idx; - } - - if (wtbl) - wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); - - return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, - buf - (u8 *)wtbl_hdr, true); -} - -int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, - struct ieee80211_ampdu_params *params, - bool add) -{ - struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; - struct mt7615_vif *mvif = msta->vif; - struct { - struct sta_req_hdr hdr; - struct sta_rec_ba ba; - u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; - } __packed req = { - .hdr = { - .bss_idx = mvif->idx, - .wlan_idx = msta->wcid.idx, - .tlv_num = cpu_to_le16(1), - .is_tlv_append = 1, - .muar_idx = mvif->omac_idx, - }, - .ba = { - .tag = cpu_to_le16(STA_REC_BA), - .len = cpu_to_le16(sizeof(struct sta_rec_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_RECIPIENT, - .amsdu = params->amsdu, - .ba_en = add << params->tid, - .ssn = cpu_to_le16(params->ssn), - .winsize = cpu_to_le16(params->buf_size), - }, - }; - struct sta_rec_wtbl *wtbl = NULL; - struct wtbl_req_hdr *wtbl_hdr; - struct wtbl_ba *wtbl_ba; - u8 *buf = req.buf; - - if (dev->fw_ver > MT7615_FIRMWARE_V1) { - req.hdr.tlv_num = cpu_to_le16(2); - wtbl = (struct sta_rec_wtbl *)buf; - wtbl->tag = cpu_to_le16(STA_REC_WTBL); - buf += sizeof(*wtbl); - } - - wtbl_hdr = (struct wtbl_req_hdr *)buf; - buf += sizeof(*wtbl_hdr); - wtbl_hdr->wlan_idx = msta->wcid.idx; - wtbl_hdr->operation = WTBL_SET; - wtbl_hdr->tlv_num = cpu_to_le16(1); - - wtbl_ba = (struct wtbl_ba *)buf; - buf += sizeof(*wtbl_ba); - wtbl_ba->tag = cpu_to_le16(WTBL_BA); - wtbl_ba->len = cpu_to_le16(sizeof(*wtbl_ba)); - wtbl_ba->tid = params->tid; - wtbl_ba->ba_type = MT_BA_TYPE_RECIPIENT; - wtbl_ba->rst_ba_tid = params->tid; - wtbl_ba->rst_ba_sel = RST_BA_MAC_TID_MATCH; - wtbl_ba->rst_ba_sb = 1; - - memcpy(wtbl_ba->peer_addr, params->sta->addr, ETH_ALEN); - - if (wtbl) - wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); - - return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, - buf - (u8 *)wtbl_hdr, add); -} - int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index db0199e60cb8..d1f7391472fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -23,6 +23,57 @@ struct mt7615_mcu_txd { u32 reserved[5]; } __packed __aligned(4); +/** + * struct mt7615_uni_txd - mcu command descriptor for firmware v3 + * @txd: hardware descriptor + * @len: total length not including txd + * @cid: command identifier + * @pkt_type: must be 0xa0 (cmd packet by long format) + * @frag_n: fragment number + * @seq: sequence number + * @checksum: 0 mean there is no checksum + * @s2d_index: index for command source and destination + * Definition | value | note + * CMD_S2D_IDX_H2N | 0x00 | command from HOST to WM + * CMD_S2D_IDX_C2N | 0x01 | command from WA to WM + * CMD_S2D_IDX_H2C | 0x02 | command from HOST to WA + * CMD_S2D_IDX_H2N_AND_H2C | 0x03 | command from HOST to WA and WM + * + * @option: command option + * BIT[0]: UNI_CMD_OPT_BIT_ACK + * set to 1 to request a fw reply + * if UNI_CMD_OPT_BIT_0_ACK is set and UNI_CMD_OPT_BIT_2_SET_QUERY + * is set, mcu firmware will send response event EID = 0x01 + * (UNI_EVENT_ID_CMD_RESULT) to the host. + * BIT[1]: UNI_CMD_OPT_BIT_UNI_CMD + * 0: original command + * 1: unified command + * BIT[2]: UNI_CMD_OPT_BIT_SET_QUERY + * 0: QUERY command + * 1: SET command + */ +struct mt7615_uni_txd { + __le32 txd[8]; + + /* DW1 */ + __le16 len; + __le16 cid; + + /* DW2 */ + u8 reserved; + u8 pkt_type; + u8 frag_n; + u8 seq; + + /* DW3 */ + __le16 checksum; + u8 s2d_index; + u8 option; + + /* DW4 */ + u8 reserved2[4]; +} __packed __aligned(4); + /* event table */ enum { MCU_EVENT_TARGET_ADDRESS_LEN = 0x01, @@ -179,16 +230,20 @@ enum { MCU_S2D_H2CN }; +#define MCU_FW_PREFIX BIT(31) +#define MCU_UNI_PREFIX BIT(30) +#define MCU_CMD_MASK ~(MCU_FW_PREFIX | MCU_UNI_PREFIX) + enum { - MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01, - MCU_CMD_FW_START_REQ = 0x02, + MCU_CMD_TARGET_ADDRESS_LEN_REQ = MCU_FW_PREFIX | 0x01, + MCU_CMD_FW_START_REQ = MCU_FW_PREFIX | 0x02, MCU_CMD_INIT_ACCESS_REG = 0x3, MCU_CMD_PATCH_START_REQ = 0x05, - MCU_CMD_PATCH_FINISH_REQ = 0x07, - MCU_CMD_PATCH_SEM_CONTROL = 0x10, + MCU_CMD_PATCH_FINISH_REQ = MCU_FW_PREFIX | 0x07, + MCU_CMD_PATCH_SEM_CONTROL = MCU_FW_PREFIX | 0x10, MCU_CMD_EXT_CID = 0xED, - MCU_CMD_FW_SCATTER = 0xEE, - MCU_CMD_RESTART_DL_REQ = 0xEF, + MCU_CMD_FW_SCATTER = MCU_FW_PREFIX | 0xEE, + MCU_CMD_RESTART_DL_REQ = MCU_FW_PREFIX | 0xEF, }; enum { @@ -215,6 +270,23 @@ enum { }; enum { + MCU_UNI_CMD_DEV_INFO_UPDATE = MCU_UNI_PREFIX | 0x01, + MCU_UNI_CMD_BSS_INFO_UPDATE = MCU_UNI_PREFIX | 0x02, + MCU_UNI_CMD_STA_REC_UPDATE = MCU_UNI_PREFIX | 0x03, +}; + +#define MCU_CMD_ACK BIT(0) +#define MCU_CMD_UNI BIT(1) +#define MCU_CMD_QUERY BIT(2) + +#define MCU_CMD_UNI_EXT_ACK (MCU_CMD_ACK | MCU_CMD_UNI | MCU_CMD_QUERY) + +enum { + UNI_BSS_INFO_BASIC = 0, + UNI_BSS_INFO_BCN_CONTENT = 7, +}; + +enum { PATCH_SEM_RELEASE = 0x0, PATCH_SEM_GET = 0x1 }; @@ -274,6 +346,11 @@ enum { __DBDC_TYPE_MAX, }; +struct tlv { + __le16 tag; + __le16 len; +} __packed; + struct bss_info_omac { __le16 tag; __le16 len; @@ -483,18 +560,28 @@ struct wtbl_raw { __le32 val; } __packed; -#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \ - sizeof(struct wtbl_generic) + \ - sizeof(struct wtbl_rx) + \ - sizeof(struct wtbl_ht) + \ - sizeof(struct wtbl_vht) + \ - sizeof(struct wtbl_tx_ps) + \ - sizeof(struct wtbl_hdr_trans) + \ - sizeof(struct wtbl_ba) + \ - sizeof(struct wtbl_bf) + \ - sizeof(struct wtbl_smps) + \ - sizeof(struct wtbl_pn) + \ - sizeof(struct wtbl_spe)) +#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \ + sizeof(struct wtbl_generic) + \ + sizeof(struct wtbl_rx) + \ + sizeof(struct wtbl_ht) + \ + sizeof(struct wtbl_vht) + \ + sizeof(struct wtbl_tx_ps) + \ + sizeof(struct wtbl_hdr_trans) +\ + sizeof(struct wtbl_ba) + \ + sizeof(struct wtbl_bf) + \ + sizeof(struct wtbl_smps) + \ + sizeof(struct wtbl_pn) + \ + sizeof(struct wtbl_spe)) + +#define MT7615_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ + sizeof(struct sta_rec_basic) + \ + sizeof(struct sta_rec_ht) + \ + sizeof(struct sta_rec_vht) + \ + sizeof(struct tlv) + \ + MT7615_WTBL_UPDATE_MAX_SIZE) + +#define MT7615_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \ + sizeof(struct wtbl_ba)) enum { WTBL_GENERIC, @@ -517,6 +604,11 @@ enum { WTBL_MAX_NUM }; +struct sta_ntlv_hdr { + u8 rsv[2]; + __le16 tlv_num; +} __packed; + struct sta_req_hdr { u8 bss_idx; u8 wlan_idx; @@ -526,6 +618,15 @@ struct sta_req_hdr { u8 rsv[2]; } __packed; +struct sta_rec_state { + __le16 tag; + __le16 len; + u8 state; + __le32 flags; + u8 vhtop; + u8 pad[2]; +} __packed; + struct sta_rec_basic { __le16 tag; __le16 len; @@ -565,11 +666,6 @@ struct sta_rec_ba { __le16 winsize; } __packed; -struct sta_rec_wtbl { - __le16 tag; - __le16 len; -} __packed; - enum { STA_REC_BASIC, STA_REC_RA, @@ -578,7 +674,7 @@ enum { STA_REC_BF, STA_REC_AMSDU, /* for CR4 */ STA_REC_BA, - STA_REC_RED, /* not used */ + STA_REC_STATE, STA_REC_TX_PROC, /* for hdr trans and CSO in CR4 */ STA_REC_HT, STA_REC_VHT, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index 0b445471b6e8..d2eff5442824 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -2,14 +2,68 @@ #include <linux/module.h> #include "mt7615.h" +#include "regs.h" #include "mac.h" #include "../trace.h" +const u32 mt7615e_reg_map[] = { + [MT_TOP_CFG_BASE] = 0x01000, + [MT_HW_BASE] = 0x01000, + [MT_PCIE_REMAP_2] = 0x02504, + [MT_ARB_BASE] = 0x20c00, + [MT_HIF_BASE] = 0x04000, + [MT_CSR_BASE] = 0x07000, + [MT_PHY_BASE] = 0x10000, + [MT_CFG_BASE] = 0x20200, + [MT_AGG_BASE] = 0x20a00, + [MT_TMAC_BASE] = 0x21000, + [MT_RMAC_BASE] = 0x21200, + [MT_DMA_BASE] = 0x21800, + [MT_WTBL_BASE_ON] = 0x23000, + [MT_WTBL_BASE_OFF] = 0x23400, + [MT_LPON_BASE] = 0x24200, + [MT_MIB_BASE] = 0x24800, + [MT_WTBL_BASE_ADDR] = 0x30000, + [MT_PCIE_REMAP_BASE2] = 0x80000, + [MT_TOP_MISC_BASE] = 0xc0000, + [MT_EFUSE_ADDR_BASE] = 0x81070000, +}; + +const u32 mt7663e_reg_map[] = { + [MT_TOP_CFG_BASE] = 0x01000, + [MT_HW_BASE] = 0x02000, + [MT_DMA_SHDL_BASE] = 0x06000, + [MT_PCIE_REMAP_2] = 0x0700c, + [MT_ARB_BASE] = 0x20c00, + [MT_HIF_BASE] = 0x04000, + [MT_CSR_BASE] = 0x07000, + [MT_PHY_BASE] = 0x10000, + [MT_CFG_BASE] = 0x20000, + [MT_AGG_BASE] = 0x22000, + [MT_TMAC_BASE] = 0x24000, + [MT_RMAC_BASE] = 0x25000, + [MT_DMA_BASE] = 0x27000, + [MT_WTBL_BASE_ON] = 0x29000, + [MT_WTBL_BASE_OFF] = 0x29800, + [MT_LPON_BASE] = 0x2b000, + [MT_MIB_BASE] = 0x2d000, + [MT_WTBL_BASE_ADDR] = 0x30000, + [MT_PCIE_REMAP_BASE2] = 0x90000, + [MT_TOP_MISC_BASE] = 0xc0000, + [MT_EFUSE_ADDR_BASE] = 0x78011000, +}; + u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) { - u32 base = addr & MT_MCU_PCIE_REMAP_2_BASE; - u32 offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; - + u32 base, offset; + + if (is_mt7663(&dev->mt76)) { + base = addr & MT7663_MCU_PCIE_REMAP_2_BASE; + offset = addr & MT7663_MCU_PCIE_REMAP_2_OFFSET; + } else { + base = addr & MT_MCU_PCIE_REMAP_2_BASE; + offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; + } mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); return MT_PCIE_REMAP_BASE_2 + offset; @@ -66,7 +120,8 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) return IRQ_HANDLED; } -int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq) +int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, + int irq, const u32 *map) { static const struct mt76_driver_ops drv_ops = { /* txwi_size = txd size + txp size */ @@ -95,6 +150,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq) dev = container_of(mdev, struct mt7615_dev, mt76); mt76_mmio_init(&dev->mt76, mem_base); + dev->reg_map = map; mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | (mt76_rr(dev, MT_HW_REV) & 0xff); dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); @@ -104,6 +160,9 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq) if (ret) goto error; + if (is_mt7663(mdev)) + mt76_wr(dev, MT_PCIE_IRQ_ENABLE, 1); + ret = mt7615_register_device(dev); if (ret) goto error; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index a84a9b4cbf4e..676ca622c35a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -38,6 +38,10 @@ #define MT7615_FIRMWARE_V1 1 #define MT7615_FIRMWARE_V2 2 +#define MT7615_FIRMWARE_V3 3 + +#define MT7663_ROM_PATCH "mediatek/mt7663pr2h_v3.bin" +#define MT7663_FIRMWARE_N9 "mediatek/mt7663_n9_v3.bin" #define MT7615_EEPROM_SIZE 1024 #define MT7615_TOKEN_SIZE 4096 @@ -144,6 +148,33 @@ struct mt7615_phy { struct mib_stats mib; }; +#define mt7615_mcu_add_tx_ba(dev, ...) (dev)->mcu_ops->add_tx_ba((dev), __VA_ARGS__) +#define mt7615_mcu_add_rx_ba(dev, ...) (dev)->mcu_ops->add_rx_ba((dev), __VA_ARGS__) +#define mt7615_mcu_sta_add(dev, ...) (dev)->mcu_ops->sta_add((dev), __VA_ARGS__) +#define mt7615_mcu_add_dev_info(dev, ...) (dev)->mcu_ops->add_dev_info((dev), __VA_ARGS__) +#define mt7615_mcu_add_bss_info(dev, ...) (dev)->mcu_ops->add_bss_info((dev), __VA_ARGS__) +#define mt7615_mcu_add_beacon(dev, ...) (dev)->mcu_ops->add_beacon_offload((dev), __VA_ARGS__) +#define mt7615_mcu_set_pm(dev, ...) (dev)->mcu_ops->set_pm_state((dev), __VA_ARGS__) +struct mt7615_mcu_ops { + int (*add_tx_ba)(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable); + int (*add_rx_ba)(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable); + int (*sta_add)(struct mt7615_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable); + int (*add_dev_info)(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable); + int (*add_bss_info)(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool enable); + int (*add_beacon_offload)(struct mt7615_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, bool enable); + int (*set_pm_state)(struct mt7615_dev *dev, int band, int state); +}; + struct mt7615_dev { union { /* must be first */ struct mt76_dev mt76; @@ -156,7 +187,9 @@ struct mt7615_dev { u16 chainmask; + const struct mt7615_mcu_ops *mcu_ops; struct regmap *infracfg; + const u32 *reg_map; struct work_struct mcu_work; @@ -257,6 +290,8 @@ mt7615_ext_phy(struct mt7615_dev *dev) } extern const struct ieee80211_ops mt7615_ops; +extern const u32 mt7615e_reg_map[__MT_BASE_MAX]; +extern const u32 mt7663e_reg_map[__MT_BASE_MAX]; extern struct pci_driver mt7615_pci_driver; extern struct platform_driver mt7622_wmac_driver; @@ -269,9 +304,11 @@ static inline int mt7622_wmac_init(struct mt7615_dev *dev) } #endif -int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq); +int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, + int irq, const u32 *map); u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); +void mt7615_init_device(struct mt7615_dev *dev); int mt7615_register_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev); int mt7615_register_ext_phy(struct mt7615_dev *dev); @@ -284,29 +321,13 @@ int mt7615_dma_init(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev); int mt7615_mcu_init(struct mt7615_dev *dev); bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev); -int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool enable); -int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en); void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates); int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev); -int mt7615_mcu_set_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, - bool en); -int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool en); -int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - int en); int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd); int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, const struct ieee80211_tx_queue_params *params); -int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, - struct ieee80211_ampdu_params *params, - bool add); -int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, - struct ieee80211_ampdu_params *params, - bool add); void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb); int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, enum mt7615_rdd_cmd cmd, u8 index, @@ -327,6 +348,11 @@ static inline bool is_mt7615(struct mt76_dev *dev) return mt76_chip(dev) == 0x7615; } +static inline bool is_mt7663(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7663; +} + static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) { mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask); @@ -347,7 +373,7 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev); int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int pid, - struct ieee80211_key_conf *key); + struct ieee80211_key_conf *key, bool beacon); void mt7615_mac_set_timing(struct mt7615_phy *phy); int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb); void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data); @@ -357,13 +383,15 @@ int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, enum set_key_cmd cmd); void mt7615_mac_reset_work(struct work_struct *work); +int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq); int mt7615_mcu_set_dbdc(struct mt7615_dev *dev); int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable); int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val); -int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int enter); int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index); void mt7615_mcu_exit(struct mt7615_dev *dev); +void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb, + int cmd, int *wait_seq); int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 43e02128cc48..c8d0f893a47f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -13,12 +13,14 @@ static const struct pci_device_id mt7615_pci_device_table[] = { { PCI_DEVICE(0x14c3, 0x7615) }, + { PCI_DEVICE(0x14c3, 0x7663) }, { }, }; static int mt7615_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + const u32 *map; int ret; ret = pcim_enable_device(pdev); @@ -35,7 +37,9 @@ static int mt7615_pci_probe(struct pci_dev *pdev, if (ret) return ret; - return mt7615_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], pdev->irq); + map = id->device == 0x7663 ? mt7663e_reg_map : mt7615e_reg_map; + return mt7615_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], + pdev->irq, map); } static void mt7615_pci_remove(struct pci_dev *pdev) @@ -57,3 +61,5 @@ MODULE_DEVICE_TABLE(pci, mt7615_pci_device_table); MODULE_FIRMWARE(MT7615_FIRMWARE_CR4); MODULE_FIRMWARE(MT7615_FIRMWARE_N9); MODULE_FIRMWARE(MT7615_ROM_PATCH); +MODULE_FIRMWARE(MT7663_FIRMWARE_N9); +MODULE_FIRMWARE(MT7663_ROM_PATCH); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index fe68f6b2cbf8..1e0d95b917e1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -4,17 +4,46 @@ #ifndef __MT7615_REGS_H #define __MT7615_REGS_H -#define MT_HW_REV 0x1000 -#define MT_HW_CHIPID 0x1008 -#define MT_TOP_STRAP_STA 0x1010 +enum mt7615_reg_base { + MT_TOP_CFG_BASE, + MT_HW_BASE, + MT_DMA_SHDL_BASE, + MT_PCIE_REMAP_2, + MT_ARB_BASE, + MT_HIF_BASE, + MT_CSR_BASE, + MT_PHY_BASE, + MT_CFG_BASE, + MT_AGG_BASE, + MT_TMAC_BASE, + MT_RMAC_BASE, + MT_DMA_BASE, + MT_WTBL_BASE_ON, + MT_WTBL_BASE_OFF, + MT_LPON_BASE, + MT_MIB_BASE, + MT_WTBL_BASE_ADDR, + MT_PCIE_REMAP_BASE2, + MT_TOP_MISC_BASE, + MT_EFUSE_ADDR_BASE, + __MT_BASE_MAX, +}; + +#define MT_HW_INFO_BASE ((dev)->reg_map[MT_HW_BASE]) +#define MT_HW_INFO(ofs) (MT_HW_INFO_BASE + (ofs)) +#define MT_HW_REV MT_HW_INFO(0x000) +#define MT_HW_CHIPID MT_HW_INFO(0x008) +#define MT_TOP_STRAP_STA MT_HW_INFO(0x010) #define MT_TOP_3NSS BIT(24) #define MT_TOP_OFF_RSV 0x1128 #define MT_TOP_OFF_RSV_FW_STATE GENMASK(18, 16) -#define MT_TOP_MISC2 0x1134 +#define MT_TOP_MISC2 ((dev)->reg_map[MT_TOP_CFG_BASE] + 0x134) #define MT_TOP_MISC2_FW_STATE GENMASK(2, 0) +#define MT7663_TOP_MISC2_FW_STATE GENMASK(3, 1) + #define MT_MCU_BASE 0x2000 #define MT_MCU(ofs) (MT_MCU_BASE + (ofs)) @@ -23,13 +52,19 @@ #define MT_MCU_PCIE_REMAP_1_BASE GENMASK(31, 18) #define MT_PCIE_REMAP_BASE_1 0x40000 -#define MT_MCU_PCIE_REMAP_2 MT_MCU(0x504) +#define MT_MCU_PCIE_REMAP_2 ((dev)->reg_map[MT_PCIE_REMAP_2]) #define MT_MCU_PCIE_REMAP_2_OFFSET GENMASK(18, 0) #define MT_MCU_PCIE_REMAP_2_BASE GENMASK(31, 19) -#define MT_PCIE_REMAP_BASE_2 0x80000 +#define MT_PCIE_REMAP_BASE_2 ((dev)->reg_map[MT_PCIE_REMAP_BASE2]) + +#define MT_HIF(ofs) ((dev)->reg_map[MT_HIF_BASE] + (ofs)) + +#define MT7663_MCU_PCIE_REMAP_2_OFFSET GENMASK(15, 0) +#define MT7663_MCU_PCIE_REMAP_2_BASE GENMASK(31, 16) -#define MT_HIF_BASE 0x4000 -#define MT_HIF(ofs) (MT_HIF_BASE + (ofs)) +#define MT_HIF2_BASE 0xf0000 +#define MT_HIF2(ofs) (MT_HIF2_BASE + (ofs)) +#define MT_PCIE_IRQ_ENABLE MT_HIF2(0x188) #define MT_CFG_LPCR_HOST MT_HIF(0x1f0) #define MT_CFG_LPCR_HOST_FW_OWN BIT(0) @@ -95,6 +130,9 @@ #define MT_WPDMA_ABT_CFG MT_HIF(0x530) #define MT_WPDMA_ABT_CFG1 MT_HIF(0x534) +#define MT_CSR(ofs) ((dev)->reg_map[MT_CSR_BASE] + (ofs)) +#define MT_CONN_HIF_ON_LPCTL MT_CSR(0x000) + #define MT_PLE_BASE 0x8000 #define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) @@ -106,7 +144,7 @@ #define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \ ((n) << 2)) -#define MT_WF_PHY_BASE 0x10000 +#define MT_WF_PHY_BASE ((dev)->reg_map[MT_PHY_BASE]) #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) #define MT_WF_PHY_WF2_RFCTRL0(n) MT_WF_PHY(0x1900 + (n) * 0x400) @@ -139,7 +177,7 @@ #define MT_WF_PHY_RXTD2_BASE MT_WF_PHY(0x2a00) #define MT_WF_PHY_RXTD2(_n) (MT_WF_PHY_RXTD2_BASE + ((_n) << 2)) -#define MT_WF_CFG_BASE 0x20200 +#define MT_WF_CFG_BASE ((dev)->reg_map[MT_CFG_BASE]) #define MT_WF_CFG(ofs) (MT_WF_CFG_BASE + (ofs)) #define MT_CFG_CCR MT_WF_CFG(0x000) @@ -148,7 +186,7 @@ #define MT_CFG_CCR_MAC_D1_2X_GC_EN BIT(30) #define MT_CFG_CCR_MAC_D0_2X_GC_EN BIT(31) -#define MT_WF_AGG_BASE 0x20a00 +#define MT_WF_AGG_BASE ((dev)->reg_map[MT_AGG_BASE]) #define MT_WF_AGG(ofs) (MT_WF_AGG_BASE + (ofs)) #define MT_AGG_ARCR MT_WF_AGG(0x010) @@ -179,7 +217,7 @@ #define MT_AGG_SCR MT_WF_AGG(0x0fc) #define MT_AGG_SCR_NLNAV_MID_PTEC_DIS BIT(3) -#define MT_WF_ARB_BASE 0x20c00 +#define MT_WF_ARB_BASE ((dev)->reg_map[MT_ARB_BASE]) #define MT_WF_ARB(ofs) (MT_WF_ARB_BASE + (ofs)) #define MT_ARB_SCR MT_WF_ARB(0x080) @@ -188,7 +226,7 @@ #define MT_ARB_SCR_TX1_DISABLE BIT(10) #define MT_ARB_SCR_RX1_DISABLE BIT(11) -#define MT_WF_TMAC_BASE 0x21000 +#define MT_WF_TMAC_BASE ((dev)->reg_map[MT_TMAC_BASE]) #define MT_WF_TMAC(ofs) (MT_WF_TMAC_BASE + (ofs)) #define MT_TMAC_CDTR MT_WF_TMAC(0x090) @@ -212,7 +250,7 @@ #define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) #define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) -#define MT_WF_RMAC_BASE 0x21200 +#define MT_WF_RMAC_BASE ((dev)->reg_map[MT_RMAC_BASE]) #define MT_WF_RMAC(ofs) (MT_WF_RMAC_BASE + (ofs)) #define MT_WF_RFCR(_band) MT_WF_RMAC((_band) ? 0x100 : 0x000) @@ -257,7 +295,7 @@ #define MT_WF_RMAC_MIB_TIME6 MT_WF_RMAC(0x03dc) #define MT_MIB_OBSSTIME_MASK GENMASK(23, 0) -#define MT_WF_DMA_BASE 0x21800 +#define MT_WF_DMA_BASE ((dev)->reg_map[MT_DMA_BASE]) #define MT_WF_DMA(ofs) (MT_WF_DMA_BASE + (ofs)) #define MT_DMA_DCR0 MT_WF_DMA(0x000) @@ -272,10 +310,10 @@ #define MT_DMA_RCFR0_RX_DROPPED_UCAST GENMASK(25, 24) #define MT_DMA_RCFR0_RX_DROPPED_MCAST GENMASK(27, 26) -#define MT_WTBL_BASE 0x30000 +#define MT_WTBL_BASE(dev) ((dev)->reg_map[MT_WTBL_BASE_ADDR]) #define MT_WTBL_ENTRY_SIZE 256 -#define MT_WTBL_OFF_BASE 0x23400 +#define MT_WTBL_OFF_BASE ((dev)->reg_map[MT_WTBL_BASE_OFF]) #define MT_WTBL_OFF(n) (MT_WTBL_OFF_BASE + (n)) #define MT_WTBL_W0_KEY_IDX GENMASK(24, 23) @@ -292,7 +330,11 @@ #define MT_WTBL_UPDATE_TX_COUNT_CLEAR BIT(14) #define MT_WTBL_UPDATE_BUSY BIT(31) -#define MT_WTBL_ON_BASE 0x23000 +#define MT_TOP_MISC(ofs) ((dev)->reg_map[MT_TOP_MISC_BASE] + (ofs)) +#define MT_CONN_ON_MISC MT_TOP_MISC(0x1140) +#define MT_TOP_MISC2_FW_N9_RDY BIT(2) + +#define MT_WTBL_ON_BASE ((dev)->reg_map[MT_WTBL_BASE_ON]) #define MT_WTBL_ON(_n) (MT_WTBL_ON_BASE + (_n)) #define MT_WTBL_RICR0 MT_WTBL_ON(0x010) @@ -328,8 +370,7 @@ #define MT_WTBL_W27_CC_BW_SEL GENMASK(6, 5) -#define MT_LPON_BASE 0x24200 -#define MT_LPON(_n) (MT_LPON_BASE + (_n)) +#define MT_LPON(_n) ((dev)->reg_map[MT_LPON_BASE] + (_n)) #define MT_LPON_T0CR MT_LPON(0x010) #define MT_LPON_T0CR_MODE GENMASK(1, 0) @@ -337,7 +378,7 @@ #define MT_LPON_UTTR0 MT_LPON(0x018) #define MT_LPON_UTTR1 MT_LPON(0x01c) -#define MT_WF_MIB_BASE 0x24800 +#define MT_WF_MIB_BASE (dev->reg_map[MT_MIB_BASE]) #define MT_WF_MIB(ofs) (MT_WF_MIB_BASE + (ofs)) #define MT_MIB_M0_MISC_CR MT_WF_MIB(0x00c) @@ -367,6 +408,8 @@ #define MT_TX_AGG_CNT(n) MT_WF_MIB(0xa8 + ((n) << 2)) +#define MT_DMA_SHDL(ofs) (dev->reg_map[MT_DMA_SHDL_BASE] + (ofs)) + #define MT_DMASHDL_BASE 0x5000a000 #define MT_DMASHDL_OPTIONAL 0x008 #define MT_DMASHDL_PAGE 0x00c @@ -406,7 +449,7 @@ #define MT_LED_STATUS_ON GENMASK(23, 16) #define MT_LED_STATUS_DURATION GENMASK(15, 0) -#define MT_EFUSE_BASE 0x81070000 +#define MT_EFUSE_BASE ((dev)->reg_map[MT_EFUSE_ADDR_BASE]) #define MT_EFUSE_BASE_CTRL 0x000 #define MT_EFUSE_BASE_CTRL_EMPTY BIT(30) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c index 07ec9ec282f5..43aa49706c66 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c @@ -47,7 +47,7 @@ static int mt7622_wmac_probe(struct platform_device *pdev) return PTR_ERR(mem_base); } - return mt7615_mmio_probe(&pdev->dev, mem_base, irq); + return mt7615_mmio_probe(&pdev->dev, mem_base, irq, mt7615e_reg_map); } static int mt7622_wmac_remove(struct platform_device *pdev) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index b56397c05218..09f34deb6ba1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -1155,7 +1155,6 @@ static void mt76x0_rf_patch_reg_array(struct mt76x02_dev *dev, static void mt76x0_phy_rf_init(struct mt76x02_dev *dev) { int i; - u8 val; mt76x0_rf_patch_reg_array(dev, mt76x0_rf_central_tab, ARRAY_SIZE(mt76x0_rf_central_tab)); @@ -1188,7 +1187,7 @@ static void mt76x0_phy_rf_init(struct mt76x02_dev *dev) */ mt76x0_rf_wr(dev, MT_RF(0, 22), min_t(u8, dev->cal.rx.freq_offset, 0xbf)); - val = mt76x0_rf_rr(dev, MT_RF(0, 22)); + mt76x0_rf_rr(dev, MT_RF(0, 22)); /* Reset procedure DAC during power-up: * - set B0.R73<7> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index c7f028e73b6b..7dcc5d342e9f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -461,6 +461,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) mutex_lock(&dev->mt76.mutex); + dev->mcu_timeout = 0; if (restart) mt76x02_reset_state(dev); @@ -544,10 +545,6 @@ static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) restart: mt76x02_watchdog_reset(dev); - mutex_lock(&dev->mt76.mcu.mutex); - dev->mcu_timeout = 0; - mutex_unlock(&dev->mt76.mcu.mutex); - dev->tx_hang_reset++; dev->tx_hang_check = 0; memset(dev->mt76.tx_dma_idx, 0xff, diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 36ba81d63f12..a981da6c35a5 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -70,10 +70,10 @@ static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u32 addr) ret = __mt76u_vendor_request(dev, req, USB_DIR_IN | USB_TYPE_VENDOR, - addr >> 16, addr, &usb->reg_val, + addr >> 16, addr, usb->data, sizeof(__le32)); if (ret == sizeof(__le32)) - data = le32_to_cpu(usb->reg_val); + data = get_unaligned_le32(usb->data); trace_usb_reg_rr(dev, addr, data); return data; @@ -125,10 +125,10 @@ static void ___mt76u_wr(struct mt76_dev *dev, u8 req, { struct mt76_usb *usb = &dev->usb; - usb->reg_val = cpu_to_le32(val); + put_unaligned_le32(val, usb->data); __mt76u_vendor_request(dev, req, USB_DIR_OUT | USB_TYPE_VENDOR, - addr >> 16, addr, &usb->reg_val, + addr >> 16, addr, usb->data, sizeof(__le32)); trace_usb_reg_wr(dev, addr, val); } @@ -672,10 +672,17 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) static void mt76u_rx_tasklet(unsigned long data) { struct mt76_dev *dev = (struct mt76_dev *)data; - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct mt76_queue *q; + int i; rcu_read_lock(); - mt76u_process_rx_queue(dev, q); + for (i = 0; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; + if (!q->ndesc) + continue; + + mt76u_process_rx_queue(dev, q); + } rcu_read_unlock(); } @@ -1150,6 +1157,7 @@ int mt76u_init(struct mt76_dev *dev, }; struct usb_device *udev = interface_to_usbdev(intf); struct mt76_usb *usb = &dev->usb; + int err = -ENOMEM; mt76u_ops.rr = ext ? mt76u_rr_ext : mt76u_rr; mt76u_ops.wr = ext ? mt76u_wr_ext : mt76u_wr; @@ -1169,10 +1177,8 @@ int mt76u_init(struct mt76_dev *dev, usb->data_len = 32; usb->data = devm_kmalloc(dev->dev, usb->data_len, GFP_KERNEL); - if (!usb->data) { - mt76u_deinit(dev); - return -ENOMEM; - } + if (!usb->data) + goto error; mutex_init(&usb->usb_ctrl_mtx); dev->bus = &mt76u_ops; @@ -1182,7 +1188,15 @@ int mt76u_init(struct mt76_dev *dev, usb->sg_en = mt76u_check_sg(dev); - return mt76u_set_endpoints(intf, usb); + err = mt76u_set_endpoints(intf, usb); + if (err < 0) + goto error; + + return 0; + +error: + mt76u_deinit(dev); + return err; } EXPORT_SYMBOL_GPL(mt76u_init); diff --git a/drivers/net/wireless/rayctl.h b/drivers/net/wireless/rayctl.h index 668444f6bf07..2b0f332043d7 100644 --- a/drivers/net/wireless/rayctl.h +++ b/drivers/net/wireless/rayctl.h @@ -570,7 +570,7 @@ struct phy_header { }; struct ray_rx_msg { struct mac_header mac; - UCHAR var[0]; + UCHAR var[]; }; struct tx_msg { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 6598c8d786ea..d6d1be4169e5 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -627,7 +627,7 @@ struct rtl8xxxu_firmware_header { u32 reserved4; u32 reserved5; - u8 data[0]; + u8 data[]; }; /* @@ -1133,6 +1133,15 @@ enum bt_mp_oper_opcode_8723b { BT_MP_OP_ENABLE_CFO_TRACKING = 0x24, }; +enum rtl8xxxu_bw_mode { + RTL8XXXU_CHANNEL_WIDTH_20 = 0, + RTL8XXXU_CHANNEL_WIDTH_40 = 1, + RTL8XXXU_CHANNEL_WIDTH_80 = 2, + RTL8XXXU_CHANNEL_WIDTH_160 = 3, + RTL8XXXU_CHANNEL_WIDTH_80_80 = 4, + RTL8XXXU_CHANNEL_WIDTH_MAX = 5, +}; + struct rtl8723bu_c2h { u8 id; u8 seq; @@ -1174,13 +1183,16 @@ struct rtl8723bu_c2h { } __packed bt_info; struct { u8 rate:7; - u8 dummy0_0:1; + u8 sgi:1; u8 macid; u8 ldpc:1; u8 txbf:1; u8 noisy_state:1; u8 dummy2_0:5; u8 dummy3_0; + u8 dummy4_0; + u8 dummy5_0; + u8 bw; } __packed ra_report; }; }; @@ -1260,6 +1272,12 @@ struct rtl8xxxu_btcoex { #define RTL8XXXU_SNR_THRESH_HIGH 50 #define RTL8XXXU_SNR_THRESH_LOW 20 +struct rtl8xxxu_ra_report { + struct rate_info txrate; + u32 bit_rate; + u8 desc_rate; +}; + struct rtl8xxxu_priv { struct ieee80211_hw *hw; struct usb_device *udev; @@ -1375,6 +1393,7 @@ struct rtl8xxxu_priv { struct sk_buff_head c2hcmd_queue; spinlock_t c2hcmd_lock; struct rtl8xxxu_btcoex bt_coex; + struct rtl8xxxu_ra_report ra_report; }; struct rtl8xxxu_rx_urb { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 54a1a4ea107b..19efae462a24 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -4328,7 +4328,7 @@ void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, u32 ramask, u8 rateid, int sgi) { struct h2c_cmd h2c; - u8 bw = 0; + u8 bw = RTL8XXXU_CHANNEL_WIDTH_20; memset(&h2c, 0, sizeof(struct h2c_cmd)); @@ -4816,8 +4816,8 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, rate = tx_rate->hw_value; if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) - dev_info(dev, "%s: TX rate: %d, pkt size %d\n", - __func__, rate, cpu_to_le16(tx_desc->pkt_size)); + dev_info(dev, "%s: TX rate: %d, pkt size %u\n", + __func__, rate, le16_to_cpu(tx_desc->pkt_size)); seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); @@ -4889,8 +4889,8 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, rate = tx_rate->hw_value; if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) - dev_info(dev, "%s: TX rate: %d, pkt size %d\n", - __func__, rate, cpu_to_le16(tx_desc40->pkt_size)); + dev_info(dev, "%s: TX rate: %d, pkt size %u\n", + __func__, rate, le16_to_cpu(tx_desc40->pkt_size)); seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); @@ -5389,6 +5389,35 @@ void rtl8723bu_handle_bt_info(struct rtl8xxxu_priv *priv) } } +static struct ieee80211_rate rtl8xxxu_legacy_ratetable[] = { + {.bitrate = 10, .hw_value = 0x00,}, + {.bitrate = 20, .hw_value = 0x01,}, + {.bitrate = 55, .hw_value = 0x02,}, + {.bitrate = 110, .hw_value = 0x03,}, + {.bitrate = 60, .hw_value = 0x04,}, + {.bitrate = 90, .hw_value = 0x05,}, + {.bitrate = 120, .hw_value = 0x06,}, + {.bitrate = 180, .hw_value = 0x07,}, + {.bitrate = 240, .hw_value = 0x08,}, + {.bitrate = 360, .hw_value = 0x09,}, + {.bitrate = 480, .hw_value = 0x0a,}, + {.bitrate = 540, .hw_value = 0x0b,}, +}; + +static void rtl8xxxu_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss) +{ + if (rate <= DESC_RATE_54M) + return; + + if (rate >= DESC_RATE_MCS0 && rate <= DESC_RATE_MCS15) { + if (rate < DESC_RATE_MCS8) + *nss = 1; + else + *nss = 2; + *mcs = rate - DESC_RATE_MCS0; + } +} + static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) { struct rtl8xxxu_priv *priv; @@ -5397,9 +5426,14 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) unsigned long flags; u8 bt_info = 0; struct rtl8xxxu_btcoex *btcoex; + struct rtl8xxxu_ra_report *rarpt; + u8 rate, sgi, bw; + u32 bit_rate; + u8 mcs = 0, nss = 0; priv = container_of(work, struct rtl8xxxu_priv, c2hcmd_work); btcoex = &priv->bt_coex; + rarpt = &priv->ra_report; if (priv->rf_paths > 1) goto out; @@ -5422,6 +5456,34 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) } rtl8723bu_handle_bt_info(priv); break; + case C2H_8723B_RA_REPORT: + rarpt->txrate.flags = 0; + rate = c2h->ra_report.rate; + sgi = c2h->ra_report.sgi; + bw = c2h->ra_report.bw; + + if (rate < DESC_RATE_MCS0) { + rarpt->txrate.legacy = + rtl8xxxu_legacy_ratetable[rate].bitrate; + } else { + rtl8xxxu_desc_to_mcsrate(rate, &mcs, &nss); + rarpt->txrate.flags |= RATE_INFO_FLAGS_MCS; + + rarpt->txrate.mcs = mcs; + rarpt->txrate.nss = nss; + + if (sgi) { + rarpt->txrate.flags |= + RATE_INFO_FLAGS_SHORT_GI; + } + + if (bw == RATE_INFO_BW_20) + rarpt->txrate.bw |= RATE_INFO_BW_20; + } + bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate); + rarpt->bit_rate = bit_rate; + rarpt->desc_rate = rate; + break; default: break; } @@ -5465,7 +5527,7 @@ static void rtl8723bu_handle_c2h(struct rtl8xxxu_priv *priv, case C2H_8723B_RA_REPORT: dev_dbg(dev, "C2H RA RPT: rate %02x, unk %i, macid %02x, noise %i\n", - c2h->ra_report.rate, c2h->ra_report.dummy0_0, + c2h->ra_report.rate, c2h->ra_report.sgi, c2h->ra_report.macid, c2h->ra_report.noisy_state); break; default: @@ -6069,6 +6131,16 @@ rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return 0; } +static void +rtl8xxxu_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct station_info *sinfo) +{ + struct rtl8xxxu_priv *priv = hw->priv; + + sinfo->txrate = priv->ra_report.txrate; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); +} + static u8 rtl8xxxu_signal_to_snr(int signal) { if (signal < RTL8XXXU_NOISE_FLOOR_MIN) @@ -6371,6 +6443,7 @@ static const struct ieee80211_ops rtl8xxxu_ops = { .sw_scan_complete = rtl8xxxu_sw_scan_complete, .set_key = rtl8xxxu_set_key, .ampdu_action = rtl8xxxu_ampdu_action, + .sta_statistics = rtl8xxxu_sta_statistics, }; static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv, diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 1cff9f07c9e9..13421cf2d201 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -1051,13 +1051,13 @@ struct rtl_hdr_3addr { u8 addr2[ETH_ALEN]; u8 addr3[ETH_ALEN]; __le16 seq_ctl; - u8 payload[0]; + u8 payload[]; } __packed; struct rtl_info_element { u8 id; u8 len; - u8 data[0]; + u8 data[]; } __packed; struct rtl_probe_rsp { @@ -1068,7 +1068,7 @@ struct rtl_probe_rsp { /*SSID, supported rates, FH params, DS params, * CF params, IBSS params, TIM (if beacon), RSN */ - struct rtl_info_element info_element[0]; + struct rtl_info_element info_element[]; } __packed; /*LED related.*/ diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c index f91dc21a8bf1..567372fb4e12 100644 --- a/drivers/net/wireless/realtek/rtw88/coex.c +++ b/drivers/net/wireless/realtek/rtw88/coex.c @@ -2503,3 +2503,495 @@ void rtw_coex_defreeze_work(struct work_struct *work) rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); mutex_unlock(&rtwdev->mutex); } + +#ifdef CONFIG_RTW88_DEBUGFS +#define INFO_SIZE 80 + +#define case_BTINFO(src) \ + case COEX_BTINFO_SRC_##src: return #src + +static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src) +{ + switch (bt_info_src) { + case_BTINFO(WL_FW); + case_BTINFO(BT_RSP); + case_BTINFO(BT_ACT); + default: + return "Unknown"; + } +} + +#define case_RSN(src) \ + case COEX_RSN_##src: return #src + +static const char *rtw_coex_get_reason_string(u8 reason) +{ + switch (reason) { + case_RSN(2GSCANSTART); + case_RSN(5GSCANSTART); + case_RSN(SCANFINISH); + case_RSN(2GSWITCHBAND); + case_RSN(5GSWITCHBAND); + case_RSN(2GCONSTART); + case_RSN(5GCONSTART); + case_RSN(2GCONFINISH); + case_RSN(5GCONFINISH); + case_RSN(2GMEDIA); + case_RSN(5GMEDIA); + case_RSN(MEDIADISCON); + case_RSN(BTINFO); + case_RSN(LPS); + case_RSN(WLSTATUS); + default: + return "Unknown"; + } +} + +static int rtw_coex_addr_info(struct rtw_dev *rtwdev, + const struct rtw_reg_domain *reg, + char addr_info[], int n) +{ + const char *rf_prefix = ""; + const char *sep = n == 0 ? "" : "/ "; + int ffs, fls; + int max_fls; + + if (INFO_SIZE - n <= 0) + return 0; + + switch (reg->domain) { + case RTW_REG_DOMAIN_MAC32: + max_fls = 31; + break; + case RTW_REG_DOMAIN_MAC16: + max_fls = 15; + break; + case RTW_REG_DOMAIN_MAC8: + max_fls = 7; + break; + case RTW_REG_DOMAIN_RF_A: + case RTW_REG_DOMAIN_RF_B: + rf_prefix = "RF_"; + max_fls = 19; + break; + default: + return 0; + } + + ffs = __ffs(reg->mask); + fls = __fls(reg->mask); + + if (ffs == 0 && fls == max_fls) + return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x", + sep, rf_prefix, reg->addr); + else if (ffs == fls) + return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]", + sep, rf_prefix, reg->addr, ffs); + else + return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]", + sep, rf_prefix, reg->addr, fls, ffs); +} + +static int rtw_coex_val_info(struct rtw_dev *rtwdev, + const struct rtw_reg_domain *reg, + char val_info[], int n) +{ + const char *sep = n == 0 ? "" : "/ "; + u8 rf_path; + + if (INFO_SIZE - n <= 0) + return 0; + + switch (reg->domain) { + case RTW_REG_DOMAIN_MAC32: + return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, + rtw_read32_mask(rtwdev, reg->addr, reg->mask)); + case RTW_REG_DOMAIN_MAC16: + return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, + rtw_read16_mask(rtwdev, reg->addr, reg->mask)); + case RTW_REG_DOMAIN_MAC8: + return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, + rtw_read8_mask(rtwdev, reg->addr, reg->mask)); + case RTW_REG_DOMAIN_RF_A: + rf_path = RF_PATH_A; + break; + case RTW_REG_DOMAIN_RF_B: + rf_path = RF_PATH_B; + break; + default: + return 0; + } + + /* only RF go through here */ + return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, + rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask)); +} + +static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m) +{ + struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_reg_domain *reg; + char addr_info[INFO_SIZE]; + int n_addr = 0; + char val_info[INFO_SIZE]; + int n_val = 0; + int i; + + for (i = 0; i < chip->coex_info_hw_regs_num; i++) { + reg = &chip->coex_info_hw_regs[i]; + + n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr); + n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val); + + if (reg->domain == RTW_REG_DOMAIN_NL) { + seq_printf(m, "%-40s = %s\n", addr_info, val_info); + n_addr = 0; + n_val = 0; + } + } + + if (n_addr != 0 && n_val != 0) + seq_printf(m, "%-40s = %s\n", addr_info, val_info); +} + +static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev, + u8 type, u16 addr, u16 *val) +{ + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + __le16 le_addr; + u8 *payload; + + le_addr = cpu_to_le16(addr); + req.op_code = BT_MP_INFO_OP_READ_REG; + req.para1 = type; + req.para2 = le16_get_bits(le_addr, GENMASK(7, 0)); + req.para3 = le16_get_bits(le_addr, GENMASK(15, 8)); + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) { + *val = 0xeaea; + return false; + } + + payload = get_payload_from_coex_resp(skb); + *val = GET_COEX_RESP_BT_REG_VAL(payload); + + return true; +} + +static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev, + u32 *patch_version) +{ + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + u8 *payload; + bool ret = false; + + req.op_code = BT_MP_INFO_OP_PATCH_VER; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) + goto out; + + payload = get_payload_from_coex_resp(skb); + *patch_version = GET_COEX_RESP_BT_PATCH_VER(payload); + ret = true; + +out: + return ret; +} + +static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev, + u32 *supported_version) +{ + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + u8 *payload; + bool ret = false; + + req.op_code = BT_MP_INFO_OP_SUPP_VER; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) + goto out; + + payload = get_payload_from_coex_resp(skb); + *supported_version = GET_COEX_RESP_BT_SUPP_VER(payload); + ret = true; + +out: + return ret; +} + +static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev, + u32 *supported_feature) +{ + struct rtw_coex_info_req req = {0}; + struct sk_buff *skb; + u8 *payload; + bool ret = false; + + req.op_code = BT_MP_INFO_OP_SUPP_FEAT; + skb = rtw_coex_info_request(rtwdev, &req); + if (!skb) + goto out; + + payload = get_payload_from_coex_resp(skb); + *supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload); + ret = true; + +out: + return ret; +} + +struct rtw_coex_sta_stat_iter_data { + struct rtw_vif *rtwvif; + struct seq_file *file; +}; + +static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw_coex_sta_stat_iter_data *sta_iter_data = data; + struct rtw_vif *rtwvif = sta_iter_data->rtwvif; + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + struct seq_file *m = sta_iter_data->file; + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + u8 rssi; + + if (si->vif != vif) + return; + + rssi = ewma_rssi_read(&si->avg_rssi); + seq_printf(m, "\tPeer %3d\n", si->mac_id); + seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi); + seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode); +} + +struct rtw_coex_vif_stat_iter_data { + struct rtw_dev *rtwdev; + struct seq_file *file; +}; + +static void rtw_coex_vif_stat_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rtw_coex_vif_stat_iter_data *vif_iter_data = data; + struct rtw_coex_sta_stat_iter_data sta_iter_data; + struct rtw_dev *rtwdev = vif_iter_data->rtwdev; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + struct seq_file *m = vif_iter_data->file; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + + seq_printf(m, "Iface on Port (%d)\n", rtwvif->port); + seq_printf(m, "\t%-32s = %d\n", + "Beacon interval", bss_conf->beacon_int); + seq_printf(m, "\t%-32s = %d\n", + "Network Type", rtwvif->net_type); + + sta_iter_data.rtwvif = rtwvif; + sta_iter_data.file = m; + rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter, + &sta_iter_data); +} + +void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_stat *coex_stat = &coex->stat; + struct rtw_coex_dm *coex_dm = &coex->dm; + struct rtw_hal *hal = &rtwdev->hal; + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_fw_state *fw = &rtwdev->fw; + struct rtw_coex_vif_stat_iter_data vif_iter_data; + u8 reason = coex_dm->reason; + u8 sys_lte; + u16 score_board_WB, score_board_BW; + u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc; + u32 lte_coex, bt_coex; + u32 bt_hi_pri, bt_lo_pri; + int i; + + score_board_BW = rtw_coex_read_scbd(rtwdev); + score_board_WB = coex_stat->score_board; + wl_reg_6c0 = rtw_read32(rtwdev, 0x6c0); + wl_reg_6c4 = rtw_read32(rtwdev, 0x6c4); + wl_reg_6c8 = rtw_read32(rtwdev, 0x6c8); + wl_reg_6cc = rtw_read32(rtwdev, 0x6cc); + wl_reg_778 = rtw_read32(rtwdev, 0x778); + bt_hi_pri = rtw_read32(rtwdev, 0x770); + bt_lo_pri = rtw_read32(rtwdev, 0x774); + rtw_write8(rtwdev, 0x76e, 0xc); + sys_lte = rtw_read8(rtwdev, 0x73); + lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38); + bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54); + + if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) { + rtw_coex_get_bt_supported_version(rtwdev, + &coex_stat->bt_supported_version); + rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver); + rtw_coex_get_bt_supported_feature(rtwdev, + &coex_stat->bt_supported_feature); + rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae); + rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac); + + if (coex_stat->patch_ver != 0) + coex_stat->bt_mailbox_reply = true; + } + + seq_printf(m, "**********************************************\n"); + seq_printf(m, "\t\tBT Coexist info %x\n", chip->id); + seq_printf(m, "**********************************************\n"); + seq_printf(m, "%-40s = %s/ %d\n", + "Mech/ RFE", + efuse->share_ant ? "Shared" : "Non-Shared", + efuse->rfe_option); + seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n", + "Coex Ver/ BT Dez/ BT Rpt", + chip->coex_para_ver, chip->bt_desired_ver, + coex_stat->bt_supported_version, + coex_stat->bt_disabled ? "(BT disabled)" : + coex_stat->bt_supported_version >= chip->bt_desired_ver ? + "(Match)" : "(Mismatch)"); + seq_printf(m, "%-40s = %s/ %u/ %d\n", + "Role/ RoleSwCnt/ IgnWL/ Feature", + coex_stat->bt_slave ? "Slave" : "Master", + coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH], + coex_dm->ignore_wl_act); + seq_printf(m, "%-40s = %u.%u/ 0x%x/ %c\n", + "WL FW/ BT FW/ KT", + fw->version, fw->sub_version, + coex_stat->patch_ver, coex_stat->kt_ver + 65); + seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n", + "AFH Map", + coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1], + coex_dm->wl_ch_info[2], hal->current_channel); + + seq_printf(m, "**********************************************\n"); + seq_printf(m, "\t\tBT Status\n"); + seq_printf(m, "**********************************************\n"); + seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n", + "BT status/ rssi/ retry/ pop", + coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" : + coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy", + coex_stat->bt_rssi - 100, + coex_stat->cnt_bt[COEX_CNT_BT_RETRY], + coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]); + seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n", + "Profiles", + coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ? + "A2DP sink," : "A2DP,") : "", + coex_stat->bt_hfp_exist ? "HFP," : "", + coex_stat->bt_hid_exist ? + (coex_stat->bt_ble_exist ? "HID(RCU)," : + coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" : + "HID(2/18),") : "", + coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ? + "OPP," : "PAN," : "", + coex_stat->bt_ble_voice ? "Voice," : "", + coex_stat->bt_multi_link); + seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n", + "Reinit/ Relink/ IgnWl/ Feature", + coex_stat->cnt_bt[COEX_CNT_BT_REINIT], + coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK], + coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT], + coex_stat->bt_supported_feature); + seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n", + "Page/ Inq/ iqk/ iqk fail", + coex_stat->cnt_bt[COEX_CNT_BT_PAGE], + coex_stat->cnt_bt[COEX_CNT_BT_INQ], + coex_stat->cnt_bt[COEX_CNT_BT_IQK], + coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]); + seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n", + "0xae/ 0xac/ score board (W->B)/ (B->W)", + coex_stat->bt_reg_vendor_ae, + coex_stat->bt_reg_vendor_ac, + score_board_WB, score_board_BW); + seq_printf(m, "%-40s = %u/%u, %u/%u\n", + "Hi-Pri TX/RX, Lo-Pri TX/RX", + bt_hi_pri & 0xffff, bt_hi_pri >> 16, + bt_lo_pri & 0xffff, bt_lo_pri >> 16); + for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++) + seq_printf(m, "%-40s = %7ph\n", + rtw_coex_get_bt_info_src_string(i), + coex_stat->bt_info_c2h[i]); + + seq_printf(m, "**********************************************\n"); + seq_printf(m, "\t\tWiFi Status\n"); + seq_printf(m, "**********************************************\n"); + seq_printf(m, "%-40s = %d\n", + "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags)); + seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n", + "G_busy/ TX/ RX", + coex_stat->wl_gl_busy, + rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput); + seq_printf(m, "%-40s = %u/ %u/ %u\n", + "IPS/ Low Power/ PS mode", + test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags), + test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags), + rtwdev->lps_conf.mode); + + vif_iter_data.rtwdev = rtwdev; + vif_iter_data.file = m; + rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data); + + seq_printf(m, "**********************************************\n"); + seq_printf(m, "\t\tMechanism\n"); + seq_printf(m, "**********************************************\n"); + seq_printf(m, "%-40s = %5ph (case-%d)\n", + "TDMA", + coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma); + seq_printf(m, "%-40s = %d\n", + "Timer base", coex_stat->tdma_timer_base); + seq_printf(m, "%-40s = %d/ 0x%08x/ 0x%08x/ 0x%08x\n", + "Table/ 0x6c0/ 0x6c4/ 0x6c8", + coex_dm->cur_table, wl_reg_6c0, wl_reg_6c4, wl_reg_6c8); + seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ reason (%s)\n", + "0x778/ 0x6cc/ Reason", + wl_reg_778, wl_reg_6cc, rtw_coex_get_reason_string(reason)); + seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n", + "Null All/ Retry/ Ack/ BT Empty/ BT Late", + coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2], + coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4], + coex_stat->wl_fw_dbg_info[5]); + seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n", + "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW", + coex_stat->wl_fw_dbg_info[6], + coex_stat->wl_fw_dbg_info[7], + coex_stat->wl_slot_extend ? "Yes" : "No", + coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]); + + seq_printf(m, "**********************************************\n"); + seq_printf(m, "\t\tHW setting\n"); + seq_printf(m, "**********************************************\n"); + seq_printf(m, "%-40s = %s/ %s\n", + "LTE Coex/ Path Owner", + lte_coex & BIT(7) ? "ON" : "OFF", + sys_lte & BIT(2) ? "WL" : "BT"); + seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n", + "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg", + lte_coex & BIT(12) ? "SW" : "HW", + lte_coex & BIT(8) ? "SW" : "HW", + lte_coex & BIT(14) ? "SW" : "HW", + lte_coex & BIT(10) ? "SW" : "HW", + sys_lte & BIT(3) ? "On" : "Off"); + seq_printf(m, "%-40s = %lu/ %lu\n", + "GNT_WL/ GNT_BT", + (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3); + seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n", + "CRC OK CCK/ OFDM/ HT/ VHT", + dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt, + dm_info->ht_ok_cnt, dm_info->vht_ok_cnt); + seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n", + "CRC ERR CCK/ OFDM/ HT/ VHT", + dm_info->cck_err_cnt, dm_info->ofdm_err_cnt, + dm_info->ht_err_cnt, dm_info->vht_err_cnt); + seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n", + "HiPr/ Locking/ Locked/ Noisy", + coex_stat->wl_hi_pri_task1 ? "Y" : "N", + coex_stat->wl_cck_lock ? "Y" : "N", + coex_stat->wl_cck_lock_ever ? "Y" : "N", + coex_stat->wl_noisy_level); + + rtw_coex_set_coexinfo_hw(rtwdev, m); +} +#endif /* CONFIG_RTW88_DEBUGFS */ diff --git a/drivers/net/wireless/realtek/rtw88/coex.h b/drivers/net/wireless/realtek/rtw88/coex.h index 008d1af5996b..4c3a01968f5e 100644 --- a/drivers/net/wireless/realtek/rtw88/coex.h +++ b/drivers/net/wireless/realtek/rtw88/coex.h @@ -46,6 +46,14 @@ (__rssi__ == COEX_RSSI_STATE_LOW || \ __rssi__ == COEX_RSSI_STATE_STAY_LOW ? true : false); }) +#define GET_COEX_RESP_BT_SUPP_VER(payload) \ + le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(39, 32)) +#define GET_COEX_RESP_BT_SUPP_FEAT(payload) \ + le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(39, 24)) +#define GET_COEX_RESP_BT_PATCH_VER(payload) \ + le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(55, 24)) +#define GET_COEX_RESP_BT_REG_VAL(payload) \ + le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(39, 24)) #define GET_COEX_RESP_BT_SCAN_TYPE(payload) \ le64_get_bits(*((__le64 *)(payload)), GENMASK(31, 24)) @@ -367,4 +375,6 @@ void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length); void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type); void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev); +void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m); + #endif diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c index 5a181e01ebef..b4964306de61 100644 --- a/drivers/net/wireless/realtek/rtw88/debug.c +++ b/drivers/net/wireless/realtek/rtw88/debug.c @@ -5,6 +5,7 @@ #include <linux/debugfs.h> #include <linux/seq_file.h> #include "main.h" +#include "coex.h" #include "sec.h" #include "fw.h" #include "debug.h" @@ -691,6 +692,56 @@ static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v) dm_info->ht_ok_cnt, dm_info->ht_err_cnt); seq_printf(m, " * VHT cnt (ok, err) = (%u, %u)\n", dm_info->vht_ok_cnt, dm_info->vht_err_cnt); + + return 0; +} + +static int rtw_debugfs_get_coex_info(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + + rtw_coex_display_coex_info(rtwdev, m); + + return 0; +} + +static ssize_t rtw_debugfs_set_coex_enable(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +{ + struct seq_file *seqpriv = (struct seq_file *)filp->private_data; + struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + struct rtw_coex *coex = &rtwdev->coex; + char tmp[32 + 1]; + bool enable; + int ret; + + rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); + + ret = kstrtobool(tmp, &enable); + if (ret) { + rtw_warn(rtwdev, "invalid arguments\n"); + return ret; + } + + mutex_lock(&rtwdev->mutex); + coex->stop_dm = enable == 0; + mutex_unlock(&rtwdev->mutex); + + return count; +} + +static int rtw_debugfs_get_coex_enable(struct seq_file *m, void *v) +{ + struct rtw_debugfs_priv *debugfs_priv = m->private; + struct rtw_dev *rtwdev = debugfs_priv->rtwdev; + struct rtw_coex *coex = &rtwdev->coex; + + seq_printf(m, "coex mechanism %s\n", + coex->stop_dm ? "disabled" : "enabled"); + return 0; } @@ -784,6 +835,15 @@ static struct rtw_debugfs_priv rtw_debug_priv_phy_info = { .cb_read = rtw_debugfs_get_phy_info, }; +static struct rtw_debugfs_priv rtw_debug_priv_coex_enable = { + .cb_write = rtw_debugfs_set_coex_enable, + .cb_read = rtw_debugfs_get_coex_enable, +}; + +static struct rtw_debugfs_priv rtw_debug_priv_coex_info = { + .cb_read = rtw_debugfs_get_coex_info, +}; + #define rtw_debugfs_add_core(name, mode, fopname, parent) \ do { \ rtw_debug_priv_ ##name.rtwdev = rtwdev; \ @@ -814,6 +874,8 @@ void rtw_debugfs_init(struct rtw_dev *rtwdev) rtw_debugfs_add_rw(dump_cam); rtw_debugfs_add_rw(rsvd_page); rtw_debugfs_add_r(phy_info); + rtw_debugfs_add_r(coex_info); + rtw_debugfs_add_rw(coex_enable); rtw_debugfs_add_r(mac_0); rtw_debugfs_add_r(mac_1); rtw_debugfs_add_r(mac_2); diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 6867bf29d4c8..05c430b3489c 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -583,7 +583,7 @@ static u8 rtw_get_rsvd_page_location(struct rtw_dev *rtwdev, struct rtw_rsvd_page *rsvd_pkt; u8 location = 0; - list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) { if (type == rsvd_pkt->type) location = rsvd_pkt->page; } @@ -636,7 +636,7 @@ u8 rtw_get_rsvd_page_probe_req_location(struct rtw_dev *rtwdev, struct rtw_rsvd_page *rsvd_pkt; u8 location = 0; - list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) { if (rsvd_pkt->type != RSVD_PROBE_REQ) continue; if ((!ssid && !rsvd_pkt->ssid) || @@ -653,7 +653,7 @@ u16 rtw_get_rsvd_page_probe_req_size(struct rtw_dev *rtwdev, struct rtw_rsvd_page *rsvd_pkt; u16 size = 0; - list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) { if (rsvd_pkt->type != RSVD_PROBE_REQ) continue; if ((!ssid && !rsvd_pkt->ssid) || @@ -690,25 +690,6 @@ void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev) rtw_fw_send_h2c_command(rtwdev, h2c_pkt); } -static struct sk_buff * -rtw_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct sk_buff *skb_new; - - if (vif->type != NL80211_IFTYPE_AP && - vif->type != NL80211_IFTYPE_ADHOC && - !ieee80211_vif_is_mesh(vif)) { - skb_new = alloc_skb(1, GFP_KERNEL); - if (!skb_new) - return NULL; - skb_put(skb_new, 1); - } else { - skb_new = ieee80211_beacon_get(hw, vif); - } - - return skb_new; -} - static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw) { struct rtw_dev *rtwdev = hw->priv; @@ -853,15 +834,31 @@ static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw) } static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, struct rtw_rsvd_page *rsvd_pkt) { + struct ieee80211_vif *vif; + struct rtw_vif *rtwvif; struct sk_buff *skb_new; struct cfg80211_ssid *ssid; + if (rsvd_pkt->type == RSVD_DUMMY) { + skb_new = alloc_skb(1, GFP_KERNEL); + if (!skb_new) + return NULL; + + skb_put(skb_new, 1); + return skb_new; + } + + rtwvif = rsvd_pkt->rtwvif; + if (!rtwvif) + return NULL; + + vif = rtwvif_to_vif(rtwvif); + switch (rsvd_pkt->type) { case RSVD_BEACON: - skb_new = rtw_beacon_get(hw, vif); + skb_new = ieee80211_beacon_get(hw, vif); break; case RSVD_PS_POLL: skb_new = ieee80211_pspoll_get(hw, vif); @@ -948,6 +945,8 @@ static struct rtw_rsvd_page *rtw_alloc_rsvd_page(struct rtw_dev *rtwdev, if (!rsvd_pkt) return NULL; + INIT_LIST_HEAD(&rsvd_pkt->vif_list); + INIT_LIST_HEAD(&rsvd_pkt->build_list); rsvd_pkt->type = type; rsvd_pkt->add_txdesc = txdesc; @@ -955,51 +954,124 @@ static struct rtw_rsvd_page *rtw_alloc_rsvd_page(struct rtw_dev *rtwdev, } static void rtw_insert_rsvd_page(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif, struct rtw_rsvd_page *rsvd_pkt) { lockdep_assert_held(&rtwdev->mutex); - list_add_tail(&rsvd_pkt->list, &rtwdev->rsvd_page_list); + + list_add_tail(&rsvd_pkt->vif_list, &rtwvif->rsvd_page_list); } -void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type, - bool txdesc) +static void rtw_add_rsvd_page(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif, + enum rtw_rsvd_packet_type type, + bool txdesc) { struct rtw_rsvd_page *rsvd_pkt; rsvd_pkt = rtw_alloc_rsvd_page(rtwdev, type, txdesc); - if (!rsvd_pkt) + if (!rsvd_pkt) { + rtw_err(rtwdev, "failed to alloc rsvd page %d\n", type); return; + } - rtw_insert_rsvd_page(rtwdev, rsvd_pkt); + rsvd_pkt->rtwvif = rtwvif; + rtw_insert_rsvd_page(rtwdev, rtwvif, rsvd_pkt); } -void rtw_add_rsvd_page_probe_req(struct rtw_dev *rtwdev, - struct cfg80211_ssid *ssid) +static void rtw_add_rsvd_page_probe_req(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif, + struct cfg80211_ssid *ssid) { struct rtw_rsvd_page *rsvd_pkt; rsvd_pkt = rtw_alloc_rsvd_page(rtwdev, RSVD_PROBE_REQ, true); - if (!rsvd_pkt) + if (!rsvd_pkt) { + rtw_err(rtwdev, "failed to alloc probe req rsvd page\n"); return; + } + rsvd_pkt->rtwvif = rtwvif; rsvd_pkt->ssid = ssid; - rtw_insert_rsvd_page(rtwdev, rsvd_pkt); + rtw_insert_rsvd_page(rtwdev, rtwvif, rsvd_pkt); } -void rtw_reset_rsvd_page(struct rtw_dev *rtwdev) +void rtw_remove_rsvd_page(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif) { struct rtw_rsvd_page *rsvd_pkt, *tmp; lockdep_assert_held(&rtwdev->mutex); - list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) { - if (rsvd_pkt->type == RSVD_BEACON) - continue; - list_del(&rsvd_pkt->list); + /* remove all of the rsvd pages for vif */ + list_for_each_entry_safe(rsvd_pkt, tmp, &rtwvif->rsvd_page_list, + vif_list) { + list_del(&rsvd_pkt->vif_list); + if (!list_empty(&rsvd_pkt->build_list)) + list_del(&rsvd_pkt->build_list); kfree(rsvd_pkt); } } +void rtw_add_rsvd_page_bcn(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif) +{ + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + + if (vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_ADHOC && + vif->type != NL80211_IFTYPE_MESH_POINT) { + rtw_warn(rtwdev, "Cannot add beacon rsvd page for %d\n", + vif->type); + return; + } + + rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_BEACON, false); +} + +void rtw_add_rsvd_page_pno(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif) +{ + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct rtw_wow_param *rtw_wow = &rtwdev->wow; + struct rtw_pno_request *rtw_pno_req = &rtw_wow->pno_req; + struct cfg80211_ssid *ssid; + int i; + + if (vif->type != NL80211_IFTYPE_STATION) { + rtw_warn(rtwdev, "Cannot add PNO rsvd page for %d\n", + vif->type); + return; + } + + for (i = 0 ; i < rtw_pno_req->match_set_cnt; i++) { + ssid = &rtw_pno_req->match_sets[i].ssid; + rtw_add_rsvd_page_probe_req(rtwdev, rtwvif, ssid); + } + + rtw_add_rsvd_page_probe_req(rtwdev, rtwvif, NULL); + rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_NLO_INFO, false); + rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_CH_INFO, true); +} + +void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif) +{ + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + + if (vif->type != NL80211_IFTYPE_STATION) { + rtw_warn(rtwdev, "Cannot add sta rsvd page for %d\n", + vif->type); + return; + } + + rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_PS_POLL, true); + rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_QOS_NULL, true); + rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_NULL, true); + rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_LPS_PG_DPK, true); + rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_LPS_PG_INFO, true); +} + int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, u8 *buf, u32 size) { @@ -1063,8 +1135,72 @@ static int rtw_download_drv_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size) return rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, size); } -static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, - struct ieee80211_vif *vif, u32 *size) +static void __rtw_build_rsvd_page_reset(struct rtw_dev *rtwdev) +{ + struct rtw_rsvd_page *rsvd_pkt, *tmp; + + list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, + build_list) { + list_del_init(&rsvd_pkt->build_list); + + /* Don't free except for the dummy rsvd page, + * others will be freed when removing vif + */ + if (rsvd_pkt->type == RSVD_DUMMY) + kfree(rsvd_pkt); + } +} + +static void rtw_build_rsvd_page_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rtw_dev *rtwdev = data; + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + struct rtw_rsvd_page *rsvd_pkt; + + list_for_each_entry(rsvd_pkt, &rtwvif->rsvd_page_list, vif_list) { + if (rsvd_pkt->type == RSVD_BEACON) + list_add(&rsvd_pkt->build_list, + &rtwdev->rsvd_page_list); + else + list_add_tail(&rsvd_pkt->build_list, + &rtwdev->rsvd_page_list); + } +} + +static int __rtw_build_rsvd_page_from_vifs(struct rtw_dev *rtwdev) +{ + struct rtw_rsvd_page *rsvd_pkt; + + __rtw_build_rsvd_page_reset(rtwdev); + + /* gather rsvd page from vifs */ + rtw_iterate_vifs_atomic(rtwdev, rtw_build_rsvd_page_iter, rtwdev); + + rsvd_pkt = list_first_entry_or_null(&rtwdev->rsvd_page_list, + struct rtw_rsvd_page, build_list); + if (!rsvd_pkt) { + WARN(1, "Should not have an empty reserved page\n"); + return -EINVAL; + } + + /* the first rsvd should be beacon, otherwise add a dummy one */ + if (rsvd_pkt->type != RSVD_BEACON) { + struct rtw_rsvd_page *dummy_pkt; + + dummy_pkt = rtw_alloc_rsvd_page(rtwdev, RSVD_DUMMY, false); + if (!dummy_pkt) { + rtw_err(rtwdev, "failed to alloc dummy rsvd page\n"); + return -ENOMEM; + } + + list_add(&dummy_pkt->build_list, &rtwdev->rsvd_page_list); + } + + return 0; +} + +static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u32 *size) { struct ieee80211_hw *hw = rtwdev->hw; struct rtw_chip_info *chip = rtwdev->chip; @@ -1074,13 +1210,21 @@ static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u8 total_page = 0; u8 page_size, page_margin, tx_desc_sz; u8 *buf; + int ret; page_size = chip->page_size; tx_desc_sz = chip->tx_pkt_desc_sz; page_margin = page_size - tx_desc_sz; - list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { - iter = rtw_get_rsvd_page_skb(hw, vif, rsvd_pkt); + ret = __rtw_build_rsvd_page_from_vifs(rtwdev); + if (ret) { + rtw_err(rtwdev, + "failed to build rsvd page from vifs, ret %d\n", ret); + return NULL; + } + + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) { + iter = rtw_get_rsvd_page_skb(hw, rsvd_pkt); if (!iter) { rtw_err(rtwdev, "failed to build rsvd packet\n"); goto release_skb; @@ -1104,7 +1248,8 @@ static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, * is smaller than the actual size of the whole rsvd_page */ if (total_page == 0) { - if (rsvd_pkt->type != RSVD_BEACON) { + if (rsvd_pkt->type != RSVD_BEACON && + rsvd_pkt->type != RSVD_DUMMY) { rtw_err(rtwdev, "first page should be a beacon\n"); goto release_skb; } @@ -1132,7 +1277,7 @@ static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, * And that rsvd_pkt does not require tx_desc because when it goes * through TX path, the TX path will generate one for it. */ - list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) { rtw_rsvd_page_list_to_buf(rtwdev, page_size, page_margin, page, buf, rsvd_pkt); if (page == 0) @@ -1148,7 +1293,7 @@ static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, return buf; release_skb: - list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) { + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) { kfree_skb(rsvd_pkt->skb); rsvd_pkt->skb = NULL; } @@ -1156,18 +1301,31 @@ release_skb: return NULL; } -static int -rtw_download_beacon(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) +static int rtw_download_beacon(struct rtw_dev *rtwdev) { struct ieee80211_hw *hw = rtwdev->hw; + struct rtw_rsvd_page *rsvd_pkt; struct sk_buff *skb; int ret = 0; - skb = rtw_beacon_get(hw, vif); + rsvd_pkt = list_first_entry_or_null(&rtwdev->rsvd_page_list, + struct rtw_rsvd_page, build_list); + if (!rsvd_pkt) { + rtw_err(rtwdev, "failed to get rsvd page from build list\n"); + return -ENOENT; + } + + if (rsvd_pkt->type != RSVD_BEACON && + rsvd_pkt->type != RSVD_DUMMY) { + rtw_err(rtwdev, "invalid rsvd page type %d, should be beacon or dummy\n", + rsvd_pkt->type); + return -EINVAL; + } + + skb = rtw_get_rsvd_page_skb(hw, rsvd_pkt); if (!skb) { rtw_err(rtwdev, "failed to get beacon skb\n"); - ret = -ENOMEM; - goto out; + return -ENOMEM; } ret = rtw_download_drv_rsvd_page(rtwdev, skb->data, skb->len); @@ -1176,17 +1334,16 @@ rtw_download_beacon(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) dev_kfree_skb(skb); -out: return ret; } -int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) +int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev) { u8 *buf; u32 size; int ret; - buf = rtw_build_rsvd_page(rtwdev, vif, &size); + buf = rtw_build_rsvd_page(rtwdev, &size); if (!buf) { rtw_err(rtwdev, "failed to build rsvd page pkt\n"); return -ENOMEM; @@ -1203,7 +1360,7 @@ int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) * the beacon again to replace the TX desc header, and we will get * a correct tx_desc for the beacon in the rsvd page. */ - ret = rtw_download_beacon(rtwdev, vif); + ret = rtw_download_beacon(rtwdev); if (ret) { rtw_err(rtwdev, "failed to download beacon\n"); goto free; diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h index ccd27bd45775..cdd244857048 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.h +++ b/drivers/net/wireless/realtek/rtw88/fw.h @@ -36,11 +36,12 @@ enum rtw_c2h_cmd_id_ext { struct rtw_c2h_cmd { u8 id; u8 seq; - u8 payload[0]; + u8 payload[]; } __packed; enum rtw_rsvd_packet_type { RSVD_BEACON, + RSVD_DUMMY, RSVD_PS_POLL, RSVD_PROBE_RESP, RSVD_NULL, @@ -98,7 +99,13 @@ struct rtw_lps_pg_info_hdr { } __packed; struct rtw_rsvd_page { - struct list_head list; + /* associated with each vif */ + struct list_head vif_list; + struct rtw_vif *rtwvif; + + /* associated when build rsvd page */ + struct list_head build_list; + struct sk_buff *skb; enum rtw_rsvd_packet_type type; u8 page; @@ -502,15 +509,17 @@ void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data); void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn); -void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type, - bool txdesc); -void rtw_add_rsvd_page_probe_req(struct rtw_dev *rtwdev, - struct cfg80211_ssid *ssid); int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, u8 *buf, u32 size); -void rtw_reset_rsvd_page(struct rtw_dev *rtwdev); -int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, - struct ieee80211_vif *vif); +void rtw_remove_rsvd_page(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif); +void rtw_add_rsvd_page_bcn(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif); +void rtw_add_rsvd_page_pno(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif); +void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif); +int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev); void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev); int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev, u32 offset, u32 size, u32 *buf); diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h index cad56389182c..2cba327e6218 100644 --- a/drivers/net/wireless/realtek/rtw88/hci.h +++ b/drivers/net/wireless/realtek/rtw88/hci.h @@ -7,9 +7,10 @@ /* ops for PCI, USB and SDIO */ struct rtw_hci_ops { - int (*tx)(struct rtw_dev *rtwdev, - struct rtw_tx_pkt_info *pkt_info, - struct sk_buff *skb); + int (*tx_write)(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb); + void (*tx_kick_off)(struct rtw_dev *rtwdev); int (*setup)(struct rtw_dev *rtwdev); int (*start)(struct rtw_dev *rtwdev); void (*stop)(struct rtw_dev *rtwdev); @@ -28,11 +29,16 @@ struct rtw_hci_ops { void (*write32)(struct rtw_dev *rtwdev, u32 addr, u32 val); }; -static inline int rtw_hci_tx(struct rtw_dev *rtwdev, - struct rtw_tx_pkt_info *pkt_info, - struct sk_buff *skb) +static inline int rtw_hci_tx_write(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb) { - return rtwdev->hci.ops->tx(rtwdev, pkt_info, skb); + return rtwdev->hci.ops->tx_write(rtwdev, pkt_info, skb); +} + +static inline void rtw_hci_tx_kick_off(struct rtw_dev *rtwdev) +{ + return rtwdev->hci.ops->tx_kick_off(rtwdev); } static inline int rtw_hci_setup(struct rtw_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index b3125e311fa2..d7d02e4c0184 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -161,6 +161,7 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee)); rtwvif->conf = &rtw_vif_port[port]; rtw_txq_init(rtwdev, vif->txq); + INIT_LIST_HEAD(&rtwvif->rsvd_page_list); mutex_lock(&rtwdev->mutex); @@ -169,18 +170,24 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: + rtw_add_rsvd_page_bcn(rtwdev, rtwvif); net_type = RTW_NET_AP_MODE; bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT; break; case NL80211_IFTYPE_ADHOC: + rtw_add_rsvd_page_bcn(rtwdev, rtwvif); net_type = RTW_NET_AD_HOC; bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT; break; case NL80211_IFTYPE_STATION: - default: + rtw_add_rsvd_page_sta(rtwdev, rtwvif); net_type = RTW_NET_NO_LINK; bcn_ctrl = BIT_EN_BCN_FUNCTION; break; + default: + WARN_ON(1); + mutex_unlock(&rtwdev->mutex); + return -EINVAL; } ether_addr_copy(rtwvif->mac_addr, vif->addr); @@ -211,6 +218,7 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw, rtw_leave_lps_deep(rtwdev); rtw_txq_cleanup(rtwdev, vif->txq); + rtw_remove_rsvd_page(rtwdev, rtwvif); eth_zero_addr(rtwvif->mac_addr); config |= PORT_SET_MAC_ADDR; @@ -342,12 +350,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, chip->ops->phy_calibration(rtwdev); rtwvif->aid = conf->aid; - rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true); - rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true); - rtw_add_rsvd_page(rtwdev, RSVD_NULL, true); - rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_DPK, true); - rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_INFO, true); - rtw_fw_download_rsvd_page(rtwdev, vif); + rtw_fw_download_rsvd_page(rtwdev); rtw_send_rsvd_page_h2c(rtwdev); rtw_coex_media_status_notify(rtwdev, conf->assoc); if (rtw_bf_support) @@ -356,7 +359,6 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, rtw_leave_lps(rtwdev); net_type = RTW_NET_NO_LINK; rtwvif->aid = 0; - rtw_reset_rsvd_page(rtwdev); rtw_bf_disassoc(rtwdev, vif, conf); } @@ -371,7 +373,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BEACON) - rtw_fw_download_rsvd_page(rtwdev, vif); + rtw_fw_download_rsvd_page(rtwdev); if (changed & BSS_CHANGED_MU_GROUPS) { struct rtw_chip_info *chip = rtwdev->chip; @@ -556,7 +558,7 @@ static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* download new cam settings for PG to backup */ if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG) - rtw_fw_download_rsvd_page(rtwdev, vif); + rtw_fw_download_rsvd_page(rtwdev); out: mutex_unlock(&rtwdev->mutex); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index dc93a4d04f25..7640e97706f5 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1394,10 +1394,6 @@ int rtw_core_init(struct rtw_dev *rtwdev) else rtwdev->lps_conf.deep_mode = rtw_fw_lps_deep_mode; - mutex_lock(&rtwdev->mutex); - rtw_add_rsvd_page(rtwdev, RSVD_BEACON, false); - mutex_unlock(&rtwdev->mutex); - rtw_stats_init(rtwdev); /* default rx filter setting */ @@ -1440,8 +1436,9 @@ void rtw_core_deinit(struct rtw_dev *rtwdev) skb_queue_purge(&rtwdev->tx_report.queue); spin_unlock_irqrestore(&rtwdev->tx_report.q_lock, flags); - list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) { - list_del(&rsvd_pkt->list); + list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, + build_list) { + list_del(&rsvd_pkt->build_list); kfree(rsvd_pkt); } diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 201ed8870754..bcc07cf9f481 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -515,6 +515,18 @@ struct rtw_hw_reg { u32 mask; }; +struct rtw_reg_domain { + u32 addr; + u32 mask; +#define RTW_REG_DOMAIN_MAC32 0 +#define RTW_REG_DOMAIN_MAC16 1 +#define RTW_REG_DOMAIN_MAC8 2 +#define RTW_REG_DOMAIN_RF_A 3 +#define RTW_REG_DOMAIN_RF_B 4 +#define RTW_REG_DOMAIN_NL 0xFF + u8 domain; +}; + struct rtw_backup_info { u8 len; u32 reg; @@ -752,6 +764,7 @@ struct rtw_vif { u8 bssid[ETH_ALEN]; u8 port; u8 bcn_ctrl; + struct list_head rsvd_page_list; struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS]; const struct rtw_vif_port *conf; @@ -1106,6 +1119,7 @@ struct rtw_chip_info { u8 bt_afh_span_bw40; u8 afh_5g_num; u8 wl_rf_para_num; + u8 coex_info_hw_regs_num; const u8 *bt_rssi_step; const u8 *wl_rssi_step; const struct coex_table_para *table_nsant; @@ -1115,6 +1129,7 @@ struct rtw_chip_info { const struct coex_rf_para *wl_rf_para_tx; const struct coex_rf_para *wl_rf_para_rx; const struct coex_5g_afh_map *afh_5g; + const struct rtw_reg_domain *coex_info_hw_regs; }; enum rtw_coex_bt_state_cnt { @@ -1161,6 +1176,7 @@ struct rtw_coex_rfe { struct rtw_coex_dm { bool cur_ps_tdma_on; bool cur_wl_rx_low_gain_en; + bool ignore_wl_act; u8 reason; u8 bt_rssi_state[4]; @@ -1241,6 +1257,9 @@ struct rtw_coex_stat { u32 bt_supported_version; u32 bt_supported_feature; + u32 patch_ver; + u16 bt_reg_vendor_ae; + u16 bt_reg_vendor_ac; s8 bt_rssi; u8 kt_ver; u8 gnt_workaround_state; @@ -1640,7 +1659,7 @@ struct rtw_dev { struct rtw_wow_param wow; /* hci related data, must be last */ - u8 priv[0] __aligned(sizeof(void *)); + u8 priv[] __aligned(sizeof(void *)); }; #include "hci.h" diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 7c525bb0337d..e37c71495c0d 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -186,6 +186,11 @@ static int rtw_pci_init_tx_ring(struct rtw_dev *rtwdev, dma_addr_t dma; u8 *head; + if (len > TRX_BD_IDX_MASK) { + rtw_err(rtwdev, "len %d exceeds maximum TX entries\n", len); + return -EINVAL; + } + head = pci_zalloc_consistent(pdev, ring_sz, &dma); if (!head) { rtw_err(rtwdev, "failed to allocate tx ring\n"); @@ -259,6 +264,11 @@ static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev, int i, allocated; int ret = 0; + if (len > TRX_BD_IDX_MASK) { + rtw_err(rtwdev, "len %d exceeds maximum RX entries\n", len); + return -EINVAL; + } + head = pci_zalloc_consistent(pdev, ring_sz, &dma); if (!head) { rtw_err(rtwdev, "failed to allocate rx ring\n"); @@ -382,6 +392,7 @@ static int rtw_pci_init(struct rtw_dev *rtwdev) rtwpci->irq_mask[3] = IMR_H2CDOK | 0; spin_lock_init(&rtwpci->irq_lock); + spin_lock_init(&rtwpci->hwirq_lock); ret = rtw_pci_init_trx_ring(rtwdev); return ret; @@ -404,56 +415,56 @@ static void rtw_pci_reset_buf_desc(struct rtw_dev *rtwdev) dma = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.dma; rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.rp = 0; rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.wp = 0; - rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_H2CQ, len); + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_H2CQ, len & TRX_BD_IDX_MASK); rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_H2CQ, dma); len = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.len; dma = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.dma; rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.rp = 0; rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.wp = 0; - rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BKQ, len); + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BKQ, len & TRX_BD_IDX_MASK); rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BKQ, dma); len = rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.len; dma = rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.dma; rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.rp = 0; rtwpci->tx_rings[RTW_TX_QUEUE_BE].r.wp = 0; - rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BEQ, len); + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_BEQ, len & TRX_BD_IDX_MASK); rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BEQ, dma); len = rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.len; dma = rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.dma; rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.rp = 0; rtwpci->tx_rings[RTW_TX_QUEUE_VO].r.wp = 0; - rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VOQ, len); + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VOQ, len & TRX_BD_IDX_MASK); rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_VOQ, dma); len = rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.len; dma = rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.dma; rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.rp = 0; rtwpci->tx_rings[RTW_TX_QUEUE_VI].r.wp = 0; - rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VIQ, len); + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_VIQ, len & TRX_BD_IDX_MASK); rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_VIQ, dma); len = rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.len; dma = rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.dma; rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.rp = 0; rtwpci->tx_rings[RTW_TX_QUEUE_MGMT].r.wp = 0; - rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_MGMTQ, len); + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_MGMTQ, len & TRX_BD_IDX_MASK); rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_MGMTQ, dma); len = rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.len; dma = rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.dma; rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.rp = 0; rtwpci->tx_rings[RTW_TX_QUEUE_HI0].r.wp = 0; - rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_HI0Q, len); + rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_HI0Q, len & TRX_BD_IDX_MASK); rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_HI0Q, dma); len = rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.len; dma = rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.dma; rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.rp = 0; rtwpci->rx_rings[RTW_RX_QUEUE_MPDU].r.wp = 0; - rtw_write16(rtwdev, RTK_PCI_RXBD_NUM_MPDUQ, len & 0xfff); + rtw_write16(rtwdev, RTK_PCI_RXBD_NUM_MPDUQ, len & TRX_BD_IDX_MASK); rtw_write32(rtwdev, RTK_PCI_RXBD_DESA_MPDUQ, dma); /* reset read/write point */ @@ -472,19 +483,35 @@ static void rtw_pci_reset_trx_ring(struct rtw_dev *rtwdev) static void rtw_pci_enable_interrupt(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) { + unsigned long flags; + + spin_lock_irqsave(&rtwpci->hwirq_lock, flags); + rtw_write32(rtwdev, RTK_PCI_HIMR0, rtwpci->irq_mask[0]); rtw_write32(rtwdev, RTK_PCI_HIMR1, rtwpci->irq_mask[1]); rtw_write32(rtwdev, RTK_PCI_HIMR3, rtwpci->irq_mask[3]); rtwpci->irq_enabled = true; + + spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags); } static void rtw_pci_disable_interrupt(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) { + unsigned long flags; + + spin_lock_irqsave(&rtwpci->hwirq_lock, flags); + + if (!rtwpci->irq_enabled) + goto out; + rtw_write32(rtwdev, RTK_PCI_HIMR0, 0); rtw_write32(rtwdev, RTK_PCI_HIMR1, 0); rtw_write32(rtwdev, RTK_PCI_HIMR3, 0); rtwpci->irq_enabled = false; + +out: + spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags); } static void rtw_pci_dma_reset(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) @@ -520,11 +547,10 @@ static void rtw_pci_dma_release(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci) static int rtw_pci_start(struct rtw_dev *rtwdev) { struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; - unsigned long flags; - spin_lock_irqsave(&rtwpci->irq_lock, flags); + spin_lock_bh(&rtwpci->irq_lock); rtw_pci_enable_interrupt(rtwdev, rtwpci); - spin_unlock_irqrestore(&rtwpci->irq_lock, flags); + spin_unlock_bh(&rtwpci->irq_lock); return 0; } @@ -532,12 +558,11 @@ static int rtw_pci_start(struct rtw_dev *rtwdev) static void rtw_pci_stop(struct rtw_dev *rtwdev) { struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; - unsigned long flags; - spin_lock_irqsave(&rtwpci->irq_lock, flags); + spin_lock_bh(&rtwpci->irq_lock); rtw_pci_disable_interrupt(rtwdev, rtwpci); rtw_pci_dma_release(rtwdev, rtwpci); - spin_unlock_irqrestore(&rtwpci->irq_lock, flags); + spin_unlock_bh(&rtwpci->irq_lock); } static void rtw_pci_deep_ps_enter(struct rtw_dev *rtwdev) @@ -590,9 +615,8 @@ static void rtw_pci_deep_ps_leave(struct rtw_dev *rtwdev) static void rtw_pci_deep_ps(struct rtw_dev *rtwdev, bool enter) { struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; - unsigned long flags; - spin_lock_irqsave(&rtwpci->irq_lock, flags); + spin_lock_bh(&rtwpci->irq_lock); if (enter && !test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) rtw_pci_deep_ps_enter(rtwdev); @@ -600,7 +624,7 @@ static void rtw_pci_deep_ps(struct rtw_dev *rtwdev, bool enter) if (!enter && test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) rtw_pci_deep_ps_leave(rtwdev); - spin_unlock_irqrestore(&rtwpci->irq_lock, flags); + spin_unlock_bh(&rtwpci->irq_lock); } static u8 ac_to_hwq[] = { @@ -667,9 +691,34 @@ static void rtw_pci_dma_check(struct rtw_dev *rtwdev, rtwpci->rx_tag = (rtwpci->rx_tag + 1) % RX_TAG_MAX; } -static int rtw_pci_xmit(struct rtw_dev *rtwdev, - struct rtw_tx_pkt_info *pkt_info, - struct sk_buff *skb, u8 queue) +static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev, u8 queue) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + struct rtw_pci_tx_ring *ring; + u32 bd_idx; + + ring = &rtwpci->tx_rings[queue]; + bd_idx = rtw_pci_tx_queue_idx_addr[queue]; + + spin_lock_bh(&rtwpci->irq_lock); + rtw_pci_deep_ps_leave(rtwdev); + rtw_write16(rtwdev, bd_idx, ring->r.wp & TRX_BD_IDX_MASK); + spin_unlock_bh(&rtwpci->irq_lock); +} + +static void rtw_pci_tx_kick_off(struct rtw_dev *rtwdev) +{ + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; + u8 queue; + + for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) + if (test_and_clear_bit(queue, rtwpci->tx_queued)) + rtw_pci_tx_kick_off_queue(rtwdev, queue); +} + +static int rtw_pci_tx_write_data(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb, u8 queue) { struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; struct rtw_chip_info *chip = rtwdev->chip; @@ -682,8 +731,6 @@ static int rtw_pci_xmit(struct rtw_dev *rtwdev, u32 psb_len; u8 *pkt_desc; struct rtw_pci_tx_buffer_desc *buf_desc; - u32 bd_idx; - unsigned long flags; ring = &rtwpci->tx_rings[queue]; @@ -720,25 +767,20 @@ static int rtw_pci_xmit(struct rtw_dev *rtwdev, tx_data->dma = dma; tx_data->sn = pkt_info->sn; - spin_lock_irqsave(&rtwpci->irq_lock, flags); + spin_lock_bh(&rtwpci->irq_lock); - rtw_pci_deep_ps_leave(rtwdev); skb_queue_tail(&ring->queue, skb); - /* kick off tx queue */ - if (queue != RTW_TX_QUEUE_BCN) { - if (++ring->r.wp >= ring->r.len) - ring->r.wp = 0; - bd_idx = rtw_pci_tx_queue_idx_addr[queue]; - rtw_write16(rtwdev, bd_idx, ring->r.wp & 0xfff); - } else { - u32 reg_bcn_work; - - reg_bcn_work = rtw_read8(rtwdev, RTK_PCI_TXBD_BCN_WORK); - reg_bcn_work |= BIT_PCI_BCNQ_FLAG; - rtw_write8(rtwdev, RTK_PCI_TXBD_BCN_WORK, reg_bcn_work); - } - spin_unlock_irqrestore(&rtwpci->irq_lock, flags); + if (queue == RTW_TX_QUEUE_BCN) + goto out_unlock; + + /* update write-index, and kick it off later */ + set_bit(queue, rtwpci->tx_queued); + if (++ring->r.wp >= ring->r.len) + ring->r.wp = 0; + +out_unlock: + spin_unlock_bh(&rtwpci->irq_lock); return 0; } @@ -747,56 +789,59 @@ static int rtw_pci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size) { struct sk_buff *skb; - struct rtw_tx_pkt_info pkt_info; - u32 tx_pkt_desc_sz; - u32 length; + struct rtw_tx_pkt_info pkt_info = {0}; + u8 reg_bcn_work; + int ret; - tx_pkt_desc_sz = rtwdev->chip->tx_pkt_desc_sz; - length = size + tx_pkt_desc_sz; - skb = dev_alloc_skb(length); + skb = rtw_tx_write_data_rsvd_page_get(rtwdev, &pkt_info, buf, size); if (!skb) return -ENOMEM; - skb_reserve(skb, tx_pkt_desc_sz); - memcpy((u8 *)skb_put(skb, size), buf, size); - memset(&pkt_info, 0, sizeof(pkt_info)); - pkt_info.tx_pkt_size = size; - pkt_info.offset = tx_pkt_desc_sz; + ret = rtw_pci_tx_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN); + if (ret) { + rtw_err(rtwdev, "failed to write rsvd page data\n"); + return ret; + } + + /* reserved pages go through beacon queue */ + reg_bcn_work = rtw_read8(rtwdev, RTK_PCI_TXBD_BCN_WORK); + reg_bcn_work |= BIT_PCI_BCNQ_FLAG; + rtw_write8(rtwdev, RTK_PCI_TXBD_BCN_WORK, reg_bcn_work); - return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN); + return 0; } static int rtw_pci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size) { struct sk_buff *skb; - struct rtw_tx_pkt_info pkt_info; - u32 tx_pkt_desc_sz; - u32 length; + struct rtw_tx_pkt_info pkt_info = {0}; + int ret; - tx_pkt_desc_sz = rtwdev->chip->tx_pkt_desc_sz; - length = size + tx_pkt_desc_sz; - skb = dev_alloc_skb(length); + skb = rtw_tx_write_data_h2c_get(rtwdev, &pkt_info, buf, size); if (!skb) return -ENOMEM; - skb_reserve(skb, tx_pkt_desc_sz); - memcpy((u8 *)skb_put(skb, size), buf, size); - memset(&pkt_info, 0, sizeof(pkt_info)); - pkt_info.tx_pkt_size = size; + ret = rtw_pci_tx_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C); + if (ret) { + rtw_err(rtwdev, "failed to write h2c data\n"); + return ret; + } + + rtw_pci_tx_kick_off_queue(rtwdev, RTW_TX_QUEUE_H2C); - return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C); + return 0; } -static int rtw_pci_tx(struct rtw_dev *rtwdev, - struct rtw_tx_pkt_info *pkt_info, - struct sk_buff *skb) +static int rtw_pci_tx_write(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + struct sk_buff *skb) { struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; struct rtw_pci_tx_ring *ring; u8 queue = rtw_hw_queue_mapping(skb); int ret; - ret = rtw_pci_xmit(rtwdev, pkt_info, skb, queue); + ret = rtw_pci_tx_write_data(rtwdev, pkt_info, skb, queue); if (ret) return ret; @@ -827,7 +872,7 @@ static void rtw_pci_tx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, bd_idx_addr = rtw_pci_tx_queue_idx_addr[hw_queue]; bd_idx = rtw_read32(rtwdev, bd_idx_addr); cur_rp = bd_idx >> 16; - cur_rp &= 0xfff; + cur_rp &= TRX_BD_IDX_MASK; if (cur_rp >= ring->r.rp) count = cur_rp - ring->r.rp; else @@ -901,7 +946,7 @@ static void rtw_pci_rx_isr(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, tmp = rtw_read32(rtwdev, RTK_PCI_RXBD_IDX_MPDUQ); cur_wp = tmp >> 16; - cur_wp &= 0xfff; + cur_wp &= TRX_BD_IDX_MASK; if (cur_wp >= ring->r.wp) count = cur_wp - ring->r.wp; else @@ -961,6 +1006,10 @@ next_rp: static void rtw_pci_irq_recognized(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, u32 *irq_status) { + unsigned long flags; + + spin_lock_irqsave(&rtwpci->hwirq_lock, flags); + irq_status[0] = rtw_read32(rtwdev, RTK_PCI_HISR0); irq_status[1] = rtw_read32(rtwdev, RTK_PCI_HISR1); irq_status[3] = rtw_read32(rtwdev, RTK_PCI_HISR3); @@ -970,6 +1019,8 @@ static void rtw_pci_irq_recognized(struct rtw_dev *rtwdev, rtw_write32(rtwdev, RTK_PCI_HISR0, irq_status[0]); rtw_write32(rtwdev, RTK_PCI_HISR1, irq_status[1]); rtw_write32(rtwdev, RTK_PCI_HISR3, irq_status[3]); + + spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags); } static irqreturn_t rtw_pci_interrupt_handler(int irq, void *dev) @@ -977,10 +1028,6 @@ static irqreturn_t rtw_pci_interrupt_handler(int irq, void *dev) struct rtw_dev *rtwdev = dev; struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; - spin_lock(&rtwpci->irq_lock); - if (!rtwpci->irq_enabled) - goto out; - /* disable RTW PCI interrupt to avoid more interrupts before the end of * thread function * @@ -990,8 +1037,6 @@ static irqreturn_t rtw_pci_interrupt_handler(int irq, void *dev) * a new HISR flag is set. */ rtw_pci_disable_interrupt(rtwdev, rtwpci); -out: - spin_unlock(&rtwpci->irq_lock); return IRQ_WAKE_THREAD; } @@ -1000,10 +1045,9 @@ static irqreturn_t rtw_pci_interrupt_threadfn(int irq, void *dev) { struct rtw_dev *rtwdev = dev; struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; - unsigned long flags; u32 irq_status[4]; - spin_lock_irqsave(&rtwpci->irq_lock, flags); + spin_lock_bh(&rtwpci->irq_lock); rtw_pci_irq_recognized(rtwdev, rtwpci, irq_status); if (irq_status[0] & IMR_MGNTDOK) @@ -1025,7 +1069,7 @@ static irqreturn_t rtw_pci_interrupt_threadfn(int irq, void *dev) /* all of the jobs for this interrupt have been done */ rtw_pci_enable_interrupt(rtwdev, rtwpci); - spin_unlock_irqrestore(&rtwpci->irq_lock, flags); + spin_unlock_bh(&rtwpci->irq_lock); return IRQ_HANDLED; } @@ -1371,7 +1415,8 @@ static void rtw_pci_destroy(struct rtw_dev *rtwdev, struct pci_dev *pdev) } static struct rtw_hci_ops rtw_pci_ops = { - .tx = rtw_pci_tx, + .tx_write = rtw_pci_tx_write, + .tx_kick_off = rtw_pci_tx_kick_off, .setup = rtw_pci_setup, .start = rtw_pci_start, .stop = rtw_pci_stop, diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h index cd4fcd064cdb..3ac4fb328d31 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.h +++ b/drivers/net/wireless/realtek/rtw88/pci.h @@ -52,6 +52,8 @@ #define RTK_PCI_TXBD_DESA_HI0Q 0x340 #define RTK_PCI_RXBD_DESA_MPDUQ 0x338 +#define TRX_BD_IDX_MASK GENMASK(11, 0) + /* BCNQ is specialized for rsvd page, does not need to specify a number */ #define RTK_PCI_TXBD_NUM_H2CQ 0x1328 #define RTK_PCI_TXBD_NUM_MGMTQ 0x380 @@ -198,12 +200,15 @@ struct rtw_pci_rx_ring { struct rtw_pci { struct pci_dev *pdev; - /* used for pci interrupt */ + /* Used for PCI interrupt. */ + spinlock_t hwirq_lock; + /* Used for PCI TX queueing. */ spinlock_t irq_lock; u32 irq_mask[4]; bool irq_enabled; u16 rx_tag; + DECLARE_BITMAP(tx_queued, RTK_MAX_TX_QUEUE_NUM); struct rtw_pci_tx_ring tx_rings[RTK_MAX_TX_QUEUE_NUM]; struct rtw_pci_rx_ring rx_rings[RTK_MAX_RX_QUEUE_NUM]; u16 link_ctrl; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 96aa332fb28d..4dd7d4143b04 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -2371,6 +2371,33 @@ static const struct rtw_pwr_track_tbl rtw8822b_rtw_pwr_track_tbl = { .pwrtrk_2g_ccka_p = rtw8822b_pwrtrk_2g_cck_a_p, }; +static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = { + {0xcb0, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0xcb4, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0xcba, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + {0xcbd, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + {0xc58, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + {0xcbd, BIT(0), RTW_REG_DOMAIN_MAC8}, + {0, 0, RTW_REG_DOMAIN_NL}, + {0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16}, + {0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + {0x45e, BIT(3), RTW_REG_DOMAIN_MAC8}, + {0x454, MASKLWORD, RTW_REG_DOMAIN_MAC16}, + {0, 0, RTW_REG_DOMAIN_NL}, + {0x4c, BIT(24) | BIT(23), RTW_REG_DOMAIN_MAC32}, + {0x64, BIT(0), RTW_REG_DOMAIN_MAC8}, + {0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8}, + {0x40, BIT(5), RTW_REG_DOMAIN_MAC8}, + {0x1, RFREG_MASK, RTW_REG_DOMAIN_RF_B}, + {0, 0, RTW_REG_DOMAIN_NL}, + {0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + {0x953, BIT(1), RTW_REG_DOMAIN_MAC8}, + {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, +}; + struct rtw_chip_info rtw8822b_hw_spec = { .ops = &rtw8822b_ops, .id = RTW_CHIP_TYPE_8822B, @@ -2439,6 +2466,9 @@ struct rtw_chip_info rtw8822b_hw_spec = { .bt_afh_span_bw40 = 0x36, .afh_5g_num = ARRAY_SIZE(afh_5g_8822b), .afh_5g = afh_5g_8822b, + + .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8822b), + .coex_info_hw_regs = coex_info_hw_regs_8822b, }; EXPORT_SYMBOL(rtw8822b_hw_spec); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 146f693c7592..dc07e6be38e8 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -4092,6 +4092,31 @@ static const struct wiphy_wowlan_support rtw_wowlan_stub_8822c = { }; #endif +static const struct rtw_reg_domain coex_info_hw_regs_8822c[] = { + {0x1860, BIT(3), RTW_REG_DOMAIN_MAC8}, + {0x4160, BIT(3), RTW_REG_DOMAIN_MAC8}, + {0x1c32, BIT(6), RTW_REG_DOMAIN_MAC8}, + {0x1c38, BIT(28), RTW_REG_DOMAIN_MAC32}, + {0, 0, RTW_REG_DOMAIN_NL}, + {0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16}, + {0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + {0x45e, BIT(3), RTW_REG_DOMAIN_MAC8}, + {0x454, MASKLWORD, RTW_REG_DOMAIN_MAC16}, + {0, 0, RTW_REG_DOMAIN_NL}, + {0x4c, BIT(24) | BIT(23), RTW_REG_DOMAIN_MAC32}, + {0x64, BIT(0), RTW_REG_DOMAIN_MAC8}, + {0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8}, + {0x40, BIT(5), RTW_REG_DOMAIN_MAC8}, + {0x1, RFREG_MASK, RTW_REG_DOMAIN_RF_B}, + {0, 0, RTW_REG_DOMAIN_NL}, + {0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + {0x953, BIT(1), RTW_REG_DOMAIN_MAC8}, + {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, +}; + struct rtw_chip_info rtw8822c_hw_spec = { .ops = &rtw8822c_ops, .id = RTW_CHIP_TYPE_8822C, @@ -4128,7 +4153,7 @@ struct rtw_chip_info rtw8822c_hw_spec = { .agc_tbl = &rtw8822c_agc_tbl, .bb_tbl = &rtw8822c_bb_tbl, .rfk_init_tbl = &rtw8822c_array_mp_cal_init_tbl, - .rf_tbl = {&rtw8822c_rf_a_tbl, &rtw8822c_rf_b_tbl}, + .rf_tbl = {&rtw8822c_rf_b_tbl, &rtw8822c_rf_a_tbl}, .rfe_defs = rtw8822c_rfe_defs, .rfe_defs_size = ARRAY_SIZE(rtw8822c_rfe_defs), .en_dis_dpd = true, @@ -4168,6 +4193,9 @@ struct rtw_chip_info rtw8822c_hw_spec = { .bt_afh_span_bw40 = 0x36, .afh_5g_num = ARRAY_SIZE(afh_5g_8822c), .afh_5g = afh_5g_8822c, + + .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8822c), + .coex_info_hw_regs = coex_info_hw_regs_8822c, }; EXPORT_SYMBOL(rtw8822c_hw_spec); diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c index 24c39c60c99a..b31eb4d9664b 100644 --- a/drivers/net/wireless/realtek/rtw88/tx.c +++ b/drivers/net/wireless/realtek/rtw88/tx.c @@ -6,6 +6,7 @@ #include "tx.h" #include "fw.h" #include "ps.h" +#include "debug.h" static void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, @@ -220,7 +221,7 @@ void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev, struct rtw_tx_pkt_info *pkt_info, - struct ieee80211_tx_control *control, + struct ieee80211_sta *sta, struct sk_buff *skb) { pkt_info->use_rate = true; @@ -230,10 +231,9 @@ static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev, static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev, struct rtw_tx_pkt_info *pkt_info, - struct ieee80211_tx_control *control, + struct ieee80211_sta *sta, struct sk_buff *skb) { - struct ieee80211_sta *sta = control->sta; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct rtw_sta_info *si; @@ -292,7 +292,7 @@ out: void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, struct rtw_tx_pkt_info *pkt_info, - struct ieee80211_tx_control *control, + struct ieee80211_sta *sta, struct sk_buff *skb) { struct rtw_chip_info *chip = rtwdev->chip; @@ -304,15 +304,15 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, u8 sec_type = 0; bool bmc; - if (control->sta) { - si = (struct rtw_sta_info *)control->sta->drv_priv; + if (sta) { + si = (struct rtw_sta_info *)sta->drv_priv; vif = si->vif; } if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc)) - rtw_tx_mgmt_pkt_info_update(rtwdev, pkt_info, control, skb); + rtw_tx_mgmt_pkt_info_update(rtwdev, pkt_info, sta, skb); else if (ieee80211_is_data(fc)) - rtw_tx_data_pkt_info_update(rtwdev, pkt_info, control, skb); + rtw_tx_data_pkt_info_update(rtwdev, pkt_info, sta, skb); if (info->control.hw_key) { struct ieee80211_key_conf *key = info->control.hw_key; @@ -368,15 +368,74 @@ void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev, pkt_info->ls = true; } +struct sk_buff * +rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *buf, u32 size) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct sk_buff *skb; + u32 tx_pkt_desc_sz; + u32 length; + + tx_pkt_desc_sz = chip->tx_pkt_desc_sz; + length = size + tx_pkt_desc_sz; + skb = dev_alloc_skb(length); + if (!skb) { + rtw_err(rtwdev, "failed to alloc write data rsvd page skb\n"); + return NULL; + } + + skb_reserve(skb, tx_pkt_desc_sz); + skb_put_data(skb, buf, size); + pkt_info->tx_pkt_size = size; + pkt_info->offset = tx_pkt_desc_sz; + + return skb; +} +EXPORT_SYMBOL(rtw_tx_write_data_rsvd_page_get); + +struct sk_buff * +rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *buf, u32 size) +{ + struct rtw_chip_info *chip = rtwdev->chip; + struct sk_buff *skb; + u32 tx_pkt_desc_sz; + u32 length; + + tx_pkt_desc_sz = chip->tx_pkt_desc_sz; + length = size + tx_pkt_desc_sz; + skb = dev_alloc_skb(length); + if (!skb) { + rtw_err(rtwdev, "failed to alloc write data h2c skb\n"); + return NULL; + } + + skb_reserve(skb, tx_pkt_desc_sz); + skb_put_data(skb, buf, size); + pkt_info->tx_pkt_size = size; + + return skb; +} +EXPORT_SYMBOL(rtw_tx_write_data_h2c_get); + void rtw_tx(struct rtw_dev *rtwdev, struct ieee80211_tx_control *control, struct sk_buff *skb) { struct rtw_tx_pkt_info pkt_info = {0}; + int ret; - rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb); - if (rtw_hci_tx(rtwdev, &pkt_info, skb)) + rtw_tx_pkt_info_update(rtwdev, &pkt_info, control->sta, skb); + ret = rtw_hci_tx_write(rtwdev, &pkt_info, skb); + if (ret) { + rtw_err(rtwdev, "failed to write TX skb to HCI\n"); goto out; + } + + rtw_hci_tx_kick_off(rtwdev); return; @@ -416,38 +475,62 @@ static void rtw_txq_check_agg(struct rtw_dev *rtwdev, ieee80211_queue_work(rtwdev->hw, &rtwdev->ba_work); } -static bool rtw_txq_dequeue(struct rtw_dev *rtwdev, - struct rtw_txq *rtwtxq) +static int rtw_txq_push_skb(struct rtw_dev *rtwdev, + struct rtw_txq *rtwtxq, + struct sk_buff *skb) { struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq); - struct ieee80211_tx_control control; - struct sk_buff *skb; - - skb = ieee80211_tx_dequeue(rtwdev->hw, txq); - if (!skb) - return false; + struct rtw_tx_pkt_info pkt_info = {0}; + int ret; rtw_txq_check_agg(rtwdev, rtwtxq, skb); - control.sta = txq->sta; - rtw_tx(rtwdev, &control, skb); + rtw_tx_pkt_info_update(rtwdev, &pkt_info, txq->sta, skb); + ret = rtw_hci_tx_write(rtwdev, &pkt_info, skb); + if (ret) { + rtw_err(rtwdev, "failed to write TX skb to HCI\n"); + return ret; + } rtwtxq->last_push = jiffies; - return true; + return 0; +} + +static struct sk_buff *rtw_txq_dequeue(struct rtw_dev *rtwdev, + struct rtw_txq *rtwtxq) +{ + struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq); + struct sk_buff *skb; + + skb = ieee80211_tx_dequeue(rtwdev->hw, txq); + if (!skb) + return NULL; + + return skb; } static void rtw_txq_push(struct rtw_dev *rtwdev, struct rtw_txq *rtwtxq, unsigned long frames) { + struct sk_buff *skb; + int ret; int i; rcu_read_lock(); - for (i = 0; i < frames; i++) - if (!rtw_txq_dequeue(rtwdev, rtwtxq)) + for (i = 0; i < frames; i++) { + skb = rtw_txq_dequeue(rtwdev, rtwtxq); + if (!skb) break; + ret = rtw_txq_push_skb(rtwdev, rtwtxq, skb); + if (ret) { + rtw_err(rtwdev, "failed to pusk skb, ret %d\n", ret); + break; + } + } + rcu_read_unlock(); } @@ -469,6 +552,8 @@ void rtw_tx_tasklet(unsigned long data) list_del_init(&rtwtxq->list); } + rtw_hci_tx_kick_off(rtwdev); + spin_unlock_bh(&rtwdev->txq_lock); } diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h index 9ca4f74a501b..e488a2643eb3 100644 --- a/drivers/net/wireless/realtek/rtw88/tx.h +++ b/drivers/net/wireless/realtek/rtw88/tx.h @@ -85,7 +85,7 @@ void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq); void rtw_tx_tasklet(unsigned long data); void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, struct rtw_tx_pkt_info *pkt_info, - struct ieee80211_tx_control *control, + struct ieee80211_sta *sta, struct sk_buff *skb); void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb); void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn); @@ -93,5 +93,13 @@ void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb); void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev, struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb); +struct sk_buff * +rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *buf, u32 size); +struct sk_buff * +rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev, + struct rtw_tx_pkt_info *pkt_info, + u8 *buf, u32 size); #endif diff --git a/drivers/net/wireless/realtek/rtw88/wow.c b/drivers/net/wireless/realtek/rtw88/wow.c index 4820dca958dd..2fcdf70a3a77 100644 --- a/drivers/net/wireless/realtek/rtw88/wow.c +++ b/drivers/net/wireless/realtek/rtw88/wow.c @@ -431,50 +431,39 @@ static void rtw_wow_fw_media_status(struct rtw_dev *rtwdev, bool connect) rtw_iterate_stas_atomic(rtwdev, rtw_wow_fw_media_status_iter, &data); } -static void rtw_wow_config_pno_rsvd_page(struct rtw_dev *rtwdev) +static void rtw_wow_config_pno_rsvd_page(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif) { - struct rtw_wow_param *rtw_wow = &rtwdev->wow; - struct rtw_pno_request *rtw_pno_req = &rtw_wow->pno_req; - struct cfg80211_ssid *ssid; - int i; - - for (i = 0 ; i < rtw_pno_req->match_set_cnt; i++) { - ssid = &rtw_pno_req->match_sets[i].ssid; - rtw_add_rsvd_page_probe_req(rtwdev, ssid); - } - rtw_add_rsvd_page_probe_req(rtwdev, NULL); - rtw_add_rsvd_page(rtwdev, RSVD_NLO_INFO, false); - rtw_add_rsvd_page(rtwdev, RSVD_CH_INFO, true); + rtw_add_rsvd_page_pno(rtwdev, rtwvif); } -static void rtw_wow_config_linked_rsvd_page(struct rtw_dev *rtwdev) +static void rtw_wow_config_linked_rsvd_page(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif) { - rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true); - rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true); - rtw_add_rsvd_page(rtwdev, RSVD_NULL, true); - rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_DPK, true); - rtw_add_rsvd_page(rtwdev, RSVD_LPS_PG_INFO, true); + rtw_add_rsvd_page_sta(rtwdev, rtwvif); } -static void rtw_wow_config_rsvd_page(struct rtw_dev *rtwdev) +static void rtw_wow_config_rsvd_page(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif) { - rtw_reset_rsvd_page(rtwdev); + rtw_remove_rsvd_page(rtwdev, rtwvif); if (rtw_wow_mgd_linked(rtwdev)) { - rtw_wow_config_linked_rsvd_page(rtwdev); + rtw_wow_config_linked_rsvd_page(rtwdev, rtwvif); } else if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags) && rtw_wow_no_link(rtwdev)) { - rtw_wow_config_pno_rsvd_page(rtwdev); + rtw_wow_config_pno_rsvd_page(rtwdev, rtwvif); } } static int rtw_wow_dl_fw_rsvd_page(struct rtw_dev *rtwdev) { struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv; - rtw_wow_config_rsvd_page(rtwdev); + rtw_wow_config_rsvd_page(rtwdev, rtwvif); - return rtw_fw_download_rsvd_page(rtwdev, wow_vif); + return rtw_fw_download_rsvd_page(rtwdev); } static int rtw_wow_swap_fw(struct rtw_dev *rtwdev, enum rtw_fw_type type) diff --git a/drivers/net/wireless/st/cw1200/wsm.h b/drivers/net/wireless/st/cw1200/wsm.h index ddea57f8c8ab..1ffa47994bb9 100644 --- a/drivers/net/wireless/st/cw1200/wsm.h +++ b/drivers/net/wireless/st/cw1200/wsm.h @@ -1623,7 +1623,7 @@ struct wsm_p2p_device_info { u8 local_devname[D11_MAX_SSID_LEN]; u8 reserved2[3]; u8 num_secdev_supported; - struct wsm_p2p_device_type secdevs[0]; + struct wsm_p2p_device_type secdevs[]; } __packed; /* 4.36 SetWCDMABand - WO */ diff --git a/drivers/net/wireless/ti/wl1251/cmd.h b/drivers/net/wireless/ti/wl1251/cmd.h index 1c1a591c6055..e5874186f9d7 100644 --- a/drivers/net/wireless/ti/wl1251/cmd.h +++ b/drivers/net/wireless/ti/wl1251/cmd.h @@ -90,7 +90,7 @@ struct wl1251_cmd_header { u16 id; u16 status; /* payload */ - u8 data[0]; + u8 data[]; } __packed; struct wl1251_command { @@ -281,7 +281,7 @@ struct wl1251_cmd_packet_template { struct wl1251_cmd_header header; __le16 size; - u8 data[0]; + u8 data[]; } __packed; #define TIM_ELE_ID 5 diff --git a/drivers/net/wireless/ti/wl1251/wl12xx_80211.h b/drivers/net/wireless/ti/wl1251/wl12xx_80211.h index 7fabe702c4cc..7e28fe435b43 100644 --- a/drivers/net/wireless/ti/wl1251/wl12xx_80211.h +++ b/drivers/net/wireless/ti/wl1251/wl12xx_80211.h @@ -65,7 +65,7 @@ struct ieee80211_header { u8 sa[ETH_ALEN]; u8 bssid[ETH_ALEN]; __le16 seq_ctl; - u8 payload[0]; + u8 payload[]; } __packed; struct wl12xx_ie_header { diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index a265fba0cb4c..c725f5855c13 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h @@ -938,7 +938,7 @@ struct acx_rx_filter_cfg { u8 action; u8 num_fields; - u8 fields[0]; + u8 fields[]; } __packed; struct acx_roaming_stats { diff --git a/drivers/net/wireless/ti/wlcore/boot.h b/drivers/net/wireless/ti/wlcore/boot.h index 14b367e98dce..24a2dfcb41ea 100644 --- a/drivers/net/wireless/ti/wlcore/boot.h +++ b/drivers/net/wireless/ti/wlcore/boot.h @@ -26,7 +26,7 @@ struct wl1271_static_data { u8 fw_version[WL1271_FW_VERSION_MAX_LEN]; u32 hw_version; u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS]; - u8 priv[0]; + u8 priv[]; }; /* number of times we try to read the INIT interrupt */ diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index bfad7b5a1ac6..f2609d5b6bf7 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -209,7 +209,7 @@ struct wl1271_cmd_header { __le16 id; __le16 status; /* payload */ - u8 data[0]; + u8 data[]; } __packed; #define WL1271_CMD_MAX_PARAMS 572 diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index 6116383ee248..31be425f2332 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h @@ -1150,7 +1150,7 @@ struct wlcore_conf { struct wlcore_conf_file { struct wlcore_conf_header header; struct wlcore_conf core; - u8 priv[0]; + u8 priv[]; } __packed; #endif diff --git a/drivers/net/wireless/ti/wlcore/wl12xx_80211.h b/drivers/net/wireless/ti/wlcore/wl12xx_80211.h index 181be725eff8..1dd7ecc11f86 100644 --- a/drivers/net/wireless/ti/wlcore/wl12xx_80211.h +++ b/drivers/net/wireless/ti/wlcore/wl12xx_80211.h @@ -66,7 +66,7 @@ struct ieee80211_header { u8 sa[ETH_ALEN]; u8 bssid[ETH_ALEN]; __le16 seq_ctl; - u8 payload[0]; + u8 payload[]; } __packed; struct wl12xx_ie_header { diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c index 01305ba2d3aa..c878097f0dda 100644 --- a/drivers/net/wireless/virt_wifi.c +++ b/drivers/net/wireless/virt_wifi.c @@ -436,10 +436,18 @@ static int virt_wifi_net_device_stop(struct net_device *dev) return 0; } +static int virt_wifi_net_device_get_iflink(const struct net_device *dev) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + + return priv->lowerdev->ifindex; +} + static const struct net_device_ops virt_wifi_ops = { .ndo_start_xmit = virt_wifi_start_xmit, - .ndo_open = virt_wifi_net_device_open, - .ndo_stop = virt_wifi_net_device_stop, + .ndo_open = virt_wifi_net_device_open, + .ndo_stop = virt_wifi_net_device_stop, + .ndo_get_iflink = virt_wifi_net_device_get_iflink, }; /* Invoked as part of rtnl lock release. */ diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h index efdce9ae36ea..b446cb369557 100644 --- a/drivers/net/wireless/wl3501.h +++ b/drivers/net/wireless/wl3501.h @@ -231,7 +231,7 @@ struct iw_mgmt_info_element { u8 id; /* one of enum iw_mgmt_info_element_ids, but sizeof(enum) > sizeof(u8) :-( */ u8 len; - u8 data[0]; + u8 data[]; } __packed; struct iw_mgmt_essid_pset { diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_usb.h b/drivers/net/wireless/zydas/zd1211rw/zd_usb.h index a52ee323a142..8f03b09a602c 100644 --- a/drivers/net/wireless/zydas/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zydas/zd1211rw/zd_usb.h @@ -69,7 +69,7 @@ enum control_requests { struct usb_req_read_regs { __le16 id; - __le16 addr[0]; + __le16 addr[]; } __packed; struct reg_data { @@ -79,7 +79,7 @@ struct reg_data { struct usb_req_write_regs { __le16 id; - struct reg_data reg_writes[0]; + struct reg_data reg_writes[]; } __packed; enum { @@ -95,7 +95,7 @@ struct usb_req_rfwrite { /* 2: other (default) */ __le16 bits; /* RF2595: 24 */ - __le16 bit_values[0]; + __le16 bit_values[]; /* (ZD_CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ } __packed; @@ -118,7 +118,7 @@ struct usb_int_header { struct usb_int_regs { struct usb_int_header hdr; - struct reg_data regs[0]; + struct reg_data regs[]; } __packed; struct usb_int_retry_fail { |