diff options
Diffstat (limited to 'drivers/net/wireless')
198 files changed, 6521 insertions, 5750 deletions
diff --git a/drivers/net/wireless/broadcom/b43/dma.c b/drivers/net/wireless/broadcom/b43/dma.c index d113bd997f4b..dfc4c34298d4 100644 --- a/drivers/net/wireless/broadcom/b43/dma.c +++ b/drivers/net/wireless/broadcom/b43/dma.c @@ -1518,13 +1518,15 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, } } else { /* More than a single header/data pair were missed. - * Report this error, and reset the controller to + * Report this error. If running with open-source + * firmware, then reset the controller to * revive operation. */ b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n", ring->index, firstused, slot); - b43_controller_restart(dev, "Out of order TX"); + if (dev->fw.opensource) + b43_controller_restart(dev, "Out of order TX"); return; } } diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index 4daa1ce8cba3..74be3c809225 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c @@ -5493,13 +5493,11 @@ err_powerdown: static void b43_one_core_detach(struct b43_bus_dev *dev) { struct b43_wldev *wldev; - struct b43_wl *wl; /* Do not cancel ieee80211-workqueue based work here. * See comment in b43_remove(). */ wldev = b43_bus_get_wldev(dev); - wl = wldev->wl; b43_debugfs_remove_device(wldev); b43_wireless_core_detach(wldev); list_del(&wldev->list); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile index 1f5a9b948abf..22fd95a736a8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile @@ -54,3 +54,5 @@ brcmfmac-$(CONFIG_BRCM_TRACING) += \ tracepoint.o brcmfmac-$(CONFIG_OF) += \ of.o +brcmfmac-$(CONFIG_DMI) += \ + dmi.o diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 94044a7a6021..e738112ed87c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -214,7 +214,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, sizeof(ifp->mac_addr)); if (err < 0) { - brcmf_err("Retreiving cur_etheraddr failed, %d\n", err); + brcmf_err("Retrieving cur_etheraddr failed, %d\n", err); goto done; } memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN); @@ -269,7 +269,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) strcpy(buf, "ver"); err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); if (err < 0) { - brcmf_err("Retreiving version information failed, %d\n", + brcmf_err("Retrieving version information failed, %d\n", err); goto done; } @@ -448,8 +448,9 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, } } if (!found) { - /* No platform data for this device, try OF (Open Firwmare) */ + /* No platform data for this device, try OF and DMI data */ brcmf_of_probe(dev, bus_type, settings); + brcmf_dmi_probe(settings, chip, chiprev); } return settings; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h index a34642cb4d2f..4ce56be90b74 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h @@ -59,6 +59,7 @@ struct brcmf_mp_device { bool iapp; bool ignore_probe_fail; struct brcmfmac_pd_cc *country_codes; + const char *board_type; union { struct brcmfmac_sdio_pd sdio; } bus; @@ -74,4 +75,11 @@ void brcmf_release_module_param(struct brcmf_mp_device *module_param); /* Sets dongle media info (drv_version, mac address). */ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); +#ifdef CONFIG_DMI +void brcmf_dmi_probe(struct brcmf_mp_device *settings, u32 chip, u32 chiprev); +#else +static inline void +brcmf_dmi_probe(struct brcmf_mp_device *settings, u32 chip, u32 chiprev) {} +#endif + #endif /* BRCMFMAC_COMMON_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c new file mode 100644 index 000000000000..51d76ac45075 --- /dev/null +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c @@ -0,0 +1,116 @@ +/* + * Copyright 2018 Hans de Goede <hdegoede@redhat.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/dmi.h> +#include <linux/mod_devicetable.h> +#include "core.h" +#include "common.h" +#include "brcm_hw_ids.h" + +/* The DMI data never changes so we can use a static buf for this */ +static char dmi_board_type[128]; + +struct brcmf_dmi_data { + u32 chip; + u32 chiprev; + const char *board_type; +}; + +/* NOTE: Please keep all entries sorted alphabetically */ + +static const struct brcmf_dmi_data gpd_win_pocket_data = { + BRCM_CC_4356_CHIP_ID, 2, "gpd-win-pocket" +}; + +static const struct brcmf_dmi_data jumper_ezpad_mini3_data = { + BRCM_CC_43430_CHIP_ID, 0, "jumper-ezpad-mini3" +}; + +static const struct brcmf_dmi_data meegopad_t08_data = { + BRCM_CC_43340_CHIP_ID, 2, "meegopad-t08" +}; + +static const struct dmi_system_id dmi_platform_data[] = { + { + /* Match for the GPDwin which unfortunately uses somewhat + * generic dmi strings, which is why we test for 4 strings. + * Comparing against 23 other byt/cht boards, board_vendor + * and board_name are unique to the GPDwin, where as only one + * other board has the same board_serial and 3 others have + * the same default product_name. Also the GPDwin is the + * only device to have both board_ and product_name not set. + */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Default string"), + DMI_MATCH(DMI_BOARD_SERIAL, "Default string"), + DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), + }, + .driver_data = (void *)&gpd_win_pocket_data, + }, + { + /* Jumper EZpad mini3 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"), + /* jumperx.T87.KFBNEEA02 with the version-nr dropped */ + DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"), + }, + .driver_data = (void *)&jumper_ezpad_mini3_data, + }, + { + /* Meegopad T08 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Default string"), + DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), + DMI_MATCH(DMI_BOARD_NAME, "T3 MRD"), + DMI_MATCH(DMI_BOARD_VERSION, "V1.1"), + }, + .driver_data = (void *)&meegopad_t08_data, + }, + {} +}; + +void brcmf_dmi_probe(struct brcmf_mp_device *settings, u32 chip, u32 chiprev) +{ + const struct dmi_system_id *match; + const struct brcmf_dmi_data *data; + const char *sys_vendor; + const char *product_name; + + /* Some models have DMI strings which are too generic, e.g. + * "Default string", we use a quirk table for these. + */ + for (match = dmi_first_match(dmi_platform_data); + match; + match = dmi_first_match(match + 1)) { + data = match->driver_data; + + if (data->chip == chip && data->chiprev == chiprev) { + settings->board_type = data->board_type; + return; + } + } + + /* Not found in the quirk-table, use sys_vendor-product_name */ + sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + product_name = dmi_get_system_info(DMI_PRODUCT_NAME); + if (sys_vendor && product_name) { + snprintf(dmi_board_type, sizeof(dmi_board_type), "%s-%s", + sys_vendor, product_name); + settings->board_type = dmi_board_type; + } +} diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 9095b830ae4d..72d8c0c3c3a1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -14,6 +14,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <linux/efi.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/device.h> @@ -445,6 +446,75 @@ struct brcmf_fw { static void brcmf_fw_request_done(const struct firmware *fw, void *ctx); +#ifdef CONFIG_EFI +/* In some cases the EFI-var stored nvram contains "ccode=ALL" or "ccode=XV" + * to specify "worldwide" compatible settings, but these 2 ccode-s do not work + * properly. "ccode=ALL" causes channels 12 and 13 to not be available, + * "ccode=XV" causes all 5GHz channels to not be available. So we replace both + * with "ccode=X2" which allows channels 12+13 and 5Ghz channels in + * no-Initiate-Radiation mode. This means that we will never send on these + * channels without first having received valid wifi traffic on the channel. + */ +static void brcmf_fw_fix_efi_nvram_ccode(char *data, unsigned long data_len) +{ + char *ccode; + + ccode = strnstr((char *)data, "ccode=ALL", data_len); + if (!ccode) + ccode = strnstr((char *)data, "ccode=XV\r", data_len); + if (!ccode) + return; + + ccode[6] = 'X'; + ccode[7] = '2'; + ccode[8] = '\r'; +} + +static u8 *brcmf_fw_nvram_from_efi(size_t *data_len_ret) +{ + const u16 name[] = { 'n', 'v', 'r', 'a', 'm', 0 }; + struct efivar_entry *nvram_efivar; + unsigned long data_len = 0; + u8 *data = NULL; + int err; + + nvram_efivar = kzalloc(sizeof(*nvram_efivar), GFP_KERNEL); + if (!nvram_efivar) + return NULL; + + memcpy(&nvram_efivar->var.VariableName, name, sizeof(name)); + nvram_efivar->var.VendorGuid = EFI_GUID(0x74b00bd9, 0x805a, 0x4d61, + 0xb5, 0x1f, 0x43, 0x26, + 0x81, 0x23, 0xd1, 0x13); + + err = efivar_entry_size(nvram_efivar, &data_len); + if (err) + goto fail; + + data = kmalloc(data_len, GFP_KERNEL); + if (!data) + goto fail; + + err = efivar_entry_get(nvram_efivar, NULL, &data_len, data); + if (err) + goto fail; + + brcmf_fw_fix_efi_nvram_ccode(data, data_len); + brcmf_info("Using nvram EFI variable\n"); + + kfree(nvram_efivar); + *data_len_ret = data_len; + return data; + +fail: + kfree(data); + kfree(nvram_efivar); + return NULL; +} +#else +static u8 *brcmf_fw_nvram_from_efi(size_t *data_len) { return NULL; } +#endif + static void brcmf_fw_free_request(struct brcmf_fw_request *req) { struct brcmf_fw_item *item; @@ -463,11 +533,12 @@ static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) { struct brcmf_fw *fwctx = ctx; struct brcmf_fw_item *cur; + bool free_bcm47xx_nvram = false; + bool kfree_nvram = false; u32 nvram_length = 0; void *nvram = NULL; u8 *data = NULL; size_t data_len; - bool raw_nvram; brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev)); @@ -476,12 +547,13 @@ static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) if (fw && fw->data) { data = (u8 *)fw->data; data_len = fw->size; - raw_nvram = false; } else { - data = bcm47xx_nvram_get_contents(&data_len); - if (!data && !(cur->flags & BRCMF_FW_REQF_OPTIONAL)) + if ((data = bcm47xx_nvram_get_contents(&data_len))) + free_bcm47xx_nvram = true; + else if ((data = brcmf_fw_nvram_from_efi(&data_len))) + kfree_nvram = true; + else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) goto fail; - raw_nvram = true; } if (data) @@ -489,8 +561,11 @@ static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) fwctx->req->domain_nr, fwctx->req->bus_nr); - if (raw_nvram) + if (free_bcm47xx_nvram) bcm47xx_nvram_release_contents(data); + if (kfree_nvram) + kfree(data); + release_firmware(fw); if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL)) goto fail; @@ -504,90 +579,75 @@ fail: return -ENOENT; } -static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async) -{ - struct brcmf_fw_item *cur; - const struct firmware *fw = NULL; - int ret; - - cur = &fwctx->req->items[fwctx->curpos]; - - brcmf_dbg(TRACE, "%srequest for %s\n", async ? "async " : "", - cur->path); - - if (async) - ret = request_firmware_nowait(THIS_MODULE, true, cur->path, - fwctx->dev, GFP_KERNEL, fwctx, - brcmf_fw_request_done); - else - ret = request_firmware(&fw, cur->path, fwctx->dev); - - if (ret < 0) { - brcmf_fw_request_done(NULL, fwctx); - } else if (!async && fw) { - brcmf_dbg(TRACE, "firmware %s %sfound\n", cur->path, - fw ? "" : "not "); - if (cur->type == BRCMF_FW_TYPE_BINARY) - cur->binary = fw; - else if (cur->type == BRCMF_FW_TYPE_NVRAM) - brcmf_fw_request_nvram_done(fw, fwctx); - else - release_firmware(fw); - - return -EAGAIN; - } - return 0; -} - -static void brcmf_fw_request_done(const struct firmware *fw, void *ctx) +static int brcmf_fw_complete_request(const struct firmware *fw, + struct brcmf_fw *fwctx) { - struct brcmf_fw *fwctx = ctx; - struct brcmf_fw_item *cur; + struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos]; int ret = 0; - cur = &fwctx->req->items[fwctx->curpos]; - - brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path, - fw ? "" : "not "); - - if (!fw) - ret = -ENOENT; + brcmf_dbg(TRACE, "firmware %s %sfound\n", cur->path, fw ? "" : "not "); switch (cur->type) { case BRCMF_FW_TYPE_NVRAM: ret = brcmf_fw_request_nvram_done(fw, fwctx); break; case BRCMF_FW_TYPE_BINARY: - cur->binary = fw; + if (fw) + cur->binary = fw; + else + ret = -ENOENT; break; default: /* something fishy here so bail out early */ brcmf_err("unknown fw type: %d\n", cur->type); release_firmware(fw); ret = -EINVAL; - goto fail; } - if (ret < 0 && !(cur->flags & BRCMF_FW_REQF_OPTIONAL)) - goto fail; + return (cur->flags & BRCMF_FW_REQF_OPTIONAL) ? 0 : ret; +} - do { - if (++fwctx->curpos == fwctx->req->n_items) { - ret = 0; - goto done; - } +static int brcmf_fw_request_firmware(const struct firmware **fw, + struct brcmf_fw *fwctx) +{ + struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos]; + int ret; - ret = brcmf_fw_request_next_item(fwctx, false); - } while (ret == -EAGAIN); + /* nvram files are board-specific, first try a board-specific path */ + if (cur->type == BRCMF_FW_TYPE_NVRAM && fwctx->req->board_type) { + char alt_path[BRCMF_FW_NAME_LEN]; - return; + strlcpy(alt_path, cur->path, BRCMF_FW_NAME_LEN); + /* strip .txt at the end */ + alt_path[strlen(alt_path) - 4] = 0; + strlcat(alt_path, ".", BRCMF_FW_NAME_LEN); + strlcat(alt_path, fwctx->req->board_type, BRCMF_FW_NAME_LEN); + strlcat(alt_path, ".txt", BRCMF_FW_NAME_LEN); -fail: - brcmf_dbg(TRACE, "failed err=%d: dev=%s, fw=%s\n", ret, - dev_name(fwctx->dev), cur->path); - brcmf_fw_free_request(fwctx->req); - fwctx->req = NULL; -done: + ret = request_firmware(fw, alt_path, fwctx->dev); + if (ret == 0) + return ret; + } + + return request_firmware(fw, cur->path, fwctx->dev); +} + +static void brcmf_fw_request_done(const struct firmware *fw, void *ctx) +{ + struct brcmf_fw *fwctx = ctx; + int ret; + + ret = brcmf_fw_complete_request(fw, fwctx); + + while (ret == 0 && ++fwctx->curpos < fwctx->req->n_items) { + brcmf_fw_request_firmware(&fw, fwctx); + ret = brcmf_fw_complete_request(fw, ctx); + } + + if (ret) { + brcmf_fw_free_request(fwctx->req); + fwctx->req = NULL; + } fwctx->done(fwctx->dev, ret, fwctx->req); kfree(fwctx); } @@ -611,7 +671,9 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, void (*fw_cb)(struct device *dev, int err, struct brcmf_fw_request *req)) { + struct brcmf_fw_item *first = &req->items[0]; struct brcmf_fw *fwctx; + int ret; brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); if (!fw_cb) @@ -628,7 +690,12 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, fwctx->req = req; fwctx->done = fw_cb; - brcmf_fw_request_next_item(fwctx, true); + ret = request_firmware_nowait(THIS_MODULE, true, first->path, + fwctx->dev, GFP_KERNEL, fwctx, + brcmf_fw_request_done); + if (ret < 0) + brcmf_fw_request_done(NULL, fwctx); + return 0; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h index 2893e56910f0..a0834be8864e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h @@ -70,6 +70,7 @@ struct brcmf_fw_request { u16 domain_nr; u16 bus_nr; u32 n_items; + const char *board_type; struct brcmf_fw_item items[0]; }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c index aee6e5937c41..84e3373289eb 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c @@ -27,11 +27,20 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, struct brcmf_mp_device *settings) { struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio; - struct device_node *np = dev->of_node; + struct device_node *root, *np = dev->of_node; + struct property *prop; int irq; u32 irqf; u32 val; + /* Set board-type to the first string of the machine compatible prop */ + root = of_find_node_by_path("/"); + if (root) { + prop = of_find_property(root, "compatible", NULL); + settings->board_type = of_prop_next_string(prop, NULL); + of_node_put(root); + } + if (!np || bus_type != BRCMF_BUSTYPE_SDIO || !of_device_is_compatible(np, "brcm,bcm4329-fmac")) return; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 3e9c4f2f5dd1..456a1bf008b3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -74,7 +74,7 @@ #define P2P_AF_MAX_WAIT_TIME msecs_to_jiffies(2000) #define P2P_INVALID_CHANNEL -1 #define P2P_CHANNEL_SYNC_RETRY 5 -#define P2P_AF_FRM_SCAN_MAX_WAIT msecs_to_jiffies(1500) +#define P2P_AF_FRM_SCAN_MAX_WAIT msecs_to_jiffies(450) #define P2P_DEFAULT_SLEEP_TIME_VSDB 200 /* WiFi P2P Public Action Frame OUI Subtypes */ @@ -1134,7 +1134,6 @@ static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p) { struct afx_hdl *afx_hdl = &p2p->afx_hdl; struct brcmf_cfg80211_vif *pri_vif; - unsigned long duration; s32 retry; brcmf_dbg(TRACE, "Enter\n"); @@ -1150,7 +1149,6 @@ static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p) * pending action frame tx is cancelled. */ retry = 0; - duration = msecs_to_jiffies(P2P_AF_FRM_SCAN_MAX_WAIT); while ((retry < P2P_CHANNEL_SYNC_RETRY) && (afx_hdl->peer_chan == P2P_INVALID_CHANNEL)) { afx_hdl->is_listen = false; @@ -1158,7 +1156,8 @@ static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p) retry); /* search peer on peer's listen channel */ schedule_work(&afx_hdl->afx_work); - wait_for_completion_timeout(&afx_hdl->act_frm_scan, duration); + wait_for_completion_timeout(&afx_hdl->act_frm_scan, + P2P_AF_FRM_SCAN_MAX_WAIT); if ((afx_hdl->peer_chan != P2P_INVALID_CHANNEL) || (!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status))) @@ -1171,7 +1170,7 @@ static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p) afx_hdl->is_listen = true; schedule_work(&afx_hdl->afx_work); wait_for_completion_timeout(&afx_hdl->act_frm_scan, - duration); + P2P_AF_FRM_SCAN_MAX_WAIT); } if ((afx_hdl->peer_chan != P2P_INVALID_CHANNEL) || (!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, @@ -1458,10 +1457,12 @@ int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp, return 0; if (e->event_code == BRCMF_E_ACTION_FRAME_COMPLETE) { - if (e->status == BRCMF_E_STATUS_SUCCESS) + if (e->status == BRCMF_E_STATUS_SUCCESS) { set_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status); - else { + if (!p2p->wait_for_offchan_complete) + complete(&p2p->send_af_done); + } else { set_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status); /* If there is no ack, we don't need to wait for * WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE event @@ -1512,6 +1513,17 @@ static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p, p2p->af_sent_channel = le32_to_cpu(af_params->channel); p2p->af_tx_sent_jiffies = jiffies; + if (test_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status) && + p2p->af_sent_channel == + ieee80211_frequency_to_channel(p2p->remain_on_channel.center_freq)) + p2p->wait_for_offchan_complete = false; + else + p2p->wait_for_offchan_complete = true; + + brcmf_dbg(TRACE, "Waiting for %s tx completion event\n", + (p2p->wait_for_offchan_complete) ? + "off-channel" : "on-channel"); + timeout = wait_for_completion_timeout(&p2p->send_af_done, P2P_AF_MAX_WAIT_TIME); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h index 0e8b34d2d85c..39f0d0218088 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h @@ -124,6 +124,7 @@ struct afx_hdl { * @gon_req_action: about to send go negotiation requets frame. * @block_gon_req_tx: drop tx go negotiation requets frame. * @p2pdev_dynamically: is p2p device if created by module param or supplicant. + * @wait_for_offchan_complete: wait for off-channel tx completion event. */ struct brcmf_p2p_info { struct brcmf_cfg80211_info *cfg; @@ -144,6 +145,7 @@ struct brcmf_p2p_info { bool gon_req_action; bool block_gon_req_tx; bool p2pdev_dynamically; + bool wait_for_offchan_complete; }; s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 5dea569d63ed..956a8b236836 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1785,6 +1785,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo) fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY; fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM; fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL; + fwreq->board_type = devinfo->settings->board_type; /* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */ fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1; fwreq->bus_nr = devinfo->pdev->bus->number; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index b2e1ab5adb64..22646a3b911e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -4174,6 +4174,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus) fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY; fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM; + fwreq->board_type = bus->sdiodev->settings->board_type; return fwreq; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c index 6255fb6d97a7..6188275b17e5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c @@ -502,6 +502,7 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } spin_lock_bh(&wl->lock); + wl->wlc->vif = vif; wl->mute_tx = false; brcms_c_mute(wl->wlc, false); if (vif->type == NL80211_IFTYPE_STATION) @@ -519,6 +520,11 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static void brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { + struct brcms_info *wl = hw->priv; + + spin_lock_bh(&wl->lock); + wl->wlc->vif = NULL; + spin_unlock_bh(&wl->lock); } static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) @@ -840,8 +846,8 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, status = brcms_c_aggregatable(wl->wlc, tid); spin_unlock_bh(&wl->lock); if (!status) { - brcms_err(wl->wlc->hw->d11core, - "START: tid %d is not agg\'able\n", tid); + brcms_dbg_ht(wl->wlc->hw->d11core, + "START: tid %d is not agg\'able\n", tid); return -EINVAL; } ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -937,6 +943,25 @@ static void brcms_ops_set_tsf(struct ieee80211_hw *hw, spin_unlock_bh(&wl->lock); } +static int brcms_ops_beacon_set_tim(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, bool set) +{ + struct brcms_info *wl = hw->priv; + struct sk_buff *beacon = NULL; + u16 tim_offset = 0; + + spin_lock_bh(&wl->lock); + if (wl->wlc->vif) + beacon = ieee80211_beacon_get_tim(hw, wl->wlc->vif, + &tim_offset, NULL); + if (beacon) + brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset, + wl->wlc->vif->bss_conf.dtim_period); + spin_unlock_bh(&wl->lock); + + return 0; +} + static const struct ieee80211_ops brcms_ops = { .tx = brcms_ops_tx, .start = brcms_ops_start, @@ -955,6 +980,7 @@ static const struct ieee80211_ops brcms_ops = { .flush = brcms_ops_flush, .get_tsf = brcms_ops_get_tsf, .set_tsf = brcms_ops_set_tsf, + .set_tim = brcms_ops_beacon_set_tim, }; void brcms_dpc(unsigned long data) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h index c4d135cff04a..9f76b880814e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h @@ -563,6 +563,7 @@ struct brcms_c_info { struct wiphy *wiphy; struct scb pri_scb; + struct ieee80211_vif *vif; struct sk_buff *beacon; u16 beacon_tim_offset; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c index e7584b842dce..40e94fe72f46 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c @@ -128,7 +128,7 @@ static void brcmu_d11n_decchspec(struct brcmu_chan *ch) } break; default: - WARN_ON_ONCE(1); + WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec); break; } @@ -140,7 +140,7 @@ static void brcmu_d11n_decchspec(struct brcmu_chan *ch) ch->band = BRCMU_CHAN_BAND_2G; break; default: - WARN_ON_ONCE(1); + WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec); break; } } @@ -167,7 +167,7 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch) ch->sb = BRCMU_CHAN_SB_U; ch->control_ch_num += CH_10MHZ_APART; } else { - WARN_ON_ONCE(1); + WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec); } break; case BRCMU_CHSPEC_D11AC_BW_80: @@ -188,7 +188,7 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch) ch->control_ch_num += CH_30MHZ_APART; break; default: - WARN_ON_ONCE(1); + WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec); break; } break; @@ -219,13 +219,13 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch) ch->control_ch_num += CH_70MHZ_APART; break; default: - WARN_ON_ONCE(1); + WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec); break; } break; case BRCMU_CHSPEC_D11AC_BW_8080: default: - WARN_ON_ONCE(1); + WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec); break; } @@ -237,7 +237,7 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch) ch->band = BRCMU_CHAN_BAND_2G; break; default: - WARN_ON_ONCE(1); + WARN_ONCE(1, "Invalid chanspec 0x%04x\n", ch->chspec); break; } } diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index 04dd7a936593..5512c7f73fce 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -5462,7 +5462,7 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) { we have to add a spin lock... */ rc = readBSSListRid(ai, doLoseSync, &BSSList_rid); while(rc == 0 && BSSList_rid.index != cpu_to_le16(0xffff)) { - ptr += sprintf(ptr, "%pM %*s rssi = %d", + ptr += sprintf(ptr, "%pM %.*s rssi = %d", BSSList_rid.bssid, (int)BSSList_rid.ssidLen, BSSList_rid.ssid, diff --git a/drivers/net/wireless/intel/iwlegacy/3945-rs.c b/drivers/net/wireless/intel/iwlegacy/3945-rs.c index e8983c6a2b7b..a697edd46e7f 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-rs.c @@ -781,7 +781,7 @@ il3945_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta, switch (scale_action) { case -1: - /* Decrese rate */ + /* Decrease rate */ if (low != RATE_INVALID) idx = low; break; diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index 280cd8ae1696..6b4488a178a7 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -559,7 +559,7 @@ il4965_translate_rx_status(struct il_priv *il, u32 decrypt_in) decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; break; } - /* fall through if TTAK OK */ + /* fall through - if TTAK OK */ default: if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; diff --git a/drivers/net/wireless/intel/iwlegacy/4965.c b/drivers/net/wireless/intel/iwlegacy/4965.c index c3c638ed0ed7..ce4144a89217 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965.c +++ b/drivers/net/wireless/intel/iwlegacy/4965.c @@ -1297,6 +1297,8 @@ il4965_send_rxon_assoc(struct il_priv *il) const struct il_rxon_cmd *rxon1 = &il->staging; const struct il_rxon_cmd *rxon2 = &il->active; + lockdep_assert_held(&il->mutex); + if (rxon1->flags == rxon2->flags && rxon1->filter_flags == rxon2->filter_flags && rxon1->cck_basic_rates == rxon2->cck_basic_rates && diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index 6514baf799fe..a2f86cbcc740 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -2695,6 +2695,7 @@ il_set_decrypted_flag(struct il_priv *il, struct ieee80211_hdr *hdr, if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == RX_RES_STATUS_BAD_KEY_TTAK) break; + /* fall through */ case RX_RES_STATUS_SEC_TYPE_WEP: if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == @@ -2704,6 +2705,7 @@ il_set_decrypted_flag(struct il_priv *il, struct ieee80211_hdr *hdr, D_RX("Packet destroyed\n"); return -1; } + /* fall through */ case RX_RES_STATUS_SEC_TYPE_CCMP: if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == RX_RES_STATUS_DECRYPT_OK) { diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c index 46686ee88ff4..76b5ddb20248 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c @@ -47,6 +47,7 @@ static const struct iwl_base_params iwl1000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, + .max_tfd_queue_size = 256, .eeprom_size = OTP_LOW_IMAGE_SIZE, .pll_cfg = true, .max_ll_items = OTP_MAX_LL_ITEMS_1000, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index a8acc755a02c..da5d5f9b2573 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -56,7 +56,7 @@ #include "iwl-config.h" /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX 38 +#define IWL_22000_UCODE_API_MAX 41 /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 39 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 37deaf4fd7b3..d55fd23cafe6 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -57,7 +57,7 @@ #include "fw/file.h" /* Highest firmware API version supported */ -#define IWL9000_UCODE_API_MAX 38 +#define IWL9000_UCODE_API_MAX 41 /* Lowest firmware API version supported */ #define IWL9000_UCODE_API_MIN 30 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index 6c5338364794..93b392f0c6a4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -165,7 +165,7 @@ struct iwl_nvm_access_resp { */ struct iwl_nvm_get_info { __le32 reserved; -} __packed; /* GRP_REGULATORY_NVM_GET_INFO_CMD_S_VER_1 */ +} __packed; /* REGULATORY_NVM_GET_INFO_CMD_API_S_VER_1 */ /** * enum iwl_nvm_info_general_flags - flags in NVM_GET_INFO resp @@ -180,14 +180,14 @@ enum iwl_nvm_info_general_flags { * @flags: bit 0: 1 - empty, 0 - non-empty * @nvm_version: nvm version * @board_type: board type - * @reserved: reserved + * @n_hw_addrs: number of reserved MAC addresses */ struct iwl_nvm_get_info_general { __le32 flags; __le16 nvm_version; u8 board_type; - u8 reserved; -} __packed; /* GRP_REGULATORY_NVM_GET_INFO_GENERAL_S_VER_1 */ + u8 n_hw_addrs; +} __packed; /* REGULATORY_NVM_GET_INFO_GENERAL_S_VER_2 */ /** * enum iwl_nvm_mac_sku_flags - flags in &iwl_nvm_get_info_sku @@ -231,7 +231,7 @@ struct iwl_nvm_get_info_sku { struct iwl_nvm_get_info_phy { __le32 tx_chains; __le32 rx_chains; -} __packed; /* GRP_REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */ +} __packed; /* REGULATORY_NVM_GET_INFO_PHY_SKU_SECTION_S_VER_1 */ #define IWL_NUM_CHANNELS (51) @@ -245,7 +245,7 @@ struct iwl_nvm_get_info_regulatory { __le32 lar_enabled; __le16 channel_profile[IWL_NUM_CHANNELS]; __le16 reserved; -} __packed; /* GRP_REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */ +} __packed; /* REGULATORY_NVM_GET_INFO_REGULATORY_S_VER_1 */ /** * struct iwl_nvm_get_info_rsp - response to get NVM data @@ -259,7 +259,7 @@ struct iwl_nvm_get_info_rsp { struct iwl_nvm_get_info_sku mac_sku; struct iwl_nvm_get_info_phy phy_sku; struct iwl_nvm_get_info_regulatory regulatory; -} __packed; /* GRP_REGULATORY_NVM_GET_INFO_CMD_RSP_S_VER_2 */ +} __packed; /* REGULATORY_NVM_GET_INFO_RSP_API_S_VER_3 */ /** * struct iwl_nvm_access_complete_cmd - NVM_ACCESS commands are completed @@ -270,22 +270,6 @@ struct iwl_nvm_access_complete_cmd { } __packed; /* NVM_ACCESS_COMPLETE_CMD_API_S_VER_1 */ /** - * struct iwl_mcc_update_cmd_v1 - Request the device to update geographic - * regulatory profile according to the given MCC (Mobile Country Code). - * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain. - * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the - * MCC in the cmd response will be the relevant MCC in the NVM. - * @mcc: given mobile country code - * @source_id: the source from where we got the MCC, see iwl_mcc_source - * @reserved: reserved for alignment - */ -struct iwl_mcc_update_cmd_v1 { - __le16 mcc; - u8 source_id; - u8 reserved; -} __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_1 */ - -/** * struct iwl_mcc_update_cmd - Request the device to update geographic * regulatory profile according to the given MCC (Mobile Country Code). * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain. @@ -306,7 +290,18 @@ struct iwl_mcc_update_cmd { } __packed; /* LAR_UPDATE_MCC_CMD_API_S_VER_2 */ /** - * struct iwl_mcc_update_resp_v1 - response to MCC_UPDATE_CMD. + * enum iwl_geo_information - geographic information. + * @GEO_NO_INFO: no special info for this geo profile. + * @GEO_WMM_ETSI_5GHZ_INFO: this geo profile limits the WMM params + * for the 5 GHz band. + */ +enum iwl_geo_information { + GEO_NO_INFO = 0, + GEO_WMM_ETSI_5GHZ_INFO = BIT(0), +}; + +/** + * struct iwl_mcc_update_resp_v3 - response to MCC_UPDATE_CMD. * Contains the new channel control profile map, if changed, and the new MCC * (mobile country code). * The new MCC may be different than what was requested in MCC_UPDATE_CMD. @@ -314,30 +309,23 @@ struct iwl_mcc_update_cmd { * @mcc: the new applied MCC * @cap: capabilities for all channels which matches the MCC * @source_id: the MCC source, see iwl_mcc_source - * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51 - * channels, depending on platform) + * @time: time elapsed from the MCC test start (in units of 30 seconds) + * @geo_info: geographic specific profile information + * see &enum iwl_geo_information. + * @n_channels: number of channels in @channels_data. * @channels: channel control data map, DWORD for each channel. Only the first * 16bits are used. */ -struct iwl_mcc_update_resp_v1 { +struct iwl_mcc_update_resp_v3 { __le32 status; __le16 mcc; u8 cap; u8 source_id; + __le16 time; + __le16 geo_info; __le32 n_channels; __le32 channels[0]; -} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_1 */ - -/** - * enum iwl_geo_information - geographic information. - * @GEO_NO_INFO: no special info for this geo profile. - * @GEO_WMM_ETSI_5GHZ_INFO: this geo profile limits the WMM params - * for the 5 GHz band. - */ -enum iwl_geo_information { - GEO_NO_INFO = 0, - GEO_WMM_ETSI_5GHZ_INFO = BIT(0), -}; +} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */ /** * struct iwl_mcc_update_resp - response to MCC_UPDATE_CMD. @@ -347,25 +335,26 @@ enum iwl_geo_information { * @status: see &enum iwl_mcc_update_status * @mcc: the new applied MCC * @cap: capabilities for all channels which matches the MCC - * @source_id: the MCC source, see iwl_mcc_source - * @time: time elapsed from the MCC test start (in 30 seconds TU) + * @time: time elapsed from the MCC test start (in units of 30 seconds) * @geo_info: geographic specific profile information * see &enum iwl_geo_information. - * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51 - * channels, depending on platform) + * @source_id: the MCC source, see iwl_mcc_source + * @reserved: for four bytes alignment. + * @n_channels: number of channels in @channels_data. * @channels: channel control data map, DWORD for each channel. Only the first * 16bits are used. */ struct iwl_mcc_update_resp { __le32 status; __le16 mcc; - u8 cap; - u8 source_id; + __le16 cap; __le16 time; __le16 geo_info; + u8 source_id; + u8 reserved[3]; __le32 n_channels; __le32 channels[0]; -} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */ +} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_4 */ /** * struct iwl_mcc_chub_notif - chub notifies of mcc change diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 415b8842b426..0537496b6eb1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -368,10 +368,10 @@ enum iwl_rx_he_phy { /* trigger encoded */ IWL_RX_HE_PHY_RU_ALLOC_MASK = 0xfe0000000000ULL, IWL_RX_HE_PHY_INFO_TYPE_MASK = 0xf000000000000000ULL, - IWL_RX_HE_PHY_INFO_TYPE_SU = 0x0, - IWL_RX_HE_PHY_INFO_TYPE_MU = 0x1, - IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO = 0x2, - IWL_RX_HE_PHY_INFO_TYPE_TB_EXT_INFO = 0x3, + IWL_RX_HE_PHY_INFO_TYPE_SU = 0x0, /* TSF low valid (first DW) */ + IWL_RX_HE_PHY_INFO_TYPE_MU = 0x1, /* TSF low/high valid (both DWs) */ + IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO = 0x2, /* same + SIGB-common0/1/2 valid */ + IWL_RX_HE_PHY_INFO_TYPE_TB = 0x3, /* TSF low/high valid (both DWs) */ /* second dword - MU data */ IWL_RX_HE_PHY_MU_SIGB_COMPRESSION = BIT_ULL(32 + 0), diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index 310b01e3cce1..18741889ec30 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -596,9 +596,12 @@ enum iwl_umac_scan_general_flags { * enum iwl_umac_scan_general_flags2 - UMAC scan general flags #2 * @IWL_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL: Whether to send a complete * notification per channel or not. + * @IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER: Whether to allow channel + * reorder optimization or not. */ enum iwl_umac_scan_general_flags2 { - IWL_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL = BIT(0), + IWL_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL = BIT(0), + IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER = BIT(1), }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 0dcf1a673478..c16757051f16 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -240,7 +240,7 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt, if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) return; - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) { + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) { /* Pull RXF1 */ iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->lmac[0].rxfifo1_size, 0, 0); @@ -254,7 +254,7 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt, LMAC2_PRPH_OFFSET, 2); } - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) { + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) { /* Pull TXF data from LMAC1 */ for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) { /* Mark the number of TXF we're pulling now */ @@ -279,7 +279,7 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt, } } - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF) && + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF) && fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) { /* Pull UMAC internal TXF data from all TXFs */ @@ -573,103 +573,95 @@ static int iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt) static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt, struct iwl_fw_error_dump_data **dump_data, - u32 sram_len, u32 sram_ofs, u32 smem_len, - u32 sram2_len) + u32 len, u32 ofs, u32 type) { - const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem = fwrt->fw->dbg_mem_tlv; struct iwl_fw_error_dump_mem *dump_mem; + + if (!len) + return; + + (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); + (*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem)); + dump_mem = (void *)(*dump_data)->data; + dump_mem->type = cpu_to_le32(type); + dump_mem->offset = cpu_to_le32(ofs); + iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len); + *dump_data = iwl_fw_error_next_data(*dump_data); + + IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type); +} + +#define ADD_LEN(len, item_len, const_len) \ + do {size_t item = item_len; len += (!!item) * const_len + item; } \ + while (0) + +static int iwl_fw_fifo_len(struct iwl_fw_runtime *fwrt, + struct iwl_fwrt_shared_mem_cfg *mem_cfg) +{ + size_t hdr_len = sizeof(struct iwl_fw_error_dump_data) + + sizeof(struct iwl_fw_error_dump_fifo); + u32 fifo_len = 0; int i; - if (!fwrt->fw->n_dbg_mem_tlv) { - (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); - (*dump_data)->len = cpu_to_le32(sram_len + sizeof(*dump_mem)); - dump_mem = (void *)(*dump_data)->data; - dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM); - dump_mem->offset = cpu_to_le32(sram_ofs); - iwl_trans_read_mem_bytes(fwrt->trans, sram_ofs, dump_mem->data, - sram_len); - *dump_data = iwl_fw_error_next_data(*dump_data); - } + if (!(fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF))) + goto dump_txf; - for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) { - u32 len = le32_to_cpu(fw_dbg_mem[i].len); - u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs); + /* Count RXF2 size */ + ADD_LEN(fifo_len, mem_cfg->rxfifo2_size, hdr_len); - (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); - (*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem)); - dump_mem = (void *)(*dump_data)->data; - dump_mem->type = fw_dbg_mem[i].data_type; - dump_mem->offset = cpu_to_le32(ofs); + /* Count RXF1 sizes */ + for (i = 0; i < mem_cfg->num_lmacs; i++) + ADD_LEN(fifo_len, mem_cfg->lmac[i].rxfifo1_size, hdr_len); - IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", - dump_mem->type); +dump_txf: + if (!(fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF))) + goto dump_internal_txf; - iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len); - *dump_data = iwl_fw_error_next_data(*dump_data); - } + /* Count TXF sizes */ + for (i = 0; i < mem_cfg->num_lmacs; i++) { + int j; - if (smem_len) { - IWL_DEBUG_INFO(fwrt, "WRT SMEM dump\n"); - (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); - (*dump_data)->len = cpu_to_le32(smem_len + sizeof(*dump_mem)); - dump_mem = (void *)(*dump_data)->data; - dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SMEM); - dump_mem->offset = cpu_to_le32(fwrt->trans->cfg->smem_offset); - iwl_trans_read_mem_bytes(fwrt->trans, - fwrt->trans->cfg->smem_offset, - dump_mem->data, smem_len); - *dump_data = iwl_fw_error_next_data(*dump_data); + for (j = 0; j < mem_cfg->num_txfifo_entries; j++) + ADD_LEN(fifo_len, mem_cfg->lmac[i].txfifo_size[j], + hdr_len); } - if (sram2_len) { - IWL_DEBUG_INFO(fwrt, "WRT SRAM dump\n"); - (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); - (*dump_data)->len = cpu_to_le32(sram2_len + sizeof(*dump_mem)); - dump_mem = (void *)(*dump_data)->data; - dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM); - dump_mem->offset = cpu_to_le32(fwrt->trans->cfg->dccm2_offset); - iwl_trans_read_mem_bytes(fwrt->trans, - fwrt->trans->cfg->dccm2_offset, - dump_mem->data, sram2_len); - *dump_data = iwl_fw_error_next_data(*dump_data); - } +dump_internal_txf: + if (!((fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF)) && + fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG))) + goto out; + + for (i = 0; i < ARRAY_SIZE(mem_cfg->internal_txfifo_size); i++) + ADD_LEN(fifo_len, mem_cfg->internal_txfifo_size[i], hdr_len); + +out: + return fifo_len; } -void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) +static struct iwl_fw_error_dump_file * +_iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, + struct iwl_fw_dump_ptrs *fw_error_dump) { struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_info *dump_info; struct iwl_fw_error_dump_smem_cfg *dump_smem_cfg; struct iwl_fw_error_dump_trigger_desc *dump_trig; - struct iwl_fw_dump_ptrs *fw_error_dump; - struct scatterlist *sg_dump_data; u32 sram_len, sram_ofs; - const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem = fwrt->fw->dbg_mem_tlv; + const struct iwl_fw_dbg_mem_seg_tlv *fw_mem = fwrt->fw->dbg.mem_tlv; struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg; - u32 file_len, fifo_data_len = 0, prph_len = 0, radio_len = 0; - u32 smem_len = fwrt->fw->n_dbg_mem_tlv ? 0 : fwrt->trans->cfg->smem_len; - u32 sram2_len = fwrt->fw->n_dbg_mem_tlv ? + u32 file_len, fifo_len = 0, prph_len = 0, radio_len = 0; + u32 smem_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->cfg->smem_len; + u32 sram2_len = fwrt->fw->dbg.n_mem_tlv ? 0 : fwrt->trans->cfg->dccm2_len; bool monitor_dump_only = false; int i; - IWL_DEBUG_INFO(fwrt, "WRT dump start\n"); - - /* there's no point in fw dump if the bus is dead */ - if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) { - IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n"); - goto out; - } - if (fwrt->dump.trig && fwrt->dump.trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY) monitor_dump_only = true; - fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL); - if (!fw_error_dump) - goto out; - /* SRAM - include stack CCM if driver knows the values for it */ if (!fwrt->trans->cfg->dccm_offset || !fwrt->trans->cfg->dccm_len) { const struct fw_img *img; @@ -684,112 +676,43 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) /* reading RXF/TXF sizes */ if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) { - fifo_data_len = 0; - - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) { - - /* Count RXF2 size */ - if (mem_cfg->rxfifo2_size) { - /* Add header info */ - fifo_data_len += - mem_cfg->rxfifo2_size + - sizeof(*dump_data) + - sizeof(struct iwl_fw_error_dump_fifo); - } - - /* Count RXF1 sizes */ - for (i = 0; i < mem_cfg->num_lmacs; i++) { - if (!mem_cfg->lmac[i].rxfifo1_size) - continue; - - /* Add header info */ - fifo_data_len += - mem_cfg->lmac[i].rxfifo1_size + - sizeof(*dump_data) + - sizeof(struct iwl_fw_error_dump_fifo); - } - } - - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) { - size_t fifo_const_len = sizeof(*dump_data) + - sizeof(struct iwl_fw_error_dump_fifo); - - /* Count TXF sizes */ - for (i = 0; i < mem_cfg->num_lmacs; i++) { - int j; - - for (j = 0; j < mem_cfg->num_txfifo_entries; - j++) { - if (!mem_cfg->lmac[i].txfifo_size[j]) - continue; - - /* Add header info */ - fifo_data_len += - fifo_const_len + - mem_cfg->lmac[i].txfifo_size[j]; - } - } - } - - if ((fwrt->fw->dbg_dump_mask & - BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF)) && - fw_has_capa(&fwrt->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) { - for (i = 0; - i < ARRAY_SIZE(mem_cfg->internal_txfifo_size); - i++) { - if (!mem_cfg->internal_txfifo_size[i]) - continue; - - /* Add header info */ - fifo_data_len += - mem_cfg->internal_txfifo_size[i] + - sizeof(*dump_data) + - sizeof(struct iwl_fw_error_dump_fifo); - } - } + fifo_len = iwl_fw_fifo_len(fwrt, mem_cfg); /* Make room for PRPH registers */ if (!fwrt->trans->cfg->gen2 && - fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PRPH)) + fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_PRPH)) prph_len += iwl_fw_get_prph_len(fwrt); if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 && - fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RADIO_REG)) + fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_RADIO_REG)) radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ; } - file_len = sizeof(*dump_file) + - fifo_data_len + - prph_len + - radio_len; + file_len = sizeof(*dump_file) + fifo_len + prph_len + radio_len; - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO)) + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO)) file_len += sizeof(*dump_data) + sizeof(*dump_info); - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG)) + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG)) file_len += sizeof(*dump_data) + sizeof(*dump_smem_cfg); - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) { - /* Make room for the SMEM, if it exists */ - if (smem_len) - file_len += sizeof(*dump_data) + smem_len + - sizeof(struct iwl_fw_error_dump_mem); - - /* Make room for the secondary SRAM, if it exists */ - if (sram2_len) - file_len += sizeof(*dump_data) + sram2_len + - sizeof(struct iwl_fw_error_dump_mem); - - /* Make room for MEM segments */ - for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) { - file_len += sizeof(*dump_data) + - le32_to_cpu(fw_dbg_mem[i].len) + - sizeof(struct iwl_fw_error_dump_mem); - } + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) { + size_t hdr_len = sizeof(*dump_data) + + sizeof(struct iwl_fw_error_dump_mem); + + /* Dump SRAM only if no mem_tlvs */ + if (!fwrt->fw->dbg.n_mem_tlv) + ADD_LEN(file_len, sram_len, hdr_len); + + /* Make room for all mem types that exist */ + ADD_LEN(file_len, smem_len, hdr_len); + ADD_LEN(file_len, sram2_len, hdr_len); + + for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++) + ADD_LEN(file_len, le32_to_cpu(fw_mem[i].len), hdr_len); } /* Make room for fw's virtual image pages, if it exists */ - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) && + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) && !fwrt->trans->cfg->gen2 && fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size && fwrt->fw_paging_db[0].fw_paging_block) @@ -809,28 +732,21 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) sizeof(*dump_info) + sizeof(*dump_smem_cfg); } - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) && + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) && fwrt->dump.desc) file_len += sizeof(*dump_data) + sizeof(*dump_trig) + fwrt->dump.desc->len; - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM) && - !fwrt->fw->n_dbg_mem_tlv) - file_len += sizeof(*dump_data) + sram_len + - sizeof(struct iwl_fw_error_dump_mem); - dump_file = vzalloc(file_len); - if (!dump_file) { - kfree(fw_error_dump); - goto out; - } + if (!dump_file) + return NULL; fw_error_dump->fwrt_ptr = dump_file; dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); dump_data = (void *)dump_file->data; - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO)) { + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO)) { dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO); dump_data->len = cpu_to_le32(sizeof(*dump_info)); dump_info = (void *)dump_data->data; @@ -851,7 +767,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) dump_data = iwl_fw_error_next_data(dump_data); } - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG)) { + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG)) { /* Dump shared memory configuration */ dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG); dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg)); @@ -882,13 +798,13 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) } /* We only dump the FIFOs if the FW is in error state */ - if (fifo_data_len) { + if (fifo_len) { iwl_fw_dump_fifos(fwrt, &dump_data); if (radio_len) iwl_read_radio_regs(fwrt, &dump_data); } - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) && + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) && fwrt->dump.desc) { dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO); dump_data->len = cpu_to_le32(sizeof(*dump_trig) + @@ -902,12 +818,32 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) /* In case we only want monitor dump, skip to dump trasport data */ if (monitor_dump_only) - goto dump_trans_data; + goto out; - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) - iwl_fw_dump_mem(fwrt, &dump_data, sram_len, sram_ofs, smem_len, - sram2_len); + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) { + const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem = + fwrt->fw->dbg.mem_tlv; + if (!fwrt->fw->dbg.n_mem_tlv) + iwl_fw_dump_mem(fwrt, &dump_data, sram_len, sram_ofs, + IWL_FW_ERROR_DUMP_MEM_SRAM); + + for (i = 0; i < fwrt->fw->dbg.n_mem_tlv; i++) { + u32 len = le32_to_cpu(fw_dbg_mem[i].len); + u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs); + + iwl_fw_dump_mem(fwrt, &dump_data, len, ofs, + le32_to_cpu(fw_dbg_mem[i].data_type)); + } + + iwl_fw_dump_mem(fwrt, &dump_data, smem_len, + fwrt->trans->cfg->smem_offset, + IWL_FW_ERROR_DUMP_MEM_SMEM); + + iwl_fw_dump_mem(fwrt, &dump_data, sram2_len, + fwrt->trans->cfg->dccm2_offset, + IWL_FW_ERROR_DUMP_MEM_SRAM); + } if (iwl_fw_dbg_is_d3_debug_enabled(fwrt) && fwrt->dump.d3_debug_data) { u32 addr = fwrt->trans->cfg->d3_debug_data_base_addr; @@ -929,7 +865,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) } /* Dump fw's virtual image */ - if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) && + if (fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) && !fwrt->trans->cfg->gen2 && fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size && fwrt->fw_paging_db[0].fw_paging_block) { @@ -965,13 +901,44 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ARRAY_SIZE(iwl_prph_dump_addr_9000)); } -dump_trans_data: +out: + dump_file->file_len = cpu_to_le32(file_len); + return dump_file; +} + +void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) +{ + struct iwl_fw_dump_ptrs *fw_error_dump; + struct iwl_fw_error_dump_file *dump_file; + struct scatterlist *sg_dump_data; + u32 file_len; + + IWL_DEBUG_INFO(fwrt, "WRT dump start\n"); + + /* there's no point in fw dump if the bus is dead */ + if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) { + IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n"); + goto out; + } + + fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL); + if (!fw_error_dump) + goto out; + + dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump); + if (!dump_file) { + kfree(fw_error_dump); + goto out; + } + fw_error_dump->trans_ptr = iwl_trans_dump_data(fwrt->trans, fwrt->dump.trig); + file_len = le32_to_cpu(dump_file->file_len); fw_error_dump->fwrt_len = file_len; - if (fw_error_dump->trans_ptr) + if (fw_error_dump->trans_ptr) { file_len += fw_error_dump->trans_ptr->len; - dump_file->file_len = cpu_to_le32(file_len); + dump_file->file_len = cpu_to_le32(file_len); + } sg_dump_data = alloc_sgtable(file_len); if (sg_dump_data) { @@ -1006,15 +973,34 @@ const struct iwl_fw_dump_desc iwl_dump_desc_assert = { }; IWL_EXPORT_SYMBOL(iwl_dump_desc_assert); -int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, - const struct iwl_fw_dump_desc *desc, - const struct iwl_fw_dbg_trigger_tlv *trigger) +void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt) { - unsigned int delay = 0; + struct iwl_fw_dump_desc *iwl_dump_desc_no_alive = + kmalloc(sizeof(*iwl_dump_desc_no_alive), GFP_KERNEL); - if (trigger) - delay = msecs_to_jiffies(le32_to_cpu(trigger->stop_delay)); + if (!iwl_dump_desc_no_alive) + return; + + iwl_dump_desc_no_alive->trig_desc.type = + cpu_to_le32(FW_DBG_TRIGGER_NO_ALIVE); + iwl_dump_desc_no_alive->len = 0; + + if (WARN_ON(fwrt->dump.desc)) + iwl_fw_free_dump_desc(fwrt); + + IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n", + FW_DBG_TRIGGER_NO_ALIVE); + fwrt->dump.desc = iwl_dump_desc_no_alive; + iwl_fw_error_dump(fwrt); + clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status); +} +IWL_EXPORT_SYMBOL(iwl_fw_alive_error_dump); + +int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, + const struct iwl_fw_dump_desc *desc, void *trigger, + unsigned int delay) +{ /* * If the loading of the FW completed successfully, the next step is to * get the SMEM config data. Thus, if fwrt->smem_cfg.num_lmacs is non @@ -1031,7 +1017,8 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, fwrt->smem_cfg.num_lmacs) return -EIO; - if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status) || + test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status)) return -EBUSY; if (WARN_ON(fwrt->dump.desc)) @@ -1052,25 +1039,38 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc); int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, enum iwl_fw_dbg_trigger trig, const char *str, size_t len, - const struct iwl_fw_dbg_trigger_tlv *trigger) + struct iwl_fw_dbg_trigger_tlv *trigger) { struct iwl_fw_dump_desc *desc; + unsigned int delay = 0; - if (trigger && trigger->flags & IWL_FW_DBG_FORCE_RESTART) { - IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", trig); - iwl_force_nmi(fwrt->trans); - return 0; + if (trigger) { + u16 occurrences = le16_to_cpu(trigger->occurrences) - 1; + + if (!le16_to_cpu(trigger->occurrences)) + return 0; + + if (trigger->flags & IWL_FW_DBG_FORCE_RESTART) { + IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", + trig); + iwl_force_nmi(fwrt->trans); + return 0; + } + + trigger->occurrences = cpu_to_le16(occurrences); + delay = le16_to_cpu(trigger->trig_dis_ms); } desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC); if (!desc) return -ENOMEM; + desc->len = len; desc->trig_desc.type = cpu_to_le32(trig); memcpy(desc->trig_desc.data, str, len); - return iwl_fw_dbg_collect_desc(fwrt, desc, trigger); + return iwl_fw_dbg_collect_desc(fwrt, desc, trigger, delay); } IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect); @@ -1078,13 +1078,9 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, struct iwl_fw_dbg_trigger_tlv *trigger, const char *fmt, ...) { - u16 occurrences = le16_to_cpu(trigger->occurrences); int ret, len = 0; char buf[64]; - if (!occurrences) - return 0; - if (fmt) { va_list ap; @@ -1107,7 +1103,6 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, if (ret) return ret; - trigger->occurrences = cpu_to_le16(occurrences - 1); return 0; } IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_trig); @@ -1118,17 +1113,17 @@ int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 conf_id) int ret; int i; - if (WARN_ONCE(conf_id >= ARRAY_SIZE(fwrt->fw->dbg_conf_tlv), + if (WARN_ONCE(conf_id >= ARRAY_SIZE(fwrt->fw->dbg.conf_tlv), "Invalid configuration %d\n", conf_id)) return -EINVAL; /* EARLY START - firmware's configuration is hard coded */ - if ((!fwrt->fw->dbg_conf_tlv[conf_id] || - !fwrt->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) && + if ((!fwrt->fw->dbg.conf_tlv[conf_id] || + !fwrt->fw->dbg.conf_tlv[conf_id]->num_of_hcmds) && conf_id == FW_DBG_START_FROM_ALIVE) return 0; - if (!fwrt->fw->dbg_conf_tlv[conf_id]) + if (!fwrt->fw->dbg.conf_tlv[conf_id]) return -EINVAL; if (fwrt->dump.conf != FW_DBG_INVALID) @@ -1136,8 +1131,8 @@ int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 conf_id) fwrt->dump.conf); /* Send all HCMDs for configuring the FW debug */ - ptr = (void *)&fwrt->fw->dbg_conf_tlv[conf_id]->hcmd; - for (i = 0; i < fwrt->fw->dbg_conf_tlv[conf_id]->num_of_hcmds; i++) { + ptr = (void *)&fwrt->fw->dbg.conf_tlv[conf_id]->hcmd; + for (i = 0; i < fwrt->fw->dbg.conf_tlv[conf_id]->num_of_hcmds; i++) { struct iwl_fw_dbg_conf_hcmd *cmd = (void *)ptr; struct iwl_host_cmd hcmd = { .id = cmd->id, @@ -1159,14 +1154,14 @@ int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 conf_id) } IWL_EXPORT_SYMBOL(iwl_fw_start_dbg_conf); -void iwl_fw_error_dump_wk(struct work_struct *work) +/* this function assumes dump_start was called beforehand and dump_end will be + * called afterwards + */ +void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt) { - struct iwl_fw_runtime *fwrt = - container_of(work, struct iwl_fw_runtime, dump.wk.work); struct iwl_fw_dbg_params params = {0}; - if (fwrt->ops && fwrt->ops->dump_start && - fwrt->ops->dump_start(fwrt->ops_ctx)) + if (!test_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) return; if (fwrt->ops && fwrt->ops->fw_running && @@ -1174,7 +1169,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work) IWL_ERR(fwrt, "Firmware not running - cannot dump error\n"); iwl_fw_free_dump_desc(fwrt); clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); - goto out; + return; } iwl_fw_dbg_stop_recording(fwrt, ¶ms); @@ -1183,12 +1178,25 @@ void iwl_fw_error_dump_wk(struct work_struct *work) /* start recording again if the firmware is not crashed */ if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) && - fwrt->fw->dbg_dest_tlv) { + fwrt->fw->dbg.dest_tlv) { /* wait before we collect the data till the DBGC stop */ udelay(500); iwl_fw_dbg_restart_recording(fwrt, ¶ms); } -out: +} +IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_sync); + +void iwl_fw_error_dump_wk(struct work_struct *work) +{ + struct iwl_fw_runtime *fwrt = + container_of(work, struct iwl_fw_runtime, dump.wk.work); + + if (fwrt->ops && fwrt->ops->dump_start && + fwrt->ops->dump_start(fwrt->ops_ctx)) + return; + + iwl_fw_dbg_collect_sync(fwrt); + if (fwrt->ops && fwrt->ops->dump_end) fwrt->ops->dump_end(fwrt->ops_ctx); } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 3c89230fae6a..6f8d3256f7b0 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -107,25 +107,25 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt) void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt); int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, const struct iwl_fw_dump_desc *desc, - const struct iwl_fw_dbg_trigger_tlv *trigger); + void *trigger, unsigned int delay); int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, enum iwl_fw_dbg_trigger trig, const char *str, size_t len, - const struct iwl_fw_dbg_trigger_tlv *trigger); + struct iwl_fw_dbg_trigger_tlv *trigger); int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, struct iwl_fw_dbg_trigger_tlv *trigger, const char *fmt, ...) __printf(3, 4); int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 id); #define iwl_fw_dbg_trigger_enabled(fw, id) ({ \ - void *__dbg_trigger = (fw)->dbg_trigger_tlv[(id)]; \ + void *__dbg_trigger = (fw)->dbg.trigger_tlv[(id)]; \ unlikely(__dbg_trigger); \ }) static inline struct iwl_fw_dbg_trigger_tlv* _iwl_fw_dbg_get_trigger(const struct iwl_fw *fw, enum iwl_fw_dbg_trigger id) { - return fw->dbg_trigger_tlv[id]; + return fw->dbg.trigger_tlv[id]; } #define iwl_fw_dbg_get_trigger(fw, id) ({ \ @@ -154,12 +154,9 @@ iwl_fw_dbg_trigger_stop_conf_match(struct iwl_fw_runtime *fwrt, } static inline bool -iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, - struct iwl_fw_dbg_trigger_tlv *trig) +iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_ms) { - unsigned long wind_jiff = - msecs_to_jiffies(le16_to_cpu(trig->trig_dis_ms)); - u32 id = le32_to_cpu(trig->id); + unsigned long wind_jiff = msecs_to_jiffies(dis_ms); /* If this is the first event checked, jump to update start ts */ if (fwrt->dump.non_collect_ts_start[id] && @@ -179,7 +176,8 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt, if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev)) return false; - if (iwl_fw_dbg_no_trig_window(fwrt, trig)) { + if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id), + le16_to_cpu(trig->trig_dis_ms))) { IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n", trig->id); return false; @@ -188,6 +186,30 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt, return iwl_fw_dbg_trigger_stop_conf_match(fwrt, trig); } +static inline struct iwl_fw_dbg_trigger_tlv* +_iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt, + struct wireless_dev *wdev, + const enum iwl_fw_dbg_trigger id) +{ + struct iwl_fw_dbg_trigger_tlv *trig; + + if (!iwl_fw_dbg_trigger_enabled(fwrt->fw, id)) + return NULL; + + trig = _iwl_fw_dbg_get_trigger(fwrt->fw, id); + + if (!iwl_fw_dbg_trigger_check_stop(fwrt, wdev, trig)) + return NULL; + + return trig; +} + +#define iwl_fw_dbg_trigger_on(fwrt, wdev, id) ({ \ + BUILD_BUG_ON(!__builtin_constant_p(id)); \ + BUILD_BUG_ON((id) >= FW_DBG_TRIGGER_MAX); \ + _iwl_fw_dbg_trigger_on((fwrt), (wdev), (id)); \ +}) + static inline void _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, struct wireless_dev *wdev, @@ -293,7 +315,7 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt) return fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_D3_DEBUG) && fwrt->trans->cfg->d3_debug_data_length && - fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA); + fwrt->fw->dbg.dump_mask & BIT(IWL_FW_ERROR_DUMP_D3_DEBUG_DATA); } void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt); @@ -344,4 +366,6 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {} #endif /* CONFIG_IWLWIFI_DEBUGFS */ +void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt); +void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt); #endif /* __iwl_fw_dbg_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index 1049bdfe1e69..3e120dd47305 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -258,11 +258,75 @@ static ssize_t iwl_dbgfs_timestamp_marker_read(struct iwl_fw_runtime *fwrt, FWRT_DEBUGFS_READ_WRITE_FILE_OPS(timestamp_marker, 16); +struct hcmd_write_data { + __be32 cmd_id; + __be32 flags; + __be16 length; + u8 data[0]; +} __packed; + +static ssize_t iwl_dbgfs_send_hcmd_write(struct iwl_fw_runtime *fwrt, char *buf, + size_t count) +{ + size_t header_size = (sizeof(u32) * 2 + sizeof(u16)) * 2; + size_t data_size = (count - 1) / 2; + int ret; + struct hcmd_write_data *data; + struct iwl_host_cmd hcmd = { + .len = { 0, }, + .data = { NULL, }, + }; + + if (fwrt->ops && fwrt->ops->fw_running && + !fwrt->ops->fw_running(fwrt->ops_ctx)) + return -EIO; + + if (count < header_size + 1 || count > 1024 * 4) + return -EINVAL; + + data = kmalloc(data_size, GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = hex2bin((u8 *)data, buf, data_size); + if (ret) + goto out; + + hcmd.id = be32_to_cpu(data->cmd_id); + hcmd.flags = be32_to_cpu(data->flags); + hcmd.len[0] = be16_to_cpu(data->length); + hcmd.data[0] = data->data; + + if (count != header_size + hcmd.len[0] * 2 + 1) { + IWL_ERR(fwrt, + "host command data size does not match header length\n"); + ret = -EINVAL; + goto out; + } + + if (fwrt->ops && fwrt->ops->send_hcmd) + ret = fwrt->ops->send_hcmd(fwrt->ops_ctx, &hcmd); + else + ret = -EPERM; + + if (ret < 0) + goto out; + + if (hcmd.flags & CMD_WANT_SKB) + iwl_free_resp(&hcmd); +out: + kfree(data); + return ret ?: count; +} + +FWRT_DEBUGFS_WRITE_FILE_OPS(send_hcmd, 512); + int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, struct dentry *dbgfs_dir) { INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk); FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, 0200); + FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200); return 0; err: IWL_ERR(fwrt, "Can't create the fwrt debugfs directory\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 6d3ef331b7d5..6fede174c664 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -328,6 +328,7 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data) * @FW_DBG_TDLS: trigger log collection upon TDLS related events. * @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when * the firmware sends a tx reply. + * @FW_DBG_TRIGGER_NO_ALIVE: trigger log collection if alive flow fails */ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_INVALID = 0, @@ -345,6 +346,7 @@ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_TX_LATENCY, FW_DBG_TRIGGER_TDLS, FW_DBG_TRIGGER_TX_STATUS, + FW_DBG_TRIGGER_NO_ALIVE, /* must be last */ FW_DBG_TRIGGER_MAX, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 63e277b07b8a..6005a41c53d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -337,7 +337,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * antenna the beacon should be transmitted * @IWL_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon * from AP and will send it upon d0i3 exit. - * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2: support LAR API V2 + * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V3: support LAR API V3 * @IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW: firmware responsible for CT-kill * @IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT: supports temperature * thresholds reporting @@ -352,6 +352,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * power reduction. * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload * @IWL_UCODE_TLV_CAPA_D3_DEBUG: supports debug recording during D3 + * @IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT: MCC response support 11ax + * capability. * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -392,7 +394,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD = (__force iwl_ucode_tlv_capa_t)70, IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71, IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72, - IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73, + IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V3 = (__force iwl_ucode_tlv_capa_t)73, IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW = (__force iwl_ucode_tlv_capa_t)74, IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT = (__force iwl_ucode_tlv_capa_t)75, IWL_UCODE_TLV_CAPA_CTDP_SUPPORT = (__force iwl_ucode_tlv_capa_t)76, @@ -402,6 +404,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_TX_POWER_ACK = (__force iwl_ucode_tlv_capa_t)84, IWL_UCODE_TLV_CAPA_D3_DEBUG = (__force iwl_ucode_tlv_capa_t)87, IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT = (__force iwl_ucode_tlv_capa_t)88, + IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89, IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96, NUM_IWL_UCODE_TLV_CAPA diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 9cc8fe8908ac..54dbbd998abf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -198,6 +198,29 @@ enum iwl_fw_type { }; /** + * struct iwl_fw_dbg - debug data + * + * @dest_tlv: points to debug destination TLV (typically SRAM or DRAM) + * @n_dest_reg: num of reg_ops in dest_tlv + * @conf_tlv: array of pointers to configuration HCMDs + * @trigger_tlv: array of pointers to triggers TLVs + * @trigger_tlv_len: lengths of the @dbg_trigger_tlv entries + * @mem_tlv: Runtime addresses to dump + * @n_mem_tlv: number of runtime addresses + * @dump_mask: bitmask of dump regions +*/ +struct iwl_fw_dbg { + struct iwl_fw_dbg_dest_tlv_v1 *dest_tlv; + u8 n_dest_reg; + struct iwl_fw_dbg_conf_tlv *conf_tlv[FW_DBG_CONF_MAX]; + struct iwl_fw_dbg_trigger_tlv *trigger_tlv[FW_DBG_TRIGGER_MAX]; + size_t trigger_tlv_len[FW_DBG_TRIGGER_MAX]; + struct iwl_fw_dbg_mem_seg_tlv *mem_tlv; + size_t n_mem_tlv; + u32 dump_mask; +}; + +/** * struct iwl_fw - variables associated with the firmware * * @ucode_ver: ucode version from the ucode file @@ -217,12 +240,6 @@ enum iwl_fw_type { * @cipher_scheme: optional external cipher scheme. * @human_readable: human readable version * we get the ALIVE from the uCode - * @dbg_dest_tlv: points to the destination TLV for debug - * @dbg_conf_tlv: array of pointers to configuration TLVs for debug - * @dbg_conf_tlv_len: lengths of the @dbg_conf_tlv entries - * @dbg_trigger_tlv: array of pointers to triggers TLVs - * @dbg_trigger_tlv_len: lengths of the @dbg_trigger_tlv entries - * @dbg_dest_reg_num: num of reg_ops in %dbg_dest_tlv */ struct iwl_fw { u32 ucode_ver; @@ -250,15 +267,7 @@ struct iwl_fw { struct iwl_fw_cipher_scheme cs[IWL_UCODE_MAX_CS]; u8 human_readable[FW_VER_HUMAN_READABLE_SZ]; - struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv; - struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX]; - size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX]; - struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX]; - struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv; - size_t n_dbg_mem_tlv; - size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX]; - u8 dbg_dest_reg_num; - u32 dbg_dump_mask; + struct iwl_fw_dbg dbg; }; static inline const char *get_fw_dbg_mode_string(int mode) @@ -280,7 +289,7 @@ static inline const char *get_fw_dbg_mode_string(int mode) static inline bool iwl_fw_dbg_conf_usniffer(const struct iwl_fw *fw, u8 id) { - const struct iwl_fw_dbg_conf_tlv *conf_tlv = fw->dbg_conf_tlv[id]; + const struct iwl_fw_dbg_conf_tlv *conf_tlv = fw->dbg.conf_tlv[id]; if (!conf_tlv) return false; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 9ed5819defaf..6b95d0e75889 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -71,6 +71,7 @@ struct iwl_fw_runtime_ops { int (*dump_start)(void *ctx); void (*dump_end)(void *ctx); bool (*fw_running)(void *ctx); + int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd); }; #define MAX_NUM_LMAC 2 @@ -88,6 +89,7 @@ struct iwl_fwrt_shared_mem_cfg { enum iwl_fw_runtime_status { IWL_FWRT_STATUS_DUMPING = 0, + IWL_FWRT_STATUS_WAIT_ALIVE, }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h index 2cc6c019d0e1..420e6d745f77 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h @@ -30,38 +30,20 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM iwlwifi_data -TRACE_EVENT(iwlwifi_dev_tx_data, - TP_PROTO(const struct device *dev, - struct sk_buff *skb, u8 hdr_len), - TP_ARGS(dev, skb, hdr_len), +TRACE_EVENT(iwlwifi_dev_tx_tb, + TP_PROTO(const struct device *dev, struct sk_buff *skb, + u8 *data_src, size_t data_len), + TP_ARGS(dev, skb, data_src, data_len), TP_STRUCT__entry( DEV_ENTRY __dynamic_array(u8, data, - iwl_trace_data(skb) ? skb->len - hdr_len : 0) + iwl_trace_data(skb) ? data_len : 0) ), TP_fast_assign( DEV_ASSIGN; if (iwl_trace_data(skb)) - skb_copy_bits(skb, hdr_len, - __get_dynamic_array(data), - skb->len - hdr_len); - ), - TP_printk("[%s] TX frame data", __get_str(dev)) -); - -TRACE_EVENT(iwlwifi_dev_tx_tso_chunk, - TP_PROTO(const struct device *dev, - u8 *data_src, size_t data_len), - TP_ARGS(dev, data_src, data_len), - TP_STRUCT__entry( - DEV_ENTRY - - __dynamic_array(u8, data, data_len) - ), - TP_fast_assign( - DEV_ASSIGN; - memcpy(__get_dynamic_array(data), data_src, data_len); + memcpy(__get_dynamic_array(data), data_src, data_len); ), TP_printk("[%s] TX frame data", __get_str(dev)) ); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index d3a60d1aacb5..ba41d23b4211 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -168,12 +168,12 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) { int i; - kfree(drv->fw.dbg_dest_tlv); - for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++) - kfree(drv->fw.dbg_conf_tlv[i]); - for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) - kfree(drv->fw.dbg_trigger_tlv[i]); - kfree(drv->fw.dbg_mem_tlv); + kfree(drv->fw.dbg.dest_tlv); + for (i = 0; i < ARRAY_SIZE(drv->fw.dbg.conf_tlv); i++) + kfree(drv->fw.dbg.conf_tlv[i]); + for (i = 0; i < ARRAY_SIZE(drv->fw.dbg.trigger_tlv); i++) + kfree(drv->fw.dbg.trigger_tlv[i]); + kfree(drv->fw.dbg.mem_tlv); kfree(drv->fw.iml); for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) @@ -303,7 +303,7 @@ struct iwl_firmware_pieces { struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX]; size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX]; struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv; - size_t n_dbg_mem_tlv; + size_t n_mem_tlv; }; /* @@ -936,7 +936,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, IWL_INFO(drv, "Found debug destination: %s\n", get_fw_dbg_mode_string(mon_mode)); - drv->fw.dbg_dest_reg_num = (dest_v1) ? + drv->fw.dbg.n_dest_reg = (dest_v1) ? tlv_len - offsetof(struct iwl_fw_dbg_dest_tlv_v1, reg_ops) : @@ -944,8 +944,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, offsetof(struct iwl_fw_dbg_dest_tlv, reg_ops); - drv->fw.dbg_dest_reg_num /= - sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]); + drv->fw.dbg.n_dest_reg /= + sizeof(drv->fw.dbg.dest_tlv->reg_ops[0]); break; } @@ -959,7 +959,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, break; } - if (conf->id >= ARRAY_SIZE(drv->fw.dbg_conf_tlv)) { + if (conf->id >= ARRAY_SIZE(drv->fw.dbg.conf_tlv)) { IWL_ERR(drv, "Skip unknown configuration: %d\n", conf->id); @@ -988,7 +988,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, (void *)tlv_data; u32 trigger_id = le32_to_cpu(trigger->id); - if (trigger_id >= ARRAY_SIZE(drv->fw.dbg_trigger_tlv)) { + if (trigger_id >= ARRAY_SIZE(drv->fw.dbg.trigger_tlv)) { IWL_ERR(drv, "Skip unknown trigger: %u\n", trigger->id); @@ -1015,7 +1015,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, break; } - drv->fw.dbg_dump_mask = + drv->fw.dbg.dump_mask = le32_to_cpup((__le32 *)tlv_data); break; } @@ -1070,13 +1070,13 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, dbg_mem->data_type); size = sizeof(*pieces->dbg_mem_tlv) * - (pieces->n_dbg_mem_tlv + 1); + (pieces->n_mem_tlv + 1); n = krealloc(pieces->dbg_mem_tlv, size, GFP_KERNEL); if (!n) return -ENOMEM; pieces->dbg_mem_tlv = n; - pieces->dbg_mem_tlv[pieces->n_dbg_mem_tlv] = *dbg_mem; - pieces->n_dbg_mem_tlv++; + pieces->dbg_mem_tlv[pieces->n_mem_tlv] = *dbg_mem; + pieces->n_mem_tlv++; break; } case IWL_UCODE_TLV_IML: { @@ -1256,7 +1256,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS; /* dump all fw memory areas by default except d3 debug data */ - fw->dbg_dump_mask = 0xfffdffff; + fw->dbg.dump_mask = 0xfffdffff; pieces = kzalloc(sizeof(*pieces), GFP_KERNEL); if (!pieces) @@ -1323,21 +1323,21 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) goto out_free_fw; if (pieces->dbg_dest_tlv_init) { - size_t dbg_dest_size = sizeof(*drv->fw.dbg_dest_tlv) + - sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]) * - drv->fw.dbg_dest_reg_num; + size_t dbg_dest_size = sizeof(*drv->fw.dbg.dest_tlv) + + sizeof(drv->fw.dbg.dest_tlv->reg_ops[0]) * + drv->fw.dbg.n_dest_reg; - drv->fw.dbg_dest_tlv = kmalloc(dbg_dest_size, GFP_KERNEL); + drv->fw.dbg.dest_tlv = kmalloc(dbg_dest_size, GFP_KERNEL); - if (!drv->fw.dbg_dest_tlv) + if (!drv->fw.dbg.dest_tlv) goto out_free_fw; if (*pieces->dbg_dest_ver == 0) { - memcpy(drv->fw.dbg_dest_tlv, pieces->dbg_dest_tlv_v1, + memcpy(drv->fw.dbg.dest_tlv, pieces->dbg_dest_tlv_v1, dbg_dest_size); } else { struct iwl_fw_dbg_dest_tlv_v1 *dest_tlv = - drv->fw.dbg_dest_tlv; + drv->fw.dbg.dest_tlv; dest_tlv->version = pieces->dbg_dest_tlv->version; dest_tlv->monitor_mode = @@ -1352,8 +1352,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) pieces->dbg_dest_tlv->base_shift; memcpy(dest_tlv->reg_ops, pieces->dbg_dest_tlv->reg_ops, - sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]) * - drv->fw.dbg_dest_reg_num); + sizeof(drv->fw.dbg.dest_tlv->reg_ops[0]) * + drv->fw.dbg.n_dest_reg); /* In version 1 of the destination tlv, which is * relevant for internal buffer exclusively, @@ -1369,15 +1369,13 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) } } - for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++) { + for (i = 0; i < ARRAY_SIZE(drv->fw.dbg.conf_tlv); i++) { if (pieces->dbg_conf_tlv[i]) { - drv->fw.dbg_conf_tlv_len[i] = - pieces->dbg_conf_tlv_len[i]; - drv->fw.dbg_conf_tlv[i] = + drv->fw.dbg.conf_tlv[i] = kmemdup(pieces->dbg_conf_tlv[i], - drv->fw.dbg_conf_tlv_len[i], + pieces->dbg_conf_tlv_len[i], GFP_KERNEL); - if (!drv->fw.dbg_conf_tlv[i]) + if (!pieces->dbg_conf_tlv_len[i]) goto out_free_fw; } } @@ -1404,7 +1402,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) trigger_tlv_sz[FW_DBG_TRIGGER_TDLS] = sizeof(struct iwl_fw_dbg_trigger_tdls); - for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) { + for (i = 0; i < ARRAY_SIZE(drv->fw.dbg.trigger_tlv); i++) { if (pieces->dbg_trigger_tlv[i]) { /* * If the trigger isn't long enough, WARN and exit. @@ -1417,22 +1415,22 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) (trigger_tlv_sz[i] + sizeof(struct iwl_fw_dbg_trigger_tlv)))) goto out_free_fw; - drv->fw.dbg_trigger_tlv_len[i] = + drv->fw.dbg.trigger_tlv_len[i] = pieces->dbg_trigger_tlv_len[i]; - drv->fw.dbg_trigger_tlv[i] = + drv->fw.dbg.trigger_tlv[i] = kmemdup(pieces->dbg_trigger_tlv[i], - drv->fw.dbg_trigger_tlv_len[i], + drv->fw.dbg.trigger_tlv_len[i], GFP_KERNEL); - if (!drv->fw.dbg_trigger_tlv[i]) + if (!drv->fw.dbg.trigger_tlv[i]) goto out_free_fw; } } /* Now that we can no longer fail, copy information */ - drv->fw.dbg_mem_tlv = pieces->dbg_mem_tlv; + drv->fw.dbg.mem_tlv = pieces->dbg_mem_tlv; pieces->dbg_mem_tlv = NULL; - drv->fw.n_dbg_mem_tlv = pieces->n_dbg_mem_tlv; + drv->fw.dbg.n_mem_tlv = pieces->n_mem_tlv; /* * The (size - 16) / 12 formula is based on the information recorded @@ -1473,6 +1471,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) break; default: WARN(1, "Invalid fw type %d\n", fw->type); + /* fall through */ case IWL_FW_MVM: op = &iwlwifi_opmode_table[MVM_OP_MODE]; break; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index ec300d388694..96e101d79662 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1335,6 +1335,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, bool lar_fw_supported = !iwlwifi_mod_params.lar_disable && fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_LAR_SUPPORT); + bool empty_otp; u32 mac_flags; u32 sbands_flags = 0; @@ -1350,7 +1351,9 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, } rsp = (void *)hcmd.resp_pkt->data; - if (le32_to_cpu(rsp->general.flags) & NVM_GENERAL_FLAGS_EMPTY_OTP) + empty_otp = !!(le32_to_cpu(rsp->general.flags) & + NVM_GENERAL_FLAGS_EMPTY_OTP); + if (empty_otp) IWL_INFO(trans, "OTP is empty\n"); nvm = kzalloc(sizeof(*nvm) + @@ -1374,6 +1377,11 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, /* Initialize general data */ nvm->nvm_version = le16_to_cpu(rsp->general.nvm_version); + nvm->n_hw_addrs = rsp->general.n_hw_addrs; + if (nvm->n_hw_addrs == 0) + IWL_WARN(trans, + "Firmware declares no reserved mac addresses. OTP is empty: %d\n", + empty_otp); /* Initialize MAC sku data */ mac_flags = le32_to_cpu(rsp->mac_sku.mac_sku_flags); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 6c636b2a6b43..26b3c73051ca 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -725,7 +725,7 @@ struct iwl_dram_data { * @dbg_dest_tlv: points to the destination TLV for debug * @dbg_conf_tlv: array of pointers to configuration TLVs for debug * @dbg_trigger_tlv: array of pointers to triggers TLVs for debug - * @dbg_dest_reg_num: num of reg_ops in %dbg_dest_tlv + * @dbg_n_dest_reg: num of reg_ops in %dbg_dest_tlv * @num_blocks: number of blocks in fw_mon * @fw_mon: address of the buffers for firmware monitor * @system_pm_mode: the system-wide power management mode in use. @@ -778,7 +778,7 @@ struct iwl_trans { const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX]; struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv; u32 dbg_dump_mask; - u8 dbg_dest_reg_num; + u8 dbg_n_dest_reg; int num_blocks; struct iwl_dram_data fw_mon[IWL_MAX_DEBUG_ALLOCATIONS]; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 210be26aadaa..843f3b41b72e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -722,8 +722,10 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm, { struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; + bool unified = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); struct wowlan_key_data key_data = { - .configure_keys = !d0i3, + .configure_keys = !d0i3 && !unified, .use_rsc_tsc = false, .tkip = &tkip_cmd, .use_tkip = false, @@ -1636,32 +1638,10 @@ out_free_resp: } static struct iwl_wowlan_status * -iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) +iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm) { - u32 base = mvm->error_event_table[0]; - struct error_table_start { - /* cf. struct iwl_error_event_table */ - u32 valid; - u32 error_id; - } err_info; int ret; - iwl_trans_read_mem_bytes(mvm->trans, base, - &err_info, sizeof(err_info)); - - if (err_info.valid) { - IWL_INFO(mvm, "error table is valid (%d) with error (%d)\n", - err_info.valid, err_info.error_id); - if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) { - struct cfg80211_wowlan_wakeup wakeup = { - .rfkill_release = true, - }; - ieee80211_report_wowlan_wakeup(vif, &wakeup, - GFP_KERNEL); - } - return ERR_PTR(-EIO); - } - /* only for tracing for now */ ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, 0, 0, NULL); if (ret) @@ -1680,7 +1660,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, bool keep; struct iwl_mvm_sta *mvm_ap_sta; - fw_status = iwl_mvm_get_wakeup_status(mvm, vif); + fw_status = iwl_mvm_get_wakeup_status(mvm); if (IS_ERR_OR_NULL(fw_status)) goto out_unlock; @@ -1805,7 +1785,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, u32 reasons = 0; int i, j, n_matches, ret; - fw_status = iwl_mvm_get_wakeup_status(mvm, vif); + fw_status = iwl_mvm_get_wakeup_status(mvm); if (!IS_ERR_OR_NULL(fw_status)) { reasons = le32_to_cpu(fw_status->wakeup_reasons); kfree(fw_status); @@ -1918,6 +1898,29 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, ieee80211_resume_disconnect(vif); } +static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) +{ + u32 base = mvm->error_event_table[0]; + struct error_table_start { + /* cf. struct iwl_error_event_table */ + u32 valid; + u32 error_id; + } err_info; + + iwl_trans_read_mem_bytes(mvm->trans, base, + &err_info, sizeof(err_info)); + + if (err_info.valid && + err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) { + struct cfg80211_wowlan_wakeup wakeup = { + .rfkill_release = true, + }; + ieee80211_report_wowlan_wakeup(vif, &wakeup, GFP_KERNEL); + } + return err_info.valid; +} + static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) { struct ieee80211_vif *vif = NULL; @@ -1949,6 +1952,15 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) /* query SRAM first in case we want event logging */ iwl_mvm_read_d3_sram(mvm); + if (iwl_mvm_check_rt_status(mvm, vif)) { + set_bit(STATUS_FW_ERROR, &mvm->trans->status); + iwl_mvm_dump_nic_error_log(mvm); + iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, + NULL, 0); + ret = 1; + goto err; + } + if (d0i3_first) { ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, 0, 0, NULL); if (ret < 0) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index de40752aa67e..3b6b3d8fb961 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -666,16 +666,11 @@ iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf, }; int ret, bt_force_ant_mode; - for (bt_force_ant_mode = 0; - bt_force_ant_mode < ARRAY_SIZE(modes_str); - bt_force_ant_mode++) { - if (!strcmp(buf, modes_str[bt_force_ant_mode])) - break; - } - - if (bt_force_ant_mode >= ARRAY_SIZE(modes_str)) - return -EINVAL; + ret = match_string(modes_str, ARRAY_SIZE(modes_str), buf); + if (ret < 0) + return ret; + bt_force_ant_mode = ret; ret = 0; mutex_lock(&mvm->mutex); if (mvm->bt_force_ant_mode == bt_force_ant_mode) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 96d26b749952..dade206d5511 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -299,6 +299,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img; static const u16 alive_cmd[] = { MVM_ALIVE }; + set_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status); if (ucode_type == IWL_UCODE_REGULAR && iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) && !(fw_has_capa(&mvm->fw->ucode_capa, @@ -363,12 +364,20 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, */ memset(&mvm->queue_info, 0, sizeof(mvm->queue_info)); - mvm->queue_info[IWL_MVM_DQA_CMD_QUEUE].hw_queue_refcount = 1; + /* + * Set a 'fake' TID for the command queue, since we use the + * hweight() of the tid_bitmap as a refcount now. Not that + * we ever even consider the command queue as one we might + * want to reuse, but be safe nevertheless. + */ + mvm->queue_info[IWL_MVM_DQA_CMD_QUEUE].tid_bitmap = + BIT(IWL_MAX_TID_COUNT + 2); for (i = 0; i < IEEE80211_MAX_QUEUES; i++) atomic_set(&mvm->mac80211_queue_stop_count[i], 0); set_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); + clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status); return 0; } @@ -699,8 +708,12 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm) enabled = !!(wifi_pkg->package.elements[1].integer.value); n_profiles = wifi_pkg->package.elements[2].integer.value; - /* in case of BIOS bug */ - if (n_profiles <= 0) { + /* + * Check the validity of n_profiles. The EWRD profiles start + * from index 1, so the maximum value allowed here is + * ACPI_SAR_PROFILES_NUM - 1. + */ + if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) { ret = -EINVAL; goto out_free; } @@ -1022,7 +1035,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) mvm->fwrt.dump.conf = FW_DBG_INVALID; /* if we have a destination, assume EARLY START */ - if (mvm->fw->dbg_dest_tlv) + if (mvm->fw->dbg.dest_tlv) mvm->fwrt.dump.conf = FW_DBG_START_FROM_ALIVE; iwl_fw_start_dbg_conf(&mvm->fwrt, FW_DBG_START_FROM_ALIVE); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 781f30356720..6486cfb33f40 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1487,12 +1487,11 @@ static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac, IWL_MVM_MISSED_BEACONS_THRESHOLD) ieee80211_beacon_loss(vif); - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, - FW_DBG_TRIGGER_MISSED_BEACONS)) + trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), + FW_DBG_TRIGGER_MISSED_BEACONS); + if (!trigger) return; - trigger = iwl_fw_dbg_get_trigger(mvm->fw, - FW_DBG_TRIGGER_MISSED_BEACONS); bcon_trig = (void *)trigger->data; stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon); stop_trig_missed_bcon_since_rx = @@ -1500,11 +1499,6 @@ static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac, /* TODO: implement start trigger */ - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(vif), - trigger)) - return; - if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx || rx_missed_bcon >= stop_trig_missed_bcon) iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index c78d017749d3..505b0385d800 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -857,16 +857,13 @@ iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_fw_dbg_trigger_tlv *trig; struct iwl_fw_dbg_trigger_ba *ba_trig; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), + FW_DBG_TRIGGER_BA); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA); ba_trig = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(vif), trig)) - return; - switch (action) { case IEEE80211_AMPDU_TX_OPERATIONAL: { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); @@ -1231,12 +1228,15 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) iwl_mvm_del_aux_sta(mvm); /* - * Clear IN_HW_RESTART flag when stopping the hw (as restart_complete() - * won't be called in this case). + * Clear IN_HW_RESTART and HW_RESTART_REQUESTED flag when stopping the + * hw (as restart_complete() won't be called in this case) and mac80211 + * won't execute the restart. * But make sure to cleanup interfaces that have gone down before/during * HW restart was requested. */ - if (test_and_clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) + if (test_and_clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) || + test_and_clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status)) ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm); @@ -2802,14 +2802,12 @@ iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm, struct iwl_fw_dbg_trigger_tlv *trig; struct iwl_fw_dbg_trigger_tdls *tdls_trig; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TDLS)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), + FW_DBG_TRIGGER_TDLS); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TDLS); tdls_trig = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(vif), trig)) - return; if (!(tdls_trig->action_bitmap & BIT(action))) return; @@ -4491,14 +4489,12 @@ static void iwl_mvm_event_mlme_callback(struct iwl_mvm *mvm, struct iwl_fw_dbg_trigger_tlv *trig; struct iwl_fw_dbg_trigger_mlme *trig_mlme; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), + FW_DBG_TRIGGER_MLME); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME); trig_mlme = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(vif), trig)) - return; if (event->u.mlme.data == ASSOC_EVENT) { if (event->u.mlme.status == MLME_DENIED) @@ -4533,14 +4529,12 @@ static void iwl_mvm_event_bar_rx_callback(struct iwl_mvm *mvm, struct iwl_fw_dbg_trigger_tlv *trig; struct iwl_fw_dbg_trigger_ba *ba_trig; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), + FW_DBG_TRIGGER_BA); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA); ba_trig = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(vif), trig)) - return; if (!(le16_to_cpu(ba_trig->rx_bar) & BIT(event->u.ba.tid))) return; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 8f71eeed50d9..7ba5bc2ed1c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -512,6 +512,7 @@ enum iwl_mvm_scan_type { IWL_SCAN_TYPE_WILD, IWL_SCAN_TYPE_MILD, IWL_SCAN_TYPE_FRAGMENTED, + IWL_SCAN_TYPE_FAST_BALANCE, }; enum iwl_mvm_sched_scan_pass_all_states { @@ -753,24 +754,12 @@ iwl_mvm_baid_data_from_reorder_buf(struct iwl_mvm_reorder_buffer *buf) * This is a state in which a single queue serves more than one TID, all of * which are not aggregated. Note that the queue is only associated to one * RA. - * @IWL_MVM_QUEUE_INACTIVE: queue is allocated but no traffic on it - * This is a state of a queue that has had traffic on it, but during the - * last %IWL_MVM_DQA_QUEUE_TIMEOUT time period there has been no traffic on - * it. In this state, when a new queue is needed to be allocated but no - * such free queue exists, an inactive queue might be freed and given to - * the new RA/TID. - * @IWL_MVM_QUEUE_RECONFIGURING: queue is being reconfigured - * This is the state of a queue that has had traffic pass through it, but - * needs to be reconfigured for some reason, e.g. the queue needs to - * become unshared and aggregations re-enabled on. */ enum iwl_mvm_queue_status { IWL_MVM_QUEUE_FREE, IWL_MVM_QUEUE_RESERVED, IWL_MVM_QUEUE_READY, IWL_MVM_QUEUE_SHARED, - IWL_MVM_QUEUE_INACTIVE, - IWL_MVM_QUEUE_RECONFIGURING, }; #define IWL_MVM_DQA_QUEUE_TIMEOUT (5 * HZ) @@ -787,6 +776,17 @@ struct iwl_mvm_geo_profile { u8 values[ACPI_GEO_TABLE_SIZE]; }; +struct iwl_mvm_dqa_txq_info { + u8 ra_sta_id; /* The RA this queue is mapped to, if exists */ + bool reserved; /* Is this the TXQ reserved for a STA */ + u8 mac80211_ac; /* The mac80211 AC this queue is mapped to */ + u8 txq_tid; /* The TID "owner" of this queue*/ + u16 tid_bitmap; /* Bitmap of the TIDs mapped to this queue */ + /* Timestamp for inactivation per TID of this queue */ + unsigned long last_frame_time[IWL_MAX_TID_COUNT + 1]; + enum iwl_mvm_queue_status status; +}; + struct iwl_mvm { /* for logger access */ struct device *dev; @@ -843,17 +843,7 @@ struct iwl_mvm { u16 hw_queue_to_mac80211[IWL_MAX_TVQM_QUEUES]; - struct { - u8 hw_queue_refcount; - u8 ra_sta_id; /* The RA this queue is mapped to, if exists */ - bool reserved; /* Is this the TXQ reserved for a STA */ - u8 mac80211_ac; /* The mac80211 AC this queue is mapped to */ - u8 txq_tid; /* The TID "owner" of this queue*/ - u16 tid_bitmap; /* Bitmap of the TIDs mapped to this queue */ - /* Timestamp for inactivation per TID of this queue */ - unsigned long last_frame_time[IWL_MAX_TID_COUNT + 1]; - enum iwl_mvm_queue_status status; - } queue_info[IWL_MAX_HW_QUEUES]; + struct iwl_mvm_dqa_txq_info queue_info[IWL_MAX_HW_QUEUES]; spinlock_t queue_info_lock; /* For syncing queue mgmt operations */ struct work_struct add_stream_wk; /* To add streams to queues */ @@ -1883,17 +1873,6 @@ void iwl_mvm_vif_set_low_latency(struct iwl_mvm_vif *mvmvif, bool set, mvmvif->low_latency &= ~cause; } -/* hw scheduler queue config */ -bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, - u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg, - unsigned int wdg_timeout); -int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue, - u8 sta_id, u8 tid, unsigned int timeout); - -int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, - u8 tid, u8 flags); -int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq); - /* Return a bitmask with all the hw supported queues, except for the * command queue, which can't be flushed. */ @@ -1905,6 +1884,11 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm) static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) { + lockdep_assert_held(&mvm->mutex); + /* calling this function without using dump_start/end since at this + * point we already hold the op mode mutex + */ + iwl_fw_dbg_collect_sync(&mvm->fwrt); iwl_fw_cancel_timestamp(&mvm->fwrt); iwl_free_fw_paging(&mvm->fwrt); clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); @@ -1990,8 +1974,6 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t); struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); bool iwl_mvm_is_vif_assoc(struct iwl_mvm *mvm); -void iwl_mvm_inactivity_check(struct iwl_mvm *mvm); - #define MVM_TCM_PERIOD_MSEC 500 #define MVM_TCM_PERIOD (HZ * MVM_TCM_PERIOD_MSEC / 1000) #define MVM_LL_PERIOD (10 * HZ) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index fff98fed35ed..3633f27d048a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -477,15 +477,11 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, u32 status; int resp_len, n_channels; u16 mcc; - bool resp_v2 = fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2); if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm))) return ERR_PTR(-EOPNOTSUPP); cmd.len[0] = sizeof(struct iwl_mcc_update_cmd); - if (!resp_v2) - cmd.len[0] = sizeof(struct iwl_mcc_update_cmd_v1); IWL_DEBUG_LAR(mvm, "send MCC update to FW with '%c%c' src = %d\n", alpha2[0], alpha2[1], src_id); @@ -497,7 +493,8 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, pkt = cmd.resp_pkt; /* Extract MCC response */ - if (resp_v2) { + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) { struct iwl_mcc_update_resp *mcc_resp = (void *)pkt->data; n_channels = __le32_to_cpu(mcc_resp->n_channels); @@ -509,9 +506,9 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, goto exit; } } else { - struct iwl_mcc_update_resp_v1 *mcc_resp_v1 = (void *)pkt->data; + struct iwl_mcc_update_resp_v3 *mcc_resp_v3 = (void *)pkt->data; - n_channels = __le32_to_cpu(mcc_resp_v1->n_channels); + n_channels = __le32_to_cpu(mcc_resp_v3->n_channels); resp_len = sizeof(struct iwl_mcc_update_resp) + n_channels * sizeof(__le32); resp_cp = kzalloc(resp_len, GFP_KERNEL); @@ -520,12 +517,14 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, goto exit; } - resp_cp->status = mcc_resp_v1->status; - resp_cp->mcc = mcc_resp_v1->mcc; - resp_cp->cap = mcc_resp_v1->cap; - resp_cp->source_id = mcc_resp_v1->source_id; - resp_cp->n_channels = mcc_resp_v1->n_channels; - memcpy(resp_cp->channels, mcc_resp_v1->channels, + resp_cp->status = mcc_resp_v3->status; + resp_cp->mcc = mcc_resp_v3->mcc; + resp_cp->cap = cpu_to_le16(mcc_resp_v3->cap); + resp_cp->source_id = mcc_resp_v3->source_id; + resp_cp->time = mcc_resp_v3->time; + resp_cp->geo_info = mcc_resp_v3->geo_info; + resp_cp->n_channels = mcc_resp_v3->n_channels; + memcpy(resp_cp->channels, mcc_resp_v3->channels, n_channels * sizeof(__le32)); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 0599d323cbeb..0e2092526fae 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -565,10 +565,23 @@ static bool iwl_mvm_fwrt_fw_running(void *ctx) return iwl_mvm_firmware_running(ctx); } +static int iwl_mvm_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd) +{ + struct iwl_mvm *mvm = (struct iwl_mvm *)ctx; + int ret; + + mutex_lock(&mvm->mutex); + ret = iwl_mvm_send_cmd(mvm, host_cmd); + mutex_unlock(&mvm->mutex); + + return ret; +} + static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = { .dump_start = iwl_mvm_fwrt_dump_start, .dump_end = iwl_mvm_fwrt_dump_end, .fw_running = iwl_mvm_fwrt_fw_running, + .send_hcmd = iwl_mvm_fwrt_send_hcmd, }; static struct iwl_op_mode * @@ -604,9 +617,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, if (cfg->max_rx_agg_size) hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size; + else + hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; if (cfg->max_tx_agg_size) hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size; + else + hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; op_mode = hw->priv; @@ -748,12 +765,12 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, iwl_trans_configure(mvm->trans, &trans_cfg); trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD; - trans->dbg_dest_tlv = mvm->fw->dbg_dest_tlv; - trans->dbg_dest_reg_num = mvm->fw->dbg_dest_reg_num; - memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv, + trans->dbg_dest_tlv = mvm->fw->dbg.dest_tlv; + trans->dbg_n_dest_reg = mvm->fw->dbg.n_dest_reg; + memcpy(trans->dbg_conf_tlv, mvm->fw->dbg.conf_tlv, sizeof(trans->dbg_conf_tlv)); - trans->dbg_trigger_tlv = mvm->fw->dbg_trigger_tlv; - trans->dbg_dump_mask = mvm->fw->dbg_dump_mask; + trans->dbg_trigger_tlv = mvm->fw->dbg.trigger_tlv; + trans->dbg_dump_mask = mvm->fw->dbg.dump_mask; trans->iml = mvm->fw->iml; trans->iml_len = mvm->fw->iml_len; @@ -784,6 +801,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, mutex_lock(&mvm->mutex); iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE); err = iwl_run_init_mvm_ucode(mvm, true); + if (test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status)) + iwl_fw_alive_error_dump(&mvm->fwrt); if (!iwlmvm_mod_params.init_dbg || !err) iwl_mvm_stop_device(mvm); iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE); @@ -953,15 +972,13 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm, struct iwl_fw_dbg_trigger_cmd *cmds_trig; int i; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_FW_NOTIF)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL, + FW_DBG_TRIGGER_FW_NOTIF); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_FW_NOTIF); cmds_trig = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig)) - return; - for (i = 0; i < ARRAY_SIZE(cmds_trig->cmds); i++) { /* don't collect on CMD 0 */ if (!cmds_trig->cmds[i].cmd_id) @@ -1223,7 +1240,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) */ if (!mvm->fw_restart && fw_error) { iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, - NULL); + NULL, 0); } else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { struct iwl_mvm_reprobe *reprobe; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 2c75f51a04e4..089972280daa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -1239,7 +1239,11 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, !(info->flags & IEEE80211_TX_STAT_AMPDU)) return; - rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate); + if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, + &tx_resp_rate)) { + WARN_ON_ONCE(1); + return; + } #ifdef CONFIG_MAC80211_DEBUGFS /* Disable last tx check if we are debugging with fixed rate but @@ -1290,7 +1294,10 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, */ table = &lq_sta->lq; lq_hwrate = le32_to_cpu(table->rs_table[0]); - rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate); + if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) { + WARN_ON_ONCE(1); + return; + } /* Here we actually compare this rate to the latest LQ command */ if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) { @@ -1392,8 +1399,12 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, /* Collect data for each rate used during failed TX attempts */ for (i = 0; i <= retries; ++i) { lq_hwrate = le32_to_cpu(table->rs_table[i]); - rs_rate_from_ucode_rate(lq_hwrate, info->band, - &lq_rate); + if (rs_rate_from_ucode_rate(lq_hwrate, info->band, + &lq_rate)) { + WARN_ON_ONCE(1); + return; + } + /* * Only collect stats if retried rate is in the same RS * table as active/search. @@ -3260,7 +3271,10 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm, for (i = 0; i < num_rates; i++) lq_cmd->rs_table[i] = ucode_rate_le32; - rs_rate_from_ucode_rate(ucode_rate, band, &rate); + if (rs_rate_from_ucode_rate(ucode_rate, band, &rate)) { + WARN_ON_ONCE(1); + return; + } if (is_mimo(&rate)) lq_cmd->mimo_delim = num_rates - 1; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index a050220da678..ef624833cf1b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -433,13 +433,14 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct ieee80211_vif *tx_blocked_vif = rcu_dereference(mvm->csa_tx_blocked_vif); + struct iwl_fw_dbg_trigger_tlv *trig; + struct ieee80211_vif *vif = mvmsta->vif; /* We have tx blocked stations (with CS bit). If we heard * frames from a blocked station on a new channel we can * TX to it again. */ - if (unlikely(tx_blocked_vif) && - mvmsta->vif == tx_blocked_vif) { + if (unlikely(tx_blocked_vif) && vif == tx_blocked_vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(tx_blocked_vif); @@ -450,23 +451,18 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, rs_update_last_rssi(mvm, mvmsta, rx_status); - if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) && - ieee80211_is_beacon(hdr->frame_control)) { - struct iwl_fw_dbg_trigger_tlv *trig; + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, + ieee80211_vif_to_wdev(vif), + FW_DBG_TRIGGER_RSSI); + + if (trig && ieee80211_is_beacon(hdr->frame_control)) { struct iwl_fw_dbg_trigger_low_rssi *rssi_trig; - bool trig_check; s32 rssi; - trig = iwl_fw_dbg_get_trigger(mvm->fw, - FW_DBG_TRIGGER_RSSI); rssi_trig = (void *)trig->data; rssi = le32_to_cpu(rssi_trig->rssi); - trig_check = - iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(mvmsta->vif), - trig); - if (trig_check && rx_status->signal < rssi) + if (rx_status->signal < rssi) iwl_fw_dbg_collect_trig(&mvm->fwrt, trig, NULL); } @@ -693,15 +689,12 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) struct iwl_fw_dbg_trigger_stats *trig_stats; u32 trig_offset, trig_thold; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_STATS)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL, FW_DBG_TRIGGER_STATS); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_STATS); trig_stats = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig)) - return; - trig_offset = le32_to_cpu(trig_stats->stop_offset); trig_thold = le32_to_cpu(trig_stats->stop_threshold); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 894dd6379b9a..26ac9402568d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -923,6 +923,185 @@ static void iwl_mvm_decode_he_sigb(struct iwl_mvm *mvm, } } +static void +iwl_mvm_decode_he_phy_ru_alloc(u64 he_phy_data, u32 rate_n_flags, + struct ieee80211_radiotap_he *he, + struct ieee80211_radiotap_he_mu *he_mu, + struct ieee80211_rx_status *rx_status) +{ + /* + * Unfortunately, we have to leave the mac80211 data + * incorrect for the case that we receive an HE-MU + * transmission and *don't* have the HE phy data (due + * to the bits being used for TSF). This shouldn't + * happen though as management frames where we need + * the TSF/timers are not be transmitted in HE-MU. + */ + u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data); + u8 offs = 0; + + rx_status->bw = RATE_INFO_BW_HE_RU; + + he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN); + + switch (ru) { + case 0 ... 36: + rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; + offs = ru; + break; + case 37 ... 52: + rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; + offs = ru - 37; + break; + case 53 ... 60: + rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; + offs = ru - 53; + break; + case 61 ... 64: + rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; + offs = ru - 61; + break; + case 65 ... 66: + rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; + offs = ru - 65; + break; + case 67: + rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; + break; + case 68: + rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; + break; + } + he->data2 |= le16_encode_bits(offs, + IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); + he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN | + IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN); + if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80) + he->data2 |= + cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC); + + if (he_mu) { +#define CHECK_BW(bw) \ + BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \ + RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS) + CHECK_BW(20); + CHECK_BW(40); + CHECK_BW(80); + CHECK_BW(160); + he_mu->flags2 |= + le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, + rate_n_flags), + IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW); + } +} + +static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, + struct iwl_rx_mpdu_desc *desc, + struct ieee80211_radiotap_he *he, + struct ieee80211_radiotap_he_mu *he_mu, + struct ieee80211_rx_status *rx_status, + u64 he_phy_data, u32 rate_n_flags, + int queue) +{ + u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; + bool sigb_data; + u16 d1known = IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN | + IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN | + IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN | + IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN | + IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN; + u16 d2known = IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN | + IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN | + IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN; + + he->data1 |= cpu_to_le16(d1known); + he->data2 |= cpu_to_le16(d2known); + he->data3 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_BSS_COLOR_MASK, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR); + he->data3 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_UPLINK, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA3_UL_DL); + he->data3 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_LDPC_EXT_SYM, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG); + he->data4 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_SPATIAL_REUSE_MASK, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE); + he->data5 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_PRE_FEC_PAD_MASK, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD); + he->data5 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_PE_DISAMBIG, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG); + he->data6 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_TXOP_DUR_MASK, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA6_TXOP); + he->data6 |= le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_DOPPLER, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA6_DOPPLER); + + switch (he_type) { + case RATE_MCS_HE_TYPE_MU: + he_mu->flags1 |= + le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_DCM, + he_phy_data), + IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM); + he_mu->flags1 |= + le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_MCS_MASK, + he_phy_data), + IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS); + he_mu->flags2 |= + le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIBG_SYM_OR_USER_NUM_MASK, + he_phy_data), + IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS); + he_mu->flags2 |= + le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_COMPRESSION, + he_phy_data), + IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP); + he_mu->flags2 |= + le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_PREAMBLE_PUNC_TYPE_MASK, + he_phy_data), + IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW); + + sigb_data = FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, + he_phy_data) == + IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO; + if (sigb_data) + iwl_mvm_decode_he_sigb(mvm, desc, rate_n_flags, he_mu); + /* fall through */ + case RATE_MCS_HE_TYPE_TRIG: + he->data2 |= + cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN); + he->data5 |= + le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_HE_LTF_NUM_MASK, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS); + break; + case RATE_MCS_HE_TYPE_SU: + case RATE_MCS_HE_TYPE_EXT_SU: + he->data1 |= + cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN); + he->data3 |= + le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_BEAM_CHNG, + he_phy_data), + IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE); + break; + } + + switch (FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data)) { + case IWL_RX_HE_PHY_INFO_TYPE_MU: + case IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO: + case IWL_RX_HE_PHY_INFO_TYPE_TB: + iwl_mvm_decode_he_phy_ru_alloc(he_phy_data, rate_n_flags, + he, he_mu, rx_status); + break; + default: + /* nothing */ + break; + } +} + static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, struct iwl_rx_mpdu_desc *desc, u32 rate_n_flags, u16 phy_info, int queue) @@ -933,9 +1112,8 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, u64 he_phy_data = HE_PHY_DATA_INVAL; struct ieee80211_radiotap_he *he = NULL; struct ieee80211_radiotap_he_mu *he_mu = NULL; - u32 he_type = 0xffffffff; + u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; u8 stbc, ltf; - static const struct ieee80211_radiotap_he known = { .data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN | IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN | @@ -953,25 +1131,19 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), }; unsigned int radiotap_len = 0; - bool overload = phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD; - bool sigb_data = false; he = skb_put_data(skb, &known, sizeof(known)); radiotap_len += sizeof(known); rx_status->flag |= RX_FLAG_RADIOTAP_HE; - he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; - if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) { - if (mvm->trans->cfg->device_family >= - IWL_DEVICE_FAMILY_22560) + if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) he_phy_data = le64_to_cpu(desc->v3.he_phy_data); else he_phy_data = le64_to_cpu(desc->v1.he_phy_data); if (he_type == RATE_MCS_HE_TYPE_MU) { - he_mu = skb_put_data(skb, &mu_known, - sizeof(mu_known)); + he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known)); radiotap_len += sizeof(mu_known); rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU; } @@ -980,60 +1152,21 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, /* temporarily hide the radiotap data */ __skb_pull(skb, radiotap_len); - if (overload && he_type == RATE_MCS_HE_TYPE_SU) { - he->data1 |= - cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN); - if (FIELD_GET(IWL_RX_HE_PHY_UPLINK, he_phy_data)) - he->data3 |= - cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA3_UL_DL); - + if (he_phy_data != HE_PHY_DATA_INVAL && + he_type == RATE_MCS_HE_TYPE_SU) { + /* report the AMPDU-EOF bit on single frames */ if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) { rx_status->flag |= RX_FLAG_AMPDU_DETAILS; rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN; if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF, he_phy_data)) rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT; } - } else if (overload && he_mu && he_phy_data != HE_PHY_DATA_INVAL) { - he_mu->flags1 |= - le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIBG_SYM_OR_USER_NUM_MASK, - he_phy_data), - IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS); - he_mu->flags1 |= - le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_DCM, - he_phy_data), - IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM); - he_mu->flags1 |= - le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_MCS_MASK, - he_phy_data), - IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS); - he_mu->flags2 |= - le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_SIGB_COMPRESSION, - he_phy_data), - IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP); - he_mu->flags2 |= - le16_encode_bits(FIELD_GET(IWL_RX_HE_PHY_MU_PREAMBLE_PUNC_TYPE_MASK, - he_phy_data), - IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW); - - sigb_data = FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, - he_phy_data) == - IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO; - if (sigb_data) - iwl_mvm_decode_he_sigb(mvm, desc, rate_n_flags, he_mu); - } - if (he_phy_data != HE_PHY_DATA_INVAL && - (he_type == RATE_MCS_HE_TYPE_SU || - he_type == RATE_MCS_HE_TYPE_MU)) { - u8 bss_color = FIELD_GET(IWL_RX_HE_PHY_BSS_COLOR_MASK, - he_phy_data); - - if (bss_color) { - he->data1 |= - cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN); - he->data3 |= cpu_to_le16(bss_color); - } } + if (he_phy_data != HE_PHY_DATA_INVAL) + iwl_mvm_decode_he_phy_data(mvm, desc, he, he_mu, rx_status, + he_phy_data, rate_n_flags, queue); + /* update aggregation data for monitor sake on default queue */ if (!queue && (phy_info & IWL_RX_MPDU_PHY_AMPDU)) { bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE; @@ -1056,84 +1189,12 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; } - if (he_phy_data != HE_PHY_DATA_INVAL && - (FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data) == - IWL_RX_HE_PHY_INFO_TYPE_MU_EXT_INFO || - FIELD_GET(IWL_RX_HE_PHY_INFO_TYPE_MASK, he_phy_data) == - IWL_RX_HE_PHY_INFO_TYPE_TB_EXT_INFO)) { - /* - * Unfortunately, we have to leave the mac80211 data - * incorrect for the case that we receive an HE-MU - * transmission and *don't* have the HE phy data (due - * to the bits being used for TSF). This shouldn't - * happen though as management frames where we need - * the TSF/timers are not be transmitted in HE-MU. - */ - u8 ru = FIELD_GET(IWL_RX_HE_PHY_RU_ALLOC_MASK, he_phy_data); - u8 offs = 0; - - rx_status->bw = RATE_INFO_BW_HE_RU; - + /* actually data is filled in mac80211 */ + if (he_type == RATE_MCS_HE_TYPE_SU || + he_type == RATE_MCS_HE_TYPE_EXT_SU) he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN); - switch (ru) { - case 0 ... 36: - rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; - offs = ru; - break; - case 37 ... 52: - rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; - offs = ru - 37; - break; - case 53 ... 60: - rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; - offs = ru - 53; - break; - case 61 ... 64: - rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; - offs = ru - 61; - break; - case 65 ... 66: - rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; - offs = ru - 65; - break; - case 67: - rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; - break; - case 68: - rx_status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; - break; - } - he->data2 |= - le16_encode_bits(offs, - IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); - he->data2 |= - cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN | - IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN); - if (he_phy_data & IWL_RX_HE_PHY_RU_ALLOC_SEC80) - he->data2 |= - cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC); - - if (he_mu) { -#define CHECK_BW(bw) \ - BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \ - RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS) - CHECK_BW(20); - CHECK_BW(40); - CHECK_BW(80); - CHECK_BW(160); - he->data2 |= - le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, - rate_n_flags), - IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW); - } - } else if (he_type == RATE_MCS_HE_TYPE_SU || - he_type == RATE_MCS_HE_TYPE_EXT_SU) { - he->data1 |= - cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN); - } - stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS; rx_status->nss = ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> @@ -1202,9 +1263,8 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, he->data5 |= le16_encode_bits(ltf, IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); - switch (he_type) { - case RATE_MCS_HE_TYPE_SU: - case RATE_MCS_HE_TYPE_EXT_SU: { + if (he_type == RATE_MCS_HE_TYPE_SU || + he_type == RATE_MCS_HE_TYPE_EXT_SU) { u16 val; /* LTF syms correspond to streams */ @@ -1234,31 +1294,10 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, rx_status->nss); val = 0; } + he->data5 |= le16_encode_bits(val, IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS); - } - break; - case RATE_MCS_HE_TYPE_MU: { - u16 val; - - if (he_phy_data == HE_PHY_DATA_INVAL) - break; - - val = FIELD_GET(IWL_RX_HE_PHY_HE_LTF_NUM_MASK, - he_phy_data); - - he->data2 |= - cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN); - he->data5 |= - cpu_to_le16(FIELD_PREP( - IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS, - val)); - } - break; - case RATE_MCS_HE_TYPE_TRIG: - /* not supported */ - break; } } @@ -1424,6 +1463,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, u8 baid = (u8)((le32_to_cpu(desc->reorder_data) & IWL_RX_MPDU_REORDER_BAID_MASK) >> IWL_RX_MPDU_REORDER_BAID_SHIFT); + struct iwl_fw_dbg_trigger_tlv *trig; + struct ieee80211_vif *vif = mvmsta->vif; if (!mvm->tcm.paused && len >= sizeof(*hdr) && !is_multicast_ether_addr(hdr->addr1) && @@ -1436,8 +1477,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, * frames from a blocked station on a new channel we can * TX to it again. */ - if (unlikely(tx_blocked_vif) && - tx_blocked_vif == mvmsta->vif) { + if (unlikely(tx_blocked_vif) && tx_blocked_vif == vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(tx_blocked_vif); @@ -1448,23 +1488,18 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, rs_update_last_rssi(mvm, mvmsta, rx_status); - if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) && - ieee80211_is_beacon(hdr->frame_control)) { - struct iwl_fw_dbg_trigger_tlv *trig; + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, + ieee80211_vif_to_wdev(vif), + FW_DBG_TRIGGER_RSSI); + + if (trig && ieee80211_is_beacon(hdr->frame_control)) { struct iwl_fw_dbg_trigger_low_rssi *rssi_trig; - bool trig_check; s32 rssi; - trig = iwl_fw_dbg_get_trigger(mvm->fw, - FW_DBG_TRIGGER_RSSI); rssi_trig = (void *)trig->data; rssi = le32_to_cpu(rssi_trig->rssi); - trig_check = - iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(mvmsta->vif), - trig); - if (trig_check && rx_status->signal < rssi) + if (rx_status->signal < rssi) iwl_fw_dbg_collect_trig(&mvm->fwrt, trig, NULL); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index e9048a98e793..cfb784fea77b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -110,6 +110,10 @@ static struct iwl_mvm_scan_timing_params scan_timing[] = { .suspend_time = 95, .max_out_time = 44, }, + [IWL_SCAN_TYPE_FAST_BALANCE] = { + .suspend_time = 30, + .max_out_time = 37, + }, }; struct iwl_mvm_scan_params { @@ -235,8 +239,32 @@ iwl_mvm_get_traffic_load_band(struct iwl_mvm *mvm, enum nl80211_band band) return mvm->tcm.result.band_load[band]; } +struct iwl_is_dcm_with_go_iterator_data { + struct ieee80211_vif *current_vif; + bool is_dcm_with_p2p_go; +}; + +static void iwl_mvm_is_dcm_with_go_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_is_dcm_with_go_iterator_data *data = _data; + struct iwl_mvm_vif *other_mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm_vif *curr_mvmvif = + iwl_mvm_vif_from_mac80211(data->current_vif); + + /* exclude the given vif */ + if (vif == data->current_vif) + return; + + if (vif->type == NL80211_IFTYPE_AP && vif->p2p && + other_mvmvif->phy_ctxt && curr_mvmvif->phy_ctxt && + other_mvmvif->phy_ctxt->id != curr_mvmvif->phy_ctxt->id) + data->is_dcm_with_p2p_go = true; +} + static enum -iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device, +iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, enum iwl_mvm_traffic_load load, bool low_latency) { @@ -249,9 +277,30 @@ iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device, if (!global_cnt) return IWL_SCAN_TYPE_UNASSOC; - if ((load == IWL_MVM_TRAFFIC_HIGH || low_latency) && !p2p_device && - fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) - return IWL_SCAN_TYPE_FRAGMENTED; + if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_FRAGMENTED_SCAN)) { + if ((load == IWL_MVM_TRAFFIC_HIGH || low_latency) && + (!vif || vif->type != NL80211_IFTYPE_P2P_DEVICE)) + return IWL_SCAN_TYPE_FRAGMENTED; + + /* in case of DCM with GO where BSS DTIM interval < 220msec + * set all scan requests as fast-balance scan + * */ + if (vif && vif->type == NL80211_IFTYPE_STATION && + vif->bss_conf.dtim_period < 220) { + struct iwl_is_dcm_with_go_iterator_data data = { + .current_vif = vif, + .is_dcm_with_p2p_go = false, + }; + + ieee80211_iterate_active_interfaces_atomic(mvm->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_is_dcm_with_go_iterator, + &data); + if (data.is_dcm_with_p2p_go) + return IWL_SCAN_TYPE_FAST_BALANCE; + } + } if (load >= IWL_MVM_TRAFFIC_MEDIUM || low_latency) return IWL_SCAN_TYPE_MILD; @@ -260,7 +309,8 @@ iwl_mvm_scan_type _iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device, } static enum -iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device) +iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) { enum iwl_mvm_traffic_load load; bool low_latency; @@ -268,12 +318,12 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device) load = iwl_mvm_get_traffic_load(mvm); low_latency = iwl_mvm_low_latency(mvm); - return _iwl_mvm_get_scan_type(mvm, p2p_device, load, low_latency); + return _iwl_mvm_get_scan_type(mvm, vif, load, low_latency); } static enum iwl_mvm_scan_type iwl_mvm_get_scan_type_band(struct iwl_mvm *mvm, - bool p2p_device, + struct ieee80211_vif *vif, enum nl80211_band band) { enum iwl_mvm_traffic_load load; @@ -282,7 +332,7 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type_band(struct iwl_mvm *mvm, load = iwl_mvm_get_traffic_load_band(mvm, band); low_latency = iwl_mvm_low_latency_band(mvm, band); - return _iwl_mvm_get_scan_type(mvm, p2p_device, load, low_latency); + return _iwl_mvm_get_scan_type(mvm, vif, load, low_latency); } static int @@ -860,6 +910,12 @@ static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params) params->scan_plans[0].iterations == 1; } +static bool iwl_mvm_is_scan_fragmented(enum iwl_mvm_scan_type type) +{ + return (type == IWL_SCAN_TYPE_FRAGMENTED || + type == IWL_SCAN_TYPE_FAST_BALANCE); +} + static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params, struct ieee80211_vif *vif) @@ -872,7 +928,7 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0) flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION; - if (params->type == IWL_SCAN_TYPE_FRAGMENTED) + if (iwl_mvm_is_scan_fragmented(params->type)) flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED; if (iwl_mvm_rrm_scan_needed(mvm) && @@ -895,7 +951,7 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, if (iwl_mvm_is_regular_scan(params) && vif->type != NL80211_IFTYPE_P2P_DEVICE && - params->type != IWL_SCAN_TYPE_FRAGMENTED) + !iwl_mvm_is_scan_fragmented(params->type)) flags |= IWL_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL; return flags; @@ -1044,7 +1100,7 @@ static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels) static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config, u32 flags, u8 channel_flags) { - enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, false); + enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, NULL); struct iwl_scan_config_v1 *cfg = config; cfg->flags = cpu_to_le32(flags); @@ -1077,9 +1133,9 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config, if (iwl_mvm_is_cdb_supported(mvm)) { enum iwl_mvm_scan_type lb_type, hb_type; - lb_type = iwl_mvm_get_scan_type_band(mvm, false, + lb_type = iwl_mvm_get_scan_type_band(mvm, NULL, NL80211_BAND_2GHZ); - hb_type = iwl_mvm_get_scan_type_band(mvm, false, + hb_type = iwl_mvm_get_scan_type_band(mvm, NULL, NL80211_BAND_5GHZ); cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] = @@ -1093,7 +1149,7 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config, cpu_to_le32(scan_timing[hb_type].suspend_time); } else { enum iwl_mvm_scan_type type = - iwl_mvm_get_scan_type(mvm, false); + iwl_mvm_get_scan_type(mvm, NULL); cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] = cpu_to_le32(scan_timing[type].max_out_time); @@ -1130,14 +1186,14 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) return -ENOBUFS; if (iwl_mvm_is_cdb_supported(mvm)) { - type = iwl_mvm_get_scan_type_band(mvm, false, + type = iwl_mvm_get_scan_type_band(mvm, NULL, NL80211_BAND_2GHZ); - hb_type = iwl_mvm_get_scan_type_band(mvm, false, + hb_type = iwl_mvm_get_scan_type_band(mvm, NULL, NL80211_BAND_5GHZ); if (type == mvm->scan_type && hb_type == mvm->hb_scan_type) return 0; } else { - type = iwl_mvm_get_scan_type(mvm, false); + type = iwl_mvm_get_scan_type(mvm, NULL); if (type == mvm->scan_type) return 0; } @@ -1162,7 +1218,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) SCAN_CONFIG_FLAG_SET_MAC_ADDR | SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS | SCAN_CONFIG_N_CHANNELS(num_channels) | - (type == IWL_SCAN_TYPE_FRAGMENTED ? + (iwl_mvm_is_scan_fragmented(type) ? SCAN_CONFIG_FLAG_SET_FRAGMENTED : SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED); @@ -1177,7 +1233,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) */ if (iwl_mvm_cdb_scan_api(mvm)) { if (iwl_mvm_is_cdb_supported(mvm)) - flags |= (hb_type == IWL_SCAN_TYPE_FRAGMENTED) ? + flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ? SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED : SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED; iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags); @@ -1338,11 +1394,11 @@ static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, if (params->n_ssids == 1 && params->ssids[0].ssid_len != 0) flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT; - if (params->type == IWL_SCAN_TYPE_FRAGMENTED) + if (iwl_mvm_is_scan_fragmented(params->type)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED; if (iwl_mvm_is_cdb_supported(mvm) && - params->hb_type == IWL_SCAN_TYPE_FRAGMENTED) + iwl_mvm_is_scan_fragmented(params->hb_type)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED; if (iwl_mvm_rrm_scan_needed(mvm) && @@ -1380,7 +1436,7 @@ static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, */ if (iwl_mvm_is_regular_scan(params) && vif->type != NL80211_IFTYPE_P2P_DEVICE && - params->type != IWL_SCAN_TYPE_FRAGMENTED && + !iwl_mvm_is_scan_fragmented(params->type) && !iwl_mvm_is_adaptive_dwell_supported(mvm) && !iwl_mvm_is_oce_supported(mvm)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL; @@ -1448,6 +1504,9 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED) cmd->v8.num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; + + cmd->v8.general_flags2 = + IWL_UMAC_SCAN_GEN_FLAGS2_ALLOW_CHNL_REORDER; } cmd->scan_start_mac_id = scan_vif->id; @@ -1586,19 +1645,20 @@ void iwl_mvm_scan_timeout_wk(struct work_struct *work) static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params, - bool p2p) + struct ieee80211_vif *vif) { if (iwl_mvm_is_cdb_supported(mvm)) { params->type = - iwl_mvm_get_scan_type_band(mvm, p2p, + iwl_mvm_get_scan_type_band(mvm, vif, NL80211_BAND_2GHZ); params->hb_type = - iwl_mvm_get_scan_type_band(mvm, p2p, + iwl_mvm_get_scan_type_band(mvm, vif, NL80211_BAND_5GHZ); } else { - params->type = iwl_mvm_get_scan_type(mvm, p2p); + params->type = iwl_mvm_get_scan_type(mvm, vif); } } + int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct cfg80211_scan_request *req, struct ieee80211_scan_ies *ies) @@ -1646,8 +1706,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, params.scan_plans = &scan_plan; params.n_scan_plans = 1; - iwl_mvm_fill_scan_type(mvm, ¶ms, - vif->type == NL80211_IFTYPE_P2P_DEVICE); + iwl_mvm_fill_scan_type(mvm, ¶ms, vif); ret = iwl_mvm_get_measurement_dwell(mvm, req, ¶ms); if (ret < 0) @@ -1742,8 +1801,7 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, params.n_scan_plans = req->n_scan_plans; params.scan_plans = req->scan_plans; - iwl_mvm_fill_scan_type(mvm, ¶ms, - vif->type == NL80211_IFTYPE_P2P_DEVICE); + iwl_mvm_fill_scan_type(mvm, ¶ms, vif); /* In theory, LMAC scans can handle a 32-bit delay, but since * waiting for over 18 hours to start the scan is a bit silly diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 8f929c774e70..1887d2b9f185 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -358,6 +358,108 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue, return ret; } +static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, + int mac80211_queue, u8 tid, u8 flags) +{ + struct iwl_scd_txq_cfg_cmd cmd = { + .scd_queue = queue, + .action = SCD_CFG_DISABLE_QUEUE, + }; + bool remove_mac_queue = mac80211_queue != IEEE80211_INVAL_HW_QUEUE; + int ret; + + if (WARN_ON(remove_mac_queue && mac80211_queue >= IEEE80211_MAX_QUEUES)) + return -EINVAL; + + if (iwl_mvm_has_new_tx_api(mvm)) { + spin_lock_bh(&mvm->queue_info_lock); + + if (remove_mac_queue) + mvm->hw_queue_to_mac80211[queue] &= + ~BIT(mac80211_queue); + + spin_unlock_bh(&mvm->queue_info_lock); + + iwl_trans_txq_free(mvm->trans, queue); + + return 0; + } + + spin_lock_bh(&mvm->queue_info_lock); + + if (WARN_ON(mvm->queue_info[queue].tid_bitmap == 0)) { + spin_unlock_bh(&mvm->queue_info_lock); + return 0; + } + + mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); + + /* + * If there is another TID with the same AC - don't remove the MAC queue + * from the mapping + */ + if (tid < IWL_MAX_TID_COUNT) { + unsigned long tid_bitmap = + mvm->queue_info[queue].tid_bitmap; + int ac = tid_to_mac80211_ac[tid]; + int i; + + for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT) { + if (tid_to_mac80211_ac[i] == ac) + remove_mac_queue = false; + } + } + + if (remove_mac_queue) + mvm->hw_queue_to_mac80211[queue] &= + ~BIT(mac80211_queue); + + cmd.action = mvm->queue_info[queue].tid_bitmap ? + SCD_CFG_ENABLE_QUEUE : SCD_CFG_DISABLE_QUEUE; + if (cmd.action == SCD_CFG_DISABLE_QUEUE) + mvm->queue_info[queue].status = IWL_MVM_QUEUE_FREE; + + IWL_DEBUG_TX_QUEUES(mvm, + "Disabling TXQ #%d tids=0x%x (mac80211 map:0x%x)\n", + queue, + mvm->queue_info[queue].tid_bitmap, + mvm->hw_queue_to_mac80211[queue]); + + /* If the queue is still enabled - nothing left to do in this func */ + if (cmd.action == SCD_CFG_ENABLE_QUEUE) { + spin_unlock_bh(&mvm->queue_info_lock); + return 0; + } + + cmd.sta_id = mvm->queue_info[queue].ra_sta_id; + cmd.tid = mvm->queue_info[queue].txq_tid; + + /* Make sure queue info is correct even though we overwrite it */ + WARN(mvm->queue_info[queue].tid_bitmap || + mvm->hw_queue_to_mac80211[queue], + "TXQ #%d info out-of-sync - mac map=0x%x, tids=0x%x\n", + queue, mvm->hw_queue_to_mac80211[queue], + mvm->queue_info[queue].tid_bitmap); + + /* If we are here - the queue is freed and we can zero out these vals */ + mvm->queue_info[queue].tid_bitmap = 0; + mvm->hw_queue_to_mac80211[queue] = 0; + + /* Regardless if this is a reserved TXQ for a STA - mark it as false */ + mvm->queue_info[queue].reserved = false; + + spin_unlock_bh(&mvm->queue_info_lock); + + iwl_trans_txq_disable(mvm->trans, queue, false); + ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, + sizeof(struct iwl_scd_txq_cfg_cmd), &cmd); + + if (ret) + IWL_ERR(mvm, "Failed to disable queue %d (ret=%d)\n", + queue, ret); + return ret; +} + static int iwl_mvm_get_queue_agg_tids(struct iwl_mvm *mvm, int queue) { struct ieee80211_sta *sta; @@ -447,11 +549,12 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue) } static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue, - bool same_sta) + u8 new_sta_id) { struct iwl_mvm_sta *mvmsta; u8 txq_curr_ac, sta_id, tid; unsigned long disable_agg_tids = 0; + bool same_sta; int ret; lockdep_assert_held(&mvm->mutex); @@ -465,6 +568,8 @@ static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue, tid = mvm->queue_info[queue].txq_tid; spin_unlock_bh(&mvm->queue_info_lock); + same_sta = sta_id == new_sta_id; + mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id); if (WARN_ON(!mvmsta)) return -EINVAL; @@ -479,10 +584,6 @@ static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue, mvmsta->vif->hw_queue[txq_curr_ac], tid, 0); if (ret) { - /* Re-mark the inactive queue as inactive */ - spin_lock_bh(&mvm->queue_info_lock); - mvm->queue_info[queue].status = IWL_MVM_QUEUE_INACTIVE; - spin_unlock_bh(&mvm->queue_info_lock); IWL_ERR(mvm, "Failed to free inactive queue %d (ret=%d)\n", queue, ret); @@ -504,7 +605,13 @@ static int iwl_mvm_get_shared_queue(struct iwl_mvm *mvm, u8 ac_to_queue[IEEE80211_NUM_ACS]; int i; + /* + * This protects us against grabbing a queue that's being reconfigured + * by the inactivity checker. + */ + lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->queue_info_lock); + if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) return -EINVAL; @@ -517,11 +624,6 @@ static int iwl_mvm_get_shared_queue(struct iwl_mvm *mvm, i != IWL_MVM_DQA_BSS_CLIENT_QUEUE) continue; - /* Don't try and take queues being reconfigured */ - if (mvm->queue_info[queue].status == - IWL_MVM_QUEUE_RECONFIGURING) - continue; - ac_to_queue[mvm->queue_info[i].mac80211_ac] = i; } @@ -562,14 +664,6 @@ static int iwl_mvm_get_shared_queue(struct iwl_mvm *mvm, return -ENOSPC; } - /* Make sure the queue isn't in the middle of being reconfigured */ - if (mvm->queue_info[queue].status == IWL_MVM_QUEUE_RECONFIGURING) { - IWL_ERR(mvm, - "TXQ %d is in the middle of re-config - try again\n", - queue); - return -EBUSY; - } - return queue; } @@ -579,9 +673,9 @@ static int iwl_mvm_get_shared_queue(struct iwl_mvm *mvm, * in such a case, otherwise - if no redirection required - it does nothing, * unless the %force param is true. */ -int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid, - int ac, int ssn, unsigned int wdg_timeout, - bool force) +static int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid, + int ac, int ssn, unsigned int wdg_timeout, + bool force) { struct iwl_scd_txq_cfg_cmd cmd = { .scd_queue = queue, @@ -616,7 +710,7 @@ int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid, cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[mvm->queue_info[queue].mac80211_ac]; cmd.tid = mvm->queue_info[queue].txq_tid; mq = mvm->hw_queue_to_mac80211[queue]; - shared_queue = (mvm->queue_info[queue].hw_queue_refcount > 1); + shared_queue = hweight16(mvm->queue_info[queue].tid_bitmap) > 1; spin_unlock_bh(&mvm->queue_info_lock); IWL_DEBUG_TX_QUEUES(mvm, "Redirecting TXQ #%d to FIFO #%d\n", @@ -674,6 +768,57 @@ out: return ret; } +static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, + u8 minq, u8 maxq) +{ + int i; + + lockdep_assert_held(&mvm->queue_info_lock); + + /* This should not be hit with new TX path */ + if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) + return -ENOSPC; + + /* Start by looking for a free queue */ + for (i = minq; i <= maxq; i++) + if (mvm->queue_info[i].tid_bitmap == 0 && + mvm->queue_info[i].status == IWL_MVM_QUEUE_FREE) + return i; + + return -ENOSPC; +} + +static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue, + u8 sta_id, u8 tid, unsigned int timeout) +{ + int queue, size = IWL_DEFAULT_QUEUE_SIZE; + + if (tid == IWL_MAX_TID_COUNT) { + tid = IWL_MGMT_TID; + size = IWL_MGMT_QUEUE_SIZE; + } + queue = iwl_trans_txq_alloc(mvm->trans, + cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE), + sta_id, tid, SCD_QUEUE_CFG, size, timeout); + + if (queue < 0) { + IWL_DEBUG_TX_QUEUES(mvm, + "Failed allocating TXQ for sta %d tid %d, ret: %d\n", + sta_id, tid, queue); + return queue; + } + + IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta %d tid %d\n", + queue, sta_id, tid); + + mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue); + IWL_DEBUG_TX_QUEUES(mvm, + "Enabling TXQ #%d (mac80211 map:0x%x)\n", + queue, mvm->hw_queue_to_mac80211[queue]); + + return queue; +} + static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm, struct ieee80211_sta *sta, u8 ac, int tid) @@ -698,12 +843,428 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm, spin_lock_bh(&mvmsta->lock); mvmsta->tid_data[tid].txq_id = queue; - mvmsta->tid_data[tid].is_tid_active = true; spin_unlock_bh(&mvmsta->lock); return 0; } +static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue, + int mac80211_queue, u8 sta_id, u8 tid) +{ + bool enable_queue = true; + + spin_lock_bh(&mvm->queue_info_lock); + + /* Make sure this TID isn't already enabled */ + if (mvm->queue_info[queue].tid_bitmap & BIT(tid)) { + spin_unlock_bh(&mvm->queue_info_lock); + IWL_ERR(mvm, "Trying to enable TXQ %d with existing TID %d\n", + queue, tid); + return false; + } + + /* Update mappings and refcounts */ + if (mvm->queue_info[queue].tid_bitmap) + enable_queue = false; + + if (mac80211_queue != IEEE80211_INVAL_HW_QUEUE) { + WARN(mac80211_queue >= + BITS_PER_BYTE * sizeof(mvm->hw_queue_to_mac80211[0]), + "cannot track mac80211 queue %d (queue %d, sta %d, tid %d)\n", + mac80211_queue, queue, sta_id, tid); + mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue); + } + + mvm->queue_info[queue].tid_bitmap |= BIT(tid); + mvm->queue_info[queue].ra_sta_id = sta_id; + + if (enable_queue) { + if (tid != IWL_MAX_TID_COUNT) + mvm->queue_info[queue].mac80211_ac = + tid_to_mac80211_ac[tid]; + else + mvm->queue_info[queue].mac80211_ac = IEEE80211_AC_VO; + + mvm->queue_info[queue].txq_tid = tid; + } + + IWL_DEBUG_TX_QUEUES(mvm, + "Enabling TXQ #%d tids=0x%x (mac80211 map:0x%x)\n", + queue, mvm->queue_info[queue].tid_bitmap, + mvm->hw_queue_to_mac80211[queue]); + + spin_unlock_bh(&mvm->queue_info_lock); + + return enable_queue; +} + +static bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, + int mac80211_queue, u16 ssn, + const struct iwl_trans_txq_scd_cfg *cfg, + unsigned int wdg_timeout) +{ + struct iwl_scd_txq_cfg_cmd cmd = { + .scd_queue = queue, + .action = SCD_CFG_ENABLE_QUEUE, + .window = cfg->frame_limit, + .sta_id = cfg->sta_id, + .ssn = cpu_to_le16(ssn), + .tx_fifo = cfg->fifo, + .aggregate = cfg->aggregate, + .tid = cfg->tid, + }; + bool inc_ssn; + + if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) + return false; + + /* Send the enabling command if we need to */ + if (!iwl_mvm_update_txq_mapping(mvm, queue, mac80211_queue, + cfg->sta_id, cfg->tid)) + return false; + + inc_ssn = iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, + NULL, wdg_timeout); + if (inc_ssn) + le16_add_cpu(&cmd.ssn, 1); + + WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd), + "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); + + return inc_ssn; +} + +static void iwl_mvm_change_queue_tid(struct iwl_mvm *mvm, int queue) +{ + struct iwl_scd_txq_cfg_cmd cmd = { + .scd_queue = queue, + .action = SCD_CFG_UPDATE_QUEUE_TID, + }; + int tid; + unsigned long tid_bitmap; + int ret; + + lockdep_assert_held(&mvm->mutex); + + if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) + return; + + spin_lock_bh(&mvm->queue_info_lock); + tid_bitmap = mvm->queue_info[queue].tid_bitmap; + spin_unlock_bh(&mvm->queue_info_lock); + + if (WARN(!tid_bitmap, "TXQ %d has no tids assigned to it\n", queue)) + return; + + /* Find any TID for queue */ + tid = find_first_bit(&tid_bitmap, IWL_MAX_TID_COUNT + 1); + cmd.tid = tid; + cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; + + ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd); + if (ret) { + IWL_ERR(mvm, "Failed to update owner of TXQ %d (ret=%d)\n", + queue, ret); + return; + } + + spin_lock_bh(&mvm->queue_info_lock); + mvm->queue_info[queue].txq_tid = tid; + spin_unlock_bh(&mvm->queue_info_lock); + IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n", + queue, tid); +} + +static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue) +{ + struct ieee80211_sta *sta; + struct iwl_mvm_sta *mvmsta; + u8 sta_id; + int tid = -1; + unsigned long tid_bitmap; + unsigned int wdg_timeout; + int ssn; + int ret = true; + + /* queue sharing is disabled on new TX path */ + if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) + return; + + lockdep_assert_held(&mvm->mutex); + + spin_lock_bh(&mvm->queue_info_lock); + sta_id = mvm->queue_info[queue].ra_sta_id; + tid_bitmap = mvm->queue_info[queue].tid_bitmap; + spin_unlock_bh(&mvm->queue_info_lock); + + /* Find TID for queue, and make sure it is the only one on the queue */ + tid = find_first_bit(&tid_bitmap, IWL_MAX_TID_COUNT + 1); + if (tid_bitmap != BIT(tid)) { + IWL_ERR(mvm, "Failed to unshare q %d, active tids=0x%lx\n", + queue, tid_bitmap); + return; + } + + IWL_DEBUG_TX_QUEUES(mvm, "Unsharing TXQ %d, keeping tid %d\n", queue, + tid); + + sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], + lockdep_is_held(&mvm->mutex)); + + if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) + return; + + mvmsta = iwl_mvm_sta_from_mac80211(sta); + wdg_timeout = iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false); + + ssn = IEEE80211_SEQ_TO_SN(mvmsta->tid_data[tid].seq_number); + + ret = iwl_mvm_scd_queue_redirect(mvm, queue, tid, + tid_to_mac80211_ac[tid], ssn, + wdg_timeout, true); + if (ret) { + IWL_ERR(mvm, "Failed to redirect TXQ %d\n", queue); + return; + } + + /* If aggs should be turned back on - do it */ + if (mvmsta->tid_data[tid].state == IWL_AGG_ON) { + struct iwl_mvm_add_sta_cmd cmd = {0}; + + mvmsta->tid_disable_agg &= ~BIT(tid); + + cmd.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color); + cmd.sta_id = mvmsta->sta_id; + cmd.add_modify = STA_MODE_MODIFY; + cmd.modify_mask = STA_MODIFY_TID_DISABLE_TX; + cmd.tfd_queue_msk = cpu_to_le32(mvmsta->tfd_queue_msk); + cmd.tid_disable_tx = cpu_to_le16(mvmsta->tid_disable_agg); + + ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, + iwl_mvm_add_sta_cmd_size(mvm), &cmd); + if (!ret) { + IWL_DEBUG_TX_QUEUES(mvm, + "TXQ #%d is now aggregated again\n", + queue); + + /* Mark queue intenally as aggregating again */ + iwl_trans_txq_set_shared_mode(mvm->trans, queue, false); + } + } + + spin_lock_bh(&mvm->queue_info_lock); + mvm->queue_info[queue].status = IWL_MVM_QUEUE_READY; + spin_unlock_bh(&mvm->queue_info_lock); +} + +/* + * Remove inactive TIDs of a given queue. + * If all queue TIDs are inactive - mark the queue as inactive + * If only some the queue TIDs are inactive - unmap them from the queue + * + * Returns %true if all TIDs were removed and the queue could be reused. + */ +static bool iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm, + struct iwl_mvm_sta *mvmsta, int queue, + unsigned long tid_bitmap, + unsigned long *unshare_queues, + unsigned long *changetid_queues) +{ + int tid; + + lockdep_assert_held(&mvmsta->lock); + lockdep_assert_held(&mvm->queue_info_lock); + + if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) + return false; + + /* Go over all non-active TIDs, incl. IWL_MAX_TID_COUNT (for mgmt) */ + for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { + /* If some TFDs are still queued - don't mark TID as inactive */ + if (iwl_mvm_tid_queued(mvm, &mvmsta->tid_data[tid])) + tid_bitmap &= ~BIT(tid); + + /* Don't mark as inactive any TID that has an active BA */ + if (mvmsta->tid_data[tid].state != IWL_AGG_OFF) + tid_bitmap &= ~BIT(tid); + } + + /* If all TIDs in the queue are inactive - return it can be reused */ + if (tid_bitmap == mvm->queue_info[queue].tid_bitmap) { + IWL_DEBUG_TX_QUEUES(mvm, "Queue %d is inactive\n", queue); + return true; + } + + /* + * If we are here, this is a shared queue and not all TIDs timed-out. + * Remove the ones that did. + */ + for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { + int mac_queue = mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]]; + u16 tid_bitmap; + + mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE; + mvm->hw_queue_to_mac80211[queue] &= ~BIT(mac_queue); + mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); + + tid_bitmap = mvm->queue_info[queue].tid_bitmap; + + /* + * We need to take into account a situation in which a TXQ was + * allocated to TID x, and then turned shared by adding TIDs y + * and z. If TID x becomes inactive and is removed from the TXQ, + * ownership must be given to one of the remaining TIDs. + * This is mainly because if TID x continues - a new queue can't + * be allocated for it as long as it is an owner of another TXQ. + * + * Mark this queue in the right bitmap, we'll send the command + * to the firmware later. + */ + if (!(tid_bitmap & BIT(mvm->queue_info[queue].txq_tid))) + set_bit(queue, changetid_queues); + + IWL_DEBUG_TX_QUEUES(mvm, + "Removing inactive TID %d from shared Q:%d\n", + tid, queue); + } + + IWL_DEBUG_TX_QUEUES(mvm, + "TXQ #%d left with tid bitmap 0x%x\n", queue, + mvm->queue_info[queue].tid_bitmap); + + /* + * There may be different TIDs with the same mac queues, so make + * sure all TIDs have existing corresponding mac queues enabled + */ + tid_bitmap = mvm->queue_info[queue].tid_bitmap; + for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { + mvm->hw_queue_to_mac80211[queue] |= + BIT(mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]]); + } + + /* If the queue is marked as shared - "unshare" it */ + if (hweight16(mvm->queue_info[queue].tid_bitmap) == 1 && + mvm->queue_info[queue].status == IWL_MVM_QUEUE_SHARED) { + IWL_DEBUG_TX_QUEUES(mvm, "Marking Q:%d for reconfig\n", + queue); + set_bit(queue, unshare_queues); + } + + return false; +} + +/* + * Check for inactivity - this includes checking if any queue + * can be unshared and finding one (and only one) that can be + * reused. + * This function is also invoked as a sort of clean-up task, + * in which case @alloc_for_sta is IWL_MVM_INVALID_STA. + * + * Returns the queue number, or -ENOSPC. + */ +static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta) +{ + unsigned long now = jiffies; + unsigned long unshare_queues = 0; + unsigned long changetid_queues = 0; + int i, ret, free_queue = -ENOSPC; + + lockdep_assert_held(&mvm->mutex); + + if (iwl_mvm_has_new_tx_api(mvm)) + return -ENOSPC; + + spin_lock_bh(&mvm->queue_info_lock); + + rcu_read_lock(); + + /* we skip the CMD queue below by starting at 1 */ + BUILD_BUG_ON(IWL_MVM_DQA_CMD_QUEUE != 0); + + for (i = 1; i < IWL_MAX_HW_QUEUES; i++) { + struct ieee80211_sta *sta; + struct iwl_mvm_sta *mvmsta; + u8 sta_id; + int tid; + unsigned long inactive_tid_bitmap = 0; + unsigned long queue_tid_bitmap; + + queue_tid_bitmap = mvm->queue_info[i].tid_bitmap; + if (!queue_tid_bitmap) + continue; + + /* If TXQ isn't in active use anyway - nothing to do here... */ + if (mvm->queue_info[i].status != IWL_MVM_QUEUE_READY && + mvm->queue_info[i].status != IWL_MVM_QUEUE_SHARED) + continue; + + /* Check to see if there are inactive TIDs on this queue */ + for_each_set_bit(tid, &queue_tid_bitmap, + IWL_MAX_TID_COUNT + 1) { + if (time_after(mvm->queue_info[i].last_frame_time[tid] + + IWL_MVM_DQA_QUEUE_TIMEOUT, now)) + continue; + + inactive_tid_bitmap |= BIT(tid); + } + + /* If all TIDs are active - finish check on this queue */ + if (!inactive_tid_bitmap) + continue; + + /* + * If we are here - the queue hadn't been served recently and is + * in use + */ + + sta_id = mvm->queue_info[i].ra_sta_id; + sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); + + /* + * If the STA doesn't exist anymore, it isn't an error. It could + * be that it was removed since getting the queues, and in this + * case it should've inactivated its queues anyway. + */ + if (IS_ERR_OR_NULL(sta)) + continue; + + mvmsta = iwl_mvm_sta_from_mac80211(sta); + + /* this isn't so nice, but works OK due to the way we loop */ + spin_unlock(&mvm->queue_info_lock); + + /* and we need this locking order */ + spin_lock(&mvmsta->lock); + spin_lock(&mvm->queue_info_lock); + ret = iwl_mvm_remove_inactive_tids(mvm, mvmsta, i, + inactive_tid_bitmap, + &unshare_queues, + &changetid_queues); + if (ret >= 0 && free_queue < 0) + free_queue = ret; + /* only unlock sta lock - we still need the queue info lock */ + spin_unlock(&mvmsta->lock); + } + + rcu_read_unlock(); + spin_unlock_bh(&mvm->queue_info_lock); + + /* Reconfigure queues requiring reconfiguation */ + for_each_set_bit(i, &unshare_queues, IWL_MAX_HW_QUEUES) + iwl_mvm_unshare_queue(mvm, i); + for_each_set_bit(i, &changetid_queues, IWL_MAX_HW_QUEUES) + iwl_mvm_change_queue_tid(mvm, i); + + if (free_queue >= 0 && alloc_for_sta != IWL_MVM_INVALID_STA) { + ret = iwl_mvm_free_inactive_queue(mvm, free_queue, + alloc_for_sta); + if (ret) + return ret; + } + + return free_queue; +} + static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, struct ieee80211_sta *sta, u8 ac, int tid, struct ieee80211_hdr *hdr) @@ -719,7 +1280,6 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false); u8 mac_queue = mvmsta->vif->hw_queue[ac]; int queue = -1; - bool using_inactive_queue = false, same_sta = false; unsigned long disable_agg_tids = 0; enum iwl_mvm_agg_state queue_state; bool shared_queue = false, inc_ssn; @@ -756,9 +1316,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, if ((queue < 0 && mvmsta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) && (mvm->queue_info[mvmsta->reserved_queue].status == - IWL_MVM_QUEUE_RESERVED || - mvm->queue_info[mvmsta->reserved_queue].status == - IWL_MVM_QUEUE_INACTIVE)) { + IWL_MVM_QUEUE_RESERVED)) { queue = mvmsta->reserved_queue; mvm->queue_info[queue].reserved = true; IWL_DEBUG_TX_QUEUES(mvm, "Using reserved queue #%d\n", queue); @@ -768,21 +1326,13 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, queue = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, IWL_MVM_DQA_MIN_DATA_QUEUE, IWL_MVM_DQA_MAX_DATA_QUEUE); + if (queue < 0) { + spin_unlock_bh(&mvm->queue_info_lock); - /* - * Check if this queue is already allocated but inactive. - * In such a case, we'll need to first free this queue before enabling - * it again, so we'll mark it as reserved to make sure no new traffic - * arrives on it - */ - if (queue > 0 && - mvm->queue_info[queue].status == IWL_MVM_QUEUE_INACTIVE) { - mvm->queue_info[queue].status = IWL_MVM_QUEUE_RESERVED; - using_inactive_queue = true; - same_sta = mvm->queue_info[queue].ra_sta_id == mvmsta->sta_id; - IWL_DEBUG_TX_QUEUES(mvm, - "Re-assigning TXQ %d: sta_id=%d, tid=%d\n", - queue, mvmsta->sta_id, tid); + /* try harder - perhaps kill an inactive queue */ + queue = iwl_mvm_inactivity_check(mvm, mvmsta->sta_id); + + spin_lock_bh(&mvm->queue_info_lock); } /* No free queue - we'll have to share */ @@ -800,7 +1350,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, * This will allow avoiding re-acquiring the lock at the end of the * configuration. On error we'll mark it back as free. */ - if ((queue > 0) && !shared_queue) + if (queue > 0 && !shared_queue) mvm->queue_info[queue].status = IWL_MVM_QUEUE_READY; spin_unlock_bh(&mvm->queue_info_lock); @@ -821,16 +1371,6 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, cfg.aggregate = (queue >= IWL_MVM_DQA_MIN_DATA_QUEUE || queue == IWL_MVM_DQA_BSS_CLIENT_QUEUE); - /* - * If this queue was previously inactive (idle) - we need to free it - * first - */ - if (using_inactive_queue) { - ret = iwl_mvm_free_inactive_queue(mvm, queue, same_sta); - if (ret) - return ret; - } - IWL_DEBUG_TX_QUEUES(mvm, "Allocating %squeue #%d to sta %d on tid %d\n", shared_queue ? "shared " : "", queue, @@ -874,7 +1414,6 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, if (inc_ssn) mvmsta->tid_data[tid].seq_number += 0x10; mvmsta->tid_data[tid].txq_id = queue; - mvmsta->tid_data[tid].is_tid_active = true; mvmsta->tfd_queue_msk |= BIT(queue); queue_state = mvmsta->tid_data[tid].state; @@ -909,129 +1448,6 @@ out_err: return ret; } -static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue) -{ - struct iwl_scd_txq_cfg_cmd cmd = { - .scd_queue = queue, - .action = SCD_CFG_UPDATE_QUEUE_TID, - }; - int tid; - unsigned long tid_bitmap; - int ret; - - lockdep_assert_held(&mvm->mutex); - - if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) - return; - - spin_lock_bh(&mvm->queue_info_lock); - tid_bitmap = mvm->queue_info[queue].tid_bitmap; - spin_unlock_bh(&mvm->queue_info_lock); - - if (WARN(!tid_bitmap, "TXQ %d has no tids assigned to it\n", queue)) - return; - - /* Find any TID for queue */ - tid = find_first_bit(&tid_bitmap, IWL_MAX_TID_COUNT + 1); - cmd.tid = tid; - cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; - - ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd); - if (ret) { - IWL_ERR(mvm, "Failed to update owner of TXQ %d (ret=%d)\n", - queue, ret); - return; - } - - spin_lock_bh(&mvm->queue_info_lock); - mvm->queue_info[queue].txq_tid = tid; - spin_unlock_bh(&mvm->queue_info_lock); - IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n", - queue, tid); -} - -static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue) -{ - struct ieee80211_sta *sta; - struct iwl_mvm_sta *mvmsta; - u8 sta_id; - int tid = -1; - unsigned long tid_bitmap; - unsigned int wdg_timeout; - int ssn; - int ret = true; - - /* queue sharing is disabled on new TX path */ - if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) - return; - - lockdep_assert_held(&mvm->mutex); - - spin_lock_bh(&mvm->queue_info_lock); - sta_id = mvm->queue_info[queue].ra_sta_id; - tid_bitmap = mvm->queue_info[queue].tid_bitmap; - spin_unlock_bh(&mvm->queue_info_lock); - - /* Find TID for queue, and make sure it is the only one on the queue */ - tid = find_first_bit(&tid_bitmap, IWL_MAX_TID_COUNT + 1); - if (tid_bitmap != BIT(tid)) { - IWL_ERR(mvm, "Failed to unshare q %d, active tids=0x%lx\n", - queue, tid_bitmap); - return; - } - - IWL_DEBUG_TX_QUEUES(mvm, "Unsharing TXQ %d, keeping tid %d\n", queue, - tid); - - sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], - lockdep_is_held(&mvm->mutex)); - - if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) - return; - - mvmsta = iwl_mvm_sta_from_mac80211(sta); - wdg_timeout = iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false); - - ssn = IEEE80211_SEQ_TO_SN(mvmsta->tid_data[tid].seq_number); - - ret = iwl_mvm_scd_queue_redirect(mvm, queue, tid, - tid_to_mac80211_ac[tid], ssn, - wdg_timeout, true); - if (ret) { - IWL_ERR(mvm, "Failed to redirect TXQ %d\n", queue); - return; - } - - /* If aggs should be turned back on - do it */ - if (mvmsta->tid_data[tid].state == IWL_AGG_ON) { - struct iwl_mvm_add_sta_cmd cmd = {0}; - - mvmsta->tid_disable_agg &= ~BIT(tid); - - cmd.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color); - cmd.sta_id = mvmsta->sta_id; - cmd.add_modify = STA_MODE_MODIFY; - cmd.modify_mask = STA_MODIFY_TID_DISABLE_TX; - cmd.tfd_queue_msk = cpu_to_le32(mvmsta->tfd_queue_msk); - cmd.tid_disable_tx = cpu_to_le16(mvmsta->tid_disable_agg); - - ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, - iwl_mvm_add_sta_cmd_size(mvm), &cmd); - if (!ret) { - IWL_DEBUG_TX_QUEUES(mvm, - "TXQ #%d is now aggregated again\n", - queue); - - /* Mark queue intenally as aggregating again */ - iwl_trans_txq_set_shared_mode(mvm->trans, queue, false); - } - } - - spin_lock_bh(&mvm->queue_info_lock); - mvm->queue_info[queue].status = IWL_MVM_QUEUE_READY; - spin_unlock_bh(&mvm->queue_info_lock); -} - static inline u8 iwl_mvm_tid_to_ac_queue(int tid) { if (tid == IWL_MAX_TID_COUNT) @@ -1100,47 +1516,12 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) struct ieee80211_sta *sta; struct iwl_mvm_sta *mvmsta; unsigned long deferred_tid_traffic; - int queue, sta_id, tid; - - /* Check inactivity of queues */ - iwl_mvm_inactivity_check(mvm); + int sta_id, tid; mutex_lock(&mvm->mutex); - /* No queue reconfiguration in TVQM mode */ - if (iwl_mvm_has_new_tx_api(mvm)) - goto alloc_queues; - - /* Reconfigure queues requiring reconfiguation */ - for (queue = 0; queue < ARRAY_SIZE(mvm->queue_info); queue++) { - bool reconfig; - bool change_owner; - - spin_lock_bh(&mvm->queue_info_lock); - reconfig = (mvm->queue_info[queue].status == - IWL_MVM_QUEUE_RECONFIGURING); + iwl_mvm_inactivity_check(mvm, IWL_MVM_INVALID_STA); - /* - * We need to take into account a situation in which a TXQ was - * allocated to TID x, and then turned shared by adding TIDs y - * and z. If TID x becomes inactive and is removed from the TXQ, - * ownership must be given to one of the remaining TIDs. - * This is mainly because if TID x continues - a new queue can't - * be allocated for it as long as it is an owner of another TXQ. - */ - change_owner = !(mvm->queue_info[queue].tid_bitmap & - BIT(mvm->queue_info[queue].txq_tid)) && - (mvm->queue_info[queue].status == - IWL_MVM_QUEUE_SHARED); - spin_unlock_bh(&mvm->queue_info_lock); - - if (reconfig) - iwl_mvm_unshare_queue(mvm, queue); - else if (change_owner) - iwl_mvm_change_queue_owner(mvm, queue); - } - -alloc_queues: /* Go over all stations with deferred traffic */ for_each_set_bit(sta_id, mvm->sta_deferred_frames, IWL_MVM_STATION_COUNT) { @@ -1167,23 +1548,19 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm, { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); int queue; - bool using_inactive_queue = false, same_sta = false; /* queue reserving is disabled on new TX path */ if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) return 0; - /* - * Check for inactive queues, so we don't reach a situation where we - * can't add a STA due to a shortage in queues that doesn't really exist - */ - iwl_mvm_inactivity_check(mvm); + /* run the general cleanup/unsharing of queues */ + iwl_mvm_inactivity_check(mvm, IWL_MVM_INVALID_STA); spin_lock_bh(&mvm->queue_info_lock); /* Make sure we have free resources for this STA */ if (vif_type == NL80211_IFTYPE_STATION && !sta->tdls && - !mvm->queue_info[IWL_MVM_DQA_BSS_CLIENT_QUEUE].hw_queue_refcount && + !mvm->queue_info[IWL_MVM_DQA_BSS_CLIENT_QUEUE].tid_bitmap && (mvm->queue_info[IWL_MVM_DQA_BSS_CLIENT_QUEUE].status == IWL_MVM_QUEUE_FREE)) queue = IWL_MVM_DQA_BSS_CLIENT_QUEUE; @@ -1193,16 +1570,13 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm, IWL_MVM_DQA_MAX_DATA_QUEUE); if (queue < 0) { spin_unlock_bh(&mvm->queue_info_lock); - IWL_ERR(mvm, "No available queues for new station\n"); - return -ENOSPC; - } else if (mvm->queue_info[queue].status == IWL_MVM_QUEUE_INACTIVE) { - /* - * If this queue is already allocated but inactive we'll need to - * first free this queue before enabling it again, we'll mark - * it as reserved to make sure no new traffic arrives on it - */ - using_inactive_queue = true; - same_sta = mvm->queue_info[queue].ra_sta_id == mvmsta->sta_id; + /* try again - this time kick out a queue if needed */ + queue = iwl_mvm_inactivity_check(mvm, mvmsta->sta_id); + if (queue < 0) { + IWL_ERR(mvm, "No available queues for new station\n"); + return -ENOSPC; + } + spin_lock_bh(&mvm->queue_info_lock); } mvm->queue_info[queue].status = IWL_MVM_QUEUE_RESERVED; @@ -1210,9 +1584,6 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm, mvmsta->reserved_queue = queue; - if (using_inactive_queue) - iwl_mvm_free_inactive_queue(mvm, queue, same_sta); - IWL_DEBUG_TX_QUEUES(mvm, "Reserving data queue #%d for sta_id %d\n", queue, mvmsta->sta_id); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 0fc211108149..de1a0a2d8723 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -312,9 +312,6 @@ enum iwl_mvm_agg_state { * Basically when next_reclaimed reaches ssn, we can tell mac80211 that * we are ready to finish the Tx AGG stop / start flow. * @tx_time: medium time consumed by this A-MPDU - * @is_tid_active: has this TID sent traffic in the last - * %IWL_MVM_DQA_QUEUE_TIMEOUT time period. If %txq_id is invalid, this - * field should be ignored. * @tpt_meas_start: time of the throughput measurements start, is reset every HZ * @tx_count_last: number of frames transmitted during the last second * @tx_count: counts the number of frames transmitted since the last reset of @@ -332,7 +329,6 @@ struct iwl_mvm_tid_data { u16 txq_id; u16 ssn; u16 tx_time; - bool is_tid_active; unsigned long tpt_meas_start; u32 tx_count_last; u32 tx_count; @@ -572,8 +568,4 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm, void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif); void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk); -int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid, - int ac, int ssn, unsigned int wdg_timeout, - bool force); - #endif /* __sta_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index cd91bc44259c..e1a6f4e22253 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -254,17 +254,14 @@ static void iwl_mvm_te_check_trigger(struct iwl_mvm *mvm, struct iwl_fw_dbg_trigger_time_event *te_trig; int i; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, + ieee80211_vif_to_wdev(te_data->vif), + FW_DBG_TRIGGER_TIME_EVENT); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT); te_trig = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(te_data->vif), - trig)) - return; - for (i = 0; i < ARRAY_SIZE(te_trig->time_events); i++) { u32 trig_te_id = le32_to_cpu(te_trig->time_events[i].id); u32 trig_action_bitmap = diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index a6877b3f8037..ec57682efe54 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -79,15 +79,12 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr, struct iwl_fw_dbg_trigger_tlv *trig; struct iwl_fw_dbg_trigger_ba *ba_trig; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL, FW_DBG_TRIGGER_BA); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA); ba_trig = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig)) - return; - if (!(le16_to_cpu(ba_trig->tx_bar) & BIT(tid))) return; @@ -1143,32 +1140,16 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM); /* Check if TXQ needs to be allocated or re-activated */ - if (unlikely(txq_id == IWL_MVM_INVALID_QUEUE || - !mvmsta->tid_data[tid].is_tid_active)) { - /* If TXQ needs to be allocated... */ - if (txq_id == IWL_MVM_INVALID_QUEUE) { - iwl_mvm_tx_add_stream(mvm, mvmsta, tid, skb); - - /* - * The frame is now deferred, and the worker scheduled - * will re-allocate it, so we can free it for now. - */ - iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); - spin_unlock(&mvmsta->lock); - return 0; - } - - /* queue should always be active in new TX path */ - WARN_ON(iwl_mvm_has_new_tx_api(mvm)); + if (unlikely(txq_id == IWL_MVM_INVALID_QUEUE)) { + iwl_mvm_tx_add_stream(mvm, mvmsta, tid, skb); - /* If we are here - TXQ exists and needs to be re-activated */ - spin_lock(&mvm->queue_info_lock); - mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_READY; - mvmsta->tid_data[tid].is_tid_active = true; - spin_unlock(&mvm->queue_info_lock); - - IWL_DEBUG_TX_QUEUES(mvm, "Re-activating queue %d for TX\n", - txq_id); + /* + * The frame is now deferred, and the worker scheduled + * will re-allocate it, so we can free it for now. + */ + iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); + spin_unlock(&mvmsta->lock); + return 0; } if (!iwl_mvm_has_new_tx_api(mvm)) { @@ -1414,15 +1395,13 @@ static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm, struct iwl_fw_dbg_trigger_tx_status *status_trig; int i; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TX_STATUS)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, NULL, + FW_DBG_TRIGGER_TX_STATUS); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TX_STATUS); status_trig = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig)) - return; - for (i = 0; i < ARRAY_SIZE(status_trig->statuses); i++) { /* don't collect on status 0 */ if (!status_trig->statuses[i].status) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index dcacc4d11abc..818e1180bbdd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -599,36 +599,6 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) iwl_mvm_dump_umac_error_log(mvm); } -int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq) -{ - int i; - - lockdep_assert_held(&mvm->queue_info_lock); - - /* This should not be hit with new TX path */ - if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) - return -ENOSPC; - - /* Start by looking for a free queue */ - for (i = minq; i <= maxq; i++) - if (mvm->queue_info[i].hw_queue_refcount == 0 && - mvm->queue_info[i].status == IWL_MVM_QUEUE_FREE) - return i; - - /* - * If no free queue found - settle for an inactive one to reconfigure - * Make sure that the inactive queue either already belongs to this STA, - * or that if it belongs to another one - it isn't the reserved queue - */ - for (i = minq; i <= maxq; i++) - if (mvm->queue_info[i].status == IWL_MVM_QUEUE_INACTIVE && - (sta_id == mvm->queue_info[i].ra_sta_id || - !mvm->queue_info[i].reserved)) - return i; - - return -ENOSPC; -} - int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id, int tid, int frame_limit, u16 ssn) { @@ -649,7 +619,7 @@ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id, return -EINVAL; spin_lock_bh(&mvm->queue_info_lock); - if (WARN(mvm->queue_info[queue].hw_queue_refcount == 0, + if (WARN(mvm->queue_info[queue].tid_bitmap == 0, "Trying to reconfig unallocated queue %d\n", queue)) { spin_unlock_bh(&mvm->queue_info_lock); return -ENXIO; @@ -665,229 +635,6 @@ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id, return ret; } -static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue, - int mac80211_queue, u8 sta_id, u8 tid) -{ - bool enable_queue = true; - - spin_lock_bh(&mvm->queue_info_lock); - - /* Make sure this TID isn't already enabled */ - if (mvm->queue_info[queue].tid_bitmap & BIT(tid)) { - spin_unlock_bh(&mvm->queue_info_lock); - IWL_ERR(mvm, "Trying to enable TXQ %d with existing TID %d\n", - queue, tid); - return false; - } - - /* Update mappings and refcounts */ - if (mvm->queue_info[queue].hw_queue_refcount > 0) - enable_queue = false; - - if (mac80211_queue != IEEE80211_INVAL_HW_QUEUE) { - WARN(mac80211_queue >= - BITS_PER_BYTE * sizeof(mvm->hw_queue_to_mac80211[0]), - "cannot track mac80211 queue %d (queue %d, sta %d, tid %d)\n", - mac80211_queue, queue, sta_id, tid); - mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue); - } - - mvm->queue_info[queue].hw_queue_refcount++; - mvm->queue_info[queue].tid_bitmap |= BIT(tid); - mvm->queue_info[queue].ra_sta_id = sta_id; - - if (enable_queue) { - if (tid != IWL_MAX_TID_COUNT) - mvm->queue_info[queue].mac80211_ac = - tid_to_mac80211_ac[tid]; - else - mvm->queue_info[queue].mac80211_ac = IEEE80211_AC_VO; - - mvm->queue_info[queue].txq_tid = tid; - } - - IWL_DEBUG_TX_QUEUES(mvm, - "Enabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", - queue, mvm->queue_info[queue].hw_queue_refcount, - mvm->hw_queue_to_mac80211[queue]); - - spin_unlock_bh(&mvm->queue_info_lock); - - return enable_queue; -} - -int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue, - u8 sta_id, u8 tid, unsigned int timeout) -{ - int queue, size = IWL_DEFAULT_QUEUE_SIZE; - - if (tid == IWL_MAX_TID_COUNT) { - tid = IWL_MGMT_TID; - size = IWL_MGMT_QUEUE_SIZE; - } - queue = iwl_trans_txq_alloc(mvm->trans, - cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE), - sta_id, tid, SCD_QUEUE_CFG, size, timeout); - - if (queue < 0) { - IWL_DEBUG_TX_QUEUES(mvm, - "Failed allocating TXQ for sta %d tid %d, ret: %d\n", - sta_id, tid, queue); - return queue; - } - - IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta %d tid %d\n", - queue, sta_id, tid); - - mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue); - IWL_DEBUG_TX_QUEUES(mvm, - "Enabling TXQ #%d (mac80211 map:0x%x)\n", - queue, mvm->hw_queue_to_mac80211[queue]); - - return queue; -} - -bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, - u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg, - unsigned int wdg_timeout) -{ - struct iwl_scd_txq_cfg_cmd cmd = { - .scd_queue = queue, - .action = SCD_CFG_ENABLE_QUEUE, - .window = cfg->frame_limit, - .sta_id = cfg->sta_id, - .ssn = cpu_to_le16(ssn), - .tx_fifo = cfg->fifo, - .aggregate = cfg->aggregate, - .tid = cfg->tid, - }; - bool inc_ssn; - - if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) - return false; - - /* Send the enabling command if we need to */ - if (!iwl_mvm_update_txq_mapping(mvm, queue, mac80211_queue, - cfg->sta_id, cfg->tid)) - return false; - - inc_ssn = iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, - NULL, wdg_timeout); - if (inc_ssn) - le16_add_cpu(&cmd.ssn, 1); - - WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd), - "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); - - return inc_ssn; -} - -int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, - u8 tid, u8 flags) -{ - struct iwl_scd_txq_cfg_cmd cmd = { - .scd_queue = queue, - .action = SCD_CFG_DISABLE_QUEUE, - }; - bool remove_mac_queue = mac80211_queue != IEEE80211_INVAL_HW_QUEUE; - int ret; - - if (WARN_ON(remove_mac_queue && mac80211_queue >= IEEE80211_MAX_QUEUES)) - return -EINVAL; - - if (iwl_mvm_has_new_tx_api(mvm)) { - spin_lock_bh(&mvm->queue_info_lock); - - if (remove_mac_queue) - mvm->hw_queue_to_mac80211[queue] &= - ~BIT(mac80211_queue); - - spin_unlock_bh(&mvm->queue_info_lock); - - iwl_trans_txq_free(mvm->trans, queue); - - return 0; - } - - spin_lock_bh(&mvm->queue_info_lock); - - if (WARN_ON(mvm->queue_info[queue].hw_queue_refcount == 0)) { - spin_unlock_bh(&mvm->queue_info_lock); - return 0; - } - - mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); - - /* - * If there is another TID with the same AC - don't remove the MAC queue - * from the mapping - */ - if (tid < IWL_MAX_TID_COUNT) { - unsigned long tid_bitmap = - mvm->queue_info[queue].tid_bitmap; - int ac = tid_to_mac80211_ac[tid]; - int i; - - for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT) { - if (tid_to_mac80211_ac[i] == ac) - remove_mac_queue = false; - } - } - - if (remove_mac_queue) - mvm->hw_queue_to_mac80211[queue] &= - ~BIT(mac80211_queue); - mvm->queue_info[queue].hw_queue_refcount--; - - cmd.action = mvm->queue_info[queue].hw_queue_refcount ? - SCD_CFG_ENABLE_QUEUE : SCD_CFG_DISABLE_QUEUE; - if (cmd.action == SCD_CFG_DISABLE_QUEUE) - mvm->queue_info[queue].status = IWL_MVM_QUEUE_FREE; - - IWL_DEBUG_TX_QUEUES(mvm, - "Disabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", - queue, - mvm->queue_info[queue].hw_queue_refcount, - mvm->hw_queue_to_mac80211[queue]); - - /* If the queue is still enabled - nothing left to do in this func */ - if (cmd.action == SCD_CFG_ENABLE_QUEUE) { - spin_unlock_bh(&mvm->queue_info_lock); - return 0; - } - - cmd.sta_id = mvm->queue_info[queue].ra_sta_id; - cmd.tid = mvm->queue_info[queue].txq_tid; - - /* Make sure queue info is correct even though we overwrite it */ - WARN(mvm->queue_info[queue].hw_queue_refcount || - mvm->queue_info[queue].tid_bitmap || - mvm->hw_queue_to_mac80211[queue], - "TXQ #%d info out-of-sync - refcount=%d, mac map=0x%x, tid=0x%x\n", - queue, mvm->queue_info[queue].hw_queue_refcount, - mvm->hw_queue_to_mac80211[queue], - mvm->queue_info[queue].tid_bitmap); - - /* If we are here - the queue is freed and we can zero out these vals */ - mvm->queue_info[queue].hw_queue_refcount = 0; - mvm->queue_info[queue].tid_bitmap = 0; - mvm->hw_queue_to_mac80211[queue] = 0; - - /* Regardless if this is a reserved TXQ for a STA - mark it as false */ - mvm->queue_info[queue].reserved = false; - - spin_unlock_bh(&mvm->queue_info_lock); - - iwl_trans_txq_disable(mvm->trans, queue, false); - ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, - sizeof(struct iwl_scd_txq_cfg_cmd), &cmd); - - if (ret) - IWL_ERR(mvm, "Failed to disable queue %d (ret=%d)\n", - queue, ret); - return ret; -} - /** * iwl_mvm_send_lq_cmd() - Send link quality command * @sync: This command can be sent synchronously. @@ -1238,14 +985,12 @@ void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_fw_dbg_trigger_tlv *trig; struct iwl_fw_dbg_trigger_mlme *trig_mlme; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), + FW_DBG_TRIGGER_MLME); + if (!trig) goto out; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME); trig_mlme = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(vif), trig)) - goto out; if (trig_mlme->stop_connection_loss && --trig_mlme->stop_connection_loss) @@ -1257,171 +1002,6 @@ out: ieee80211_connection_loss(vif); } -/* - * Remove inactive TIDs of a given queue. - * If all queue TIDs are inactive - mark the queue as inactive - * If only some the queue TIDs are inactive - unmap them from the queue - */ -static void iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm, - struct iwl_mvm_sta *mvmsta, int queue, - unsigned long tid_bitmap) -{ - int tid; - - lockdep_assert_held(&mvmsta->lock); - lockdep_assert_held(&mvm->queue_info_lock); - - if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) - return; - - /* Go over all non-active TIDs, incl. IWL_MAX_TID_COUNT (for mgmt) */ - for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { - /* If some TFDs are still queued - don't mark TID as inactive */ - if (iwl_mvm_tid_queued(mvm, &mvmsta->tid_data[tid])) - tid_bitmap &= ~BIT(tid); - - /* Don't mark as inactive any TID that has an active BA */ - if (mvmsta->tid_data[tid].state != IWL_AGG_OFF) - tid_bitmap &= ~BIT(tid); - } - - /* If all TIDs in the queue are inactive - mark queue as inactive. */ - if (tid_bitmap == mvm->queue_info[queue].tid_bitmap) { - mvm->queue_info[queue].status = IWL_MVM_QUEUE_INACTIVE; - - for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) - mvmsta->tid_data[tid].is_tid_active = false; - - IWL_DEBUG_TX_QUEUES(mvm, "Queue %d marked as inactive\n", - queue); - return; - } - - /* - * If we are here, this is a shared queue and not all TIDs timed-out. - * Remove the ones that did. - */ - for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { - int mac_queue = mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]]; - - mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE; - mvm->hw_queue_to_mac80211[queue] &= ~BIT(mac_queue); - mvm->queue_info[queue].hw_queue_refcount--; - mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); - mvmsta->tid_data[tid].is_tid_active = false; - - IWL_DEBUG_TX_QUEUES(mvm, - "Removing inactive TID %d from shared Q:%d\n", - tid, queue); - } - - IWL_DEBUG_TX_QUEUES(mvm, - "TXQ #%d left with tid bitmap 0x%x\n", queue, - mvm->queue_info[queue].tid_bitmap); - - /* - * There may be different TIDs with the same mac queues, so make - * sure all TIDs have existing corresponding mac queues enabled - */ - tid_bitmap = mvm->queue_info[queue].tid_bitmap; - for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { - mvm->hw_queue_to_mac80211[queue] |= - BIT(mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]]); - } - - /* If the queue is marked as shared - "unshare" it */ - if (mvm->queue_info[queue].hw_queue_refcount == 1 && - mvm->queue_info[queue].status == IWL_MVM_QUEUE_SHARED) { - mvm->queue_info[queue].status = IWL_MVM_QUEUE_RECONFIGURING; - IWL_DEBUG_TX_QUEUES(mvm, "Marking Q:%d for reconfig\n", - queue); - } -} - -void iwl_mvm_inactivity_check(struct iwl_mvm *mvm) -{ - unsigned long timeout_queues_map = 0; - unsigned long now = jiffies; - int i; - - if (iwl_mvm_has_new_tx_api(mvm)) - return; - - spin_lock_bh(&mvm->queue_info_lock); - for (i = 0; i < IWL_MAX_HW_QUEUES; i++) - if (mvm->queue_info[i].hw_queue_refcount > 0) - timeout_queues_map |= BIT(i); - spin_unlock_bh(&mvm->queue_info_lock); - - rcu_read_lock(); - - /* - * If a queue time outs - mark it as INACTIVE (don't remove right away - * if we don't have to.) This is an optimization in case traffic comes - * later, and we don't HAVE to use a currently-inactive queue - */ - for_each_set_bit(i, &timeout_queues_map, IWL_MAX_HW_QUEUES) { - struct ieee80211_sta *sta; - struct iwl_mvm_sta *mvmsta; - u8 sta_id; - int tid; - unsigned long inactive_tid_bitmap = 0; - unsigned long queue_tid_bitmap; - - spin_lock_bh(&mvm->queue_info_lock); - queue_tid_bitmap = mvm->queue_info[i].tid_bitmap; - - /* If TXQ isn't in active use anyway - nothing to do here... */ - if (mvm->queue_info[i].status != IWL_MVM_QUEUE_READY && - mvm->queue_info[i].status != IWL_MVM_QUEUE_SHARED) { - spin_unlock_bh(&mvm->queue_info_lock); - continue; - } - - /* Check to see if there are inactive TIDs on this queue */ - for_each_set_bit(tid, &queue_tid_bitmap, - IWL_MAX_TID_COUNT + 1) { - if (time_after(mvm->queue_info[i].last_frame_time[tid] + - IWL_MVM_DQA_QUEUE_TIMEOUT, now)) - continue; - - inactive_tid_bitmap |= BIT(tid); - } - spin_unlock_bh(&mvm->queue_info_lock); - - /* If all TIDs are active - finish check on this queue */ - if (!inactive_tid_bitmap) - continue; - - /* - * If we are here - the queue hadn't been served recently and is - * in use - */ - - sta_id = mvm->queue_info[i].ra_sta_id; - sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); - - /* - * If the STA doesn't exist anymore, it isn't an error. It could - * be that it was removed since getting the queues, and in this - * case it should've inactivated its queues anyway. - */ - if (IS_ERR_OR_NULL(sta)) - continue; - - mvmsta = iwl_mvm_sta_from_mac80211(sta); - - spin_lock_bh(&mvmsta->lock); - spin_lock(&mvm->queue_info_lock); - iwl_mvm_remove_inactive_tids(mvm, mvmsta, i, - inactive_tid_bitmap); - spin_unlock(&mvm->queue_info_lock); - spin_unlock_bh(&mvmsta->lock); - } - - rcu_read_unlock(); -} - void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm, struct ieee80211_vif *vif, const struct ieee80211_sta *sta, @@ -1430,14 +1010,12 @@ void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm, struct iwl_fw_dbg_trigger_tlv *trig; struct iwl_fw_dbg_trigger_ba *ba_trig; - if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_BA)) + trig = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), + FW_DBG_TRIGGER_BA); + if (!trig) return; - trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_BA); ba_trig = (void *)trig->data; - if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, - ieee80211_vif_to_wdev(vif), trig)) - return; if (!(le16_to_cpu(ba_trig->frame_timeout) & BIT(tid))) return; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index d519e7ebdbe8..e965cc588850 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1144,6 +1144,14 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) kfree(trans_pcie->rxq); } +static void iwl_pcie_rx_move_to_allocator(struct iwl_rxq *rxq, + struct iwl_rb_allocator *rba) +{ + spin_lock(&rba->lock); + list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); + spin_unlock(&rba->lock); +} + /* * iwl_pcie_rx_reuse_rbd - Recycle used RBDs * @@ -1175,9 +1183,7 @@ static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans, if ((rxq->used_count % RX_CLAIM_REQ_ALLOC) == RX_POST_REQ_ALLOC) { /* Move the 2 RBDs to the allocator ownership. Allocator has another 6 from pool for the request completion*/ - spin_lock(&rba->lock); - list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); - spin_unlock(&rba->lock); + iwl_pcie_rx_move_to_allocator(rxq, rba); atomic_inc(&rba->req_pending); queue_work(rba->alloc_wq, &rba->rx_alloc); @@ -1400,10 +1406,18 @@ restart: IWL_DEBUG_RX(trans, "Q %d: HW = SW = %d\n", rxq->id, r); while (i != r) { + struct iwl_rb_allocator *rba = &trans_pcie->rba; struct iwl_rx_mem_buffer *rxb; - - if (unlikely(rxq->used_count == rxq->queue_size / 2)) + /* number of RBDs still waiting for page allocation */ + u32 rb_pending_alloc = + atomic_read(&trans_pcie->rba.req_pending) * + RX_CLAIM_REQ_ALLOC; + + if (unlikely(rb_pending_alloc >= rxq->queue_size / 2 && + !emergency)) { + iwl_pcie_rx_move_to_allocator(rxq, rba); emergency = true; + } rxb = iwl_pcie_get_rxb(trans, rxq, i); if (!rxb) @@ -1425,17 +1439,13 @@ restart: iwl_pcie_rx_allocator_get(trans, rxq); if (rxq->used_count % RX_CLAIM_REQ_ALLOC == 0 && !emergency) { - struct iwl_rb_allocator *rba = &trans_pcie->rba; - /* Add the remaining empty RBDs for allocator use */ - spin_lock(&rba->lock); - list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); - spin_unlock(&rba->lock); + iwl_pcie_rx_move_to_allocator(rxq, rba); } else if (emergency) { count++; if (count == 8) { count = 0; - if (rxq->used_count < rxq->queue_size / 3) + if (rb_pending_alloc < rxq->queue_size / 3) emergency = false; rxq->read = i; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index bc6682a11fa4..5bafb3f46eb8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -931,7 +931,7 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans) else IWL_WARN(trans, "PCI should have external buffer debug\n"); - for (i = 0; i < trans->dbg_dest_reg_num; i++) { + for (i = 0; i < trans->dbg_n_dest_reg; i++) { u32 addr = le32_to_cpu(dest->reg_ops[i].addr); u32 val = le32_to_cpu(dest->reg_ops[i].val); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index ba9d37bed4c2..e880f69eac26 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -330,7 +330,7 @@ static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans, goto out_err; } iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len); - trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr, tb_len); + trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr, tb_len); /* add this subframe's headers' length to the tx_cmd */ le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start); @@ -347,8 +347,8 @@ static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans, goto out_err; } iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len); - trace_iwlwifi_dev_tx_tso_chunk(trans->dev, tso.data, - tb_len); + trace_iwlwifi_dev_tx_tb(trans->dev, skb, tso.data, + tb_len); data_left -= tb_len; tso_build_data(skb, &tso, tb_len); @@ -438,6 +438,11 @@ static int iwl_pcie_gen2_tx_add_frags(struct iwl_trans *trans, return -ENOMEM; tb_idx = iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, skb_frag_size(frag)); + trace_iwlwifi_dev_tx_tb(trans->dev, skb, + skb_frag_address(frag), + skb_frag_size(frag)); + if (tb_idx < 0) + return tb_idx; out_meta->tbs |= BIT(tb_idx); } @@ -452,7 +457,8 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_cmd_meta *out_meta, int hdr_len, - int tx_cmd_len) + int tx_cmd_len, + bool pad) { int idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr); struct iwl_tfh_tfd *tfd = iwl_pcie_get_tfd(trans, txq, idx); @@ -476,7 +482,10 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans, len = tx_cmd_len + sizeof(struct iwl_cmd_header) + hdr_len - IWL_FIRST_TB_SIZE; - tb1_len = ALIGN(len, 4); + if (pad) + tb1_len = ALIGN(len, 4); + else + tb1_len = len; /* map the data for TB1 */ tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE; @@ -484,6 +493,8 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans, if (unlikely(dma_mapping_error(trans->dev, tb_phys))) goto out_err; iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb1_len); + trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd), &dev_cmd->hdr, + IWL_FIRST_TB_SIZE + tb1_len, hdr_len); /* set up TFD's third entry to point to remainder of skb's head */ tb2_len = skb_headlen(skb) - hdr_len; @@ -494,15 +505,14 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans, if (unlikely(dma_mapping_error(trans->dev, tb_phys))) goto out_err; iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb2_len); + trace_iwlwifi_dev_tx_tb(trans->dev, skb, + skb->data + hdr_len, + tb2_len); } if (iwl_pcie_gen2_tx_add_frags(trans, skb, tfd, out_meta)) goto out_err; - trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd), &dev_cmd->hdr, - IWL_FIRST_TB_SIZE + tb1_len, hdr_len); - trace_iwlwifi_dev_tx_data(trans->dev, skb, hdr_len); - return tfd; out_err: @@ -549,7 +559,7 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans, out_meta, hdr_len, len); return iwl_pcie_gen2_build_tx(trans, txq, dev_cmd, skb, out_meta, - hdr_len, len); + hdr_len, len, !amsdu); } int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 67820bfaba64..87b7225fe289 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1994,6 +1994,9 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb, head_tb_len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(trans->dev, tb_phys))) return -EINVAL; + trace_iwlwifi_dev_tx_tb(trans->dev, skb, + skb->data + hdr_len, + head_tb_len); iwl_pcie_txq_build_tfd(trans, txq, tb_phys, head_tb_len, false); } @@ -2011,8 +2014,13 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb, if (unlikely(dma_mapping_error(trans->dev, tb_phys))) return -EINVAL; + trace_iwlwifi_dev_tx_tb(trans->dev, skb, + skb_frag_address(frag), + skb_frag_size(frag)); tb_idx = iwl_pcie_txq_build_tfd(trans, txq, tb_phys, skb_frag_size(frag), false); + if (tb_idx < 0) + return tb_idx; out_meta->tbs |= BIT(tb_idx); } @@ -2188,8 +2196,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, } iwl_pcie_txq_build_tfd(trans, txq, hdr_tb_phys, hdr_tb_len, false); - trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr, - hdr_tb_len); + trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr, + hdr_tb_len); /* add this subframe's headers' length to the tx_cmd */ le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start); @@ -2214,8 +2222,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, iwl_pcie_txq_build_tfd(trans, txq, tb_phys, size, false); - trace_iwlwifi_dev_tx_tso_chunk(trans->dev, tso.data, - size); + trace_iwlwifi_dev_tx_tb(trans->dev, skb, tso.data, + size); data_left -= size; tso_build_data(skb, &tso, size); @@ -2396,6 +2404,13 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, goto out_err; iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, false); + trace_iwlwifi_dev_tx(trans->dev, skb, + iwl_pcie_get_tfd(trans, txq, + txq->write_ptr), + trans_pcie->tfd_size, + &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len, + hdr_len); + /* * If gso_size wasn't set, don't give the frame "amsdu treatment" * (adding subframes, etc.). @@ -2419,14 +2434,6 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, out_meta))) goto out_err; } - - trace_iwlwifi_dev_tx(trans->dev, skb, - iwl_pcie_get_tfd(trans, txq, - txq->write_ptr), - trans_pcie->tfd_size, - &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len, - hdr_len); - trace_iwlwifi_dev_tx_data(trans->dev, skb, hdr_len); } /* building the A-MSDU might have changed this data, so memcpy it now */ diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c index 21bb68457cfe..40a8b941ad5c 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c @@ -908,6 +908,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv, case EZUSB_CTX_REQ_SUBMITTED: if (!ctx->in_rid) break; + /* fall through */ default: err("%s: Unexpected context state %d", __func__, state); diff --git a/drivers/net/wireless/intersil/prism54/isl_38xx.c b/drivers/net/wireless/intersil/prism54/isl_38xx.c index ce9d4db0d9ca..b0eb58a62c90 100644 --- a/drivers/net/wireless/intersil/prism54/isl_38xx.c +++ b/drivers/net/wireless/intersil/prism54/isl_38xx.c @@ -235,6 +235,7 @@ isl38xx_in_queue(isl38xx_control_block *cb, int queue) /* send queues */ case ISL38XX_CB_TX_MGMTQ: BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE); + /* fall through */ case ISL38XX_CB_TX_DATA_LQ: case ISL38XX_CB_TX_DATA_HQ: diff --git a/drivers/net/wireless/intersil/prism54/isl_ioctl.c b/drivers/net/wireless/intersil/prism54/isl_ioctl.c index 334717b0a2be..3ccf2a4b548c 100644 --- a/drivers/net/wireless/intersil/prism54/isl_ioctl.c +++ b/drivers/net/wireless/intersil/prism54/isl_ioctl.c @@ -1691,6 +1691,7 @@ static int prism54_get_encodeext(struct net_device *ndev, case DOT11_AUTH_BOTH: case DOT11_AUTH_SK: wrqu->encoding.flags |= IW_ENCODE_RESTRICTED; + /* fall through */ case DOT11_AUTH_OS: default: wrqu->encoding.flags |= IW_ENCODE_OPEN; diff --git a/drivers/net/wireless/intersil/prism54/islpci_dev.c b/drivers/net/wireless/intersil/prism54/islpci_dev.c index 325176d4d796..ad6d3a56ae06 100644 --- a/drivers/net/wireless/intersil/prism54/islpci_dev.c +++ b/drivers/net/wireless/intersil/prism54/islpci_dev.c @@ -932,6 +932,7 @@ islpci_set_state(islpci_private *priv, islpci_state_t new_state) switch (new_state) { case PRV_STATE_OFF: priv->state_off++; + /* fall through */ default: priv->state = new_state; break; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index f3863101af78..aa8058264d5b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -495,7 +495,6 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = { static spinlock_t hwsim_radio_lock; static LIST_HEAD(hwsim_radios); -static struct workqueue_struct *hwsim_wq; static struct rhashtable hwsim_radios_rht; static int hwsim_radio_idx; static int hwsim_radios_generation = 1; @@ -521,7 +520,6 @@ struct mac80211_hwsim_data { int channels, idx; bool use_chanctx; bool destroy_on_close; - struct work_struct destroy_work; u32 portid; char alpha2[2]; const struct ieee80211_regdomain *regd; @@ -2931,8 +2929,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, hwsim_radios_generation++; spin_unlock_bh(&hwsim_radio_lock); - if (idx > 0) - hwsim_mcast_new_radio(idx, info, param); + hwsim_mcast_new_radio(idx, info, param); return idx; @@ -3561,30 +3558,27 @@ static struct genl_family hwsim_genl_family __ro_after_init = { .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps), }; -static void destroy_radio(struct work_struct *work) -{ - struct mac80211_hwsim_data *data = - container_of(work, struct mac80211_hwsim_data, destroy_work); - - hwsim_radios_generation++; - mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL); -} - static void remove_user_radios(u32 portid) { struct mac80211_hwsim_data *entry, *tmp; + LIST_HEAD(list); spin_lock_bh(&hwsim_radio_lock); list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) { if (entry->destroy_on_close && entry->portid == portid) { - list_del(&entry->list); + list_move(&entry->list, &list); rhashtable_remove_fast(&hwsim_radios_rht, &entry->rht, hwsim_rht_params); - INIT_WORK(&entry->destroy_work, destroy_radio); - queue_work(hwsim_wq, &entry->destroy_work); + hwsim_radios_generation++; } } spin_unlock_bh(&hwsim_radio_lock); + + list_for_each_entry_safe(entry, tmp, &list, list) { + list_del(&entry->list); + mac80211_hwsim_del_radio(entry, wiphy_name(entry->hw->wiphy), + NULL); + } } static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, @@ -3642,6 +3636,7 @@ static __net_init int hwsim_init_net(struct net *net) static void __net_exit hwsim_exit_net(struct net *net) { struct mac80211_hwsim_data *data, *tmp; + LIST_HEAD(list); spin_lock_bh(&hwsim_radio_lock); list_for_each_entry_safe(data, tmp, &hwsim_radios, list) { @@ -3652,17 +3647,19 @@ static void __net_exit hwsim_exit_net(struct net *net) if (data->netgroup == hwsim_net_get_netgroup(&init_net)) continue; - list_del(&data->list); + list_move(&data->list, &list); rhashtable_remove_fast(&hwsim_radios_rht, &data->rht, hwsim_rht_params); hwsim_radios_generation++; - spin_unlock_bh(&hwsim_radio_lock); + } + spin_unlock_bh(&hwsim_radio_lock); + + list_for_each_entry_safe(data, tmp, &list, list) { + list_del(&data->list); mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL); - spin_lock_bh(&hwsim_radio_lock); } - spin_unlock_bh(&hwsim_radio_lock); ida_simple_remove(&hwsim_netgroup_ida, hwsim_net_get_netgroup(net)); } @@ -3694,13 +3691,9 @@ static int __init init_mac80211_hwsim(void) spin_lock_init(&hwsim_radio_lock); - hwsim_wq = alloc_workqueue("hwsim_wq", 0, 0); - if (!hwsim_wq) - return -ENOMEM; - err = rhashtable_init(&hwsim_radios_rht, &hwsim_rht_params); if (err) - goto out_free_wq; + return err; err = register_pernet_device(&hwsim_net_ops); if (err) @@ -3831,8 +3824,6 @@ out_unregister_pernet: unregister_pernet_device(&hwsim_net_ops); out_free_rht: rhashtable_destroy(&hwsim_radios_rht); -out_free_wq: - destroy_workqueue(hwsim_wq); return err; } module_init(init_mac80211_hwsim); @@ -3844,12 +3835,10 @@ static void __exit exit_mac80211_hwsim(void) hwsim_exit_netlink(); mac80211_hwsim_free(); - flush_workqueue(hwsim_wq); rhashtable_destroy(&hwsim_radios_rht); unregister_netdev(hwsim_mon); platform_driver_unregister(&mac80211_hwsim_driver); unregister_pernet_device(&hwsim_net_ops); - destroy_workqueue(hwsim_wq); } module_exit(exit_mac80211_hwsim); diff --git a/drivers/net/wireless/marvell/libertas/if_cs.c b/drivers/net/wireless/marvell/libertas/if_cs.c index 7d88223f890b..cebf03c6a622 100644 --- a/drivers/net/wireless/marvell/libertas/if_cs.c +++ b/drivers/net/wireless/marvell/libertas/if_cs.c @@ -900,8 +900,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) /* Make this card known to the libertas driver */ priv = lbs_add_card(card, &p_dev->dev); - if (!priv) { - ret = -ENOMEM; + if (IS_ERR(priv)) { + ret = PTR_ERR(priv); goto out2; } diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index 43743c26c071..8d98e7fdd27c 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -1206,8 +1206,8 @@ static int if_sdio_probe(struct sdio_func *func, priv = lbs_add_card(card, &func->dev); - if (!priv) { - ret = -ENOMEM; + if (IS_ERR(priv)) { + ret = PTR_ERR(priv); goto free; } @@ -1317,6 +1317,10 @@ static int if_sdio_suspend(struct device *dev) if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { dev_info(dev, "Suspend without wake params -- powering down card\n"); if (priv->fw_ready) { + ret = lbs_suspend(priv); + if (ret) + return ret; + priv->power_up_on_resume = true; if_sdio_power_off(card); } diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c index e9aec6cb1105..7c3224b83ef7 100644 --- a/drivers/net/wireless/marvell/libertas/if_spi.c +++ b/drivers/net/wireless/marvell/libertas/if_spi.c @@ -796,15 +796,13 @@ static void if_spi_h2c(struct if_spi_card *card, { struct lbs_private *priv = card->priv; int err = 0; - u16 int_type, port_reg; + u16 port_reg; switch (type) { case MVMS_DAT: - int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER; port_reg = IF_SPI_DATA_RDWRPORT_REG; break; case MVMS_CMD: - int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER; port_reg = IF_SPI_CMD_RDWRPORT_REG; break; default: @@ -1146,8 +1144,8 @@ static int if_spi_probe(struct spi_device *spi) * This will call alloc_etherdev. */ priv = lbs_add_card(card, &spi->dev); - if (!priv) { - err = -ENOMEM; + if (IS_ERR(priv)) { + err = PTR_ERR(priv); goto free_card; } card->priv = priv; diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c index c67a8e7be310..220dcdee8d2b 100644 --- a/drivers/net/wireless/marvell/libertas/if_usb.c +++ b/drivers/net/wireless/marvell/libertas/if_usb.c @@ -254,8 +254,11 @@ static int if_usb_probe(struct usb_interface *intf, goto dealloc; } - if (!(priv = lbs_add_card(cardp, &intf->dev))) + priv = lbs_add_card(cardp, &intf->dev); + if (IS_ERR(priv)) { + r = PTR_ERR(priv); goto err_add_card; + } cardp->priv = priv; @@ -456,8 +459,6 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp); - cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; - lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) { lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret); diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c index f22e1c220cba..f7db60bc7c7f 100644 --- a/drivers/net/wireless/marvell/libertas/main.c +++ b/drivers/net/wireless/marvell/libertas/main.c @@ -907,25 +907,29 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) struct net_device *dev; struct wireless_dev *wdev; struct lbs_private *priv = NULL; + int err; /* Allocate an Ethernet device and register it */ wdev = lbs_cfg_alloc(dmdev); if (IS_ERR(wdev)) { + err = PTR_ERR(wdev); pr_err("cfg80211 init failed\n"); - goto done; + goto err_cfg; } wdev->iftype = NL80211_IFTYPE_STATION; priv = wdev_priv(wdev); priv->wdev = wdev; - if (lbs_init_adapter(priv)) { + err = lbs_init_adapter(priv); + if (err) { pr_err("failed to initialize adapter structure\n"); goto err_wdev; } dev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup); if (!dev) { + err = -ENOMEM; dev_err(dmdev, "no memory for network device instance\n"); goto err_adapter; } @@ -949,6 +953,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) init_waitqueue_head(&priv->waitq); priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main"); if (IS_ERR(priv->main_thread)) { + err = PTR_ERR(priv->main_thread); lbs_deb_thread("Error creating main thread.\n"); goto err_ndev; } @@ -961,7 +966,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) priv->wol_gap = 20; priv->ehs_remove_supported = true; - goto done; + return priv; err_ndev: free_netdev(dev); @@ -972,10 +977,8 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) err_wdev: lbs_cfg_free(priv); - priv = NULL; - -done: - return priv; + err_cfg: + return ERR_PTR(err); } EXPORT_SYMBOL_GPL(lbs_add_card); diff --git a/drivers/net/wireless/marvell/mwifiex/ie.c b/drivers/net/wireless/marvell/mwifiex/ie.c index 75cbd609d606..6845eb57b39a 100644 --- a/drivers/net/wireless/marvell/mwifiex/ie.c +++ b/drivers/net/wireless/marvell/mwifiex/ie.c @@ -363,6 +363,7 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv, (const u8 *)hdr, hdr->len + sizeof(struct ieee_types_header))) break; + /* fall through */ default: memcpy(gen_ie->ie_buffer + ie_len, hdr, hdr->len + sizeof(struct ieee_types_header)); diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index 7f24aad94efd..0ccbcd7e887d 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -13,44 +13,5 @@ config MT76x02_USB tristate select MT76_USB -config MT76x0_COMMON - tristate - select MT76x02_LIB - -config MT76x2_COMMON - tristate - select MT76x02_LIB - -config MT76x0U - tristate "MediaTek MT76x0U (USB) support" - select MT76x0_COMMON - select MT76x02_USB - depends on MAC80211 - depends on USB - help - This adds support for MT7610U-based wireless USB dongles. - -config MT76x0E - tristate "MediaTek MT76x0E (PCIe) support" - select MT76x0_COMMON - depends on MAC80211 - depends on PCI - help - This adds support for MT7610/MT7630-based wireless PCIe devices. - -config MT76x2E - tristate "MediaTek MT76x2E (PCIe) support" - select MT76x2_COMMON - depends on MAC80211 - depends on PCI - ---help--- - This adds support for MT7612/MT7602/MT7662-based wireless PCIe devices. - -config MT76x2U - tristate "MediaTek MT76x2U (USB) support" - select MT76x2_COMMON - select MT76x02_USB - depends on MAC80211 - depends on USB - help - This adds support for MT7612U-based wireless USB dongles. +source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" +source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 2346a1b768bc..9b8d7488c545 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -1,11 +1,7 @@ obj-$(CONFIG_MT76_CORE) += mt76.o obj-$(CONFIG_MT76_USB) += mt76-usb.o -obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o -obj-$(CONFIG_MT76x2_COMMON) += mt76x2-common.o -obj-$(CONFIG_MT76x2E) += mt76x2e.o -obj-$(CONFIG_MT76x2U) += mt76x2u.o mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o tx.o agg-rx.o @@ -14,25 +10,13 @@ mt76-usb-y := usb.o usb_trace.o usb_mcu.o CFLAGS_trace.o := -I$(src) CFLAGS_usb_trace.o := -I$(src) +CFLAGS_mt76x02_trace.o := -I$(src) mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \ - mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o + mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o \ + mt76x02_txrx.o mt76x02_trace.o mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o -mt76x2-common-y := \ - mt76x2_eeprom.o mt76x2_tx_common.o mt76x2_mac_common.o \ - mt76x2_init_common.o mt76x2_common.o mt76x2_phy_common.o \ - mt76x2_debugfs.o mt76x2_mcu_common.o - -mt76x2e-y := \ - mt76x2_pci.o mt76x2_dma.o \ - mt76x2_main.o mt76x2_init.o mt76x2_tx.o \ - mt76x2_core.o mt76x2_mac.o mt76x2_mcu.o mt76x2_phy.o \ - mt76x2_dfs.o mt76x2_trace.o - -mt76x2u-y := \ - mt76x2_usb.o mt76x2u_init.o mt76x2u_main.o mt76x2u_mac.o \ - mt76x2u_mcu.o mt76x2u_phy.o mt76x2u_core.o - -CFLAGS_mt76x2_trace.o := -I$(src) +obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ +obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index 30a5d928e655..1d6bbce76041 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -79,6 +79,7 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) .copy = mt76_mmio_copy, .wr_rp = mt76_mmio_wr_rp, .rd_rp = mt76_mmio_rd_rp, + .type = MT76_BUS_MMIO, }; dev->bus = &mt76_mmio_ops; diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index f2dd4d87e355..3bfa7f5e3513 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -38,6 +38,11 @@ struct mt76_reg_pair { u32 value; }; +enum mt76_bus_type { + MT76_BUS_MMIO, + MT76_BUS_USB, +}; + struct mt76_bus_ops { u32 (*rr)(struct mt76_dev *dev, u32 offset); void (*wr)(struct mt76_dev *dev, u32 offset, u32 val); @@ -48,8 +53,12 @@ struct mt76_bus_ops { const struct mt76_reg_pair *rp, int len); int (*rd_rp)(struct mt76_dev *dev, u32 base, struct mt76_reg_pair *rp, int len); + enum mt76_bus_type type; }; +#define mt76_is_usb(dev) ((dev)->mt76.bus->type == MT76_BUS_USB) +#define mt76_is_mmio(dev) ((dev)->mt76.bus->type == MT76_BUS_MMIO) + enum mt76_txq_id { MT_TXQ_VO = IEEE80211_AC_VO, MT_TXQ_VI = IEEE80211_AC_VI, @@ -262,8 +271,6 @@ struct mt76_driver_ops { void (*sta_ps)(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps); - s8 (*get_max_txpwr_adj)(struct mt76_dev *dev, - const struct ieee80211_tx_rate *rate); }; struct mt76_channel_state { @@ -519,8 +526,8 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76xx_chip(dev) mt76_chip(&((dev)->mt76)) #define mt76xx_rev(dev) mt76_rev(&((dev)->mt76)) -#define __mt76_init_queues(dev) (dev)->queue_ops->init((dev)) -#define __mt76_queue_alloc(dev, ...) (dev)->queue_ops->alloc((dev), __VA_ARGS__) +#define mt76_init_queues(dev) (dev)->mt76.queue_ops->init(&((dev)->mt76)) +#define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_add_buf(dev, ...) (dev)->mt76.queue_ops->add_buf(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig new file mode 100644 index 000000000000..9a6157db3893 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig @@ -0,0 +1,20 @@ +config MT76x0_COMMON + tristate + select MT76x02_LIB + +config MT76x0U + tristate "MediaTek MT76x0U (USB) support" + select MT76x0_COMMON + select MT76x02_USB + depends on MAC80211 + depends on USB + help + This adds support for MT7610U-based wireless USB dongles. + +config MT76x0E + tristate "MediaTek MT76x0E (PCIe) support" + select MT76x0_COMMON + depends on MAC80211 + depends on PCI + help + This adds support for MT7610/MT7630-based wireless PCIe devices. diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile index 254d94efd24d..20672978dceb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_MT76x0_COMMON) += mt76x0-common.o mt76x0-common-y := \ init.o main.o trace.o eeprom.o phy.o \ - mac.o debugfs.o tx.o + mac.o debugfs.o mt76x0u-y := usb.o usb_mcu.o mt76x0e-y := pci.o pci_mcu.o diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c index ddc1af626b3b..3224e5b1a1e5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/debugfs.c @@ -21,7 +21,7 @@ static int mt76x0_ampdu_stat_read(struct seq_file *file, void *data) { - struct mt76x0_dev *dev = file->private; + struct mt76x02_dev *dev = file->private; int i, j; #define stat_printf(grp, off, name) \ @@ -75,7 +75,7 @@ static const struct file_operations fops_ampdu_stat = { .release = single_release, }; -void mt76x0_init_debugfs(struct mt76x0_dev *dev) +void mt76x0_init_debugfs(struct mt76x02_dev *dev) { struct dentry *dir; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/dma.h b/drivers/net/wireless/mediatek/mt76/mt76x0/dma.h deleted file mode 100644 index 891ce1c3461f..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/dma.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> - * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MT76X0U_DMA_H -#define __MT76X0U_DMA_H - -#include <asm/unaligned.h> -#include <linux/skbuff.h> - -#define MT_DMA_HDR_LEN 4 -#define MT_RX_INFO_LEN 4 -#define MT_FCE_INFO_LEN 4 -#define MT_DMA_HDRS (MT_DMA_HDR_LEN + MT_RX_INFO_LEN) - -/* Common Tx DMA descriptor fields */ -#define MT_TXD_INFO_LEN GENMASK(15, 0) -#define MT_TXD_INFO_D_PORT GENMASK(29, 27) -#define MT_TXD_INFO_TYPE GENMASK(31, 30) - -/* Tx DMA MCU command specific flags */ -#define MT_TXD_CMD_SEQ GENMASK(19, 16) -#define MT_TXD_CMD_TYPE GENMASK(26, 20) - -enum mt76_msg_port { - WLAN_PORT, - CPU_RX_PORT, - CPU_TX_PORT, - HOST_PORT, - VIRTUAL_CPU_RX_PORT, - VIRTUAL_CPU_TX_PORT, - DISCARD, -}; - -enum mt76_info_type { - DMA_PACKET, - DMA_COMMAND, -}; - -/* Tx DMA packet specific flags */ -#define MT_TXD_PKT_INFO_NEXT_VLD BIT(16) -#define MT_TXD_PKT_INFO_TX_BURST BIT(17) -#define MT_TXD_PKT_INFO_80211 BIT(19) -#define MT_TXD_PKT_INFO_TSO BIT(20) -#define MT_TXD_PKT_INFO_CSO BIT(21) -#define MT_TXD_PKT_INFO_WIV BIT(24) -#define MT_TXD_PKT_INFO_QSEL GENMASK(26, 25) - -enum mt76_qsel { - MT_QSEL_MGMT, - MT_QSEL_HCCA, - MT_QSEL_EDCA, - MT_QSEL_EDCA_2, -}; - - -static inline int mt76x0_dma_skb_wrap(struct sk_buff *skb, - enum mt76_msg_port d_port, - enum mt76_info_type type, u32 flags) -{ - u32 info; - - /* Buffer layout: - * | 4B | xfer len | pad | 4B | - * | TXINFO | pkt/cmd | zero pad to 4B | zero | - * - * length field of TXINFO should be set to 'xfer len'. - */ - - info = flags | - FIELD_PREP(MT_TXD_INFO_LEN, round_up(skb->len, 4)) | - FIELD_PREP(MT_TXD_INFO_D_PORT, d_port) | - FIELD_PREP(MT_TXD_INFO_TYPE, type); - - put_unaligned_le32(info, skb_push(skb, sizeof(info))); - return skb_put_padto(skb, round_up(skb->len, 4) + 4); -} - -static inline int -mt76x0_dma_skb_wrap_pkt(struct sk_buff *skb, enum mt76_qsel qsel, u32 flags) -{ - flags |= FIELD_PREP(MT_TXD_PKT_INFO_QSEL, qsel); - return mt76x0_dma_skb_wrap(skb, WLAN_PORT, DMA_PACKET, flags); -} - -/* Common Rx DMA descriptor fields */ -#define MT_RXD_INFO_LEN GENMASK(13, 0) -#define MT_RXD_INFO_PCIE_INTR BIT(24) -#define MT_RXD_INFO_QSEL GENMASK(26, 25) -#define MT_RXD_INFO_PORT GENMASK(29, 27) -#define MT_RXD_INFO_TYPE GENMASK(31, 30) - -/* Rx DMA packet specific flags */ -#define MT_RXD_PKT_INFO_UDP_ERR BIT(16) -#define MT_RXD_PKT_INFO_TCP_ERR BIT(17) -#define MT_RXD_PKT_INFO_IP_ERR BIT(18) -#define MT_RXD_PKT_INFO_PKT_80211 BIT(19) -#define MT_RXD_PKT_INFO_L3L4_DONE BIT(20) -#define MT_RXD_PKT_INFO_MAC_LEN GENMASK(23, 21) - -/* Rx DMA MCU command specific flags */ -#define MT_RXD_CMD_INFO_SELF_GEN BIT(15) -#define MT_RXD_CMD_INFO_CMD_SEQ GENMASK(19, 16) -#define MT_RXD_CMD_INFO_EVT_TYPE GENMASK(23, 20) - -enum mt76_evt_type { - CMD_DONE, - CMD_ERROR, - CMD_RETRY, - EVENT_PWR_RSP, - EVENT_WOW_RSP, - EVENT_CARRIER_DETECT_RSP, - EVENT_DFS_DETECT_RSP, -}; - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index 166a1fd8644e..ab4fd6e0f23a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -25,14 +25,14 @@ #define MT_MAP_READS DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16) static int -mt76x0_efuse_physical_size_check(struct mt76x0_dev *dev) +mt76x0_efuse_physical_size_check(struct mt76x02_dev *dev) { u8 data[MT_MAP_READS * 16]; int ret, i; u32 start = 0, end = 0, cnt_free; - ret = mt76x02_get_efuse_data(&dev->mt76, MT_EE_USAGE_MAP_START, - data, sizeof(data), MT_EE_PHYSICAL_READ); + ret = mt76x02_get_efuse_data(dev, MT_EE_USAGE_MAP_START, data, + sizeof(data), MT_EE_PHYSICAL_READ); if (ret) return ret; @@ -53,12 +53,12 @@ mt76x0_efuse_physical_size_check(struct mt76x0_dev *dev) return 0; } -static void mt76x0_set_chip_cap(struct mt76x0_dev *dev) +static void mt76x0_set_chip_cap(struct mt76x02_dev *dev) { - u16 nic_conf0 = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_0); - u16 nic_conf1 = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_1); + u16 nic_conf0 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0); + u16 nic_conf1 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); - mt76x02_eeprom_parse_hw_cap(&dev->mt76); + mt76x02_eeprom_parse_hw_cap(dev); dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n", dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz); @@ -82,46 +82,44 @@ static void mt76x0_set_chip_cap(struct mt76x0_dev *dev) dev_err(dev->mt76.dev, "invalid tx-rx stream\n"); } -static void mt76x0_set_temp_offset(struct mt76x0_dev *dev) +static void mt76x0_set_temp_offset(struct mt76x02_dev *dev) { u8 val; - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_2G_TARGET_POWER) >> 8; + val = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER) >> 8; if (mt76x02_field_valid(val)) - dev->caldata.temp_offset = mt76x02_sign_extend(val, 8); + dev->cal.rx.temp_offset = mt76x02_sign_extend(val, 8); else - dev->caldata.temp_offset = -10; + dev->cal.rx.temp_offset = -10; } -static void mt76x0_set_freq_offset(struct mt76x0_dev *dev) +static void mt76x0_set_freq_offset(struct mt76x02_dev *dev) { - struct mt76x0_caldata *caldata = &dev->caldata; + struct mt76x02_rx_freq_cal *caldata = &dev->cal.rx; u8 val; - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_FREQ_OFFSET); + val = mt76x02_eeprom_get(dev, MT_EE_FREQ_OFFSET); if (!mt76x02_field_valid(val)) val = 0; caldata->freq_offset = val; - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TSSI_BOUND4) >> 8; + val = mt76x02_eeprom_get(dev, MT_EE_TSSI_BOUND4) >> 8; if (!mt76x02_field_valid(val)) val = 0; caldata->freq_offset -= mt76x02_sign_extend(val, 8); } -void mt76x0_read_rx_gain(struct mt76x0_dev *dev) +void mt76x0_read_rx_gain(struct mt76x02_dev *dev) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; - struct mt76x0_caldata *caldata = &dev->caldata; + struct mt76x02_rx_freq_cal *caldata = &dev->cal.rx; s8 val, lna_5g[3], lna_2g; u16 rssi_offset; int i; - mt76x02_get_rx_gain(&dev->mt76, chan->band, &rssi_offset, - &lna_2g, lna_5g); - caldata->lna_gain = mt76x02_get_lna_gain(&dev->mt76, &lna_2g, - lna_5g, chan); + mt76x02_get_rx_gain(dev, chan->band, &rssi_offset, &lna_2g, lna_5g); + caldata->lna_gain = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); for (i = 0; i < ARRAY_SIZE(caldata->rssi_offset); i++) { val = rssi_offset >> (8 * i); @@ -132,12 +130,12 @@ void mt76x0_read_rx_gain(struct mt76x0_dev *dev) } } -static s8 mt76x0_get_delta(struct mt76_dev *dev) +static s8 mt76x0_get_delta(struct mt76x02_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->chandef; + struct cfg80211_chan_def *chandef = &dev->mt76.chandef; u8 val; - if (mt76x02_tssi_enabled(dev)) + if (mt76x0_tssi_enabled(dev)) return 0; if (chandef->width == NL80211_CHAN_WIDTH_80) { @@ -157,66 +155,66 @@ static s8 mt76x0_get_delta(struct mt76_dev *dev) return mt76x02_rate_power_val(val); } -void mt76x0_get_tx_power_per_rate(struct mt76x0_dev *dev) +void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; bool is_2ghz = chan->band == NL80211_BAND_2GHZ; struct mt76_rate_power *t = &dev->mt76.rate_power; - s8 delta = mt76x0_get_delta(&dev->mt76); + s8 delta = mt76x0_get_delta(dev); u16 val, addr; memset(t, 0, sizeof(*t)); /* cck 1M, 2M, 5.5M, 11M */ - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_BYRATE_BASE); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_BYRATE_BASE); t->cck[0] = t->cck[1] = s6_to_s8(val); t->cck[2] = t->cck[3] = s6_to_s8(val >> 8); /* ofdm 6M, 9M, 12M, 18M */ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 2 : 0x120; - val = mt76x02_eeprom_get(&dev->mt76, addr); + val = mt76x02_eeprom_get(dev, addr); t->ofdm[0] = t->ofdm[1] = s6_to_s8(val); t->ofdm[2] = t->ofdm[3] = s6_to_s8(val >> 8); /* ofdm 24M, 36M, 48M, 54M */ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 4 : 0x122; - val = mt76x02_eeprom_get(&dev->mt76, addr); + val = mt76x02_eeprom_get(dev, addr); t->ofdm[4] = t->ofdm[5] = s6_to_s8(val); t->ofdm[6] = t->ofdm[7] = s6_to_s8(val >> 8); /* ht-vht mcs 1ss 0, 1, 2, 3 */ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 6 : 0x124; - val = mt76x02_eeprom_get(&dev->mt76, addr); + val = mt76x02_eeprom_get(dev, addr); t->ht[0] = t->ht[1] = t->vht[0] = t->vht[1] = s6_to_s8(val); t->ht[2] = t->ht[3] = t->vht[2] = t->vht[3] = s6_to_s8(val >> 8); /* ht-vht mcs 1ss 4, 5, 6 */ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 8 : 0x126; - val = mt76x02_eeprom_get(&dev->mt76, addr); + val = mt76x02_eeprom_get(dev, addr); t->ht[4] = t->ht[5] = t->vht[4] = t->vht[5] = s6_to_s8(val); t->ht[6] = t->vht[6] = s6_to_s8(val >> 8); /* ht-vht mcs 1ss 0, 1, 2, 3 stbc */ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 14 : 0xec; - val = mt76x02_eeprom_get(&dev->mt76, addr); + val = mt76x02_eeprom_get(dev, addr); t->stbc[0] = t->stbc[1] = s6_to_s8(val); t->stbc[2] = t->stbc[3] = s6_to_s8(val >> 8); /* ht-vht mcs 1ss 4, 5, 6 stbc */ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 16 : 0xee; - val = mt76x02_eeprom_get(&dev->mt76, addr); + val = mt76x02_eeprom_get(dev, addr); t->stbc[4] = t->stbc[5] = s6_to_s8(val); t->stbc[6] = t->stbc[7] = s6_to_s8(val >> 8); /* vht mcs 8, 9 5GHz */ - val = mt76x02_eeprom_get(&dev->mt76, 0x132); + val = mt76x02_eeprom_get(dev, 0x132); t->vht[7] = s6_to_s8(val); t->vht[8] = s6_to_s8(val >> 8); mt76x02_add_rate_power_offset(t, delta); } -void mt76x0_get_power_info(struct mt76x0_dev *dev, u8 *info) +void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info) { struct mt76x0_chan_map { u8 chan; @@ -266,7 +264,7 @@ void mt76x0_get_power_info(struct mt76x0_dev *dev, u8 *info) addr = MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE + 2 + offset; } - data = mt76x02_eeprom_get(&dev->mt76, addr); + data = mt76x02_eeprom_get(dev, addr); info[0] = data; if (!info[0] || info[0] > 0x3f) @@ -277,7 +275,7 @@ void mt76x0_get_power_info(struct mt76x0_dev *dev, u8 *info) info[1] = 5; } -static int mt76x0_check_eeprom(struct mt76x0_dev *dev) +static int mt76x0_check_eeprom(struct mt76x02_dev *dev) { u16 val; @@ -297,7 +295,7 @@ static int mt76x0_check_eeprom(struct mt76x0_dev *dev) } } -static int mt76x0_load_eeprom(struct mt76x0_dev *dev) +static int mt76x0_load_eeprom(struct mt76x02_dev *dev) { int found; @@ -312,11 +310,11 @@ static int mt76x0_load_eeprom(struct mt76x0_dev *dev) if (found < 0) return found; - return mt76x02_get_efuse_data(&dev->mt76, 0, dev->mt76.eeprom.data, + return mt76x02_get_efuse_data(dev, 0, dev->mt76.eeprom.data, MT76X0_EEPROM_SIZE, MT_EE_READ); } -int mt76x0_eeprom_init(struct mt76x0_dev *dev) +int mt76x0_eeprom_init(struct mt76x02_dev *dev) { u8 version, fae; u16 data; @@ -326,7 +324,7 @@ int mt76x0_eeprom_init(struct mt76x0_dev *dev) if (err < 0) return err; - data = mt76x02_eeprom_get(&dev->mt76, MT_EE_VERSION); + data = mt76x02_eeprom_get(dev, MT_EE_VERSION); version = data >> 8; fae = data; @@ -337,8 +335,7 @@ int mt76x0_eeprom_init(struct mt76x0_dev *dev) dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n", version, fae); - mt76x02_mac_setaddr(&dev->mt76, - dev->mt76.eeprom.data + MT_EE_MAC_ADDR); + mt76x02_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR); mt76x0_set_chip_cap(dev); mt76x0_set_freq_offset(dev); mt76x0_set_temp_offset(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h index 4e1fafa5b8c3..ee9ade9f3c8b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h @@ -18,23 +18,15 @@ #include "../mt76x02_eeprom.h" -struct mt76x0_dev; +struct mt76x02_dev; #define MT76X0U_EE_MAX_VER 0x0c #define MT76X0_EEPROM_SIZE 512 -struct mt76x0_caldata { - s8 rssi_offset[2]; - s8 lna_gain; - - s16 temp_offset; - u8 freq_offset; -}; - -int mt76x0_eeprom_init(struct mt76x0_dev *dev); -void mt76x0_read_rx_gain(struct mt76x0_dev *dev); -void mt76x0_get_tx_power_per_rate(struct mt76x0_dev *dev); -void mt76x0_get_power_info(struct mt76x0_dev *dev, u8 *info); +int mt76x0_eeprom_init(struct mt76x02_dev *dev); +void mt76x0_read_rx_gain(struct mt76x02_dev *dev); +void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev); +void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info); static inline s8 s6_to_s8(u32 val) { @@ -45,4 +37,10 @@ static inline s8 s6_to_s8(u32 val) return ret; } +static inline bool mt76x0_tssi_enabled(struct mt76x02_dev *dev) +{ + return (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) & + MT_EE_NIC_CONF_1_TX_ALC_EN); +} + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index edfd5d94d197..4a9408801260 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -18,9 +18,6 @@ #include "eeprom.h" #include "trace.h" #include "mcu.h" -#include "../mt76x02_util.h" -#include "../mt76x02_dma.h" - #include "initvals.h" static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband) @@ -42,7 +39,7 @@ static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband) } static void -mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable) +mt76x0_set_wlan_state(struct mt76x02_dev *dev, u32 val, bool enable) { u32 mask = MT_CMB_CTRL_XTAL_RDY | MT_CMB_CTRL_PLL_LD; @@ -69,12 +66,10 @@ mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable) dev_err(dev->mt76.dev, "PLL and XTAL check failed\n"); } -void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset) +void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset) { u32 val; - mutex_lock(&dev->hw_atomic_mutex); - val = mt76_rr(dev, MT_WLAN_FUN_CTRL); if (reset) { @@ -96,12 +91,10 @@ void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset) udelay(20); mt76x0_set_wlan_state(dev, val, enable); - - mutex_unlock(&dev->hw_atomic_mutex); } EXPORT_SYMBOL_GPL(mt76x0_chip_onoff); -static void mt76x0_reset_csr_bbp(struct mt76x0_dev *dev) +static void mt76x0_reset_csr_bbp(struct mt76x02_dev *dev) { mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR | @@ -116,7 +109,7 @@ static void mt76x0_reset_csr_bbp(struct mt76x0_dev *dev) mt76_wr_rp(dev, MT_MCU_MEMMAP_WLAN, \ tab, ARRAY_SIZE(tab)) -static int mt76x0_init_bbp(struct mt76x0_dev *dev) +static int mt76x0_init_bbp(struct mt76x02_dev *dev) { int ret, i; @@ -139,13 +132,13 @@ static int mt76x0_init_bbp(struct mt76x0_dev *dev) return 0; } -static void mt76x0_init_mac_registers(struct mt76x0_dev *dev) +static void mt76x0_init_mac_registers(struct mt76x02_dev *dev) { u32 reg; RANDOM_WRITE(dev, common_mac_reg_table); - mt76x02_set_beacon_offsets(&dev->mt76); + mt76x02_set_beacon_offsets(dev); /* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */ RANDOM_WRITE(dev, mt76x0_mac_reg_table); @@ -172,15 +165,9 @@ static void mt76x0_init_mac_registers(struct mt76x0_dev *dev) reg &= ~0x000003FF; reg |= 0x00000201; mt76_wr(dev, MT_WMM_CTRL, reg); - - /* TODO: Probably not needed */ - mt76_wr(dev, 0x7028, 0); - mt76_wr(dev, 0x7010, 0); - mt76_wr(dev, 0x7024, 0); - msleep(10); } -static int mt76x0_init_wcid_mem(struct mt76x0_dev *dev) +static int mt76x0_init_wcid_mem(struct mt76x02_dev *dev) { u32 *vals; int i; @@ -199,14 +186,14 @@ static int mt76x0_init_wcid_mem(struct mt76x0_dev *dev) return 0; } -static void mt76x0_init_key_mem(struct mt76x0_dev *dev) +static void mt76x0_init_key_mem(struct mt76x02_dev *dev) { u32 vals[4] = {}; mt76_wr_copy(dev, MT_SKEY_MODE_BASE_0, vals, ARRAY_SIZE(vals)); } -static int mt76x0_init_wcid_attr_mem(struct mt76x0_dev *dev) +static int mt76x0_init_wcid_attr_mem(struct mt76x02_dev *dev) { u32 *vals; int i; @@ -223,7 +210,7 @@ static int mt76x0_init_wcid_attr_mem(struct mt76x0_dev *dev) return 0; } -static void mt76x0_reset_counters(struct mt76x0_dev *dev) +static void mt76x0_reset_counters(struct mt76x02_dev *dev) { mt76_rr(dev, MT_RX_STAT_0); mt76_rr(dev, MT_RX_STAT_1); @@ -233,7 +220,7 @@ static void mt76x0_reset_counters(struct mt76x0_dev *dev) mt76_rr(dev, MT_TX_STA_2); } -int mt76x0_mac_start(struct mt76x0_dev *dev) +int mt76x0_mac_start(struct mt76x02_dev *dev) { mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX); @@ -248,7 +235,7 @@ int mt76x0_mac_start(struct mt76x0_dev *dev) } EXPORT_SYMBOL_GPL(mt76x0_mac_start); -void mt76x0_mac_stop(struct mt76x0_dev *dev) +void mt76x0_mac_stop(struct mt76x02_dev *dev) { int i = 200, ok = 0; @@ -281,7 +268,7 @@ void mt76x0_mac_stop(struct mt76x0_dev *dev) } EXPORT_SYMBOL_GPL(mt76x0_mac_stop); -int mt76x0_init_hardware(struct mt76x0_dev *dev) +int mt76x0_init_hardware(struct mt76x02_dev *dev) { int ret; @@ -293,7 +280,7 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev) return -ETIMEDOUT; mt76x0_reset_csr_bbp(dev); - ret = mt76x02_mcu_function_select(&dev->mt76, Q_SELECT, 1, false); + ret = mt76x02_mcu_function_select(dev, Q_SELECT, 1, false); if (ret) return ret; @@ -335,12 +322,12 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev) } EXPORT_SYMBOL_GPL(mt76x0_init_hardware); -struct mt76x0_dev * +struct mt76x02_dev * mt76x0_alloc_device(struct device *pdev, const struct mt76_driver_ops *drv_ops, const struct ieee80211_ops *ops) { - struct mt76x0_dev *dev; + struct mt76x02_dev *dev; struct mt76_dev *mdev; mdev = mt76_alloc_device(sizeof(*dev), ops); @@ -350,18 +337,15 @@ mt76x0_alloc_device(struct device *pdev, mdev->dev = pdev; mdev->drv = drv_ops; - dev = container_of(mdev, struct mt76x0_dev, mt76); - mutex_init(&dev->reg_atomic_mutex); - mutex_init(&dev->hw_atomic_mutex); - spin_lock_init(&dev->mac_lock); - spin_lock_init(&dev->con_mon_lock); + dev = container_of(mdev, struct mt76x02_dev, mt76); + mutex_init(&dev->phy_mutex); atomic_set(&dev->avg_ampdu_len, 1); return dev; } EXPORT_SYMBOL_GPL(mt76x0_alloc_device); -int mt76x0_register_device(struct mt76x0_dev *dev) +int mt76x0_register_device(struct mt76x02_dev *dev) { struct mt76_dev *mdev = &dev->mt76; struct ieee80211_hw *hw = mdev->hw; @@ -384,7 +368,10 @@ int mt76x0_register_device(struct mt76x0_dev *dev) hw->max_rates = 1; hw->max_report_rates = 7; hw->max_rate_tries = 1; - hw->extra_tx_headroom = sizeof(struct mt76x02_txwi) + 4 + 2; + hw->extra_tx_headroom = 2; + if (mt76_is_usb(dev)) + hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) + + MT_DMA_HDR_LEN; hw->sta_data_size = sizeof(struct mt76x02_sta); hw->vif_data_size = sizeof(struct mt76x02_vif); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h index 6f26dc6dabde..236dce6860b4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h @@ -83,7 +83,8 @@ static const struct mt76_reg_pair mt76x0_mac_reg_table[] = { { MT_LDO_CTRL_1, 0x6B006464 }, { MT_HT_BASIC_RATE, 0x00004003 }, { MT_HT_CTRL_CFG, 0x000001FF }, - { MT_TXOP_HLDR_ET, 0x00000000 } + { MT_TXOP_HLDR_ET, 0x00000000 }, + { MT_PN_PAD_MODE, 0x00000003 }, }; static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c index f55734a922aa..7a422c590211 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c @@ -13,13 +13,13 @@ * GNU General Public License for more details. */ +#include <linux/etherdevice.h> + #include "mt76x0.h" #include "trace.h" -#include "../mt76x02_util.h" -#include <linux/etherdevice.h> -void mt76x0_mac_set_protection(struct mt76x0_dev *dev, bool legacy_prot, - int ht_mode) +void mt76x0_mac_set_protection(struct mt76x02_dev *dev, bool legacy_prot, + int ht_mode) { int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION; bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); @@ -77,7 +77,7 @@ void mt76x0_mac_set_protection(struct mt76x0_dev *dev, bool legacy_prot, mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]); } -void mt76x0_mac_set_short_preamble(struct mt76x0_dev *dev, bool short_preamb) +void mt76x0_mac_set_short_preamble(struct mt76x02_dev *dev, bool short_preamb) { if (short_preamb) mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT); @@ -85,7 +85,7 @@ void mt76x0_mac_set_short_preamble(struct mt76x0_dev *dev, bool short_preamb) mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT); } -void mt76x0_mac_config_tsf(struct mt76x0_dev *dev, bool enable, int interval) +void mt76x0_mac_config_tsf(struct mt76x02_dev *dev, bool enable, int interval) { u32 val = mt76_rr(dev, MT_BEACON_TIME_CFG); @@ -105,7 +105,7 @@ void mt76x0_mac_config_tsf(struct mt76x0_dev *dev, bool enable, int interval) MT_BEACON_TIME_CFG_TBTT_EN; } -static void mt76x0_check_mac_err(struct mt76x0_dev *dev) +static void mt76x0_check_mac_err(struct mt76x02_dev *dev) { u32 val = mt76_rr(dev, 0x10f4); @@ -120,7 +120,7 @@ static void mt76x0_check_mac_err(struct mt76x0_dev *dev) } void mt76x0_mac_work(struct work_struct *work) { - struct mt76x0_dev *dev = container_of(work, struct mt76x0_dev, + struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, mac_work.work); struct { u32 addr_base; @@ -171,7 +171,7 @@ void mt76x0_mac_work(struct work_struct *work) ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, 10 * HZ); } -void mt76x0_mac_set_ampdu_factor(struct mt76x0_dev *dev) +void mt76x0_mac_set_ampdu_factor(struct mt76x02_dev *dev) { struct ieee80211_sta *sta; struct mt76_wcid *wcid; @@ -195,67 +195,3 @@ void mt76x0_mac_set_ampdu_factor(struct mt76x0_dev *dev) mt76_wr(dev, MT_MAX_LEN_CFG, 0xa0fff | FIELD_PREP(MT_MAX_LEN_CFG_AMPDU, min_factor)); } - -static void -mt76x0_rx_monitor_beacon(struct mt76x0_dev *dev, struct mt76x02_rxwi *rxwi, - u16 rate, int rssi) -{ - dev->bcn_phy_mode = FIELD_GET(MT_RXWI_RATE_PHY, rate); - dev->avg_rssi = ((dev->avg_rssi * 15) / 16 + (rssi << 8)) / 256; -} - -static int -mt76x0_rx_is_our_beacon(struct mt76x0_dev *dev, u8 *data) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; - - return ieee80211_is_beacon(hdr->frame_control) && - ether_addr_equal(hdr->addr2, dev->ap_bssid); -} - -u32 mt76x0_mac_process_rx(struct mt76x0_dev *dev, struct sk_buff *skb, - void *rxi) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb; - struct mt76x02_rxwi *rxwi = rxi; - u32 len, ctl = le32_to_cpu(rxwi->ctl); - u16 rate = le16_to_cpu(rxwi->rate); - int rssi, pad_len = 0; - - len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl); - if (WARN_ON(len < 10)) - return 0; - - if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) { - status->flag |= RX_FLAG_DECRYPTED; - status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; - } - - if (rxwi->rxinfo & MT_RXINFO_L2PAD) - pad_len += 2; - - mt76x02_remove_hdr_pad(skb, pad_len); - - pskb_trim(skb, len); - status->chains = BIT(0); - rssi = mt76x0_phy_get_rssi(dev, rxwi); - status->chain_signal[0] = status->signal = rssi; - status->freq = dev->mt76.chandef.chan->center_freq; - status->band = dev->mt76.chandef.chan->band; - - mt76x02_mac_process_rate(status, rate); - - spin_lock_bh(&dev->con_mon_lock); - if (mt76x0_rx_is_our_beacon(dev, skb->data)) { - mt76x0_rx_monitor_beacon(dev, rxwi, rate, rssi); - } else if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST)) { - if (dev->avg_rssi == 0) - dev->avg_rssi = rssi; - else - dev->avg_rssi = (dev->avg_rssi * 15) / 16 + rssi / 16; - - } - spin_unlock_bh(&dev->con_mon_lock); - - return len; -} diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.h deleted file mode 100644 index b887693a56b6..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> - * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MT76_MAC_H -#define __MT76_MAC_H - -u32 mt76x0_mac_process_rx(struct mt76x0_dev *dev, struct sk_buff *skb, - void *rxi); -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index c3cea52ec0dc..9273d2d2764a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -13,21 +13,33 @@ * GNU General Public License for more details. */ -#include "mt76x0.h" -#include "mac.h" -#include "../mt76x02_util.h" #include <linux/etherdevice.h> +#include "mt76x0.h" + +static int +mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) +{ + int ret; + + cancel_delayed_work_sync(&dev->cal_work); + + mt76_set_channel(&dev->mt76); + ret = mt76x0_phy_set_channel(dev, chandef); + mt76_txq_schedule_all(&dev->mt76); + + return ret; +} int mt76x0_config(struct ieee80211_hw *hw, u32 changed) { - struct mt76x0_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; int ret = 0; mutex_lock(&dev->mt76.mutex); if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ieee80211_stop_queues(hw); - ret = mt76x0_phy_set_channel(dev, &hw->conf.chandef); + ret = mt76x0_set_channel(dev, &hw->conf.chandef); ieee80211_wake_queues(hw); } @@ -54,7 +66,7 @@ int mt76x0_config(struct ieee80211_hw *hw, u32 changed) EXPORT_SYMBOL_GPL(mt76x0_config); static void -mt76x0_addr_wr(struct mt76x0_dev *dev, const u32 offset, const u8 *addr) +mt76x0_addr_wr(struct mt76x02_dev *dev, const u32 offset, const u8 *addr) { mt76_wr(dev, offset, get_unaligned_le32(addr)); mt76_wr(dev, offset + 4, addr[4] | addr[5] << 8); @@ -64,13 +76,10 @@ void mt76x0_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { - struct mt76x0_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); - if (changed & BSS_CHANGED_ASSOC) - mt76x0_phy_con_cal_onoff(dev, info); - if (changed & BSS_CHANGED_BSSID) { mt76x0_addr_wr(dev, MT_MAC_BSSID_DW0, info->bssid); @@ -117,10 +126,8 @@ EXPORT_SYMBOL_GPL(mt76x0_bss_info_changed); void mt76x0_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac_addr) { - struct mt76x0_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; - cancel_delayed_work_sync(&dev->cal_work); - mt76x0_agc_save(dev); set_bit(MT76_SCANNING, &dev->mt76.state); } EXPORT_SYMBOL_GPL(mt76x0_sw_scan); @@ -128,19 +135,15 @@ EXPORT_SYMBOL_GPL(mt76x0_sw_scan); void mt76x0_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt76x0_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; - mt76x0_agc_restore(dev); clear_bit(MT76_SCANNING, &dev->mt76.state); - - ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, - MT_CALIBRATE_INTERVAL); } EXPORT_SYMBOL_GPL(mt76x0_sw_scan_complete); int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { - struct mt76x0_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mt76_rmw_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH, value); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h index 297bf6b94d8c..3b34e1d2769f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h @@ -17,7 +17,7 @@ #include "../mt76x02_mcu.h" -struct mt76x0_dev; +struct mt76x02_dev; #define MT_MCU_IVB_SIZE 0x40 #define MT_MCU_DLM_OFFSET 0x80000 @@ -39,11 +39,14 @@ enum mcu_calibrate { MCU_CAL_TXDCOC, MCU_CAL_RX_GROUP_DELAY, MCU_CAL_TX_GROUP_DELAY, + MCU_CAL_VCO, + MCU_CAL_NO_SIGNAL = 0xfe, + MCU_CAL_FULL = 0xff, }; -int mt76x0e_mcu_init(struct mt76x0_dev *dev); -int mt76x0u_mcu_init(struct mt76x0_dev *dev); -static inline int mt76x0_firmware_running(struct mt76x0_dev *dev) +int mt76x0e_mcu_init(struct mt76x02_dev *dev); +int mt76x0u_mcu_init(struct mt76x02_dev *dev); +static inline int mt76x0_firmware_running(struct mt76x02_dev *dev) { return mt76_rr(dev, MT_MCU_COM_REG0) == 1; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h index a37dbf944b15..2187bafaf2e9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h @@ -25,114 +25,33 @@ #include <net/mac80211.h> #include <linux/debugfs.h> -#include "../mt76.h" -#include "../mt76x02_regs.h" -#include "../mt76x02_mac.h" +#include "../mt76x02.h" #include "eeprom.h" #define MT_CALIBRATE_INTERVAL (4 * HZ) -#define MT_FREQ_CAL_INIT_DELAY (30 * HZ) -#define MT_FREQ_CAL_CHECK_INTERVAL (10 * HZ) -#define MT_FREQ_CAL_ADJ_INTERVAL (HZ / 2) - -#define MT_BBP_REG_VERSION 0x00 - #define MT_USB_AGGR_SIZE_LIMIT 21 /* * 1024B */ #define MT_USB_AGGR_TIMEOUT 0x80 /* * 33ns */ -struct mac_stats { - u64 rx_stat[6]; - u64 tx_stat[6]; - u64 aggr_stat[2]; - u64 aggr_n[32]; - u64 zero_len_del[2]; -}; - -struct mt76x0_eeprom_params; - -#define MT_EE_TEMPERATURE_SLOPE 39 -#define MT_FREQ_OFFSET_INVALID -128 - -/* addr req mask */ -#define MT_VEND_TYPE_EEPROM BIT(31) -#define MT_VEND_TYPE_CFG BIT(30) -#define MT_VEND_TYPE_MASK (MT_VEND_TYPE_EEPROM | MT_VEND_TYPE_CFG) - -#define MT_VEND_ADDR(type, n) (MT_VEND_TYPE_##type | (n)) - -enum mt_bw { - MT_BW_20, - MT_BW_40, -}; - -/** - * struct mt76x0_dev - adapter structure - * @lock: protects @wcid->tx_rate. - * @mac_lock: locks out mac80211's tx status and rx paths. - * @con_mon_lock: protects @ap_bssid, @bcn_*, @avg_rssi. - * @mutex: ensures exclusive access from mac80211 callbacks. - * @reg_atomic_mutex: ensures atomicity of indirect register accesses - * (accesses to RF and BBP). - * @hw_atomic_mutex: ensures exclusive access to HW during critical - * operations (power management, channel switch). - */ -struct mt76x0_dev { - struct mt76_dev mt76; /* must be first */ - - u8 data[32]; - - struct delayed_work cal_work; - struct delayed_work mac_work; - - spinlock_t mac_lock; - - struct mt76x0_caldata caldata; - - struct mutex reg_atomic_mutex; - struct mutex hw_atomic_mutex; - - atomic_t avg_ampdu_len; - - /* Connection monitoring things */ - spinlock_t con_mon_lock; - u8 ap_bssid[ETH_ALEN]; - - s8 bcn_freq_off; - u8 bcn_phy_mode; - - int avg_rssi; /* starts at 0 and converges */ - - u8 agc_save; - - bool no_2ghz; - - struct mac_stats stats; -}; - -static inline bool is_mt7610e(struct mt76x0_dev *dev) +static inline bool is_mt7610e(struct mt76x02_dev *dev) { /* TODO */ return false; } -void mt76x0_init_debugfs(struct mt76x0_dev *dev); - -/* Compatibility with mt76 */ -#define mt76_rmw_field(_dev, _reg, _field, _val) \ - mt76_rmw(_dev, _reg, _field, FIELD_PREP(_field, _val)) +void mt76x0_init_debugfs(struct mt76x02_dev *dev); /* Init */ -struct mt76x0_dev * +struct mt76x02_dev * mt76x0_alloc_device(struct device *pdev, const struct mt76_driver_ops *drv_ops, const struct ieee80211_ops *ops); -int mt76x0_init_hardware(struct mt76x0_dev *dev); -int mt76x0_register_device(struct mt76x0_dev *dev); -void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset); +int mt76x0_init_hardware(struct mt76x02_dev *dev); +int mt76x0_register_device(struct mt76x02_dev *dev); +void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset); -int mt76x0_mac_start(struct mt76x0_dev *dev); -void mt76x0_mac_stop(struct mt76x0_dev *dev); +int mt76x0_mac_start(struct mt76x02_dev *dev); +void mt76x0_mac_stop(struct mt76x02_dev *dev); int mt76x0_config(struct ieee80211_hw *hw, u32 changed); void mt76x0_bss_info_changed(struct ieee80211_hw *hw, @@ -145,35 +64,20 @@ void mt76x0_sw_scan_complete(struct ieee80211_hw *hw, int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value); /* PHY */ -void mt76x0_phy_init(struct mt76x0_dev *dev); -int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev); -void mt76x0_agc_save(struct mt76x0_dev *dev); -void mt76x0_agc_restore(struct mt76x0_dev *dev); -int mt76x0_phy_set_channel(struct mt76x0_dev *dev, +void mt76x0_phy_init(struct mt76x02_dev *dev); +int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev); +int mt76x0_phy_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef); -void mt76x0_phy_recalibrate_after_assoc(struct mt76x0_dev *dev); -int mt76x0_phy_get_rssi(struct mt76x0_dev *dev, struct mt76x02_rxwi *rxwi); -void mt76x0_phy_con_cal_onoff(struct mt76x0_dev *dev, - struct ieee80211_bss_conf *info); -void mt76x0_phy_set_txpower(struct mt76x0_dev *dev); +void mt76x0_phy_recalibrate_after_assoc(struct mt76x02_dev *dev); +void mt76x0_phy_set_txpower(struct mt76x02_dev *dev); +void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on); /* MAC */ void mt76x0_mac_work(struct work_struct *work); -void mt76x0_mac_set_protection(struct mt76x0_dev *dev, bool legacy_prot, +void mt76x0_mac_set_protection(struct mt76x02_dev *dev, bool legacy_prot, int ht_mode); -void mt76x0_mac_set_short_preamble(struct mt76x0_dev *dev, bool short_preamb); -void mt76x0_mac_config_tsf(struct mt76x0_dev *dev, bool enable, int interval); -void mt76x0_mac_set_ampdu_factor(struct mt76x0_dev *dev); - -/* TX */ -void mt76x0_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, - struct sk_buff *skb); -struct mt76x02_txwi * -mt76x0_push_txwi(struct mt76x0_dev *dev, struct sk_buff *skb, - struct ieee80211_sta *sta, struct mt76_wcid *wcid, - int pkt_len); - -void mt76x0_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, - struct sk_buff *skb); +void mt76x0_mac_set_short_preamble(struct mt76x02_dev *dev, bool short_preamb); +void mt76x0_mac_config_tsf(struct mt76x02_dev *dev, bool enable, int interval); +void mt76x0_mac_set_ampdu_factor(struct mt76x02_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index 876291dd3c1e..522c86059bcb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -20,16 +20,15 @@ #include "mt76x0.h" #include "mcu.h" -#include "../mt76x02_dma.h" -#include "../mt76x02_util.h" static int mt76x0e_start(struct ieee80211_hw *hw) { - struct mt76x0_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); - mt76x02_mac_start(&dev->mt76); + mt76x02_mac_start(dev); + mt76x0_phy_calibrate(dev, true); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, MT_CALIBRATE_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, @@ -41,13 +40,8 @@ static int mt76x0e_start(struct ieee80211_hw *hw) return 0; } -static void mt76x0e_stop(struct ieee80211_hw *hw) +static void mt76x0e_stop_hw(struct mt76x02_dev *dev) { - struct mt76x0_dev *dev = hw->priv; - - mutex_lock(&dev->mt76.mutex); - - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); cancel_delayed_work_sync(&dev->cal_work); cancel_delayed_work_sync(&dev->mac_work); @@ -62,21 +56,38 @@ static void mt76x0e_stop(struct ieee80211_hw *hw) 0, 1000)) dev_warn(dev->mt76.dev, "TX DMA did not stop\n"); mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN); +} +static void mt76x0e_stop(struct ieee80211_hw *hw) +{ + struct mt76x02_dev *dev = hw->priv; + + mutex_lock(&dev->mt76.mutex); + clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + mt76x0e_stop_hw(dev); mutex_unlock(&dev->mt76.mutex); } static const struct ieee80211_ops mt76x0e_ops = { - .tx = mt76x0_tx, + .tx = mt76x02_tx, .start = mt76x0e_start, .stop = mt76x0e_stop, - .config = mt76x0_config, .add_interface = mt76x02_add_interface, .remove_interface = mt76x02_remove_interface, + .config = mt76x0_config, .configure_filter = mt76x02_configure_filter, + .sta_add = mt76x02_sta_add, + .sta_remove = mt76x02_sta_remove, + .set_key = mt76x02_set_key, + .conf_tx = mt76x02_conf_tx, + .sw_scan_start = mt76x0_sw_scan, + .sw_scan_complete = mt76x0_sw_scan_complete, + .ampdu_action = mt76x02_ampdu_action, + .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update, + .wake_tx_queue = mt76_wake_tx_queue, }; -static int mt76x0e_register_device(struct mt76x0_dev *dev) +static int mt76x0e_register_device(struct mt76x02_dev *dev) { int err; @@ -84,12 +95,12 @@ static int mt76x0e_register_device(struct mt76x0_dev *dev) if (!mt76x02_wait_for_mac(&dev->mt76)) return -ETIMEDOUT; - mt76x02_dma_disable(&dev->mt76); + mt76x02_dma_disable(dev); err = mt76x0e_mcu_init(dev); if (err < 0) return err; - err = mt76x02_dma_init(&dev->mt76); + err = mt76x02_dma_init(dev); if (err < 0) return err; @@ -101,30 +112,36 @@ static int mt76x0e_register_device(struct mt76x0_dev *dev) u16 val; mt76_clear(dev, MT_COEXCFG0, BIT(0)); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_0); - if (val & MT_EE_NIC_CONF_0_PA_IO_CURRENT) { - u32 data; - - /* set external external PA I/O - * current to 16mA - */ - data = mt76_rr(dev, 0x11c); - val |= 0xc03; - mt76_wr(dev, 0x11c, val); - } + + val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0); + if (!(val & MT_EE_NIC_CONF_0_PA_IO_CURRENT)) + mt76_set(dev, MT_XO_CTRL7, 0xc03); } mt76_clear(dev, 0x110, BIT(9)); mt76_set(dev, MT_MAX_LEN_CFG, BIT(13)); + err = mt76x0_register_device(dev); + if (err < 0) + return err; + + set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + return 0; } static int mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct mt76x0_dev *dev; - int ret = -ENODEV; + static const struct mt76_driver_ops drv_ops = { + .txwi_size = sizeof(struct mt76x02_txwi), + .tx_prepare_skb = mt76x02_tx_prepare_skb, + .tx_complete_skb = mt76x02_tx_complete_skb, + .rx_skb = mt76x02_queue_rx_skb, + .rx_poll_complete = mt76x02_rx_poll_complete, + }; + struct mt76x02_dev *dev; + int ret; ret = pcim_enable_device(pdev); if (ret) @@ -140,7 +157,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; - dev = mt76x0_alloc_device(&pdev->dev, NULL, &mt76x0e_ops); + dev = mt76x0_alloc_device(&pdev->dev, &drv_ops, &mt76x0e_ops); if (!dev) return -ENOMEM; @@ -149,6 +166,11 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); + ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto error; + ret = mt76x0e_register_device(dev); if (ret < 0) goto error; @@ -160,12 +182,23 @@ error: return ret; } +static void mt76x0e_cleanup(struct mt76x02_dev *dev) +{ + clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + mt76x0_chip_onoff(dev, false, false); + mt76x0e_stop_hw(dev); + mt76x02_dma_cleanup(dev); + mt76x02_mcu_cleanup(dev); +} + static void mt76x0e_remove(struct pci_dev *pdev) { struct mt76_dev *mdev = pci_get_drvdata(pdev); + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); mt76_unregister_device(mdev); + mt76x0e_cleanup(dev); ieee80211_free_hw(mdev->hw); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c index e3cf049314bb..569861289aa5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c @@ -24,7 +24,7 @@ #define MT_MCU_IVB_ADDR (MT_MCU_ILM_ADDR + 0x54000 - MT_MCU_IVB_SIZE) -static int mt76x0e_load_firmware(struct mt76x0_dev *dev) +static int mt76x0e_load_firmware(struct mt76x02_dev *dev) { bool is_combo_chip = mt76_chip(&dev->mt76) != 0x7610; u32 val, ilm_len, dlm_len, offset = 0; @@ -116,6 +116,7 @@ static int mt76x0e_load_firmware(struct mt76x0_dev *dev) goto out; } + mt76x02_set_ethtool_fwver(dev, hdr); dev_dbg(dev->mt76.dev, "Firmware running!\n"); out: @@ -126,7 +127,7 @@ out: return err; } -int mt76x0e_mcu_init(struct mt76x0_dev *dev) +int mt76x0e_mcu_init(struct mt76x02_dev *dev) { static const struct mt76_mcu_ops mt76x0e_mcu_ops = { .mcu_msg_alloc = mt76x02_mcu_msg_alloc, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 4fd2c65e196a..cf024950e0ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -14,6 +14,9 @@ * GNU General Public License for more details. */ +#include <linux/kernel.h> +#include <linux/etherdevice.h> + #include "mt76x0.h" #include "mcu.h" #include "eeprom.h" @@ -23,10 +26,8 @@ #include "initvals_phy.h" #include "../mt76x02_phy.h" -#include <linux/etherdevice.h> - static int -mt76x0_rf_csr_wr(struct mt76x0_dev *dev, u32 offset, u8 value) +mt76x0_rf_csr_wr(struct mt76x02_dev *dev, u32 offset, u8 value) { int ret = 0; u8 bank, reg; @@ -37,10 +38,10 @@ mt76x0_rf_csr_wr(struct mt76x0_dev *dev, u32 offset, u8 value) bank = MT_RF_BANK(offset); reg = MT_RF_REG(offset); - if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8) + if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank > 8)) return -EINVAL; - mutex_lock(&dev->reg_atomic_mutex); + mutex_lock(&dev->phy_mutex); if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100)) { ret = -ETIMEDOUT; @@ -55,7 +56,7 @@ mt76x0_rf_csr_wr(struct mt76x0_dev *dev, u32 offset, u8 value) MT_RF_CSR_CFG_KICK); trace_mt76x0_rf_write(&dev->mt76, bank, offset, value); out: - mutex_unlock(&dev->reg_atomic_mutex); + mutex_unlock(&dev->phy_mutex); if (ret < 0) dev_err(dev->mt76.dev, "Error: RF write %d:%d failed:%d!!\n", @@ -64,8 +65,7 @@ out: return ret; } -static int -mt76x0_rf_csr_rr(struct mt76x0_dev *dev, u32 offset) +static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 offset) { int ret = -ETIMEDOUT; u32 val; @@ -77,10 +77,10 @@ mt76x0_rf_csr_rr(struct mt76x0_dev *dev, u32 offset) bank = MT_RF_BANK(offset); reg = MT_RF_REG(offset); - if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8) + if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank > 8)) return -EINVAL; - mutex_lock(&dev->reg_atomic_mutex); + mutex_lock(&dev->phy_mutex); if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100)) goto out; @@ -100,7 +100,7 @@ mt76x0_rf_csr_rr(struct mt76x0_dev *dev, u32 offset) trace_mt76x0_rf_read(&dev->mt76, bank, offset, ret); } out: - mutex_unlock(&dev->reg_atomic_mutex); + mutex_unlock(&dev->phy_mutex); if (ret < 0) dev_err(dev->mt76.dev, "Error: RF read %d:%d failed:%d!!\n", @@ -110,36 +110,38 @@ out: } static int -rf_wr(struct mt76x0_dev *dev, u32 offset, u8 val) +rf_wr(struct mt76x02_dev *dev, u32 offset, u8 val) { - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) { + if (mt76_is_usb(dev)) { struct mt76_reg_pair pair = { .reg = offset, .value = val, }; + WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING, + &dev->mt76.state)); return mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1); } else { - WARN_ON_ONCE(1); return mt76x0_rf_csr_wr(dev, offset, val); } } static int -rf_rr(struct mt76x0_dev *dev, u32 offset) +rf_rr(struct mt76x02_dev *dev, u32 offset) { int ret; u32 val; - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) { + if (mt76_is_usb(dev)) { struct mt76_reg_pair pair = { .reg = offset, }; + WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING, + &dev->mt76.state)); ret = mt76_rd_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1); val = pair.value; } else { - WARN_ON_ONCE(1); ret = val = mt76x0_rf_csr_rr(dev, offset); } @@ -147,7 +149,7 @@ rf_rr(struct mt76x0_dev *dev, u32 offset) } static int -rf_rmw(struct mt76x0_dev *dev, u32 offset, u8 mask, u8 val) +rf_rmw(struct mt76x02_dev *dev, u32 offset, u8 mask, u8 val) { int ret; @@ -163,31 +165,43 @@ rf_rmw(struct mt76x0_dev *dev, u32 offset, u8 mask, u8 val) } static int -rf_set(struct mt76x0_dev *dev, u32 offset, u8 val) +rf_set(struct mt76x02_dev *dev, u32 offset, u8 val) { return rf_rmw(dev, offset, 0, val); } #if 0 static int -rf_clear(struct mt76x0_dev *dev, u32 offset, u8 mask) +rf_clear(struct mt76x02_dev *dev, u32 offset, u8 mask) { return rf_rmw(dev, offset, mask, 0); } #endif -#define RF_RANDOM_WRITE(dev, tab) \ - mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, \ - tab, ARRAY_SIZE(tab)) +static void +mt76x0_rf_csr_wr_rp(struct mt76x02_dev *dev, const struct mt76_reg_pair *data, + int n) +{ + while (n-- > 0) { + mt76x0_rf_csr_wr(dev, data->reg, data->value); + data++; + } +} + +#define RF_RANDOM_WRITE(dev, tab) do { \ + if (mt76_is_mmio(dev)) \ + mt76x0_rf_csr_wr_rp(dev, tab, ARRAY_SIZE(tab)); \ + else \ + mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, tab, ARRAY_SIZE(tab));\ +} while (0) -int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev) +int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev) { int i = 20; u32 val; do { val = mt76_rr(dev, MT_BBP(CORE, 0)); - printk("BBP version %08x\n", val); if (val && ~val) break; } while (--i); @@ -197,44 +211,11 @@ int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev) return -EIO; } + dev_dbg(dev->mt76.dev, "BBP version %08x\n", val); return 0; } -static void -mt76x0_bbp_set_ctrlch(struct mt76x0_dev *dev, enum nl80211_chan_width width, - u8 ctrl) -{ - int core_val, agc_val; - - switch (width) { - case NL80211_CHAN_WIDTH_80: - core_val = 3; - agc_val = 7; - break; - case NL80211_CHAN_WIDTH_40: - core_val = 2; - agc_val = 3; - break; - default: - core_val = 0; - agc_val = 1; - break; - } - - mt76_rmw_field(dev, MT_BBP(CORE, 1), MT_BBP_CORE_R1_BW, core_val); - mt76_rmw_field(dev, MT_BBP(AGC, 0), MT_BBP_AGC_R0_BW, agc_val); - mt76_rmw_field(dev, MT_BBP(AGC, 0), MT_BBP_AGC_R0_CTRL_CHAN, ctrl); - mt76_rmw_field(dev, MT_BBP(TXBE, 0), MT_BBP_TXBE_R0_CTRL_CHAN, ctrl); -} - -int mt76x0_phy_get_rssi(struct mt76x0_dev *dev, struct mt76x02_rxwi *rxwi) -{ - struct mt76x0_caldata *caldata = &dev->caldata; - - return rxwi->rssi[0] + caldata->rssi_offset[0] - caldata->lna_gain; -} - -static void mt76x0_vco_cal(struct mt76x0_dev *dev, u8 channel) +static void mt76x0_vco_cal(struct mt76x02_dev *dev, u8 channel) { u8 val; @@ -291,14 +272,7 @@ static void mt76x0_vco_cal(struct mt76x0_dev *dev, u8 channel) } static void -mt76x0_mac_set_ctrlch(struct mt76x0_dev *dev, bool primary_upper) -{ - mt76_rmw_field(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_UPPER_40M, - primary_upper); -} - -static void -mt76x0_phy_set_band(struct mt76x0_dev *dev, enum nl80211_band band) +mt76x0_phy_set_band(struct mt76x02_dev *dev, enum nl80211_band band) { switch (band) { case NL80211_BAND_2GHZ: @@ -307,9 +281,6 @@ mt76x0_phy_set_band(struct mt76x0_dev *dev, enum nl80211_band band) rf_wr(dev, MT_RF(5, 0), 0x45); rf_wr(dev, MT_RF(6, 0), 0x44); - mt76_set(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_2G); - mt76_clear(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_5G); - mt76_wr(dev, MT_TX_ALC_VGA3, 0x00050007); mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x003E0002); break; @@ -319,9 +290,6 @@ mt76x0_phy_set_band(struct mt76x0_dev *dev, enum nl80211_band band) rf_wr(dev, MT_RF(5, 0), 0x44); rf_wr(dev, MT_RF(6, 0), 0x45); - mt76_clear(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_2G); - mt76_set(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_5G); - mt76_wr(dev, MT_TX_ALC_VGA3, 0x00000005); mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x01010102); break; @@ -331,7 +299,7 @@ mt76x0_phy_set_band(struct mt76x0_dev *dev, enum nl80211_band band) } static void -mt76x0_phy_set_chan_rf_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band) +mt76x0_phy_set_chan_rf_params(struct mt76x02_dev *dev, u8 channel, u16 rf_bw_band) { u16 rf_band = rf_bw_band & 0xff00; u16 rf_bw = rf_bw_band & 0x00ff; @@ -483,7 +451,7 @@ mt76x0_phy_set_chan_rf_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band mt76_wr(dev, MT_RF_MISC, mac_reg); band = (rf_band & RF_G_BAND) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; - if (mt76x02_ext_pa_enabled(&dev->mt76, band)) { + if (mt76x02_ext_pa_enabled(dev, band)) { /* MT_RF_MISC (offset: 0x0518) [2]1'b1: enable external A band PA, 1'b0: disable external A band PA @@ -522,7 +490,7 @@ mt76x0_phy_set_chan_rf_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band } static void -mt76x0_phy_set_chan_bbp_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_band) +mt76x0_phy_set_chan_bbp_params(struct mt76x02_dev *dev, u16 rf_bw_band) { int i; @@ -538,7 +506,7 @@ mt76x0_phy_set_chan_bbp_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_ban u8 gain; gain = FIELD_GET(MT_BBP_AGC_GAIN, val); - gain -= dev->caldata.lna_gain * 2; + gain -= dev->cal.rx.lna_gain * 2; val &= ~MT_BBP_AGC_GAIN; val |= FIELD_PREP(MT_BBP_AGC_GAIN, gain); mt76_wr(dev, pair->reg, val); @@ -548,7 +516,7 @@ mt76x0_phy_set_chan_bbp_params(struct mt76x0_dev *dev, u8 channel, u16 rf_bw_ban } } -static void mt76x0_ant_select(struct mt76x0_dev *dev) +static void mt76x0_ant_select(struct mt76x02_dev *dev) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; @@ -568,7 +536,7 @@ static void mt76x0_ant_select(struct mt76x0_dev *dev) } static void -mt76x0_bbp_set_bw(struct mt76x0_dev *dev, enum nl80211_chan_width width) +mt76x0_bbp_set_bw(struct mt76x02_dev *dev, enum nl80211_chan_width width) { enum { BW_20 = 0, BW_40 = 1, BW_80 = 2, BW_10 = 4}; int bw; @@ -595,10 +563,10 @@ mt76x0_bbp_set_bw(struct mt76x0_dev *dev, enum nl80211_chan_width width) return ; } - mt76x02_mcu_function_select(&dev->mt76, BW_SETTING, bw, false); + mt76x02_mcu_function_select(dev, BW_SETTING, bw, false); } -void mt76x0_phy_set_txpower(struct mt76x0_dev *dev) +void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) { struct mt76_rate_power *t = &dev->mt76.rate_power; u8 info[2]; @@ -611,12 +579,53 @@ void mt76x0_phy_set_txpower(struct mt76x0_dev *dev) dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t); mt76x02_add_rate_power_offset(t, -info[0]); - mt76x02_phy_set_txpower(&dev->mt76, info[0], info[1]); + mt76x02_phy_set_txpower(dev, info[0], info[1]); } -static int -__mt76x0_phy_set_channel(struct mt76x0_dev *dev, - struct cfg80211_chan_def *chandef) +void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on) +{ + struct ieee80211_channel *chan = dev->mt76.chandef.chan; + u32 val, tx_alc, reg_val; + + if (power_on) { + mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, chan->hw_value, + false); + usleep_range(10, 20); + /* XXX: tssi */ + } + + tx_alc = mt76_rr(dev, MT_TX_ALC_CFG_0); + mt76_wr(dev, MT_TX_ALC_CFG_0, 0); + usleep_range(500, 700); + + reg_val = mt76_rr(dev, MT_BBP(IBI, 9)); + mt76_wr(dev, MT_BBP(IBI, 9), 0xffffff7e); + + if (chan->band == NL80211_BAND_5GHZ) { + if (chan->hw_value < 100) + val = 0x701; + else if (chan->hw_value < 140) + val = 0x801; + else + val = 0x901; + } else { + val = 0x600; + } + + mt76x02_mcu_calibrate(dev, MCU_CAL_FULL, val, false); + msleep(350); + mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 1, false); + usleep_range(15000, 20000); + + mt76_wr(dev, MT_BBP(IBI, 9), reg_val); + mt76_wr(dev, MT_TX_ALC_CFG_0, tx_alc); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1, false); +} +EXPORT_SYMBOL_GPL(mt76x0_phy_calibrate); + +int mt76x0_phy_set_channel(struct mt76x02_dev *dev, + struct cfg80211_chan_def *chandef) { u32 ext_cca_chan[4] = { [0] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 0) | @@ -674,9 +683,19 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev, break; } - mt76x0_bbp_set_bw(dev, chandef->width); - mt76x0_bbp_set_ctrlch(dev, chandef->width, ch_group_index); - mt76x0_mac_set_ctrlch(dev, ch_group_index & 1); + if (mt76_is_usb(dev)) { + mt76x0_bbp_set_bw(dev, chandef->width); + } else { + if (chandef->width == NL80211_CHAN_WIDTH_80 || + chandef->width == NL80211_CHAN_WIDTH_40) + val = 0x201; + else + val = 0x601; + mt76_wr(dev, MT_TX_SW_CFG0, val); + } + mt76x02_phy_set_bw(dev, chandef->width, ch_group_index); + mt76x02_phy_set_band(dev, chandef->chan->band, + ch_group_index & 1); mt76x0_ant_select(dev); mt76_rmw(dev, MT_EXT_CCA_CFG, @@ -689,7 +708,6 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev, mt76x0_phy_set_band(dev, chandef->chan->band); mt76x0_phy_set_chan_rf_params(dev, channel, rf_bw_band); - mt76x0_read_rx_gain(dev); /* set Japan Tx filter at channel 14 */ val = mt76_rr(dev, MT_BBP(CORE, 1)); @@ -699,39 +717,37 @@ __mt76x0_phy_set_channel(struct mt76x0_dev *dev, val &= ~0x20; mt76_wr(dev, MT_BBP(CORE, 1), val); - mt76x0_phy_set_chan_bbp_params(dev, channel, rf_bw_band); + mt76x0_read_rx_gain(dev); + mt76x0_phy_set_chan_bbp_params(dev, rf_bw_band); + mt76x02_init_agc_gain(dev); - /* Vendor driver don't do it */ - /* mt76x0_phy_set_tx_power(dev, channel, rf_bw_band); */ + if (mt76_is_usb(dev)) { + mt76x0_vco_cal(dev, channel); + } else { + /* enable vco */ + rf_set(dev, MT_RF(0, 4), BIT(7)); + } - mt76x0_vco_cal(dev, channel); if (scan) - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, 1, false); + return 0; + if (mt76_is_mmio(dev)) + mt76x0_phy_calibrate(dev, false); mt76x0_phy_set_txpower(dev); - return 0; -} - -int mt76x0_phy_set_channel(struct mt76x0_dev *dev, - struct cfg80211_chan_def *chandef) -{ - int ret; - - mutex_lock(&dev->hw_atomic_mutex); - ret = __mt76x0_phy_set_channel(dev, chandef); - mutex_unlock(&dev->hw_atomic_mutex); + ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, + MT_CALIBRATE_INTERVAL); - return ret; + return 0; } -void mt76x0_phy_recalibrate_after_assoc(struct mt76x0_dev *dev) +void mt76x0_phy_recalibrate_after_assoc(struct mt76x02_dev *dev) { u32 tx_alc, reg_val; u8 channel = dev->mt76.chandef.chan->hw_value; int is_5ghz = (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) ? 1 : 0; - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_R, 0, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, false); mt76x0_vco_cal(dev, channel); @@ -739,124 +755,119 @@ void mt76x0_phy_recalibrate_after_assoc(struct mt76x0_dev *dev) mt76_wr(dev, MT_TX_ALC_CFG_0, 0); usleep_range(500, 700); - reg_val = mt76_rr(dev, 0x2124); - reg_val &= 0xffffff7e; - mt76_wr(dev, 0x2124, reg_val); + reg_val = mt76_rr(dev, MT_BBP(IBI, 9)); + mt76_wr(dev, MT_BBP(IBI, 9), 0xffffff7e); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, 0, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 0, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_LC, is_5ghz, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_LOFT, is_5ghz, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TXIQ, is_5ghz, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TX_GROUP_DELAY, - is_5ghz, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXIQ, is_5ghz, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RX_GROUP_DELAY, - is_5ghz, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_LC, is_5ghz, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_LOFT, is_5ghz, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_TX_GROUP_DELAY, is_5ghz, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQ, is_5ghz, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_RX_GROUP_DELAY, is_5ghz, false); - mt76_wr(dev, 0x2124, reg_val); + mt76_wr(dev, MT_BBP(IBI, 9), reg_val); mt76_wr(dev, MT_TX_ALC_CFG_0, tx_alc); msleep(100); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, 1, false); -} - -void mt76x0_agc_save(struct mt76x0_dev *dev) -{ - /* Only one RX path */ - dev->agc_save = FIELD_GET(MT_BBP_AGC_GAIN, mt76_rr(dev, MT_BBP(AGC, 8))); -} - -void mt76x0_agc_restore(struct mt76x0_dev *dev) -{ - mt76_rmw_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN, dev->agc_save); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1, false); } -static void mt76x0_temp_sensor(struct mt76x0_dev *dev) +static void mt76x0_temp_sensor(struct mt76x02_dev *dev) { u8 rf_b7_73, rf_b0_66, rf_b0_67; - int cycle, temp; - u32 val; - s32 sval; + s8 val; rf_b7_73 = rf_rr(dev, MT_RF(7, 73)); rf_b0_66 = rf_rr(dev, MT_RF(0, 66)); - rf_b0_67 = rf_rr(dev, MT_RF(0, 73)); + rf_b0_67 = rf_rr(dev, MT_RF(0, 67)); rf_wr(dev, MT_RF(7, 73), 0x02); rf_wr(dev, MT_RF(0, 66), 0x23); - rf_wr(dev, MT_RF(0, 73), 0x01); + rf_wr(dev, MT_RF(0, 67), 0x01); mt76_wr(dev, MT_BBP(CORE, 34), 0x00080055); - for (cycle = 0; cycle < 2000; cycle++) { - val = mt76_rr(dev, MT_BBP(CORE, 34)); - if (!(val & 0x10)) - break; - udelay(3); - } - - if (cycle >= 2000) { - val &= 0x10; - mt76_wr(dev, MT_BBP(CORE, 34), val); + if (!mt76_poll(dev, MT_BBP(CORE, 34), BIT(4), 0, 2000)) { + mt76_clear(dev, MT_BBP(CORE, 34), BIT(4)); goto done; } - sval = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff; - if (!(sval & 0x80)) - sval &= 0x7f; /* Positive */ - else - sval |= 0xffffff00; /* Negative */ + val = mt76_rr(dev, MT_BBP(CORE, 35)); + val = (35 * (val - dev->cal.rx.temp_offset)) / 10 + 25; - temp = (35 * (sval - dev->caldata.temp_offset)) / 10 + 25; + if (abs(val - dev->cal.temp_vco) > 20) { + mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, + dev->mt76.chandef.chan->hw_value, + false); + dev->cal.temp_vco = val; + } + if (abs(val - dev->cal.temp) > 30) { + mt76x0_phy_calibrate(dev, false); + dev->cal.temp = val; + } done: rf_wr(dev, MT_RF(7, 73), rf_b7_73); rf_wr(dev, MT_RF(0, 66), rf_b0_66); - rf_wr(dev, MT_RF(0, 73), rf_b0_67); + rf_wr(dev, MT_RF(0, 67), rf_b0_67); } -static void mt76x0_dynamic_vga_tuning(struct mt76x0_dev *dev) +static void mt76x0_phy_set_gain_val(struct mt76x02_dev *dev) { - u32 val, init_vga; - - init_vga = (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) ? 0x54 : 0x4E; - if (dev->avg_rssi > -60) - init_vga -= 0x20; - else if (dev->avg_rssi > -70) - init_vga -= 0x10; - - val = mt76_rr(dev, MT_BBP(AGC, 8)); - val &= 0xFFFF80FF; - val |= init_vga << 8; - mt76_wr(dev, MT_BBP(AGC,8), val); + u8 gain = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust; + u32 val = 0x122c << 16 | 0xf2; + + mt76_wr(dev, MT_BBP(AGC, 8), + val | FIELD_PREP(MT_BBP_AGC_GAIN, gain)); } -static void mt76x0_phy_calibrate(struct work_struct *work) +static void +mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev) { - struct mt76x0_dev *dev = container_of(work, struct mt76x0_dev, - cal_work.work); + bool gain_change; + u8 gain_delta; + int low_gain; - mt76x0_dynamic_vga_tuning(dev); - mt76x0_temp_sensor(dev); + dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev); - ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, - MT_CALIBRATE_INTERVAL); + low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) + + (dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev)); + + gain_change = (dev->cal.low_gain & 2) ^ (low_gain & 2); + dev->cal.low_gain = low_gain; + + if (!gain_change) { + if (mt76x02_phy_adjust_vga_gain(dev)) + mt76x0_phy_set_gain_val(dev); + return; + } + + dev->cal.agc_gain_adjust = (low_gain == 2) ? 0 : 10; + gain_delta = (low_gain == 2) ? 10 : 0; + + dev->cal.agc_gain_cur[0] = dev->cal.agc_gain_init[0] - gain_delta; + mt76x0_phy_set_gain_val(dev); + + /* clear false CCA counters */ + mt76_rr(dev, MT_RX_STAT_1); } -void mt76x0_phy_con_cal_onoff(struct mt76x0_dev *dev, - struct ieee80211_bss_conf *info) +static void mt76x0_phy_calibration_work(struct work_struct *work) { - /* Start/stop collecting beacon data */ - spin_lock_bh(&dev->con_mon_lock); - ether_addr_copy(dev->ap_bssid, info->bssid); - dev->avg_rssi = 0; - dev->bcn_freq_off = MT_FREQ_OFFSET_INVALID; - spin_unlock_bh(&dev->con_mon_lock); + struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, + cal_work.work); + + mt76x0_phy_update_channel_gain(dev); + if (!mt76x0_tssi_enabled(dev)) + mt76x0_temp_sensor(dev); + + ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, + MT_CALIBRATE_INTERVAL); } -static void -mt76x0_rf_init(struct mt76x0_dev *dev) +static void mt76x0_rf_init(struct mt76x02_dev *dev) { int i; u8 val; @@ -889,7 +900,7 @@ mt76x0_rf_init(struct mt76x0_dev *dev) E2: B0.R21<0>: xo_cxo<0>, B0.R22<7:0>: xo_cxo<8:1> */ rf_wr(dev, MT_RF(0, 22), - min_t(u8, dev->caldata.freq_offset, 0xbf)); + min_t(u8, dev->cal.rx.freq_offset, 0xbf)); val = rf_rr(dev, MT_RF(0, 22)); /* @@ -909,11 +920,11 @@ mt76x0_rf_init(struct mt76x0_dev *dev) rf_set(dev, MT_RF(0, 4), 0x80); } -void mt76x0_phy_init(struct mt76x0_dev *dev) +void mt76x0_phy_init(struct mt76x02_dev *dev) { - INIT_DELAYED_WORK(&dev->cal_work, mt76x0_phy_calibrate); + INIT_DELAYED_WORK(&dev->cal_work, mt76x0_phy_calibration_work); mt76x0_rf_init(dev); - mt76x02_phy_set_rxpath(&dev->mt76); - mt76x02_phy_set_txdac(&dev->mt76); + mt76x02_phy_set_rxpath(dev); + mt76x02_phy_set_txdac(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/trace.h b/drivers/net/wireless/mediatek/mt76/mt76x0/trace.h index 36bbdd585163..75d1d6738c34 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/trace.h @@ -17,7 +17,6 @@ #include <linux/tracepoint.h> #include "mt76x0.h" -#include "mac.h" #undef TRACE_SYSTEM #define TRACE_SYSTEM mt76x0 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c b/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c deleted file mode 100644 index b3c5dc2ffeb1..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> - * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "mt76x0.h" -#include "trace.h" -#include "../mt76x02_util.h" -#include "../mt76x02_usb.h" - -struct mt76x02_txwi * -mt76x0_push_txwi(struct mt76x0_dev *dev, struct sk_buff *skb, - struct ieee80211_sta *sta, struct mt76_wcid *wcid, - int pkt_len) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rate = &info->control.rates[0]; - struct mt76x02_txwi *txwi; - unsigned long flags; - u16 rate_ctl; - u8 nss; - - txwi = (struct mt76x02_txwi *)skb_push(skb, sizeof(struct mt76x02_txwi)); - memset(txwi, 0, sizeof(*txwi)); - - if (!wcid->tx_rate_set) - ieee80211_get_tx_rates(info->control.vif, sta, skb, - info->control.rates, 1); - - spin_lock_irqsave(&dev->mt76.lock, flags); - if (rate->idx < 0 || !rate->count) { - rate_ctl = wcid->tx_rate; - nss = wcid->tx_rate_nss; - } else { - rate_ctl = mt76x02_mac_tx_rate_val(&dev->mt76, rate, &nss); - } - spin_unlock_irqrestore(&dev->mt76.lock, flags); - - txwi->wcid = wcid->idx; - txwi->rate = cpu_to_le16(rate_ctl); - txwi->pktid = (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) ? 1 : 0; - - mt76x02_mac_fill_txwi(txwi, skb, sta, pkt_len, nss); - - return txwi; -} -EXPORT_SYMBOL_GPL(mt76x0_push_txwi); - -void mt76x0_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct mt76x0_dev *dev = hw->priv; - struct ieee80211_vif *vif = info->control.vif; - struct mt76_wcid *wcid = &dev->mt76.global_wcid; - - if (control->sta) { - struct mt76x02_sta *msta; - - msta = (struct mt76x02_sta *)control->sta->drv_priv; - wcid = &msta->wcid; - /* sw encrypted frames */ - if (!info->control.hw_key && wcid->hw_key_idx != 0xff) - control->sta = NULL; - } - - if (vif && !control->sta) { - struct mt76x02_vif *mvif; - - mvif = (struct mt76x02_vif *)vif->drv_priv; - wcid = &mvif->group_wcid; - } - - mt76_tx(&dev->mt76, control->sta, wcid, skb); -} -EXPORT_SYMBOL_GPL(mt76x0_tx); - -void mt76x0_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, - struct sk_buff *skb) -{ - struct mt76x0_dev *dev = container_of(mdev, struct mt76x0_dev, mt76); - void *rxwi = skb->data; - - skb_pull(skb, sizeof(struct mt76x02_rxwi)); - if (!mt76x0_mac_process_rx(dev, skb, rxwi)) { - dev_kfree_skb(skb); - return; - } - - mt76_rx(&dev->mt76, q, skb); -} -EXPORT_SYMBOL_GPL(mt76x0_queue_rx_skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index a76043213f55..a7fd36c2f633 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -18,7 +18,6 @@ #include "mt76x0.h" #include "mcu.h" #include "trace.h" -#include "../mt76x02_util.h" #include "../mt76x02_usb.h" static struct usb_device_id mt76x0_device_table[] = { @@ -49,7 +48,7 @@ static struct usb_device_id mt76x0_device_table[] = { { 0, } }; -static void mt76x0_init_usb_dma(struct mt76x0_dev *dev) +static void mt76x0_init_usb_dma(struct mt76x02_dev *dev) { u32 val; @@ -76,7 +75,7 @@ static void mt76x0_init_usb_dma(struct mt76x0_dev *dev) mt76_wr(dev, MT_USB_DMA_CFG, val); } -static void mt76x0u_cleanup(struct mt76x0_dev *dev) +static void mt76x0u_cleanup(struct mt76x02_dev *dev) { clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); mt76x0_chip_onoff(dev, false, false); @@ -84,16 +83,16 @@ static void mt76x0u_cleanup(struct mt76x0_dev *dev) mt76u_mcu_deinit(&dev->mt76); } -static void mt76x0u_mac_stop(struct mt76x0_dev *dev) +static void mt76x0u_mac_stop(struct mt76x02_dev *dev) { - if (test_bit(MT76_REMOVED, &dev->mt76.state)) - return; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); cancel_delayed_work_sync(&dev->cal_work); cancel_delayed_work_sync(&dev->mac_work); mt76u_stop_stat_wk(&dev->mt76); + if (test_bit(MT76_REMOVED, &dev->mt76.state)) + return; + mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN | MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN | MT_BEACON_TIME_CFG_BEACON_TX); @@ -109,7 +108,7 @@ static void mt76x0u_mac_stop(struct mt76x0_dev *dev) static int mt76x0u_start(struct ieee80211_hw *hw) { - struct mt76x0_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; int ret; mutex_lock(&dev->mt76.mutex); @@ -131,7 +130,7 @@ out: static void mt76x0u_stop(struct ieee80211_hw *hw) { - struct mt76x0_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); mt76x0u_mac_stop(dev); @@ -139,7 +138,7 @@ static void mt76x0u_stop(struct ieee80211_hw *hw) } static const struct ieee80211_ops mt76x0u_ops = { - .tx = mt76x0_tx, + .tx = mt76x02_tx, .start = mt76x0u_start, .stop = mt76x0u_stop, .add_interface = mt76x02_add_interface, @@ -159,48 +158,33 @@ static const struct ieee80211_ops mt76x0u_ops = { .wake_tx_queue = mt76_wake_tx_queue, }; -static int mt76x0u_tx_prepare_skb(struct mt76_dev *mdev, void *data, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info) -{ - struct mt76x0_dev *dev = container_of(mdev, struct mt76x0_dev, mt76); - struct mt76x02_txwi *txwi; - int len = skb->len; - - mt76x02_insert_hdr_pad(skb); - txwi = mt76x0_push_txwi(dev, skb, sta, wcid, len); - - return mt76x02u_set_txinfo(skb, wcid, q2ep(q->hw_idx)); -} - -static int mt76x0u_register_device(struct mt76x0_dev *dev) +static int mt76x0u_register_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = dev->mt76.hw; int err; - err = mt76u_mcu_init_rx(&dev->mt76); + err = mt76u_alloc_queues(&dev->mt76); if (err < 0) - return err; + goto out_err; - err = mt76u_alloc_queues(&dev->mt76); + err = mt76u_mcu_init_rx(&dev->mt76); if (err < 0) - return err; + goto out_err; mt76x0_chip_onoff(dev, true, true); if (!mt76x02_wait_for_mac(&dev->mt76)) { err = -ETIMEDOUT; - goto err; + goto out_err; } err = mt76x0u_mcu_init(dev); if (err < 0) - goto err; + goto out_err; mt76x0_init_usb_dma(dev); err = mt76x0_init_hardware(dev); if (err < 0) - goto err; + goto out_err; mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e); mt76_wr(dev, MT_TXOP_CTRL_CFG, @@ -209,7 +193,7 @@ static int mt76x0u_register_device(struct mt76x0_dev *dev) err = mt76x0_register_device(dev); if (err < 0) - goto err; + goto out_err; /* check hw sg support in order to enable AMSDU */ if (mt76u_check_sg(&dev->mt76)) @@ -221,7 +205,7 @@ static int mt76x0u_register_device(struct mt76x0_dev *dev) return 0; -err: +out_err: mt76x0u_cleanup(dev); return err; } @@ -230,13 +214,13 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, const struct usb_device_id *id) { static const struct mt76_driver_ops drv_ops = { - .tx_prepare_skb = mt76x0u_tx_prepare_skb, - .tx_complete_skb = mt76x02_tx_complete_skb, + .tx_prepare_skb = mt76x02u_tx_prepare_skb, + .tx_complete_skb = mt76x02u_tx_complete_skb, .tx_status_data = mt76x02_tx_status_data, - .rx_skb = mt76x0_queue_rx_skb, + .rx_skb = mt76x02_queue_rx_skb, }; struct usb_device *usb_dev = interface_to_usbdev(usb_intf); - struct mt76x0_dev *dev; + struct mt76x02_dev *dev; u32 asic_rev, mac_rev; int ret; @@ -292,7 +276,7 @@ err: static void mt76x0_disconnect(struct usb_interface *usb_intf) { - struct mt76x0_dev *dev = usb_get_intfdata(usb_intf); + struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); bool initalized = test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); if (!initalized) @@ -310,7 +294,7 @@ static void mt76x0_disconnect(struct usb_interface *usb_intf) static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf, pm_message_t state) { - struct mt76x0_dev *dev = usb_get_intfdata(usb_intf); + struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); struct mt76_usb *usb = &dev->mt76.usb; mt76u_stop_queues(&dev->mt76); @@ -322,7 +306,7 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf, static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf) { - struct mt76x0_dev *dev = usb_get_intfdata(usb_intf); + struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); struct mt76_usb *usb = &dev->mt76.usb; int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c index 4c5b7a6f15ce..a9f14d5149d1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c @@ -25,7 +25,7 @@ #define MT7610U_FIRMWARE "mediatek/mt7610u.bin" static int -mt76x0u_upload_firmware(struct mt76x0_dev *dev, +mt76x0u_upload_firmware(struct mt76x02_dev *dev, const struct mt76x02_fw_header *hdr) { u8 *fw_payload = (u8 *)(hdr + 1); @@ -40,8 +40,7 @@ mt76x0u_upload_firmware(struct mt76x0_dev *dev, ilm_len = le32_to_cpu(hdr->ilm_len) - MT_MCU_IVB_SIZE; dev_dbg(dev->mt76.dev, "loading FW - ILM %u + IVB %u\n", ilm_len, MT_MCU_IVB_SIZE); - err = mt76x02u_mcu_fw_send_data(&dev->mt76, - fw_payload + MT_MCU_IVB_SIZE, + err = mt76x02u_mcu_fw_send_data(dev, fw_payload + MT_MCU_IVB_SIZE, ilm_len, MCU_FW_URB_MAX_PAYLOAD, MT_MCU_IVB_SIZE); if (err) @@ -49,7 +48,7 @@ mt76x0u_upload_firmware(struct mt76x0_dev *dev, dlm_len = le32_to_cpu(hdr->dlm_len); dev_dbg(dev->mt76.dev, "loading FW - DLM %u\n", dlm_len); - err = mt76x02u_mcu_fw_send_data(&dev->mt76, + err = mt76x02u_mcu_fw_send_data(dev, fw_payload + le32_to_cpu(hdr->ilm_len), dlm_len, MCU_FW_URB_MAX_PAYLOAD, MT_MCU_DLM_OFFSET); @@ -76,7 +75,7 @@ out: return err; } -static int mt76x0u_load_firmware(struct mt76x0_dev *dev) +static int mt76x0u_load_firmware(struct mt76x02_dev *dev) { const struct firmware *fw; const struct mt76x02_fw_header *hdr; @@ -121,7 +120,7 @@ static int mt76x0u_load_firmware(struct mt76x0_dev *dev) mt76_set(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN | MT_USB_DMA_CFG_TX_BULK_EN) | FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20)); - mt76x02u_mcu_fw_reset(&dev->mt76); + mt76x02u_mcu_fw_reset(dev); usleep_range(5000, 6000); /* mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN | @@ -160,7 +159,7 @@ err_inv_fw: return -ENOENT; } -int mt76x0u_mcu_init(struct mt76x0_dev *dev) +int mt76x0u_mcu_init(struct mt76x02_dev *dev) { int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h new file mode 100644 index 000000000000..47c42c607964 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> + * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __MT76X02_UTIL_H +#define __MT76X02_UTIL_H + +#include <linux/kfifo.h> + +#include "mt76.h" +#include "mt76x02_regs.h" +#include "mt76x02_mac.h" +#include "mt76x02_dfs.h" +#include "mt76x02_dma.h" + +struct mt76x02_mac_stats { + u64 rx_stat[6]; + u64 tx_stat[6]; + u64 aggr_stat[2]; + u64 aggr_n[32]; + u64 zero_len_del[2]; +}; + +#define MT_MAX_CHAINS 2 +struct mt76x02_rx_freq_cal { + s8 high_gain[MT_MAX_CHAINS]; + s8 rssi_offset[MT_MAX_CHAINS]; + s8 lna_gain; + u32 mcu_gain; + s16 temp_offset; + u8 freq_offset; +}; + +struct mt76x02_calibration { + struct mt76x02_rx_freq_cal rx; + + u8 agc_gain_init[MT_MAX_CHAINS]; + u8 agc_gain_cur[MT_MAX_CHAINS]; + + u16 false_cca; + s8 avg_rssi_all; + s8 agc_gain_adjust; + s8 low_gain; + + s8 temp_vco; + s8 temp; + + bool init_cal_done; + bool tssi_cal_done; + bool tssi_comp_pending; + bool dpd_cal_done; + bool channel_cal_done; +}; + +struct mt76x02_dev { + struct mt76_dev mt76; /* must be first */ + + struct mac_address macaddr_list[8]; + + struct mutex phy_mutex; + struct mutex mutex; + + u8 txdone_seq; + DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); + + struct sk_buff *rx_head; + + struct tasklet_struct tx_tasklet; + struct tasklet_struct pre_tbtt_tasklet; + struct delayed_work cal_work; + struct delayed_work mac_work; + + struct mt76x02_mac_stats stats; + atomic_t avg_ampdu_len; + u32 aggr_stats[32]; + + struct sk_buff *beacons[8]; + u8 beacon_mask; + u8 beacon_data_mask; + + u8 tbtt_count; + u16 beacon_int; + + struct mt76x02_calibration cal; + + s8 target_power; + s8 target_power_delta[2]; + bool enable_tpc; + + bool no_2ghz; + + u8 coverage_class; + u8 slottime; + + struct mt76x02_dfs_pattern_detector dfs_pd; +}; + +extern struct ieee80211_rate mt76x02_rates[12]; + +void mt76x02_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, u64 multicast); +int mt76x02_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int mt76x02_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + +void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, + unsigned int idx); +int mt76x02_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); +void mt76x02_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); + +int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params); +int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); +int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u16 queue, const struct ieee80211_tx_queue_params *params); +void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev, + const struct ieee80211_tx_rate *rate); +s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr, + s8 max_txpwr_adj); +void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr); +int mt76x02_insert_hdr_pad(struct sk_buff *skb); +void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len); +void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb); +bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update); +void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb); +void mt76x02_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); +irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance); +void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb); +int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi, + struct sk_buff *skb, struct mt76_queue *q, + struct mt76_wcid *wcid, struct ieee80211_sta *sta, + u32 *tx_info); + +extern const u16 mt76x02_beacon_offsets[16]; +void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev); +void mt76x02_set_irq_mask(struct mt76x02_dev *dev, u32 clear, u32 set); +void mt76x02_mac_start(struct mt76x02_dev *dev); + +static inline bool is_mt76x2(struct mt76x02_dev *dev) +{ + return mt76_chip(&dev->mt76) == 0x7612 || + mt76_chip(&dev->mt76) == 0x7662 || + mt76_chip(&dev->mt76) == 0x7602; +} + +static inline void mt76x02_irq_enable(struct mt76x02_dev *dev, u32 mask) +{ + mt76x02_set_irq_mask(dev, 0, mask); +} + +static inline void mt76x02_irq_disable(struct mt76x02_dev *dev, u32 mask) +{ + mt76x02_set_irq_mask(dev, mask, 0); +} + +static inline bool +mt76x02_wait_for_txrx_idle(struct mt76_dev *dev) +{ + return __mt76_poll_msec(dev, MT_MAC_STATUS, + MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, + 0, 100); +} + +static inline struct mt76x02_sta * +mt76x02_rx_get_sta(struct mt76_dev *dev, u8 idx) +{ + struct mt76_wcid *wcid; + + if (idx >= ARRAY_SIZE(dev->wcid)) + return NULL; + + wcid = rcu_dereference(dev->wcid[idx]); + if (!wcid) + return NULL; + + return container_of(wcid, struct mt76x02_sta, wcid); +} + +static inline struct mt76_wcid * +mt76x02_rx_get_sta_wcid(struct mt76x02_sta *sta, bool unicast) +{ + if (!sta) + return NULL; + + if (unicast) + return &sta->wcid; + else + return &sta->vif->group_wcid; +} + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h index 693f421bf096..7e177c934592 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h @@ -14,8 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef __MT76x2_DFS_H -#define __MT76x2_DFS_H +#ifndef __MT76x02_DFS_H +#define __MT76x02_DFS_H #include <linux/types.h> #include <linux/nl80211.h> @@ -49,7 +49,7 @@ #define MT_DFS_ETSI_MAX_PRI (133333 + 125000 + 117647 + 1000) #define MT_DFS_ETSI_MIN_PRI (4500 - 20) -struct mt76x2_radar_specs { +struct mt76x02_radar_specs { u8 mode; u16 avg_len; u16 e_low; @@ -70,7 +70,7 @@ struct mt76x2_radar_specs { #define MT_DFS_EVENT_ENGINE(x) (((x) & BIT(31)) ? 2 : 0) #define MT_DFS_EVENT_TIMESTAMP(x) ((x) & GENMASK(21, 0)) #define MT_DFS_EVENT_WIDTH(x) ((x) & GENMASK(11, 0)) -struct mt76x2_dfs_event { +struct mt76x02_dfs_event { unsigned long fetch_ts; u32 ts; u16 width; @@ -78,12 +78,12 @@ struct mt76x2_dfs_event { }; #define MT_DFS_EVENT_BUFLEN 256 -struct mt76x2_dfs_event_rb { - struct mt76x2_dfs_event data[MT_DFS_EVENT_BUFLEN]; +struct mt76x02_dfs_event_rb { + struct mt76x02_dfs_event data[MT_DFS_EVENT_BUFLEN]; int h_rb, t_rb; }; -struct mt76x2_dfs_sequence { +struct mt76x02_dfs_sequence { struct list_head head; u32 first_ts; u32 last_ts; @@ -92,7 +92,7 @@ struct mt76x2_dfs_sequence { u8 engine; }; -struct mt76x2_dfs_hw_pulse { +struct mt76x02_dfs_hw_pulse { u8 engine; u32 period; u32 w1; @@ -100,47 +100,41 @@ struct mt76x2_dfs_hw_pulse { u32 burst; }; -struct mt76x2_dfs_sw_detector_params { +struct mt76x02_dfs_sw_detector_params { u32 min_pri; u32 max_pri; u32 pri_margin; }; -struct mt76x2_dfs_engine_stats { +struct mt76x02_dfs_engine_stats { u32 hw_pattern; u32 hw_pulse_discarded; u32 sw_pattern; }; -struct mt76x2_dfs_seq_stats { +struct mt76x02_dfs_seq_stats { u32 seq_pool_len; u32 seq_len; }; -struct mt76x2_dfs_pattern_detector { +struct mt76x02_dfs_pattern_detector { enum nl80211_dfs_regions region; u8 chirp_pulse_cnt; u32 chirp_pulse_ts; - struct mt76x2_dfs_sw_detector_params sw_dpd_params; - struct mt76x2_dfs_event_rb event_rb[2]; + struct mt76x02_dfs_sw_detector_params sw_dpd_params; + struct mt76x02_dfs_event_rb event_rb[2]; struct list_head sequences; struct list_head seq_pool; - struct mt76x2_dfs_seq_stats seq_stats; + struct mt76x02_dfs_seq_stats seq_stats; unsigned long last_sw_check; u32 last_event_ts; - struct mt76x2_dfs_engine_stats stats[MT_DFS_NUM_ENGINES]; + struct mt76x02_dfs_engine_stats stats[MT_DFS_NUM_ENGINES]; struct tasklet_struct dfs_tasklet; }; -void mt76x2_dfs_init_params(struct mt76x2_dev *dev); -void mt76x2_dfs_init_detector(struct mt76x2_dev *dev); -void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev); -void mt76x2_dfs_set_domain(struct mt76x2_dev *dev, - enum nl80211_dfs_regions region); - -#endif /* __MT76x2_DFS_H */ +#endif /* __MT76x02_DFS_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dma.h b/drivers/net/wireless/mediatek/mt76/mt76x02_dma.h index 65b97f5713d3..6394010a565f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dma.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dma.h @@ -17,8 +17,8 @@ #ifndef __MT76x02_DMA_H #define __MT76x02_DMA_H +#include "mt76x02.h" #include "dma.h" -#include "mt76x02_regs.h" #define MT_TXD_INFO_LEN GENMASK(15, 0) #define MT_TXD_INFO_NEXT_VLD BIT(16) @@ -70,8 +70,8 @@ mt76x02_wait_for_wpdma(struct mt76_dev *dev, int timeout) 0, timeout); } -int mt76x02_dma_init(struct mt76_dev *dev); -void mt76x02_dma_enable(struct mt76_dev *dev); -void mt76x02_dma_disable(struct mt76_dev *dev); +int mt76x02_dma_init(struct mt76x02_dev *dev); +void mt76x02_dma_disable(struct mt76x02_dev *dev); +void mt76x02_dma_cleanup(struct mt76x02_dev *dev); #endif /* __MT76x02_DMA_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c index d3efeb8a72b7..9390de2a323e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c @@ -17,46 +17,43 @@ #include <asm/unaligned.h> -#include "mt76.h" #include "mt76x02_eeprom.h" -#include "mt76x02_regs.h" static int -mt76x02_efuse_read(struct mt76_dev *dev, u16 addr, u8 *data, +mt76x02_efuse_read(struct mt76x02_dev *dev, u16 addr, u8 *data, enum mt76x02_eeprom_modes mode) { u32 val; int i; - val = __mt76_rr(dev, MT_EFUSE_CTRL); + val = mt76_rr(dev, MT_EFUSE_CTRL); val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE); val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf); val |= FIELD_PREP(MT_EFUSE_CTRL_MODE, mode); val |= MT_EFUSE_CTRL_KICK; - __mt76_wr(dev, MT_EFUSE_CTRL, val); + mt76_wr(dev, MT_EFUSE_CTRL, val); - if (!__mt76_poll_msec(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, - 0, 1000)) + if (!mt76_poll_msec(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000)) return -ETIMEDOUT; udelay(2); - val = __mt76_rr(dev, MT_EFUSE_CTRL); + val = mt76_rr(dev, MT_EFUSE_CTRL); if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) { memset(data, 0xff, 16); return 0; } for (i = 0; i < 4; i++) { - val = __mt76_rr(dev, MT_EFUSE_DATA(i)); + val = mt76_rr(dev, MT_EFUSE_DATA(i)); put_unaligned_le32(val, data + 4 * i); } return 0; } -int mt76x02_get_efuse_data(struct mt76_dev *dev, u16 base, void *buf, +int mt76x02_get_efuse_data(struct mt76x02_dev *dev, u16 base, void *buf, int len, enum mt76x02_eeprom_modes mode) { int ret, i; @@ -71,26 +68,26 @@ int mt76x02_get_efuse_data(struct mt76_dev *dev, u16 base, void *buf, } EXPORT_SYMBOL_GPL(mt76x02_get_efuse_data); -void mt76x02_eeprom_parse_hw_cap(struct mt76_dev *dev) +void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev) { u16 val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0); switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) { case BOARD_TYPE_5GHZ: - dev->cap.has_5ghz = true; + dev->mt76.cap.has_5ghz = true; break; case BOARD_TYPE_2GHZ: - dev->cap.has_2ghz = true; + dev->mt76.cap.has_2ghz = true; break; default: - dev->cap.has_2ghz = true; - dev->cap.has_5ghz = true; + dev->mt76.cap.has_2ghz = true; + dev->mt76.cap.has_5ghz = true; break; } } EXPORT_SYMBOL_GPL(mt76x02_eeprom_parse_hw_cap); -bool mt76x02_ext_pa_enabled(struct mt76_dev *dev, enum nl80211_band band) +bool mt76x02_ext_pa_enabled(struct mt76x02_dev *dev, enum nl80211_band band) { u16 conf0 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0); @@ -101,7 +98,7 @@ bool mt76x02_ext_pa_enabled(struct mt76_dev *dev, enum nl80211_band band) } EXPORT_SYMBOL_GPL(mt76x02_ext_pa_enabled); -void mt76x02_get_rx_gain(struct mt76_dev *dev, enum nl80211_band band, +void mt76x02_get_rx_gain(struct mt76x02_dev *dev, enum nl80211_band band, u16 *rssi_offset, s8 *lna_2g, s8 *lna_5g) { u16 val; @@ -129,7 +126,7 @@ void mt76x02_get_rx_gain(struct mt76_dev *dev, enum nl80211_band band, } EXPORT_SYMBOL_GPL(mt76x02_get_rx_gain); -u8 mt76x02_get_lna_gain(struct mt76_dev *dev, +u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev, s8 *lna_2g, s8 *lna_5g, struct ieee80211_channel *chan) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h index bcd05f7c5f45..b3ec74835d10 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.h @@ -18,6 +18,8 @@ #ifndef __MT76x02_EEPROM_H #define __MT76x02_EEPROM_H +#include "mt76x02.h" + enum mt76x02_eeprom_field { MT_EE_CHIP_ID = 0x000, MT_EE_VERSION = 0x002, @@ -168,44 +170,23 @@ static inline s8 mt76x02_rate_power_val(u8 val) } static inline int -mt76x02_eeprom_get(struct mt76_dev *dev, +mt76x02_eeprom_get(struct mt76x02_dev *dev, enum mt76x02_eeprom_field field) { if ((field & 1) || field >= __MT_EE_MAX) return -1; - return get_unaligned_le16(dev->eeprom.data + field); -} - -static inline bool -mt76x02_temp_tx_alc_enabled(struct mt76_dev *dev) -{ - u16 val; - - val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G); - if (!(val & BIT(15))) - return false; - - return mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) & - MT_EE_NIC_CONF_1_TEMP_TX_ALC; -} - -static inline bool -mt76x02_tssi_enabled(struct mt76_dev *dev) -{ - return !mt76x02_temp_tx_alc_enabled(dev) && - (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) & - MT_EE_NIC_CONF_1_TX_ALC_EN); + return get_unaligned_le16(dev->mt76.eeprom.data + field); } -bool mt76x02_ext_pa_enabled(struct mt76_dev *dev, enum nl80211_band band); -int mt76x02_get_efuse_data(struct mt76_dev *dev, u16 base, void *buf, +bool mt76x02_ext_pa_enabled(struct mt76x02_dev *dev, enum nl80211_band band); +int mt76x02_get_efuse_data(struct mt76x02_dev *dev, u16 base, void *buf, int len, enum mt76x02_eeprom_modes mode); -void mt76x02_get_rx_gain(struct mt76_dev *dev, enum nl80211_band band, +void mt76x02_get_rx_gain(struct mt76x02_dev *dev, enum nl80211_band band, u16 *rssi_offset, s8 *lna_2g, s8 *lna_5g); -u8 mt76x02_get_lna_gain(struct mt76_dev *dev, +u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev, s8 *lna_2g, s8 *lna_5g, struct ieee80211_channel *chan); -void mt76x02_eeprom_parse_hw_cap(struct mt76_dev *dev); +void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev); #endif /* __MT76x02_EEPROM_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index df4366a702c9..10578e4cb269 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -15,9 +15,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "mt76.h" -#include "mt76x02_regs.h" -#include "mt76x02_mac.h" +#include "mt76x02.h" +#include "mt76x02_trace.h" enum mt76x02_cipher_type mt76x02_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) @@ -46,8 +45,8 @@ mt76x02_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) } EXPORT_SYMBOL_GPL(mt76x02_mac_get_key_info); -int mt76x02_mac_shared_key_setup(struct mt76_dev *dev, u8 vif_idx, u8 key_idx, - struct ieee80211_key_conf *key) +int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx, + u8 key_idx, struct ieee80211_key_conf *key) { enum mt76x02_cipher_type cipher; u8 key_data[32]; @@ -57,20 +56,20 @@ int mt76x02_mac_shared_key_setup(struct mt76_dev *dev, u8 vif_idx, u8 key_idx, if (cipher == MT_CIPHER_NONE && key) return -EOPNOTSUPP; - val = __mt76_rr(dev, MT_SKEY_MODE(vif_idx)); + val = mt76_rr(dev, MT_SKEY_MODE(vif_idx)); val &= ~(MT_SKEY_MODE_MASK << MT_SKEY_MODE_SHIFT(vif_idx, key_idx)); val |= cipher << MT_SKEY_MODE_SHIFT(vif_idx, key_idx); - __mt76_wr(dev, MT_SKEY_MODE(vif_idx), val); + mt76_wr(dev, MT_SKEY_MODE(vif_idx), val); - __mt76_wr_copy(dev, MT_SKEY(vif_idx, key_idx), key_data, - sizeof(key_data)); + mt76_wr_copy(dev, MT_SKEY(vif_idx, key_idx), key_data, + sizeof(key_data)); return 0; } EXPORT_SYMBOL_GPL(mt76x02_mac_shared_key_setup); -int mt76x02_mac_wcid_set_key(struct mt76_dev *dev, u8 idx, - struct ieee80211_key_conf *key) +int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, + struct ieee80211_key_conf *key) { enum mt76x02_cipher_type cipher; u8 key_data[32]; @@ -80,25 +79,26 @@ int mt76x02_mac_wcid_set_key(struct mt76_dev *dev, u8 idx, if (cipher == MT_CIPHER_NONE && key) return -EOPNOTSUPP; - __mt76_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data)); - __mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PKEY_MODE, cipher); + mt76_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data)); + mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PKEY_MODE, cipher); memset(iv_data, 0, sizeof(iv_data)); if (key) { - __mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE, - !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); + mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE, + !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); iv_data[3] = key->keyidx << 6; if (cipher >= MT_CIPHER_TKIP) iv_data[3] |= 0x20; } - __mt76_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data)); + mt76_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data)); return 0; } EXPORT_SYMBOL_GPL(mt76x02_mac_wcid_set_key); -void mt76x02_mac_wcid_setup(struct mt76_dev *dev, u8 idx, u8 vif_idx, u8 *mac) +void mt76x02_mac_wcid_setup(struct mt76x02_dev *dev, u8 idx, + u8 vif_idx, u8 *mac) { struct mt76_wcid_addr addr = {}; u32 attr; @@ -106,10 +106,10 @@ void mt76x02_mac_wcid_setup(struct mt76_dev *dev, u8 idx, u8 vif_idx, u8 *mac) attr = FIELD_PREP(MT_WCID_ATTR_BSS_IDX, vif_idx & 7) | FIELD_PREP(MT_WCID_ATTR_BSS_IDX_EXT, !!(vif_idx & 8)); - __mt76_wr(dev, MT_WCID_ATTR(idx), attr); + mt76_wr(dev, MT_WCID_ATTR(idx), attr); - __mt76_wr(dev, MT_WCID_TX_RATE(idx), 0); - __mt76_wr(dev, MT_WCID_TX_RATE(idx) + 4, 0); + mt76_wr(dev, MT_WCID_TX_RATE(idx), 0); + mt76_wr(dev, MT_WCID_TX_RATE(idx) + 4, 0); if (idx >= 128) return; @@ -117,22 +117,22 @@ void mt76x02_mac_wcid_setup(struct mt76_dev *dev, u8 idx, u8 vif_idx, u8 *mac) if (mac) memcpy(addr.macaddr, mac, ETH_ALEN); - __mt76_wr_copy(dev, MT_WCID_ADDR(idx), &addr, sizeof(addr)); + mt76_wr_copy(dev, MT_WCID_ADDR(idx), &addr, sizeof(addr)); } EXPORT_SYMBOL_GPL(mt76x02_mac_wcid_setup); -void mt76x02_mac_wcid_set_drop(struct mt76_dev *dev, u8 idx, bool drop) +void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop) { - u32 val = __mt76_rr(dev, MT_WCID_DROP(idx)); + u32 val = mt76_rr(dev, MT_WCID_DROP(idx)); u32 bit = MT_WCID_DROP_MASK(idx); /* prevent unnecessary writes */ if ((val & bit) != (bit * drop)) - __mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop)); + mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop)); } EXPORT_SYMBOL_GPL(mt76x02_mac_wcid_set_drop); -void mt76x02_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq) +void mt76x02_txq_init(struct mt76x02_dev *dev, struct ieee80211_txq *txq) { struct mt76_txq *mtxq; @@ -152,55 +152,13 @@ void mt76x02_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq) mtxq->wcid = &mvif->group_wcid; } - mt76_txq_init(dev, txq); + mt76_txq_init(&dev->mt76, txq); } EXPORT_SYMBOL_GPL(mt76x02_txq_init); -void mt76x02_mac_fill_txwi(struct mt76x02_txwi *txwi, struct sk_buff *skb, - struct ieee80211_sta *sta, int len, u8 nss) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 txwi_flags = 0; - - if (info->flags & IEEE80211_TX_CTL_LDPC) - txwi->rate |= cpu_to_le16(MT_RXWI_RATE_LDPC); - if ((info->flags & IEEE80211_TX_CTL_STBC) && nss == 1) - txwi->rate |= cpu_to_le16(MT_RXWI_RATE_STBC); - if (nss > 1 && sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC) - txwi_flags |= MT_TXWI_FLAGS_MMPS; - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - txwi->ack_ctl |= MT_TXWI_ACK_CTL_REQ; - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) - txwi->ack_ctl |= MT_TXWI_ACK_CTL_NSEQ; - if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) - txwi->pktid |= MT_TXWI_PKTID_PROBE; - if ((info->flags & IEEE80211_TX_CTL_AMPDU) && sta) { - u8 ba_size = IEEE80211_MIN_AMPDU_BUF; - - ba_size <<= sta->ht_cap.ampdu_factor; - ba_size = min_t(int, 63, ba_size - 1); - if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) - ba_size = 0; - txwi->ack_ctl |= FIELD_PREP(MT_TXWI_ACK_CTL_BA_WINDOW, ba_size); - - txwi_flags |= MT_TXWI_FLAGS_AMPDU | - FIELD_PREP(MT_TXWI_FLAGS_MPDU_DENSITY, - sta->ht_cap.ampdu_density); - } - - if (ieee80211_is_probe_resp(hdr->frame_control) || - ieee80211_is_beacon(hdr->frame_control)) - txwi_flags |= MT_TXWI_FLAGS_TS; - - txwi->flags |= cpu_to_le16(txwi_flags); - txwi->len_ctl = cpu_to_le16(len); -} -EXPORT_SYMBOL_GPL(mt76x02_mac_fill_txwi); - -__le16 -mt76x02_mac_tx_rate_val(struct mt76_dev *dev, - const struct ieee80211_tx_rate *rate, u8 *nss_val) +static __le16 +mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, + const struct ieee80211_tx_rate *rate, u8 *nss_val) { u16 rateval; u8 phy, rate_idx; @@ -225,10 +183,10 @@ mt76x02_mac_tx_rate_val(struct mt76_dev *dev, bw = 1; } else { const struct ieee80211_rate *r; - int band = dev->chandef.chan->band; + int band = dev->mt76.chandef.chan->band; u16 val; - r = &dev->hw->wiphy->bands[band]->bitrates[rate->idx]; + r = &dev->mt76.hw->wiphy->bands[band]->bitrates[rate->idx]; if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) val = r->hw_value_short; else @@ -248,24 +206,23 @@ mt76x02_mac_tx_rate_val(struct mt76_dev *dev, *nss_val = nss; return cpu_to_le16(rateval); } -EXPORT_SYMBOL_GPL(mt76x02_mac_tx_rate_val); -void mt76x02_mac_wcid_set_rate(struct mt76_dev *dev, struct mt76_wcid *wcid, - const struct ieee80211_tx_rate *rate) +void mt76x02_mac_wcid_set_rate(struct mt76x02_dev *dev, struct mt76_wcid *wcid, + const struct ieee80211_tx_rate *rate) { - spin_lock_bh(&dev->lock); + spin_lock_bh(&dev->mt76.lock); wcid->tx_rate = mt76x02_mac_tx_rate_val(dev, rate, &wcid->tx_rate_nss); wcid->tx_rate_set = true; - spin_unlock_bh(&dev->lock); + spin_unlock_bh(&dev->mt76.lock); } -bool mt76x02_mac_load_tx_status(struct mt76_dev *dev, - struct mt76x02_tx_status *stat) +bool mt76x02_mac_load_tx_status(struct mt76x02_dev *dev, + struct mt76x02_tx_status *stat) { u32 stat1, stat2; - stat2 = __mt76_rr(dev, MT_TX_STAT_FIFO_EXT); - stat1 = __mt76_rr(dev, MT_TX_STAT_FIFO); + stat2 = mt76_rr(dev, MT_TX_STAT_FIFO_EXT); + stat1 = mt76_rr(dev, MT_TX_STAT_FIFO); stat->valid = !!(stat1 & MT_TX_STAT_FIFO_VALID); if (!stat->valid) @@ -341,10 +298,103 @@ mt76x02_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate, return 0; } +void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, int len) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rate = &info->control.rates[0]; + struct ieee80211_key_conf *key = info->control.hw_key; + u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2)); + u16 txwi_flags = 0; + u8 nss; + s8 txpwr_adj, max_txpwr_adj; + u8 ccmp_pn[8], nstreams = dev->mt76.chainmask & 0xf; + + memset(txwi, 0, sizeof(*txwi)); + + if (wcid) + txwi->wcid = wcid->idx; + else + txwi->wcid = 0xff; + + txwi->pktid = 1; + + if (wcid && wcid->sw_iv && key) { + u64 pn = atomic64_inc_return(&key->tx_pn); + ccmp_pn[0] = pn; + ccmp_pn[1] = pn >> 8; + ccmp_pn[2] = 0; + ccmp_pn[3] = 0x20 | (key->keyidx << 6); + ccmp_pn[4] = pn >> 16; + ccmp_pn[5] = pn >> 24; + ccmp_pn[6] = pn >> 32; + ccmp_pn[7] = pn >> 40; + txwi->iv = *((__le32 *)&ccmp_pn[0]); + txwi->eiv = *((__le32 *)&ccmp_pn[1]); + } + + spin_lock_bh(&dev->mt76.lock); + if (wcid && (rate->idx < 0 || !rate->count)) { + txwi->rate = wcid->tx_rate; + max_txpwr_adj = wcid->max_txpwr_adj; + nss = wcid->tx_rate_nss; + } else { + txwi->rate = mt76x02_mac_tx_rate_val(dev, rate, &nss); + max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate); + } + spin_unlock_bh(&dev->mt76.lock); + + txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->mt76.txpower_conf, + max_txpwr_adj); + txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj); + + if (nstreams > 1 && mt76_rev(&dev->mt76) >= MT76XX_REV_E4) + txwi->txstream = 0x13; + else if (nstreams > 1 && mt76_rev(&dev->mt76) >= MT76XX_REV_E3 && + !(txwi->rate & cpu_to_le16(rate_ht_mask))) + txwi->txstream = 0x93; + + if (is_mt76x2(dev) && (info->flags & IEEE80211_TX_CTL_LDPC)) + txwi->rate |= cpu_to_le16(MT_RXWI_RATE_LDPC); + if ((info->flags & IEEE80211_TX_CTL_STBC) && nss == 1) + txwi->rate |= cpu_to_le16(MT_RXWI_RATE_STBC); + if (nss > 1 && sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC) + txwi_flags |= MT_TXWI_FLAGS_MMPS; + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) + txwi->ack_ctl |= MT_TXWI_ACK_CTL_REQ; + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) + txwi->ack_ctl |= MT_TXWI_ACK_CTL_NSEQ; + if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) + txwi->pktid |= MT_TXWI_PKTID_PROBE; + if ((info->flags & IEEE80211_TX_CTL_AMPDU) && sta) { + u8 ba_size = IEEE80211_MIN_AMPDU_BUF; + + ba_size <<= sta->ht_cap.ampdu_factor; + ba_size = min_t(int, 63, ba_size - 1); + if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) + ba_size = 0; + txwi->ack_ctl |= FIELD_PREP(MT_TXWI_ACK_CTL_BA_WINDOW, ba_size); + + txwi_flags |= MT_TXWI_FLAGS_AMPDU | + FIELD_PREP(MT_TXWI_FLAGS_MPDU_DENSITY, + sta->ht_cap.ampdu_density); + } + + if (ieee80211_is_probe_resp(hdr->frame_control) || + ieee80211_is_beacon(hdr->frame_control)) + txwi_flags |= MT_TXWI_FLAGS_TS; + + txwi->flags |= cpu_to_le16(txwi_flags); + txwi->len_ctl = cpu_to_le16(len); +} +EXPORT_SYMBOL_GPL(mt76x02_mac_write_txwi); + static void -mt76x02_mac_fill_tx_status(struct mt76_dev *dev, - struct ieee80211_tx_info *info, - struct mt76x02_tx_status *st, int n_frames) +mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev, + struct ieee80211_tx_info *info, + struct mt76x02_tx_status *st, int n_frames) { struct ieee80211_tx_rate *rate = info->status.rates; int cur_idx, last_rate; @@ -355,7 +405,7 @@ mt76x02_mac_fill_tx_status(struct mt76_dev *dev, last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1); mt76x02_mac_process_tx_rate(&rate[last_rate], st->rate, - dev->chandef.chan->band); + dev->mt76.chandef.chan->band); if (last_rate < IEEE80211_TX_MAX_RATES - 1) rate[last_rate + 1].idx = -1; @@ -383,8 +433,8 @@ mt76x02_mac_fill_tx_status(struct mt76_dev *dev, info->flags |= IEEE80211_TX_STAT_ACK; } -void mt76x02_send_tx_status(struct mt76_dev *dev, - struct mt76x02_tx_status *stat, u8 *update) +void mt76x02_send_tx_status(struct mt76x02_dev *dev, + struct mt76x02_tx_status *stat, u8 *update) { struct ieee80211_tx_info info = {}; struct ieee80211_sta *sta = NULL; @@ -392,8 +442,8 @@ void mt76x02_send_tx_status(struct mt76_dev *dev, struct mt76x02_sta *msta = NULL; rcu_read_lock(); - if (stat->wcid < ARRAY_SIZE(dev->wcid)) - wcid = rcu_dereference(dev->wcid[stat->wcid]); + if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid)) + wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]); if (wcid) { void *priv; @@ -418,7 +468,7 @@ void mt76x02_send_tx_status(struct mt76_dev *dev, } mt76x02_mac_fill_tx_status(dev, &info, &msta->status, - msta->n_frames); + msta->n_frames); msta->status = *stat; msta->n_frames = 1; @@ -428,7 +478,7 @@ void mt76x02_send_tx_status(struct mt76_dev *dev, *update = 1; } - ieee80211_tx_status_noskb(dev->hw, sta, &info); + ieee80211_tx_status_noskb(dev->mt76.hw, sta, &info); out: rcu_read_unlock(); @@ -503,20 +553,185 @@ mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate) } EXPORT_SYMBOL_GPL(mt76x02_mac_process_rate); -void mt76x02_mac_setaddr(struct mt76_dev *dev, u8 *addr) +void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr) { - ether_addr_copy(dev->macaddr, addr); + ether_addr_copy(dev->mt76.macaddr, addr); - if (!is_valid_ether_addr(dev->macaddr)) { - eth_random_addr(dev->macaddr); - dev_info(dev->dev, + if (!is_valid_ether_addr(dev->mt76.macaddr)) { + eth_random_addr(dev->mt76.macaddr); + dev_info(dev->mt76.dev, "Invalid MAC address, using random address %pM\n", - dev->macaddr); + dev->mt76.macaddr); } - __mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr)); - __mt76_wr(dev, MT_MAC_ADDR_DW1, - get_unaligned_le16(dev->macaddr + 4) | - FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff)); + mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->mt76.macaddr)); + mt76_wr(dev, MT_MAC_ADDR_DW1, + get_unaligned_le16(dev->mt76.macaddr + 4) | + FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff)); } EXPORT_SYMBOL_GPL(mt76x02_mac_setaddr); + +static int +mt76x02_mac_get_rssi(struct mt76x02_dev *dev, s8 rssi, int chain) +{ + struct mt76x02_rx_freq_cal *cal = &dev->cal.rx; + + rssi += cal->rssi_offset[chain]; + rssi -= cal->lna_gain; + + return rssi; +} + +int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, + void *rxi) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb; + struct mt76x02_rxwi *rxwi = rxi; + struct mt76x02_sta *sta; + u32 rxinfo = le32_to_cpu(rxwi->rxinfo); + u32 ctl = le32_to_cpu(rxwi->ctl); + u16 rate = le16_to_cpu(rxwi->rate); + u16 tid_sn = le16_to_cpu(rxwi->tid_sn); + bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST); + int i, pad_len = 0, nstreams = dev->mt76.chainmask & 0xf; + s8 signal; + u8 pn_len; + u8 wcid; + int len; + + if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + return -EINVAL; + + if (rxinfo & MT_RXINFO_L2PAD) + pad_len += 2; + + if (rxinfo & MT_RXINFO_DECRYPT) { + status->flag |= RX_FLAG_DECRYPTED; + status->flag |= RX_FLAG_MMIC_STRIPPED; + status->flag |= RX_FLAG_MIC_STRIPPED; + status->flag |= RX_FLAG_IV_STRIPPED; + } + + wcid = FIELD_GET(MT_RXWI_CTL_WCID, ctl); + sta = mt76x02_rx_get_sta(&dev->mt76, wcid); + status->wcid = mt76x02_rx_get_sta_wcid(sta, unicast); + + len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl); + pn_len = FIELD_GET(MT_RXINFO_PN_LEN, rxinfo); + if (pn_len) { + int offset = ieee80211_get_hdrlen_from_skb(skb) + pad_len; + u8 *data = skb->data + offset; + + status->iv[0] = data[7]; + status->iv[1] = data[6]; + status->iv[2] = data[5]; + status->iv[3] = data[4]; + status->iv[4] = data[1]; + status->iv[5] = data[0]; + + /* + * Driver CCMP validation can't deal with fragments. + * Let mac80211 take care of it. + */ + if (rxinfo & MT_RXINFO_FRAG) { + status->flag &= ~RX_FLAG_IV_STRIPPED; + } else { + pad_len += pn_len << 2; + len -= pn_len << 2; + } + } + + mt76x02_remove_hdr_pad(skb, pad_len); + + if ((rxinfo & MT_RXINFO_BA) && !(rxinfo & MT_RXINFO_NULL)) + status->aggr = true; + + if (WARN_ON_ONCE(len > skb->len)) + return -EINVAL; + + pskb_trim(skb, len); + + status->chains = BIT(0); + signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0); + for (i = 1; i < nstreams; i++) { + status->chains |= BIT(i); + status->chain_signal[i] = mt76x02_mac_get_rssi(dev, + rxwi->rssi[i], + i); + signal = max_t(s8, signal, status->chain_signal[i]); + } + status->signal = signal; + status->freq = dev->mt76.chandef.chan->center_freq; + status->band = dev->mt76.chandef.chan->band; + + status->tid = FIELD_GET(MT_RXWI_TID, tid_sn); + status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn); + + if (sta) { + ewma_signal_add(&sta->rssi, status->signal); + sta->inactive_count = 0; + } + + return mt76x02_mac_process_rate(status, rate); +} + +void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq) +{ + struct mt76x02_tx_status stat = {}; + unsigned long flags; + u8 update = 1; + bool ret; + + if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + return; + + trace_mac_txstat_poll(dev); + + while (!irq || !kfifo_is_full(&dev->txstatus_fifo)) { + spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags); + ret = mt76x02_mac_load_tx_status(dev, &stat); + spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags); + + if (!ret) + break; + + trace_mac_txstat_fetch(dev, &stat); + + if (!irq) { + mt76x02_send_tx_status(dev, &stat, &update); + continue; + } + + kfifo_put(&dev->txstatus_fifo, stat); + } +} +EXPORT_SYMBOL_GPL(mt76x02_mac_poll_tx_status); + +static void +mt76x02_mac_queue_txdone(struct mt76x02_dev *dev, struct sk_buff *skb, + void *txwi_ptr) +{ + struct mt76x02_tx_info *txi = mt76x02_skb_tx_info(skb); + struct mt76x02_txwi *txwi = txwi_ptr; + + mt76x02_mac_poll_tx_status(dev, false); + + txi->tries = 0; + txi->jiffies = jiffies; + txi->wcid = txwi->wcid; + txi->pktid = txwi->pktid; + trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid); + mt76x02_tx_complete(&dev->mt76, skb); +} + +void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, + struct mt76_queue_entry *e, bool flush) +{ + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); + + if (e->txwi) + mt76x02_mac_queue_txdone(dev, e->skb, &e->txwi->txwi); + else + dev_kfree_skb_any(e->skb); +} +EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 62072291e416..d99c18743969 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -20,6 +20,8 @@ #include <linux/average.h> +struct mt76x02_dev; + struct mt76x02_tx_status { u8 valid:1; u8 success:1; @@ -40,6 +42,15 @@ struct mt76x02_vif { struct mt76_wcid group_wcid; }; +struct mt76x02_tx_info { + unsigned long jiffies; + u8 tries; + + u8 wcid; + u8 pktid; + u8 retry; +}; + DECLARE_EWMA(signal, 10, 8); struct mt76x02_sta { @@ -179,28 +190,40 @@ static inline bool mt76x02_wait_for_mac(struct mt76_dev *dev) return false; } -void mt76x02_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq); -void mt76x02_mac_fill_txwi(struct mt76x02_txwi *txwi, struct sk_buff *skb, - struct ieee80211_sta *sta, int len, u8 nss); +static inline struct mt76x02_tx_info * +mt76x02_skb_tx_info(struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + return (void *)info->status.status_driver_data; +} + +void mt76x02_txq_init(struct mt76x02_dev *dev, struct ieee80211_txq *txq); enum mt76x02_cipher_type mt76x02_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data); -int mt76x02_mac_shared_key_setup(struct mt76_dev *dev, u8 vif_idx, u8 key_idx, - struct ieee80211_key_conf *key); -int mt76x02_mac_wcid_set_key(struct mt76_dev *dev, u8 idx, - struct ieee80211_key_conf *key); -void mt76x02_mac_wcid_setup(struct mt76_dev *dev, u8 idx, u8 vif_idx, u8 *mac); -void mt76x02_mac_wcid_set_drop(struct mt76_dev *dev, u8 idx, bool drop); -void mt76x02_mac_wcid_set_rate(struct mt76_dev *dev, struct mt76_wcid *wcid, - const struct ieee80211_tx_rate *rate); -__le16 -mt76x02_mac_tx_rate_val(struct mt76_dev *dev, - const struct ieee80211_tx_rate *rate, u8 *nss_val); -bool mt76x02_mac_load_tx_status(struct mt76_dev *dev, - struct mt76x02_tx_status *stat); -void mt76x02_send_tx_status(struct mt76_dev *dev, - struct mt76x02_tx_status *stat, u8 *update); +int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx, + u8 key_idx, struct ieee80211_key_conf *key); +int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, + struct ieee80211_key_conf *key); +void mt76x02_mac_wcid_setup(struct mt76x02_dev *dev, u8 idx, u8 vif_idx, + u8 *mac); +void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop); +void mt76x02_mac_wcid_set_rate(struct mt76x02_dev *dev, struct mt76_wcid *wcid, + const struct ieee80211_tx_rate *rate); +bool mt76x02_mac_load_tx_status(struct mt76x02_dev *dev, + struct mt76x02_tx_status *stat); +void mt76x02_send_tx_status(struct mt76x02_dev *dev, + struct mt76x02_tx_status *stat, u8 *update); +int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, + void *rxi); int mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate); -void mt76x02_mac_setaddr(struct mt76_dev *dev, u8 *addr); +void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr); +void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, + struct sk_buff *skb, struct mt76_wcid *wcid, + struct ieee80211_sta *sta, int len); +void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq); +void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, + struct mt76_queue_entry *e, bool flush); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index 6d565133b7af..1b853bb723fb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -19,9 +19,7 @@ #include <linux/firmware.h> #include <linux/delay.h> -#include "mt76.h" #include "mt76x02_mcu.h" -#include "mt76x02_dma.h" struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len) { @@ -37,7 +35,7 @@ struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len) EXPORT_SYMBOL_GPL(mt76x02_mcu_msg_alloc); static struct sk_buff * -mt76x02_mcu_get_response(struct mt76_dev *dev, unsigned long expires) +mt76x02_mcu_get_response(struct mt76x02_dev *dev, unsigned long expires) { unsigned long timeout; @@ -45,17 +43,17 @@ mt76x02_mcu_get_response(struct mt76_dev *dev, unsigned long expires) return NULL; timeout = expires - jiffies; - wait_event_timeout(dev->mmio.mcu.wait, - !skb_queue_empty(&dev->mmio.mcu.res_q), + wait_event_timeout(dev->mt76.mmio.mcu.wait, + !skb_queue_empty(&dev->mt76.mmio.mcu.res_q), timeout); - return skb_dequeue(&dev->mmio.mcu.res_q); + return skb_dequeue(&dev->mt76.mmio.mcu.res_q); } static int -mt76x02_tx_queue_mcu(struct mt76_dev *dev, enum mt76_txq_id qid, +mt76x02_tx_queue_mcu(struct mt76x02_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, int cmd, int seq) { - struct mt76_queue *q = &dev->q_tx[qid]; + struct mt76_queue *q = &dev->mt76.q_tx[qid]; struct mt76_queue_buf buf; dma_addr_t addr; u32 tx_info; @@ -66,24 +64,26 @@ mt76x02_tx_queue_mcu(struct mt76_dev *dev, enum mt76_txq_id qid, FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | FIELD_PREP(MT_MCU_MSG_LEN, skb->len); - addr = dma_map_single(dev->dev, skb->data, skb->len, + addr = dma_map_single(dev->mt76.dev, skb->data, skb->len, DMA_TO_DEVICE); - if (dma_mapping_error(dev->dev, addr)) + if (dma_mapping_error(dev->mt76.dev, addr)) return -ENOMEM; buf.addr = addr; buf.len = skb->len; + spin_lock_bh(&q->lock); - dev->queue_ops->add_buf(dev, q, &buf, 1, tx_info, skb, NULL); - dev->queue_ops->kick(dev, q); + mt76_queue_add_buf(dev, q, &buf, 1, tx_info, skb, NULL); + mt76_queue_kick(dev, q); spin_unlock_bh(&q->lock); return 0; } -int mt76x02_mcu_msg_send(struct mt76_dev *dev, struct sk_buff *skb, +int mt76x02_mcu_msg_send(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, bool wait_resp) { + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); unsigned long expires = jiffies + HZ; int ret; u8 seq; @@ -91,11 +91,11 @@ int mt76x02_mcu_msg_send(struct mt76_dev *dev, struct sk_buff *skb, if (!skb) return -EINVAL; - mutex_lock(&dev->mmio.mcu.mutex); + mutex_lock(&mdev->mmio.mcu.mutex); - seq = ++dev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mmio.mcu.msg_seq & 0xf; if (!seq) - seq = ++dev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mmio.mcu.msg_seq & 0xf; ret = mt76x02_tx_queue_mcu(dev, MT_TXQ_MCU, skb, cmd, seq); if (ret) @@ -107,7 +107,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *dev, struct sk_buff *skb, skb = mt76x02_mcu_get_response(dev, expires); if (!skb) { - dev_err(dev->dev, + dev_err(mdev->dev, "MCU message %d (seq %d) timed out\n", cmd, seq); ret = -ETIMEDOUT; @@ -125,13 +125,13 @@ int mt76x02_mcu_msg_send(struct mt76_dev *dev, struct sk_buff *skb, } out: - mutex_unlock(&dev->mmio.mcu.mutex); + mutex_unlock(&mdev->mmio.mcu.mutex); return ret; } EXPORT_SYMBOL_GPL(mt76x02_mcu_msg_send); -int mt76x02_mcu_function_select(struct mt76_dev *dev, +int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func, u32 val, bool wait_resp) { @@ -144,13 +144,12 @@ int mt76x02_mcu_function_select(struct mt76_dev *dev, .value = cpu_to_le32(val), }; - skb = dev->mcu_ops->mcu_msg_alloc(&msg, sizeof(msg)); - return dev->mcu_ops->mcu_send_msg(dev, skb, CMD_FUN_SET_OP, - wait_resp); + skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg)); + return mt76_mcu_send_msg(dev, skb, CMD_FUN_SET_OP, wait_resp); } EXPORT_SYMBOL_GPL(mt76x02_mcu_function_select); -int mt76x02_mcu_set_radio_state(struct mt76_dev *dev, bool on, +int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on, bool wait_resp) { struct sk_buff *skb; @@ -162,13 +161,12 @@ int mt76x02_mcu_set_radio_state(struct mt76_dev *dev, bool on, .level = cpu_to_le32(0), }; - skb = dev->mcu_ops->mcu_msg_alloc(&msg, sizeof(msg)); - return dev->mcu_ops->mcu_send_msg(dev, skb, CMD_POWER_SAVING_OP, - wait_resp); + skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg)); + return mt76_mcu_send_msg(dev, skb, CMD_POWER_SAVING_OP, wait_resp); } EXPORT_SYMBOL_GPL(mt76x02_mcu_set_radio_state); -int mt76x02_mcu_calibrate(struct mt76_dev *dev, int type, +int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param, bool wait) { struct sk_buff *skb; @@ -182,44 +180,44 @@ int mt76x02_mcu_calibrate(struct mt76_dev *dev, int type, int ret; if (wait) - dev->bus->rmw(dev, MT_MCU_COM_REG0, BIT(31), 0); + mt76_rmw(dev, MT_MCU_COM_REG0, BIT(31), 0); - skb = dev->mcu_ops->mcu_msg_alloc(&msg, sizeof(msg)); - ret = dev->mcu_ops->mcu_send_msg(dev, skb, CMD_CALIBRATION_OP, true); + skb = mt76_mcu_msg_alloc(dev, &msg, sizeof(msg)); + ret = mt76_mcu_send_msg(dev, skb, CMD_CALIBRATION_OP, true); if (ret) return ret; if (wait && - WARN_ON(!__mt76_poll_msec(dev, MT_MCU_COM_REG0, - BIT(31), BIT(31), 100))) + WARN_ON(!mt76_poll_msec(dev, MT_MCU_COM_REG0, + BIT(31), BIT(31), 100))) return -ETIMEDOUT; return 0; } EXPORT_SYMBOL_GPL(mt76x02_mcu_calibrate); -int mt76x02_mcu_cleanup(struct mt76_dev *dev) +int mt76x02_mcu_cleanup(struct mt76x02_dev *dev) { struct sk_buff *skb; - dev->bus->wr(dev, MT_MCU_INT_LEVEL, 1); + mt76_wr(dev, MT_MCU_INT_LEVEL, 1); usleep_range(20000, 30000); - while ((skb = skb_dequeue(&dev->mmio.mcu.res_q)) != NULL) + while ((skb = skb_dequeue(&dev->mt76.mmio.mcu.res_q)) != NULL) dev_kfree_skb(skb); return 0; } EXPORT_SYMBOL_GPL(mt76x02_mcu_cleanup); -void mt76x02_set_ethtool_fwver(struct mt76_dev *dev, +void mt76x02_set_ethtool_fwver(struct mt76x02_dev *dev, const struct mt76x02_fw_header *h) { u16 bld = le16_to_cpu(h->build_ver); u16 ver = le16_to_cpu(h->fw_ver); - snprintf(dev->hw->wiphy->fw_version, - sizeof(dev->hw->wiphy->fw_version), + snprintf(dev->mt76.hw->wiphy->fw_version, + sizeof(dev->mt76.hw->wiphy->fw_version), "%d.%d.%02d-b%x", (ver >> 12) & 0xf, (ver >> 8) & 0xf, ver & 0xf, bld); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h index d30a58b5df29..2d8fd2514570 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h @@ -15,7 +15,9 @@ */ #ifndef __MT76x02_MCU_H -#define __MT76x0x_MCU_H +#define __MT76x02_MCU_H + +#include "mt76x02.h" #define MT_MCU_RESET_CTL 0x070C #define MT_MCU_INT_LEVEL 0x0718 @@ -94,18 +96,18 @@ struct mt76x02_patch_header { u8 pad[2]; }; -int mt76x02_mcu_cleanup(struct mt76_dev *dev); -int mt76x02_mcu_calibrate(struct mt76_dev *dev, int type, +int mt76x02_mcu_cleanup(struct mt76x02_dev *dev); +int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param, bool wait); struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len); -int mt76x02_mcu_msg_send(struct mt76_dev *dev, struct sk_buff *skb, +int mt76x02_mcu_msg_send(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, bool wait_resp); -int mt76x02_mcu_function_select(struct mt76_dev *dev, +int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func, u32 val, bool wait_resp); -int mt76x02_mcu_set_radio_state(struct mt76_dev *dev, bool on, +int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on, bool wait_resp); -void mt76x02_set_ethtool_fwver(struct mt76_dev *dev, +void mt76x02_set_ethtool_fwver(struct mt76x02_dev *dev, const struct mt76x02_fw_header *h); #endif /* __MT76x02_MCU_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 1146fbfd8df5..39f092034240 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -16,23 +16,22 @@ */ #include <linux/kernel.h> +#include <linux/irq.h> -#include "mt76.h" -#include "mt76x02_dma.h" -#include "mt76x02_util.h" -#include "mt76x02_mac.h" +#include "mt76x02.h" +#include "mt76x02_trace.h" static int -mt76x02_init_tx_queue(struct mt76_dev *dev, struct mt76_queue *q, +mt76x02_init_tx_queue(struct mt76x02_dev *dev, struct mt76_queue *q, int idx, int n_desc) { int ret; - q->regs = dev->mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE; + q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE; q->ndesc = n_desc; q->hw_idx = idx; - ret = __mt76_queue_alloc(dev, q); + ret = mt76_queue_alloc(dev, q); if (ret) return ret; @@ -42,16 +41,16 @@ mt76x02_init_tx_queue(struct mt76_dev *dev, struct mt76_queue *q, } static int -mt76x02_init_rx_queue(struct mt76_dev *dev, struct mt76_queue *q, +mt76x02_init_rx_queue(struct mt76x02_dev *dev, struct mt76_queue *q, int idx, int n_desc, int bufsize) { int ret; - q->regs = dev->mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE; + q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE; q->ndesc = n_desc; q->buf_size = bufsize; - ret = __mt76_queue_alloc(dev, q); + ret = mt76_queue_alloc(dev, q); if (ret) return ret; @@ -60,100 +59,200 @@ mt76x02_init_rx_queue(struct mt76_dev *dev, struct mt76_queue *q, return 0; } -int mt76x02_dma_init(struct mt76_dev *dev) +static void mt76x02_process_tx_status_fifo(struct mt76x02_dev *dev) +{ + struct mt76x02_tx_status stat; + u8 update = 1; + + while (kfifo_get(&dev->txstatus_fifo, &stat)) + mt76x02_send_tx_status(dev, &stat, &update); +} + +static void mt76x02_tx_tasklet(unsigned long data) +{ + struct mt76x02_dev *dev = (struct mt76x02_dev *)data; + int i; + + mt76x02_process_tx_status_fifo(dev); + + for (i = MT_TXQ_MCU; i >= 0; i--) + mt76_queue_tx_cleanup(dev, i, false); + + mt76x02_mac_poll_tx_status(dev, false); + mt76x02_irq_enable(dev, MT_INT_TX_DONE_ALL); +} + +int mt76x02_dma_init(struct mt76x02_dev *dev) { struct mt76_txwi_cache __maybe_unused *t; + int i, ret, fifo_size; struct mt76_queue *q; - int i, ret; + void *status_fifo; BUILD_BUG_ON(sizeof(t->txwi) < sizeof(struct mt76x02_txwi)); BUILD_BUG_ON(sizeof(struct mt76x02_rxwi) > MT_RX_HEADROOM); - mt76_dma_attach(dev); - __mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); + fifo_size = roundup_pow_of_two(32 * sizeof(struct mt76x02_tx_status)); + status_fifo = devm_kzalloc(dev->mt76.dev, fifo_size, GFP_KERNEL); + if (!status_fifo) + return -ENOMEM; + + tasklet_init(&dev->tx_tasklet, mt76x02_tx_tasklet, (unsigned long) dev); + kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size); + + mt76_dma_attach(&dev->mt76); + + mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); for (i = 0; i < IEEE80211_NUM_ACS; i++) { - ret = mt76x02_init_tx_queue(dev, &dev->q_tx[i], + ret = mt76x02_init_tx_queue(dev, &dev->mt76.q_tx[i], mt76_ac_to_hwq(i), MT_TX_RING_SIZE); if (ret) return ret; } - ret = mt76x02_init_tx_queue(dev, &dev->q_tx[MT_TXQ_PSD], + ret = mt76x02_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD], MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE); if (ret) return ret; - ret = mt76x02_init_tx_queue(dev, &dev->q_tx[MT_TXQ_MCU], + ret = mt76x02_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE); if (ret) return ret; - ret = mt76x02_init_rx_queue(dev, &dev->q_rx[MT_RXQ_MCU], 1, + ret = mt76x02_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1, MT_MCU_RING_SIZE, MT_RX_BUF_SIZE); if (ret) return ret; - q = &dev->q_rx[MT_RXQ_MAIN]; + q = &dev->mt76.q_rx[MT_RXQ_MAIN]; q->buf_offset = MT_RX_HEADROOM - sizeof(struct mt76x02_rxwi); ret = mt76x02_init_rx_queue(dev, q, 0, MT76X02_RX_RING_SIZE, MT_RX_BUF_SIZE); if (ret) return ret; - return __mt76_init_queues(dev); + return mt76_init_queues(dev); } EXPORT_SYMBOL_GPL(mt76x02_dma_init); -void mt76x02_set_irq_mask(struct mt76_dev *dev, u32 clear, u32 set) +void mt76x02_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +{ + struct mt76x02_dev *dev; + + dev = container_of(mdev, struct mt76x02_dev, mt76); + mt76x02_irq_enable(dev, MT_INT_RX_DONE(q)); +} +EXPORT_SYMBOL_GPL(mt76x02_rx_poll_complete); + +irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) +{ + struct mt76x02_dev *dev = dev_instance; + u32 intr; + + intr = mt76_rr(dev, MT_INT_SOURCE_CSR); + mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) + return IRQ_NONE; + + trace_dev_irq(dev, intr, dev->mt76.mmio.irqmask); + + intr &= dev->mt76.mmio.irqmask; + + if (intr & MT_INT_TX_DONE_ALL) { + mt76x02_irq_disable(dev, MT_INT_TX_DONE_ALL); + tasklet_schedule(&dev->tx_tasklet); + } + + if (intr & MT_INT_RX_DONE(0)) { + mt76x02_irq_disable(dev, MT_INT_RX_DONE(0)); + napi_schedule(&dev->mt76.napi[0]); + } + + if (intr & MT_INT_RX_DONE(1)) { + mt76x02_irq_disable(dev, MT_INT_RX_DONE(1)); + napi_schedule(&dev->mt76.napi[1]); + } + + if (intr & MT_INT_PRE_TBTT) + tasklet_schedule(&dev->pre_tbtt_tasklet); + + /* send buffered multicast frames now */ + if (intr & MT_INT_TBTT) + mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]); + + if (intr & MT_INT_TX_STAT) { + mt76x02_mac_poll_tx_status(dev, true); + tasklet_schedule(&dev->tx_tasklet); + } + + if (intr & MT_INT_GPTIMER) { + mt76x02_irq_disable(dev, MT_INT_GPTIMER); + tasklet_schedule(&dev->dfs_pd.dfs_tasklet); + } + + return IRQ_HANDLED; +} +EXPORT_SYMBOL_GPL(mt76x02_irq_handler); + +void mt76x02_set_irq_mask(struct mt76x02_dev *dev, u32 clear, u32 set) { unsigned long flags; - spin_lock_irqsave(&dev->mmio.irq_lock, flags); - dev->mmio.irqmask &= ~clear; - dev->mmio.irqmask |= set; - __mt76_wr(dev, MT_INT_MASK_CSR, dev->mmio.irqmask); - spin_unlock_irqrestore(&dev->mmio.irq_lock, flags); + spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags); + dev->mt76.mmio.irqmask &= ~clear; + dev->mt76.mmio.irqmask |= set; + mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask); + spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags); } EXPORT_SYMBOL_GPL(mt76x02_set_irq_mask); -void mt76x02_dma_enable(struct mt76_dev *dev) +static void mt76x02_dma_enable(struct mt76x02_dev *dev) { u32 val; - __mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX); - mt76x02_wait_for_wpdma(dev, 1000); + mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX); + mt76x02_wait_for_wpdma(&dev->mt76, 1000); usleep_range(50, 100); val = FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3) | MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN; - __mt76_set(dev, MT_WPDMA_GLO_CFG, val); - __mt76_clear(dev, MT_WPDMA_GLO_CFG, - MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + mt76_set(dev, MT_WPDMA_GLO_CFG, val); + mt76_clear(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); } EXPORT_SYMBOL_GPL(mt76x02_dma_enable); -void mt76x02_dma_disable(struct mt76_dev *dev) +void mt76x02_dma_cleanup(struct mt76x02_dev *dev) +{ + tasklet_kill(&dev->tx_tasklet); + mt76_dma_cleanup(&dev->mt76); +} +EXPORT_SYMBOL_GPL(mt76x02_dma_cleanup); + +void mt76x02_dma_disable(struct mt76x02_dev *dev) { - u32 val = __mt76_rr(dev, MT_WPDMA_GLO_CFG); + u32 val = mt76_rr(dev, MT_WPDMA_GLO_CFG); val &= MT_WPDMA_GLO_CFG_DMA_BURST_SIZE | MT_WPDMA_GLO_CFG_BIG_ENDIAN | MT_WPDMA_GLO_CFG_HDR_SEG_LEN; val |= MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE; - __mt76_wr(dev, MT_WPDMA_GLO_CFG, val); + mt76_wr(dev, MT_WPDMA_GLO_CFG, val); } EXPORT_SYMBOL_GPL(mt76x02_dma_disable); -void mt76x02_mac_start(struct mt76_dev *dev) +void mt76x02_mac_start(struct mt76x02_dev *dev) { mt76x02_dma_enable(dev); - __mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter); - __mt76_wr(dev, MT_MAC_SYS_CTRL, - MT_MAC_SYS_CTRL_ENABLE_TX | - MT_MAC_SYS_CTRL_ENABLE_RX); + mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter); + mt76_wr(dev, MT_MAC_SYS_CTRL, + MT_MAC_SYS_CTRL_ENABLE_TX | + MT_MAC_SYS_CTRL_ENABLE_RX); mt76x02_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | MT_INT_TX_STAT); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c index e29914d78b72..0f1d7b5c9f68 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c @@ -17,17 +17,17 @@ #include <linux/kernel.h> -#include "mt76.h" +#include "mt76x02.h" #include "mt76x02_phy.h" -void mt76x02_phy_set_rxpath(struct mt76_dev *dev) +void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev) { u32 val; - val = __mt76_rr(dev, MT_BBP(AGC, 0)); + val = mt76_rr(dev, MT_BBP(AGC, 0)); val &= ~BIT(4); - switch (dev->chainmask & 0xf) { + switch (dev->mt76.chainmask & 0xf) { case 2: val |= BIT(3); break; @@ -36,23 +36,23 @@ void mt76x02_phy_set_rxpath(struct mt76_dev *dev) break; } - __mt76_wr(dev, MT_BBP(AGC, 0), val); + mt76_wr(dev, MT_BBP(AGC, 0), val); mb(); - val = __mt76_rr(dev, MT_BBP(AGC, 0)); + val = mt76_rr(dev, MT_BBP(AGC, 0)); } EXPORT_SYMBOL_GPL(mt76x02_phy_set_rxpath); -void mt76x02_phy_set_txdac(struct mt76_dev *dev) +void mt76x02_phy_set_txdac(struct mt76x02_dev *dev) { int txpath; - txpath = (dev->chainmask >> 8) & 0xf; + txpath = (dev->mt76.chainmask >> 8) & 0xf; switch (txpath) { case 2: - __mt76_set(dev, MT_BBP(TXBE, 5), 0x3); + mt76_set(dev, MT_BBP(TXBE, 5), 0x3); break; default: - __mt76_clear(dev, MT_BBP(TXBE, 5), 0x3); + mt76_clear(dev, MT_BBP(TXBE, 5), 0x3); break; } } @@ -101,35 +101,158 @@ void mt76x02_add_rate_power_offset(struct mt76_rate_power *r, int offset) } EXPORT_SYMBOL_GPL(mt76x02_add_rate_power_offset); -void mt76x02_phy_set_txpower(struct mt76_dev *dev, int txp_0, int txp_1) +void mt76x02_phy_set_txpower(struct mt76x02_dev *dev, int txp_0, int txp_1) { - struct mt76_rate_power *t = &dev->rate_power; - - __mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_0, - txp_0); - __mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_1, - txp_1); - - __mt76_wr(dev, MT_TX_PWR_CFG_0, - mt76x02_tx_power_mask(t->cck[0], t->cck[2], t->ofdm[0], - t->ofdm[2])); - __mt76_wr(dev, MT_TX_PWR_CFG_1, - mt76x02_tx_power_mask(t->ofdm[4], t->ofdm[6], t->ht[0], - t->ht[2])); - __mt76_wr(dev, MT_TX_PWR_CFG_2, - mt76x02_tx_power_mask(t->ht[4], t->ht[6], t->ht[8], - t->ht[10])); - __mt76_wr(dev, MT_TX_PWR_CFG_3, - mt76x02_tx_power_mask(t->ht[12], t->ht[14], t->stbc[0], - t->stbc[2])); - __mt76_wr(dev, MT_TX_PWR_CFG_4, - mt76x02_tx_power_mask(t->stbc[4], t->stbc[6], 0, 0)); - __mt76_wr(dev, MT_TX_PWR_CFG_7, - mt76x02_tx_power_mask(t->ofdm[7], t->vht[8], t->ht[7], - t->vht[9])); - __mt76_wr(dev, MT_TX_PWR_CFG_8, - mt76x02_tx_power_mask(t->ht[14], 0, t->vht[8], t->vht[9])); - __mt76_wr(dev, MT_TX_PWR_CFG_9, - mt76x02_tx_power_mask(t->ht[7], 0, t->stbc[8], t->stbc[9])); + struct mt76_rate_power *t = &dev->mt76.rate_power; + + mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_0, txp_0); + mt76_rmw_field(dev, MT_TX_ALC_CFG_0, MT_TX_ALC_CFG_0_CH_INIT_1, txp_1); + + mt76_wr(dev, MT_TX_PWR_CFG_0, + mt76x02_tx_power_mask(t->cck[0], t->cck[2], t->ofdm[0], + t->ofdm[2])); + mt76_wr(dev, MT_TX_PWR_CFG_1, + mt76x02_tx_power_mask(t->ofdm[4], t->ofdm[6], t->ht[0], + t->ht[2])); + mt76_wr(dev, MT_TX_PWR_CFG_2, + mt76x02_tx_power_mask(t->ht[4], t->ht[6], t->ht[8], + t->ht[10])); + mt76_wr(dev, MT_TX_PWR_CFG_3, + mt76x02_tx_power_mask(t->ht[12], t->ht[14], t->stbc[0], + t->stbc[2])); + mt76_wr(dev, MT_TX_PWR_CFG_4, + mt76x02_tx_power_mask(t->stbc[4], t->stbc[6], 0, 0)); + mt76_wr(dev, MT_TX_PWR_CFG_7, + mt76x02_tx_power_mask(t->ofdm[7], t->vht[8], t->ht[7], + t->vht[9])); + mt76_wr(dev, MT_TX_PWR_CFG_8, + mt76x02_tx_power_mask(t->ht[14], 0, t->vht[8], t->vht[9])); + mt76_wr(dev, MT_TX_PWR_CFG_9, + mt76x02_tx_power_mask(t->ht[7], 0, t->stbc[8], t->stbc[9])); } EXPORT_SYMBOL_GPL(mt76x02_phy_set_txpower); + +int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev) +{ + struct mt76x02_sta *sta; + struct mt76_wcid *wcid; + int i, j, min_rssi = 0; + s8 cur_rssi; + + local_bh_disable(); + rcu_read_lock(); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid_mask); i++) { + unsigned long mask = dev->mt76.wcid_mask[i]; + + if (!mask) + continue; + + for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) { + if (!(mask & 1)) + continue; + + wcid = rcu_dereference(dev->mt76.wcid[j]); + if (!wcid) + continue; + + sta = container_of(wcid, struct mt76x02_sta, wcid); + spin_lock(&dev->mt76.rx_lock); + if (sta->inactive_count++ < 5) + cur_rssi = ewma_signal_read(&sta->rssi); + else + cur_rssi = 0; + spin_unlock(&dev->mt76.rx_lock); + + if (cur_rssi < min_rssi) + min_rssi = cur_rssi; + } + } + + rcu_read_unlock(); + local_bh_enable(); + + if (!min_rssi) + return -75; + + return min_rssi; +} +EXPORT_SYMBOL_GPL(mt76x02_phy_get_min_avg_rssi); + +void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl) +{ + int core_val, agc_val; + + switch (width) { + case NL80211_CHAN_WIDTH_80: + core_val = 3; + agc_val = 7; + break; + case NL80211_CHAN_WIDTH_40: + core_val = 2; + agc_val = 3; + break; + default: + core_val = 0; + agc_val = 1; + break; + } + + mt76_rmw_field(dev, MT_BBP(CORE, 1), MT_BBP_CORE_R1_BW, core_val); + mt76_rmw_field(dev, MT_BBP(AGC, 0), MT_BBP_AGC_R0_BW, agc_val); + mt76_rmw_field(dev, MT_BBP(AGC, 0), MT_BBP_AGC_R0_CTRL_CHAN, ctrl); + mt76_rmw_field(dev, MT_BBP(TXBE, 0), MT_BBP_TXBE_R0_CTRL_CHAN, ctrl); +} +EXPORT_SYMBOL_GPL(mt76x02_phy_set_bw); + +void mt76x02_phy_set_band(struct mt76x02_dev *dev, int band, + bool primary_upper) +{ + switch (band) { + case NL80211_BAND_2GHZ: + mt76_set(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_2G); + mt76_clear(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_5G); + break; + case NL80211_BAND_5GHZ: + mt76_clear(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_2G); + mt76_set(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_5G); + break; + } + + mt76_rmw_field(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_UPPER_40M, + primary_upper); +} +EXPORT_SYMBOL_GPL(mt76x02_phy_set_band); + +bool mt76x02_phy_adjust_vga_gain(struct mt76x02_dev *dev) +{ + u8 limit = dev->cal.low_gain > 0 ? 16 : 4; + bool ret = false; + u32 false_cca; + + false_cca = FIELD_GET(MT_RX_STAT_1_CCA_ERRORS, mt76_rr(dev, MT_RX_STAT_1)); + dev->cal.false_cca = false_cca; + if (false_cca > 800 && dev->cal.agc_gain_adjust < limit) { + dev->cal.agc_gain_adjust += 2; + ret = true; + } else if ((false_cca < 10 && dev->cal.agc_gain_adjust > 0) || + (dev->cal.agc_gain_adjust >= limit && false_cca < 500)) { + dev->cal.agc_gain_adjust -= 2; + ret = true; + } + + return ret; +} +EXPORT_SYMBOL_GPL(mt76x02_phy_adjust_vga_gain); + +void mt76x02_init_agc_gain(struct mt76x02_dev *dev) +{ + dev->cal.agc_gain_init[0] = mt76_get_field(dev, MT_BBP(AGC, 8), + MT_BBP_AGC_GAIN); + dev->cal.agc_gain_init[1] = mt76_get_field(dev, MT_BBP(AGC, 9), + MT_BBP_AGC_GAIN); + memcpy(dev->cal.agc_gain_cur, dev->cal.agc_gain_init, + sizeof(dev->cal.agc_gain_cur)); + dev->cal.low_gain = -1; +} +EXPORT_SYMBOL_GPL(mt76x02_init_agc_gain); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h index df69f8fade75..2b316cf7c70c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h @@ -19,11 +19,43 @@ #include "mt76x02_regs.h" +static inline int +mt76x02_get_rssi_gain_thresh(struct mt76x02_dev *dev) +{ + switch (dev->mt76.chandef.width) { + case NL80211_CHAN_WIDTH_80: + return -62; + case NL80211_CHAN_WIDTH_40: + return -65; + default: + return -68; + } +} + +static inline int +mt76x02_get_low_rssi_gain_thresh(struct mt76x02_dev *dev) +{ + switch (dev->mt76.chandef.width) { + case NL80211_CHAN_WIDTH_80: + return -76; + case NL80211_CHAN_WIDTH_40: + return -79; + default: + return -82; + } +} + void mt76x02_add_rate_power_offset(struct mt76_rate_power *r, int offset); -void mt76x02_phy_set_txpower(struct mt76_dev *dev, int txp_0, int txp_2); +void mt76x02_phy_set_txpower(struct mt76x02_dev *dev, int txp_0, int txp_2); void mt76x02_limit_rate_power(struct mt76_rate_power *r, int limit); int mt76x02_get_max_rate_power(struct mt76_rate_power *r); -void mt76x02_phy_set_rxpath(struct mt76_dev *dev); -void mt76x02_phy_set_txdac(struct mt76_dev *dev); +void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev); +void mt76x02_phy_set_txdac(struct mt76x02_dev *dev); +int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev); +void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl); +void mt76x02_phy_set_band(struct mt76x02_dev *dev, int band, + bool primary_upper); +bool mt76x02_phy_adjust_vga_gain(struct mt76x02_dev *dev); +void mt76x02_init_agc_gain(struct mt76x02_dev *dev); #endif /* __MT76x02_PHY_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index 24d1e6d747dd..f7de77d09d28 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -205,8 +205,8 @@ #define MT_TXQ_STA 0x0434 #define MT_RF_CSR_CFG 0x0500 #define MT_RF_CSR_CFG_DATA GENMASK(7, 0) -#define MT_RF_CSR_CFG_REG_ID GENMASK(13, 8) -#define MT_RF_CSR_CFG_REG_BANK GENMASK(17, 14) +#define MT_RF_CSR_CFG_REG_ID GENMASK(14, 8) +#define MT_RF_CSR_CFG_REG_BANK GENMASK(17, 15) #define MT_RF_CSR_CFG_WR BIT(30) #define MT_RF_CSR_CFG_KICK BIT(31) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_trace.c b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.c index a09f117848d6..5b42d2c87937 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_trace.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.c @@ -18,6 +18,6 @@ #ifndef __CHECKER__ #define CREATE_TRACE_POINTS -#include "mt76x2_trace.h" +#include "mt76x02_trace.h" #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_trace.h b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h index eb5afeaefa44..713f12d3c8de 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h @@ -14,14 +14,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#if !defined(__MT76x2_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -#define __MT76x2_TRACE_H +#if !defined(__MT76x02_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __MT76x02_TRACE_H #include <linux/tracepoint.h> -#include "mt76x2.h" +#include "mt76x02.h" #undef TRACE_SYSTEM -#define TRACE_SYSTEM mt76x2 +#define TRACE_SYSTEM mt76x02 #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) @@ -35,7 +35,7 @@ #define TXID_PR_ARG __entry->wcid, __entry->pktid DECLARE_EVENT_CLASS(dev_evt, - TP_PROTO(struct mt76x2_dev *dev), + TP_PROTO(struct mt76x02_dev *dev), TP_ARGS(dev), TP_STRUCT__entry( DEV_ENTRY @@ -47,7 +47,7 @@ DECLARE_EVENT_CLASS(dev_evt, ); DECLARE_EVENT_CLASS(dev_txid_evt, - TP_PROTO(struct mt76x2_dev *dev, u8 wcid, u8 pktid), + TP_PROTO(struct mt76x02_dev *dev, u8 wcid, u8 pktid), TP_ARGS(dev, wcid, pktid), TP_STRUCT__entry( DEV_ENTRY @@ -63,18 +63,18 @@ DECLARE_EVENT_CLASS(dev_txid_evt, ) ); -DEFINE_EVENT(dev_evt, mac_txstat_poll, - TP_PROTO(struct mt76x2_dev *dev), - TP_ARGS(dev) -); - DEFINE_EVENT(dev_txid_evt, mac_txdone_add, - TP_PROTO(struct mt76x2_dev *dev, u8 wcid, u8 pktid), + TP_PROTO(struct mt76x02_dev *dev, u8 wcid, u8 pktid), TP_ARGS(dev, wcid, pktid) ); +DEFINE_EVENT(dev_evt, mac_txstat_poll, + TP_PROTO(struct mt76x02_dev *dev), + TP_ARGS(dev) +); + TRACE_EVENT(mac_txstat_fetch, - TP_PROTO(struct mt76x2_dev *dev, + TP_PROTO(struct mt76x02_dev *dev, struct mt76x02_tx_status *stat), TP_ARGS(dev, stat), @@ -110,9 +110,8 @@ TRACE_EVENT(mac_txstat_fetch, ) ); - TRACE_EVENT(dev_irq, - TP_PROTO(struct mt76x2_dev *dev, u32 val, u32 mask), + TP_PROTO(struct mt76x02_dev *dev, u32 val, u32 mask), TP_ARGS(dev, val, mask), @@ -139,6 +138,6 @@ TRACE_EVENT(dev_irq, #undef TRACE_INCLUDE_PATH #define TRACE_INCLUDE_PATH . #undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE mt76x2_trace +#define TRACE_INCLUDE_FILE mt76x02_trace #include <trace/define_trace.h> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c new file mode 100644 index 000000000000..d3de08872d6e --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> + * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/kernel.h> + +#include "mt76x02.h" + +void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct mt76x02_dev *dev = hw->priv; + struct ieee80211_vif *vif = info->control.vif; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + + if (control->sta) { + struct mt76x02_sta *msta; + + msta = (struct mt76x02_sta *)control->sta->drv_priv; + wcid = &msta->wcid; + /* sw encrypted frames */ + if (!info->control.hw_key && wcid->hw_key_idx != 0xff) + control->sta = NULL; + } + + if (vif && !control->sta) { + struct mt76x02_vif *mvif; + + mvif = (struct mt76x02_vif *)vif->drv_priv; + wcid = &mvif->group_wcid; + } + + mt76_tx(&dev->mt76, control->sta, wcid, skb); +} +EXPORT_SYMBOL_GPL(mt76x02_tx); + +void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb) +{ + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); + void *rxwi = skb->data; + + if (q == MT_RXQ_MCU) { + /* this is used just by mmio code */ + skb_queue_tail(&mdev->mmio.mcu.res_q, skb); + wake_up(&mdev->mmio.mcu.wait); + return; + } + + skb_pull(skb, sizeof(struct mt76x02_rxwi)); + if (mt76x02_mac_process_rx(dev, skb, rxwi)) { + dev_kfree_skb(skb); + return; + } + + mt76_rx(mdev, q, skb); +} +EXPORT_SYMBOL_GPL(mt76x02_queue_rx_skb); + +s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev, + const struct ieee80211_tx_rate *rate) +{ + s8 max_txpwr; + + if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { + u8 mcs = ieee80211_rate_get_vht_mcs(rate); + + if (mcs == 8 || mcs == 9) { + max_txpwr = dev->mt76.rate_power.vht[8]; + } else { + u8 nss, idx; + + nss = ieee80211_rate_get_vht_nss(rate); + idx = ((nss - 1) << 3) + mcs; + max_txpwr = dev->mt76.rate_power.ht[idx & 0xf]; + } + } else if (rate->flags & IEEE80211_TX_RC_MCS) { + max_txpwr = dev->mt76.rate_power.ht[rate->idx & 0xf]; + } else { + enum nl80211_band band = dev->mt76.chandef.chan->band; + + if (band == NL80211_BAND_2GHZ) { + const struct ieee80211_rate *r; + struct wiphy *wiphy = dev->mt76.hw->wiphy; + struct mt76_rate_power *rp = &dev->mt76.rate_power; + + r = &wiphy->bands[band]->bitrates[rate->idx]; + if (r->flags & IEEE80211_RATE_SHORT_PREAMBLE) + max_txpwr = rp->cck[r->hw_value & 0x3]; + else + max_txpwr = rp->ofdm[r->hw_value & 0x7]; + } else { + max_txpwr = dev->mt76.rate_power.ofdm[rate->idx & 0x7]; + } + } + + return max_txpwr; +} +EXPORT_SYMBOL_GPL(mt76x02_tx_get_max_txpwr_adj); + +s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr, s8 max_txpwr_adj) +{ + txpwr = min_t(s8, txpwr, dev->mt76.txpower_conf); + txpwr -= (dev->target_power + dev->target_power_delta[0]); + txpwr = min_t(s8, txpwr, max_txpwr_adj); + + if (!dev->enable_tpc) + return 0; + else if (txpwr >= 0) + return min_t(s8, txpwr, 7); + else + return (txpwr < -16) ? 8 : (txpwr + 32) / 2; +} +EXPORT_SYMBOL_GPL(mt76x02_tx_get_txpwr_adj); + +void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr) +{ + s8 txpwr_adj; + + txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, txpwr, + dev->mt76.rate_power.ofdm[4]); + mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG, + MT_PROT_AUTO_TX_CFG_PROT_PADJ, txpwr_adj); + mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG, + MT_PROT_AUTO_TX_CFG_AUTO_PADJ, txpwr_adj); +} +EXPORT_SYMBOL_GPL(mt76x02_tx_set_txpwr_auto); + +void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + ieee80211_free_txskb(dev->hw, skb); + } else { + ieee80211_tx_info_clear_status(info); + info->status.rates[0].idx = -1; + info->flags |= IEEE80211_TX_STAT_ACK; + ieee80211_tx_status(dev->hw, skb); + } +} +EXPORT_SYMBOL_GPL(mt76x02_tx_complete); + +bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update) +{ + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); + struct mt76x02_tx_status stat; + + if (!mt76x02_mac_load_tx_status(dev, &stat)) + return false; + + mt76x02_send_tx_status(dev, &stat, update); + + return true; +} +EXPORT_SYMBOL_GPL(mt76x02_tx_status_data); + +int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi, + struct sk_buff *skb, struct mt76_queue *q, + struct mt76_wcid *wcid, struct ieee80211_sta *sta, + u32 *tx_info) +{ + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + int qsel = MT_QSEL_EDCA; + int ret; + + if (q == &dev->mt76.q_tx[MT_TXQ_PSD] && wcid && wcid->idx < 128) + mt76x02_mac_wcid_set_drop(dev, wcid->idx, false); + + mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, skb->len); + + ret = mt76x02_insert_hdr_pad(skb); + if (ret < 0) + return ret; + + if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) + qsel = MT_QSEL_MGMT; + + *tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) | + MT_TXD_INFO_80211; + + if (!wcid || wcid->hw_key_idx == 0xff || wcid->sw_iv) + *tx_info |= MT_TXD_INFO_WIV; + + return 0; +} +EXPORT_SYMBOL_GPL(mt76x02_tx_prepare_skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h index 2482f9761fcd..0126e51d77ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h @@ -15,15 +15,20 @@ */ #ifndef __MT76x02_USB_H -#define __MT76x0x_USB_H +#define __MT76x02_USB_H -#include "mt76.h" +#include "mt76x02.h" void mt76x02u_init_mcu(struct mt76_dev *dev); -void mt76x02u_mcu_fw_reset(struct mt76_dev *dev); -int mt76x02u_mcu_fw_send_data(struct mt76_dev *dev, const void *data, +void mt76x02u_mcu_fw_reset(struct mt76x02_dev *dev); +int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data, int data_len, u32 max_payload, u32 offset); int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags); -int mt76x02u_set_txinfo(struct sk_buff *skb, struct mt76_wcid *wcid, u8 ep); +int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, + struct sk_buff *skb, struct mt76_queue *q, + struct mt76_wcid *wcid, struct ieee80211_sta *sta, + u32 *tx_info); +void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, + struct mt76_queue_entry *e, bool flush); #endif /* __MT76x02_USB_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index aecbe0c429ea..dc2226c722dd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -14,8 +14,25 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "mt76.h" -#include "mt76x02_dma.h" +#include "mt76x02.h" + +static void mt76x02u_remove_dma_hdr(struct sk_buff *skb) +{ + int hdr_len; + + skb_pull(skb, sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN); + hdr_len = ieee80211_get_hdrlen_from_skb(skb); + if (hdr_len % 4) + mt76x02_remove_hdr_pad(skb, 2); +} + +void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, + struct mt76_queue_entry *e, bool flush) +{ + mt76x02u_remove_dma_hdr(e->skb); + mt76x02_tx_complete(mdev, e->skb); +} +EXPORT_SYMBOL_GPL(mt76x02u_tx_complete_skb); int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) { @@ -50,7 +67,8 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) return 0; } -int mt76x02u_set_txinfo(struct sk_buff *skb, struct mt76_wcid *wcid, u8 ep) +static int +mt76x02u_set_txinfo(struct sk_buff *skb, struct mt76_wcid *wcid, u8 ep) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); enum mt76_qsel qsel; @@ -69,4 +87,21 @@ int mt76x02u_set_txinfo(struct sk_buff *skb, struct mt76_wcid *wcid, u8 ep) return mt76x02u_skb_dma_info(skb, WLAN_PORT, flags); } -EXPORT_SYMBOL_GPL(mt76x02u_set_txinfo); + +int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, + struct sk_buff *skb, struct mt76_queue *q, + struct mt76_wcid *wcid, struct ieee80211_sta *sta, + u32 *tx_info) +{ + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); + struct mt76x02_txwi *txwi; + int len = skb->len; + + mt76x02_insert_hdr_pad(skb); + + txwi = skb_push(skb, sizeof(struct mt76x02_txwi)); + mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len); + + return mt76x02u_set_txinfo(skb, wcid, q2ep(q->hw_idx)); +} +EXPORT_SYMBOL_GPL(mt76x02u_tx_prepare_skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index cb5f073f08af..da299b8a1334 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -17,8 +17,7 @@ #include <linux/module.h> #include <linux/firmware.h> -#include "mt76.h" -#include "mt76x02_dma.h" +#include "mt76x02.h" #include "mt76x02_mcu.h" #include "mt76x02_usb.h" @@ -255,16 +254,16 @@ mt76x02u_mcu_rd_rp(struct mt76_dev *dev, u32 base, return ret; } -void mt76x02u_mcu_fw_reset(struct mt76_dev *dev) +void mt76x02u_mcu_fw_reset(struct mt76x02_dev *dev) { - mt76u_vendor_request(dev, MT_VEND_DEV_MODE, + mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE, USB_DIR_OUT | USB_TYPE_VENDOR, 0x1, 0, NULL, 0); } EXPORT_SYMBOL_GPL(mt76x02u_mcu_fw_reset); static int -__mt76x02u_mcu_fw_send_data(struct mt76_dev *dev, struct mt76u_buf *buf, +__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, const void *fw_data, int len, u32 dst_addr) { u8 *data = sg_virt(&buf->urb->sg[0]); @@ -281,14 +280,14 @@ __mt76x02u_mcu_fw_send_data(struct mt76_dev *dev, struct mt76u_buf *buf, memcpy(data + sizeof(info), fw_data, len); memset(data + sizeof(info) + len, 0, 4); - mt76u_single_wr(dev, MT_VEND_WRITE_FCE, + mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE, MT_FCE_DMA_ADDR, dst_addr); len = roundup(len, 4); - mt76u_single_wr(dev, MT_VEND_WRITE_FCE, + mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE, MT_FCE_DMA_LEN, len << 16); buf->len = MT_CMD_HDR_LEN + len + sizeof(info); - err = mt76u_submit_buf(dev, USB_DIR_OUT, + err = mt76u_submit_buf(&dev->mt76, USB_DIR_OUT, MT_EP_OUT_INBAND_CMD, buf, GFP_KERNEL, mt76u_mcu_complete_urb, &cmpl); @@ -297,31 +296,31 @@ __mt76x02u_mcu_fw_send_data(struct mt76_dev *dev, struct mt76u_buf *buf, if (!wait_for_completion_timeout(&cmpl, msecs_to_jiffies(1000))) { - dev_err(dev->dev, "firmware upload timed out\n"); + dev_err(dev->mt76.dev, "firmware upload timed out\n"); usb_kill_urb(buf->urb); return -ETIMEDOUT; } if (mt76u_urb_error(buf->urb)) { - dev_err(dev->dev, "firmware upload failed: %d\n", + dev_err(dev->mt76.dev, "firmware upload failed: %d\n", buf->urb->status); return buf->urb->status; } - val = mt76u_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX); + val = mt76_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX); val++; - mt76u_wr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX, val); + mt76_wr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX, val); return 0; } -int mt76x02u_mcu_fw_send_data(struct mt76_dev *dev, const void *data, +int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data, int data_len, u32 max_payload, u32 offset) { int err, len, pos = 0, max_len = max_payload - 8; struct mt76u_buf buf; - err = mt76u_buf_alloc(dev, &buf, 1, max_payload, max_payload, + err = mt76u_buf_alloc(&dev->mt76, &buf, 1, max_payload, max_payload, GFP_KERNEL); if (err < 0) return err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index ec422c3980e8..ca05332f81fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -16,10 +16,7 @@ */ #include <linux/module.h> -#include "mt76.h" -#include "mt76x02_dma.h" -#include "mt76x02_regs.h" -#include "mt76x02_mac.h" +#include "mt76x02.h" #define CCK_RATE(_idx, _rate) { \ .bitrate = _rate, \ @@ -51,21 +48,21 @@ struct ieee80211_rate mt76x02_rates[] = { EXPORT_SYMBOL_GPL(mt76x02_rates); void mt76x02_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, u64 multicast) + unsigned int changed_flags, + unsigned int *total_flags, u64 multicast) { - struct mt76_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; u32 flags = 0; #define MT76_FILTER(_flag, _hw) do { \ flags |= *total_flags & FIF_##_flag; \ - dev->rxfilter &= ~(_hw); \ - dev->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + dev->mt76.rxfilter &= ~(_hw); \ + dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \ } while (0) - mutex_lock(&dev->mutex); + mutex_lock(&dev->mt76.mutex); - dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS; + dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS; MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR); MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR); @@ -78,25 +75,25 @@ void mt76x02_configure_filter(struct ieee80211_hw *hw, MT76_FILTER(PSPOLL, MT_RX_FILTR_CFG_PSPOLL); *total_flags = flags; - dev->bus->wr(dev, MT_RX_FILTR_CFG, dev->rxfilter); + mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter); - mutex_unlock(&dev->mutex); + mutex_unlock(&dev->mt76.mutex); } EXPORT_SYMBOL_GPL(mt76x02_configure_filter); int mt76x02_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta) { - struct mt76_dev *dev = hw->priv; - struct mt76x02_sta *msta = (struct mt76x02_sta *) sta->drv_priv; - struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv; + struct mt76x02_dev *dev = hw->priv; + struct mt76x02_sta *msta = (struct mt76x02_sta *)sta->drv_priv; + struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; int ret = 0; int idx = 0; int i; - mutex_lock(&dev->mutex); + mutex_lock(&dev->mt76.mutex); - idx = mt76_wcid_alloc(dev->wcid_mask, ARRAY_SIZE(dev->wcid)); + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, ARRAY_SIZE(dev->mt76.wcid)); if (idx < 0) { ret = -ENOSPC; goto out; @@ -116,40 +113,40 @@ int mt76x02_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ewma_signal_init(&msta->rssi); - rcu_assign_pointer(dev->wcid[idx], &msta->wcid); + rcu_assign_pointer(dev->mt76.wcid[idx], &msta->wcid); out: - mutex_unlock(&dev->mutex); + mutex_unlock(&dev->mt76.mutex); return ret; } EXPORT_SYMBOL_GPL(mt76x02_sta_add); int mt76x02_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta) { - struct mt76_dev *dev = hw->priv; - struct mt76x02_sta *msta = (struct mt76x02_sta *) sta->drv_priv; + struct mt76x02_dev *dev = hw->priv; + struct mt76x02_sta *msta = (struct mt76x02_sta *)sta->drv_priv; int idx = msta->wcid.idx; int i; - mutex_lock(&dev->mutex); - rcu_assign_pointer(dev->wcid[idx], NULL); + mutex_lock(&dev->mt76.mutex); + rcu_assign_pointer(dev->mt76.wcid[idx], NULL); for (i = 0; i < ARRAY_SIZE(sta->txq); i++) - mt76_txq_remove(dev, sta->txq[i]); + mt76_txq_remove(&dev->mt76, sta->txq[i]); mt76x02_mac_wcid_set_drop(dev, idx, true); - mt76_wcid_free(dev->wcid_mask, idx); + mt76_wcid_free(dev->mt76.wcid_mask, idx); mt76x02_mac_wcid_setup(dev, idx, 0, NULL); - mutex_unlock(&dev->mutex); + mutex_unlock(&dev->mt76.mutex); return 0; } EXPORT_SYMBOL_GPL(mt76x02_sta_remove); -void mt76x02_vif_init(struct mt76_dev *dev, struct ieee80211_vif *vif, - unsigned int idx) +void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, + unsigned int idx) { - struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv; + struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; mvif->idx = idx; mvif->group_wcid.idx = MT_VIF_WCID(idx); @@ -161,11 +158,11 @@ EXPORT_SYMBOL_GPL(mt76x02_vif_init); int mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt76_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; unsigned int idx = 0; if (vif->addr[0] & BIT(1)) - idx = 1 + (((dev->macaddr[0] ^ vif->addr[0]) >> 2) & 7); + idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7); /* * Client mode typically only has one configurable BSSID register, @@ -189,20 +186,20 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) EXPORT_SYMBOL_GPL(mt76x02_add_interface); void mt76x02_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) + struct ieee80211_vif *vif) { - struct mt76_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; - mt76_txq_remove(dev, vif->txq); + mt76_txq_remove(&dev->mt76, vif->txq); } EXPORT_SYMBOL_GPL(mt76x02_remove_interface); int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params) + struct ieee80211_ampdu_params *params) { enum ieee80211_ampdu_mlme_action action = params->action; struct ieee80211_sta *sta = params->sta; - struct mt76_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; struct mt76x02_sta *msta = (struct mt76x02_sta *) sta->drv_priv; struct ieee80211_txq *txq = sta->txq[params->tid]; u16 tid = params->tid; @@ -216,12 +213,14 @@ int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, switch (action) { case IEEE80211_AMPDU_RX_START: - mt76_rx_aggr_start(dev, &msta->wcid, tid, *ssn, params->buf_size); - __mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid)); + mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, + *ssn, params->buf_size); + mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid)); break; case IEEE80211_AMPDU_RX_STOP: - mt76_rx_aggr_stop(dev, &msta->wcid, tid); - __mt76_clear(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid)); + mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); + mt76_clear(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, + BIT(16 + tid)); break; case IEEE80211_AMPDU_TX_OPERATIONAL: mtxq->aggr = true; @@ -248,11 +247,11 @@ int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, EXPORT_SYMBOL_GPL(mt76x02_ampdu_action); int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { - struct mt76_dev *dev = hw->priv; - struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv; + struct mt76x02_dev *dev = hw->priv; + struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; struct mt76x02_sta *msta; struct mt76_wcid *wcid; int idx = key->keyidx; @@ -298,7 +297,7 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, key = NULL; } - mt76_wcid_key_setup(dev, wcid, key); + mt76_wcid_key_setup(&dev->mt76, wcid, key); if (!msta) { if (key || wcid->hw_key_idx == idx) { @@ -315,13 +314,13 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, EXPORT_SYMBOL_GPL(mt76x02_set_key); int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 queue, const struct ieee80211_tx_queue_params *params) + u16 queue, const struct ieee80211_tx_queue_params *params) { - struct mt76_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; u8 cw_min = 5, cw_max = 10, qid; u32 val; - qid = dev->q_tx[queue].hw_idx; + qid = dev->mt76.q_tx[queue].hw_idx; if (params->cw_min) cw_min = fls(params->cw_min); @@ -332,27 +331,27 @@ int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, FIELD_PREP(MT_EDCA_CFG_AIFSN, params->aifs) | FIELD_PREP(MT_EDCA_CFG_CWMIN, cw_min) | FIELD_PREP(MT_EDCA_CFG_CWMAX, cw_max); - __mt76_wr(dev, MT_EDCA_CFG_AC(qid), val); + mt76_wr(dev, MT_EDCA_CFG_AC(qid), val); - val = __mt76_rr(dev, MT_WMM_TXOP(qid)); + val = mt76_rr(dev, MT_WMM_TXOP(qid)); val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(qid)); val |= params->txop << MT_WMM_TXOP_SHIFT(qid); - __mt76_wr(dev, MT_WMM_TXOP(qid), val); + mt76_wr(dev, MT_WMM_TXOP(qid), val); - val = __mt76_rr(dev, MT_WMM_AIFSN); + val = mt76_rr(dev, MT_WMM_AIFSN); val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(qid)); val |= params->aifs << MT_WMM_AIFSN_SHIFT(qid); - __mt76_wr(dev, MT_WMM_AIFSN, val); + mt76_wr(dev, MT_WMM_AIFSN, val); - val = __mt76_rr(dev, MT_WMM_CWMIN); + val = mt76_rr(dev, MT_WMM_CWMIN); val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(qid)); val |= cw_min << MT_WMM_CWMIN_SHIFT(qid); - __mt76_wr(dev, MT_WMM_CWMIN, val); + mt76_wr(dev, MT_WMM_CWMIN, val); - val = __mt76_rr(dev, MT_WMM_CWMAX); + val = mt76_rr(dev, MT_WMM_CWMAX); val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(qid)); val |= cw_max << MT_WMM_CWMAX_SHIFT(qid); - __mt76_wr(dev, MT_WMM_CWMAX, val); + mt76_wr(dev, MT_WMM_CWMAX, val); return 0; } @@ -362,7 +361,7 @@ void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt76_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; struct mt76x02_sta *msta = (struct mt76x02_sta *) sta->drv_priv; struct ieee80211_sta_rates *rates = rcu_dereference(sta->rates); struct ieee80211_tx_rate rate = {}; @@ -373,9 +372,7 @@ void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw, rate.idx = rates->rate[0].idx; rate.flags = rates->rate[0].flags; mt76x02_mac_wcid_set_rate(dev, &msta->wcid, &rate); - - if (dev->drv && dev->drv->get_max_txpwr_adj) - msta->wcid.max_txpwr_adj = dev->drv->get_max_txpwr_adj(dev, &rate); + msta->wcid.max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, &rate); } EXPORT_SYMBOL_GPL(mt76x02_sta_rate_tbl_update); @@ -408,52 +405,6 @@ void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len) } EXPORT_SYMBOL_GPL(mt76x02_remove_hdr_pad); -static void mt76x02_remove_dma_hdr(struct sk_buff *skb) -{ - int hdr_len; - - skb_pull(skb, sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN); - hdr_len = ieee80211_get_hdrlen_from_skb(skb); - if (hdr_len % 4) - mt76x02_remove_hdr_pad(skb, 2); -} - -void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - ieee80211_free_txskb(dev->hw, skb); - } else { - ieee80211_tx_info_clear_status(info); - info->status.rates[0].idx = -1; - info->flags |= IEEE80211_TX_STAT_ACK; - ieee80211_tx_status(dev->hw, skb); - } -} -EXPORT_SYMBOL_GPL(mt76x02_tx_complete); - -void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush) -{ - mt76x02_remove_dma_hdr(e->skb); - mt76x02_tx_complete(mdev, e->skb); -} -EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb); - -bool mt76x02_tx_status_data(struct mt76_dev *dev, u8 *update) -{ - struct mt76x02_tx_status stat; - - if (!mt76x02_mac_load_tx_status(dev, &stat)) - return false; - - mt76x02_send_tx_status(dev, &stat, update); - - return true; -} -EXPORT_SYMBOL_GPL(mt76x02_tx_status_data); - const u16 mt76x02_beacon_offsets[16] = { /* 1024 byte per beacon */ 0xc000, @@ -476,7 +427,7 @@ const u16 mt76x02_beacon_offsets[16] = { }; EXPORT_SYMBOL_GPL(mt76x02_beacon_offsets); -void mt76x02_set_beacon_offsets(struct mt76_dev *dev) +void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev) { u16 val, base = MT_BEACON_BASE; u32 regs[4] = {}; @@ -488,7 +439,7 @@ void mt76x02_set_beacon_offsets(struct mt76_dev *dev) } for (i = 0; i < 4; i++) - __mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]); + mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]); } EXPORT_SYMBOL_GPL(mt76x02_set_beacon_offsets); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.h b/drivers/net/wireless/mediatek/mt76/mt76x02_util.h deleted file mode 100644 index ff4cab5ca038..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> - * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __MT76X02_UTIL_H -#define __MT76X02_UTIL_H - -extern struct ieee80211_rate mt76x02_rates[12]; - -void mt76x02_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, u64 multicast); -int mt76x02_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int mt76x02_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); - -void mt76x02_vif_init(struct mt76_dev *dev, struct ieee80211_vif *vif, - unsigned int idx); -int mt76x02_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); -void mt76x02_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); - -int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_ampdu_params *params); -int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); -int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 queue, const struct ieee80211_tx_queue_params *params); -void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int mt76x02_insert_hdr_pad(struct sk_buff *skb); -void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len); -void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb); -void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush); -bool mt76x02_tx_status_data(struct mt76_dev *dev, u8 *update); - -extern const u16 mt76x02_beacon_offsets[16]; -void mt76x02_set_beacon_offsets(struct mt76_dev *dev); -void mt76x02_set_irq_mask(struct mt76_dev *dev, u32 clear, u32 set); -void mt76x02_mac_start(struct mt76_dev *dev); - -static inline void mt76x02_irq_enable(struct mt76_dev *dev, u32 mask) -{ - mt76x02_set_irq_mask(dev, 0, mask); -} - -static inline void mt76x02_irq_disable(struct mt76_dev *dev, u32 mask) -{ - mt76x02_set_irq_mask(dev, mask, 0); -} - -static inline bool -mt76x02_wait_for_txrx_idle(struct mt76_dev *dev) -{ - return __mt76_poll_msec(dev, MT_MAC_STATUS, - MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, - 0, 100); -} - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2.h deleted file mode 100644 index d6ccab06a594..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __MT76x2_H -#define __MT76x2_H - -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <linux/spinlock.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/bitops.h> -#include <linux/kfifo.h> - -#define MT7662_FIRMWARE "mt7662.bin" -#define MT7662_ROM_PATCH "mt7662_rom_patch.bin" -#define MT7662_EEPROM_SIZE 512 - -#define MT7662U_FIRMWARE "mediatek/mt7662u.bin" -#define MT7662U_ROM_PATCH "mediatek/mt7662u_rom_patch.bin" - -#define MT_MAX_CHAINS 2 - -#define MT_CALIBRATE_INTERVAL HZ - -#include "mt76.h" -#include "mt76x02_regs.h" -#include "mt76x2_mac.h" -#include "mt76x2_dfs.h" - -struct mt76x2_rx_freq_cal { - s8 high_gain[MT_MAX_CHAINS]; - s8 rssi_offset[MT_MAX_CHAINS]; - s8 lna_gain; - u32 mcu_gain; -}; - -struct mt76x2_calibration { - struct mt76x2_rx_freq_cal rx; - - u8 agc_gain_init[MT_MAX_CHAINS]; - u8 agc_gain_cur[MT_MAX_CHAINS]; - - u16 false_cca; - s8 avg_rssi_all; - s8 agc_gain_adjust; - s8 low_gain; - - u8 temp; - - bool init_cal_done; - bool tssi_cal_done; - bool tssi_comp_pending; - bool dpd_cal_done; - bool channel_cal_done; -}; - -struct mt76x2_dev { - struct mt76_dev mt76; /* must be first */ - - struct mac_address macaddr_list[8]; - - struct mutex mutex; - - u8 txdone_seq; - DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); - - struct sk_buff *rx_head; - - struct tasklet_struct tx_tasklet; - struct tasklet_struct pre_tbtt_tasklet; - struct delayed_work cal_work; - struct delayed_work mac_work; - - u32 aggr_stats[32]; - - struct sk_buff *beacons[8]; - u8 beacon_mask; - u8 beacon_data_mask; - - u8 tbtt_count; - u16 beacon_int; - - struct mt76x2_calibration cal; - - s8 target_power; - s8 target_power_delta[2]; - bool enable_tpc; - - u8 coverage_class; - u8 slottime; - - struct mt76x2_dfs_pattern_detector dfs_pd; -}; - -static inline bool is_mt7612(struct mt76x2_dev *dev) -{ - return mt76_chip(&dev->mt76) == 0x7612; -} - -static inline bool mt76x2_channel_silent(struct mt76x2_dev *dev) -{ - struct ieee80211_channel *chan = dev->mt76.chandef.chan; - - return ((chan->flags & IEEE80211_CHAN_RADAR) && - chan->dfs_state != NL80211_DFS_AVAILABLE); -} - -extern const struct ieee80211_ops mt76x2_ops; - -struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev); -int mt76x2_register_device(struct mt76x2_dev *dev); -void mt76x2_init_debugfs(struct mt76x2_dev *dev); -void mt76x2_init_device(struct mt76x2_dev *dev); - -irqreturn_t mt76x2_irq_handler(int irq, void *dev_instance); -void mt76x2_phy_power_on(struct mt76x2_dev *dev); -int mt76x2_init_hardware(struct mt76x2_dev *dev); -void mt76x2_stop_hardware(struct mt76x2_dev *dev); -int mt76x2_eeprom_init(struct mt76x2_dev *dev); -int mt76x2_apply_calibration_data(struct mt76x2_dev *dev, int channel); -void mt76x2_set_tx_ackto(struct mt76x2_dev *dev); - -void mt76x2_phy_set_antenna(struct mt76x2_dev *dev); -int mt76x2_phy_start(struct mt76x2_dev *dev); -int mt76x2_phy_set_channel(struct mt76x2_dev *dev, - struct cfg80211_chan_def *chandef); -int mt76x2_mac_get_rssi(struct mt76x2_dev *dev, s8 rssi, int chain); -void mt76x2_phy_calibrate(struct work_struct *work); -void mt76x2_phy_set_txpower(struct mt76x2_dev *dev); - -int mt76x2_mcu_init(struct mt76x2_dev *dev); -int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw, - u8 bw_index, bool scan); -int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level, - u8 channel); - -void mt76x2_tx_tasklet(unsigned long data); -void mt76x2_dma_cleanup(struct mt76x2_dev *dev); - -void mt76x2_cleanup(struct mt76x2_dev *dev); - -void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, - struct sk_buff *skb); -int mt76x2_tx_prepare_skb(struct mt76_dev *mdev, void *txwi, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info); -void mt76x2_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush); -void mt76x2_mac_set_tx_protection(struct mt76x2_dev *dev, u32 val); - -void mt76x2_pre_tbtt_tasklet(unsigned long arg); - -void mt76x2_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); -void mt76x2_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, - struct sk_buff *skb); - -void mt76x2_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps); - -void mt76x2_update_channel(struct mt76_dev *mdev); - -s8 mt76x2_tx_get_max_txpwr_adj(struct mt76_dev *dev, - const struct ieee80211_tx_rate *rate); -s8 mt76x2_tx_get_txpwr_adj(struct mt76x2_dev *dev, s8 txpwr, s8 max_txpwr_adj); -void mt76x2_tx_set_txpwr_auto(struct mt76x2_dev *dev, s8 txpwr); - - -void mt76x2_reset_wlan(struct mt76x2_dev *dev, bool enable); -void mt76x2_init_txpower(struct mt76x2_dev *dev, - struct ieee80211_supported_band *sband); -void mt76_write_mac_initvals(struct mt76x2_dev *dev); - -int mt76x2_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int mt76x2_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void mt76x2_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); -int mt76x2_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 queue, const struct ieee80211_tx_queue_params *params); -void mt76x2_txq_init(struct mt76x2_dev *dev, struct ieee80211_txq *txq); - -void mt76x2_phy_tssi_compensate(struct mt76x2_dev *dev, bool wait); -void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev, - enum nl80211_band band); -void mt76x2_configure_tx_delay(struct mt76x2_dev *dev, - enum nl80211_band band, u8 bw); -void mt76x2_phy_set_bw(struct mt76x2_dev *dev, int width, u8 ctrl); -void mt76x2_phy_set_band(struct mt76x2_dev *dev, int band, bool primary_upper); -int mt76x2_phy_get_min_avg_rssi(struct mt76x2_dev *dev); -void mt76x2_apply_gain_adj(struct mt76x2_dev *dev); - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig new file mode 100644 index 000000000000..2b414a0e9088 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig @@ -0,0 +1,20 @@ +config MT76x2_COMMON + tristate + select MT76x02_LIB + +config MT76x2E + tristate "MediaTek MT76x2E (PCIe) support" + select MT76x2_COMMON + depends on MAC80211 + depends on PCI + ---help--- + This adds support for MT7612/MT7602/MT7662-based wireless PCIe devices. + +config MT76x2U + tristate "MediaTek MT76x2U (USB) support" + select MT76x2_COMMON + select MT76x02_USB + depends on MAC80211 + depends on USB + help + This adds support for MT7612U-based wireless USB dongles. diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile new file mode 100644 index 000000000000..b71bb1049170 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile @@ -0,0 +1,16 @@ +obj-$(CONFIG_MT76x2_COMMON) += mt76x2-common.o +obj-$(CONFIG_MT76x2E) += mt76x2e.o +obj-$(CONFIG_MT76x2U) += mt76x2u.o + +mt76x2-common-y := \ + eeprom.o mac.o init.o phy.o debugfs.o mcu.o + +mt76x2e-y := \ + pci.o pci_main.o pci_init.o pci_tx.o \ + pci_mac.o pci_mcu.o pci_phy.o pci_dfs.o + +mt76x2u-y := \ + usb.o usb_init.o usb_main.o usb_mac.o usb_mcu.o \ + usb_phy.o + +CFLAGS_pci_trace.o := -I$(src) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x2/debugfs.c index ea373bae1522..e8f8ccc0a5ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/debugfs.c @@ -20,7 +20,7 @@ static int mt76x2_ampdu_stat_read(struct seq_file *file, void *data) { - struct mt76x2_dev *dev = file->private; + struct mt76x02_dev *dev = file->private; int i, j; for (i = 0; i < 4; i++) { @@ -49,7 +49,7 @@ mt76x2_ampdu_stat_open(struct inode *inode, struct file *f) static int read_txpower(struct seq_file *file, void *data) { - struct mt76x2_dev *dev = dev_get_drvdata(file->private); + struct mt76x02_dev *dev = dev_get_drvdata(file->private); seq_printf(file, "Target power: %d\n", dev->target_power); @@ -68,9 +68,9 @@ static const struct file_operations fops_ampdu_stat = { static int mt76x2_dfs_stat_read(struct seq_file *file, void *data) { + struct mt76x02_dev *dev = file->private; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; int i; - struct mt76x2_dev *dev = file->private; - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; seq_printf(file, "allocated sequences:\t%d\n", dfs_pd->seq_stats.seq_pool_len); @@ -106,7 +106,7 @@ static const struct file_operations fops_dfs_stat = { static int read_agc(struct seq_file *file, void *data) { - struct mt76x2_dev *dev = dev_get_drvdata(file->private); + struct mt76x02_dev *dev = dev_get_drvdata(file->private); seq_printf(file, "avg_rssi: %d\n", dev->cal.avg_rssi_all); seq_printf(file, "low_gain: %d\n", dev->cal.low_gain); @@ -116,7 +116,7 @@ static int read_agc(struct seq_file *file, void *data) return 0; } -void mt76x2_init_debugfs(struct mt76x2_dev *dev) +void mt76x2_init_debugfs(struct mt76x02_dev *dev) { struct dentry *dir; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h new file mode 100644 index 000000000000..3cb9d1864286 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/dfs.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __DFS_H +#define __DFS_H + +void mt76x2_dfs_init_params(struct mt76x02_dev *dev); +void mt76x2_dfs_init_detector(struct mt76x02_dev *dev); +void mt76x2_dfs_adjust_agc(struct mt76x02_dev *dev); +void mt76x2_dfs_set_domain(struct mt76x02_dev *dev, + enum nl80211_dfs_regions region); + +#endif /* __DFS_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c index 136faa4066a5..f39b622d03f4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c @@ -17,12 +17,12 @@ #include <linux/module.h> #include <asm/unaligned.h> #include "mt76x2.h" -#include "mt76x2_eeprom.h" +#include "eeprom.h" #define EE_FIELD(_name, _value) [MT_EE_##_name] = (_value) | 1 static int -mt76x2_eeprom_copy(struct mt76x2_dev *dev, enum mt76x02_eeprom_field field, +mt76x2_eeprom_copy(struct mt76x02_dev *dev, enum mt76x02_eeprom_field field, void *dest, int len) { if (field + len > dev->mt76.eeprom.size) @@ -33,7 +33,7 @@ mt76x2_eeprom_copy(struct mt76x2_dev *dev, enum mt76x02_eeprom_field field, } static int -mt76x2_eeprom_get_macaddr(struct mt76x2_dev *dev) +mt76x2_eeprom_get_macaddr(struct mt76x02_dev *dev) { void *src = dev->mt76.eeprom.data + MT_EE_MAC_ADDR; @@ -42,7 +42,7 @@ mt76x2_eeprom_get_macaddr(struct mt76x2_dev *dev) } static bool -mt76x2_has_cal_free_data(struct mt76x2_dev *dev, u8 *efuse) +mt76x2_has_cal_free_data(struct mt76x02_dev *dev, u8 *efuse) { u16 *efuse_w = (u16 *) efuse; @@ -68,7 +68,7 @@ mt76x2_has_cal_free_data(struct mt76x2_dev *dev, u8 *efuse) } static void -mt76x2_apply_cal_free_data(struct mt76x2_dev *dev, u8 *efuse) +mt76x2_apply_cal_free_data(struct mt76x02_dev *dev, u8 *efuse) { #define GROUP_5G(_id) \ MT_EE_TX_POWER_0_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id), \ @@ -137,7 +137,7 @@ mt76x2_apply_cal_free_data(struct mt76x2_dev *dev, u8 *efuse) eeprom[MT_EE_BT_PMUCFG] = val & 0xff; } -static int mt76x2_check_eeprom(struct mt76x2_dev *dev) +static int mt76x2_check_eeprom(struct mt76x02_dev *dev) { u16 val = get_unaligned_le16(dev->mt76.eeprom.data); @@ -155,7 +155,7 @@ static int mt76x2_check_eeprom(struct mt76x2_dev *dev) } static int -mt76x2_eeprom_load(struct mt76x2_dev *dev) +mt76x2_eeprom_load(struct mt76x02_dev *dev) { void *efuse; bool found; @@ -177,8 +177,8 @@ mt76x2_eeprom_load(struct mt76x2_dev *dev) efuse = dev->mt76.otp.data; - if (mt76x02_get_efuse_data(&dev->mt76, 0, efuse, - MT7662_EEPROM_SIZE, MT_EE_READ)) + if (mt76x02_get_efuse_data(dev, 0, efuse, MT7662_EEPROM_SIZE, + MT_EE_READ)) goto out; if (found) { @@ -197,7 +197,7 @@ out: } static void -mt76x2_set_rx_gain_group(struct mt76x2_dev *dev, u8 val) +mt76x2_set_rx_gain_group(struct mt76x02_dev *dev, u8 val) { s8 *dest = dev->cal.rx.high_gain; @@ -212,7 +212,7 @@ mt76x2_set_rx_gain_group(struct mt76x2_dev *dev, u8 val) } static void -mt76x2_set_rssi_offset(struct mt76x2_dev *dev, int chain, u8 val) +mt76x2_set_rssi_offset(struct mt76x02_dev *dev, int chain, u8 val) { s8 *dest = dev->cal.rx.rssi_offset; @@ -241,34 +241,34 @@ mt76x2_get_cal_channel_group(int channel) } static u8 -mt76x2_get_5g_rx_gain(struct mt76x2_dev *dev, u8 channel) +mt76x2_get_5g_rx_gain(struct mt76x02_dev *dev, u8 channel) { enum mt76x2_cal_channel_group group; group = mt76x2_get_cal_channel_group(channel); switch (group) { case MT_CH_5G_JAPAN: - return mt76x02_eeprom_get(&dev->mt76, + return mt76x02_eeprom_get(dev, MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN); case MT_CH_5G_UNII_1: - return mt76x02_eeprom_get(&dev->mt76, + return mt76x02_eeprom_get(dev, MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN) >> 8; case MT_CH_5G_UNII_2: - return mt76x02_eeprom_get(&dev->mt76, + return mt76x02_eeprom_get(dev, MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN); case MT_CH_5G_UNII_2E_1: - return mt76x02_eeprom_get(&dev->mt76, + return mt76x02_eeprom_get(dev, MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN) >> 8; case MT_CH_5G_UNII_2E_2: - return mt76x02_eeprom_get(&dev->mt76, + return mt76x02_eeprom_get(dev, MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN); default: - return mt76x02_eeprom_get(&dev->mt76, + return mt76x02_eeprom_get(dev, MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN) >> 8; } } -void mt76x2_read_rx_gain(struct mt76x2_dev *dev) +void mt76x2_read_rx_gain(struct mt76x02_dev *dev) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; int channel = chan->hw_value; @@ -277,14 +277,13 @@ void mt76x2_read_rx_gain(struct mt76x2_dev *dev) u16 val; if (chan->band == NL80211_BAND_2GHZ) - val = mt76x02_eeprom_get(&dev->mt76, - MT_EE_RF_2G_RX_HIGH_GAIN) >> 8; + val = mt76x02_eeprom_get(dev, MT_EE_RF_2G_RX_HIGH_GAIN) >> 8; else val = mt76x2_get_5g_rx_gain(dev, channel); mt76x2_set_rx_gain_group(dev, val); - mt76x02_get_rx_gain(&dev->mt76, chan->band, &val, &lna_2g, lna_5g); + mt76x02_get_rx_gain(dev, chan->band, &val, &lna_2g, lna_5g); mt76x2_set_rssi_offset(dev, 0, val); mt76x2_set_rssi_offset(dev, 1, val >> 8); @@ -293,12 +292,12 @@ void mt76x2_read_rx_gain(struct mt76x2_dev *dev) dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24; - lna = mt76x02_get_lna_gain(&dev->mt76, &lna_2g, lna_5g, chan); + lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); } EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); -void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t, +void mt76x2_get_rate_power(struct mt76x02_dev *dev, struct mt76_rate_power *t, struct ieee80211_channel *chan) { bool is_5ghz; @@ -308,53 +307,49 @@ void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t, memset(t, 0, sizeof(*t)); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_CCK); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_CCK); t->cck[0] = t->cck[1] = mt76x02_rate_power_val(val); t->cck[2] = t->cck[3] = mt76x02_rate_power_val(val >> 8); if (is_5ghz) - val = mt76x02_eeprom_get(&dev->mt76, - MT_EE_TX_POWER_OFDM_5G_6M); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_OFDM_5G_6M); else - val = mt76x02_eeprom_get(&dev->mt76, - MT_EE_TX_POWER_OFDM_2G_6M); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_OFDM_2G_6M); t->ofdm[0] = t->ofdm[1] = mt76x02_rate_power_val(val); t->ofdm[2] = t->ofdm[3] = mt76x02_rate_power_val(val >> 8); if (is_5ghz) - val = mt76x02_eeprom_get(&dev->mt76, - MT_EE_TX_POWER_OFDM_5G_24M); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_OFDM_5G_24M); else - val = mt76x02_eeprom_get(&dev->mt76, - MT_EE_TX_POWER_OFDM_2G_24M); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_OFDM_2G_24M); t->ofdm[4] = t->ofdm[5] = mt76x02_rate_power_val(val); t->ofdm[6] = t->ofdm[7] = mt76x02_rate_power_val(val >> 8); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS0); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS0); t->ht[0] = t->ht[1] = mt76x02_rate_power_val(val); t->ht[2] = t->ht[3] = mt76x02_rate_power_val(val >> 8); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS4); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS4); t->ht[4] = t->ht[5] = mt76x02_rate_power_val(val); t->ht[6] = t->ht[7] = mt76x02_rate_power_val(val >> 8); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS8); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS8); t->ht[8] = t->ht[9] = mt76x02_rate_power_val(val); t->ht[10] = t->ht[11] = mt76x02_rate_power_val(val >> 8); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_HT_MCS12); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS12); t->ht[12] = t->ht[13] = mt76x02_rate_power_val(val); t->ht[14] = t->ht[15] = mt76x02_rate_power_val(val >> 8); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_VHT_MCS0); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS0); t->vht[0] = t->vht[1] = mt76x02_rate_power_val(val); t->vht[2] = t->vht[3] = mt76x02_rate_power_val(val >> 8); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_VHT_MCS4); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS4); t->vht[4] = t->vht[5] = mt76x02_rate_power_val(val); t->vht[6] = t->vht[7] = mt76x02_rate_power_val(val >> 8); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_VHT_MCS8); + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS8); if (!is_5ghz) val >>= 8; t->vht[8] = t->vht[9] = mt76x02_rate_power_val(val >> 8); @@ -366,8 +361,10 @@ void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t, EXPORT_SYMBOL_GPL(mt76x2_get_rate_power); static void -mt76x2_get_power_info_2g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t, - struct ieee80211_channel *chan, int chain, int offset) +mt76x2_get_power_info_2g(struct mt76x02_dev *dev, + struct mt76x2_tx_power_info *t, + struct ieee80211_channel *chan, + int chain, int offset) { int channel = chan->hw_value; int delta_idx; @@ -388,13 +385,15 @@ mt76x2_get_power_info_2g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t, t->chain[chain].target_power = data[2]; t->chain[chain].delta = mt76x02_sign_extend_optional(data[delta_idx], 7); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_RF_2G_TSSI_OFF_TXPOWER); + val = mt76x02_eeprom_get(dev, MT_EE_RF_2G_TSSI_OFF_TXPOWER); t->target_power = val >> 8; } static void -mt76x2_get_power_info_5g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t, - struct ieee80211_channel *chan, int chain, int offset) +mt76x2_get_power_info_5g(struct mt76x02_dev *dev, + struct mt76x2_tx_power_info *t, + struct ieee80211_channel *chan, + int chain, int offset) { int channel = chan->hw_value; enum mt76x2_cal_channel_group group; @@ -437,11 +436,11 @@ mt76x2_get_power_info_5g(struct mt76x2_dev *dev, struct mt76x2_tx_power_info *t, t->chain[chain].target_power = data[2]; t->chain[chain].delta = mt76x02_sign_extend_optional(data[delta_idx], 7); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_RF_2G_RX_HIGH_GAIN); + val = mt76x02_eeprom_get(dev, MT_EE_RF_2G_RX_HIGH_GAIN); t->target_power = val & 0xff; } -void mt76x2_get_power_info(struct mt76x2_dev *dev, +void mt76x2_get_power_info(struct mt76x02_dev *dev, struct mt76x2_tx_power_info *t, struct ieee80211_channel *chan) { @@ -449,8 +448,8 @@ void mt76x2_get_power_info(struct mt76x2_dev *dev, memset(t, 0, sizeof(*t)); - bw40 = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_DELTA_BW40); - bw80 = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_DELTA_BW80); + bw40 = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40); + bw80 = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW80); if (chan->band == NL80211_BAND_5GHZ) { bw40 >>= 8; @@ -465,7 +464,7 @@ void mt76x2_get_power_info(struct mt76x2_dev *dev, MT_EE_TX_POWER_1_START_2G); } - if (mt76x02_tssi_enabled(&dev->mt76) || + if (mt76x2_tssi_enabled(dev) || !mt76x02_field_valid(t->target_power)) t->target_power = t->chain[0].target_power; @@ -474,7 +473,7 @@ void mt76x2_get_power_info(struct mt76x2_dev *dev, } EXPORT_SYMBOL_GPL(mt76x2_get_power_info); -int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t) +int mt76x2_get_temp_comp(struct mt76x02_dev *dev, struct mt76x2_temp_comp *t) { enum nl80211_band band = dev->mt76.chandef.chan->band; u16 val, slope; @@ -482,23 +481,20 @@ int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t) memset(t, 0, sizeof(*t)); - if (!mt76x02_temp_tx_alc_enabled(&dev->mt76)) + if (!mt76x2_temp_tx_alc_enabled(dev)) return -EINVAL; - if (!mt76x02_ext_pa_enabled(&dev->mt76, band)) + if (!mt76x02_ext_pa_enabled(dev, band)) return -EINVAL; - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_TX_POWER_EXT_PA_5G) >> 8; + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G) >> 8; t->temp_25_ref = val & 0x7f; if (band == NL80211_BAND_5GHZ) { - slope = mt76x02_eeprom_get(&dev->mt76, - MT_EE_RF_TEMP_COMP_SLOPE_5G); - bounds = mt76x02_eeprom_get(&dev->mt76, - MT_EE_TX_POWER_EXT_PA_5G); + slope = mt76x02_eeprom_get(dev, MT_EE_RF_TEMP_COMP_SLOPE_5G); + bounds = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G); } else { - slope = mt76x02_eeprom_get(&dev->mt76, - MT_EE_RF_TEMP_COMP_SLOPE_2G); - bounds = mt76x02_eeprom_get(&dev->mt76, + slope = mt76x02_eeprom_get(dev, MT_EE_RF_TEMP_COMP_SLOPE_2G); + bounds = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW80) >> 8; } @@ -511,7 +507,7 @@ int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t) } EXPORT_SYMBOL_GPL(mt76x2_get_temp_comp); -int mt76x2_eeprom_init(struct mt76x2_dev *dev) +int mt76x2_eeprom_init(struct mt76x02_dev *dev) { int ret; @@ -519,7 +515,7 @@ int mt76x2_eeprom_init(struct mt76x2_dev *dev) if (ret) return ret; - mt76x02_eeprom_parse_hw_cap(&dev->mt76); + mt76x02_eeprom_parse_hw_cap(dev); mt76x2_eeprom_get_macaddr(dev); mt76_eeprom_override(&dev->mt76); dev->mt76.macaddr[0] &= ~BIT(1); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h index c2e99bbeac3b..9e735524d367 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h @@ -17,7 +17,7 @@ #ifndef __MT76x2_EEPROM_H #define __MT76x2_EEPROM_H -#include "mt76x02_eeprom.h" +#include "../mt76x02_eeprom.h" enum mt76x2_cal_channel_group { MT_CH_5G_JAPAN, @@ -51,18 +51,18 @@ struct mt76x2_temp_comp { unsigned int low_slope; /* J / dB */ }; -void mt76x2_get_rate_power(struct mt76x2_dev *dev, struct mt76_rate_power *t, +void mt76x2_get_rate_power(struct mt76x02_dev *dev, struct mt76_rate_power *t, struct ieee80211_channel *chan); -void mt76x2_get_power_info(struct mt76x2_dev *dev, +void mt76x2_get_power_info(struct mt76x02_dev *dev, struct mt76x2_tx_power_info *t, struct ieee80211_channel *chan); -int mt76x2_get_temp_comp(struct mt76x2_dev *dev, struct mt76x2_temp_comp *t); -void mt76x2_read_rx_gain(struct mt76x2_dev *dev); +int mt76x2_get_temp_comp(struct mt76x02_dev *dev, struct mt76x2_temp_comp *t); +void mt76x2_read_rx_gain(struct mt76x02_dev *dev); static inline bool -mt76x2_has_ext_lna(struct mt76x2_dev *dev) +mt76x2_has_ext_lna(struct mt76x02_dev *dev) { - u32 val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_1); + u32 val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ) return val & MT_EE_NIC_CONF_1_LNA_EXT_2G; @@ -70,4 +70,25 @@ mt76x2_has_ext_lna(struct mt76x2_dev *dev) return val & MT_EE_NIC_CONF_1_LNA_EXT_5G; } +static inline bool +mt76x2_temp_tx_alc_enabled(struct mt76x02_dev *dev) +{ + u16 val; + + val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G); + if (!(val & BIT(15))) + return false; + + return mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) & + MT_EE_NIC_CONF_1_TEMP_TX_ALC; +} + +static inline bool +mt76x2_tssi_enabled(struct mt76x02_dev *dev) +{ + return !mt76x2_temp_tx_alc_enabled(dev) && + (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) & + MT_EE_NIC_CONF_1_TX_ALC_EN); +} + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_init_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index f4c4cde9301e..3c73fdeaf30f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_init_common.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c @@ -16,11 +16,11 @@ */ #include "mt76x2.h" -#include "mt76x2_eeprom.h" -#include "mt76x02_phy.h" +#include "eeprom.h" +#include "../mt76x02_phy.h" static void -mt76x2_set_wlan_state(struct mt76x2_dev *dev, bool enable) +mt76x2_set_wlan_state(struct mt76x02_dev *dev, bool enable) { u32 val = mt76_rr(dev, MT_WLAN_FUN_CTRL); @@ -35,7 +35,7 @@ mt76x2_set_wlan_state(struct mt76x2_dev *dev, bool enable) udelay(20); } -void mt76x2_reset_wlan(struct mt76x2_dev *dev, bool enable) +void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable) { u32 val; @@ -62,7 +62,7 @@ out: } EXPORT_SYMBOL_GPL(mt76x2_reset_wlan); -void mt76_write_mac_initvals(struct mt76x2_dev *dev) +void mt76_write_mac_initvals(struct mt76x02_dev *dev) { #define DEFAULT_PROT_CFG_CCK \ (FIELD_PREP(MT_PROT_CFG_RATE, 0x3) | \ @@ -158,7 +158,7 @@ void mt76_write_mac_initvals(struct mt76x2_dev *dev) } EXPORT_SYMBOL_GPL(mt76_write_mac_initvals); -void mt76x2_init_device(struct mt76x2_dev *dev) +void mt76x2_init_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); @@ -167,6 +167,9 @@ void mt76x2_init_device(struct mt76x2_dev *dev) hw->max_report_rates = 7; hw->max_rate_tries = 1; hw->extra_tx_headroom = 2; + if (mt76_is_usb(dev)) + hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) + + MT_DMA_HDR_LEN; hw->sta_data_size = sizeof(struct mt76x02_sta); hw->vif_data_size = sizeof(struct mt76x02_vif); @@ -187,7 +190,7 @@ void mt76x2_init_device(struct mt76x2_dev *dev) } EXPORT_SYMBOL_GPL(mt76x2_init_device); -void mt76x2_init_txpower(struct mt76x2_dev *dev, +void mt76x2_init_txpower(struct mt76x02_dev *dev, struct ieee80211_supported_band *sband) { struct ieee80211_channel *chan; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c index 3e667d8c0ee7..e25905c91ee2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_common.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c @@ -16,27 +16,39 @@ */ #include "mt76x2.h" -#include "mt76x02_mac.h" -void mt76x2_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, - struct sk_buff *skb) +void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force) { - struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76); - void *rxwi = skb->data; - - if (q == MT_RXQ_MCU) { - /* this is used just by mmio code */ - skb_queue_tail(&mdev->mmio.mcu.res_q, skb); - wake_up(&mdev->mmio.mcu.wait); - return; + bool stopped = false; + u32 rts_cfg; + int i; + + mt76_wr(dev, MT_MAC_SYS_CTRL, 0); + + rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); + mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); + + /* Wait for MAC to become idle */ + for (i = 0; i < 300; i++) { + if ((mt76_rr(dev, MT_MAC_STATUS) & + (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) || + mt76_rr(dev, MT_BBP(IBI, 12))) { + udelay(1); + continue; + } + + stopped = true; + break; } - skb_pull(skb, sizeof(struct mt76x02_rxwi)); - if (mt76x2_mac_process_rx(dev, skb, rxwi)) { - dev_kfree_skb(skb); - return; + if (force && !stopped) { + mt76_set(dev, MT_BBP(CORE, 4), BIT(1)); + mt76_clear(dev, MT_BBP(CORE, 4), BIT(1)); + + mt76_set(dev, MT_BBP(CORE, 4), BIT(0)); + mt76_clear(dev, MT_BBP(CORE, 4), BIT(0)); } - mt76_rx(&dev->mt76, q, skb); + mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg); } -EXPORT_SYMBOL_GPL(mt76x2_queue_rx_skb); +EXPORT_SYMBOL_GPL(mt76x2_mac_stop); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h index 7e5eccda47f8..a31bd49ae6cb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h @@ -14,26 +14,24 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifndef __MT76x2_MAC_H +#define __MT76x2_MAC_H + #include "mt76x2.h" -#include "mt76x02_dma.h" -#include "mt76x02_util.h" -void mt76x2_tx_tasklet(unsigned long data) -{ - struct mt76x2_dev *dev = (struct mt76x2_dev *) data; - int i; +struct mt76x02_dev; +struct mt76x2_sta; +struct mt76x02_vif; - mt76x2_mac_process_tx_status_fifo(dev); +int mt76x2_mac_start(struct mt76x02_dev *dev); +void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force); +void mt76x2_mac_resume(struct mt76x02_dev *dev); +void mt76x2_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr); - for (i = MT_TXQ_MCU; i >= 0; i--) - mt76_queue_tx_cleanup(dev, i, false); +int mt76x2_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, + struct sk_buff *skb); +void mt76x2_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, bool val); - mt76x2_mac_poll_tx_status(dev, false); - mt76x02_irq_enable(&dev->mt76, MT_INT_TX_DONE_ALL); -} +void mt76x2_mac_work(struct work_struct *work); -void mt76x2_dma_cleanup(struct mt76x2_dev *dev) -{ - tasklet_kill(&dev->tx_tasklet); - mt76_dma_cleanup(&dev->mt76); -} +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c index eff483333183..88bd62cfbdf9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu_common.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c @@ -20,11 +20,10 @@ #include <linux/delay.h> #include "mt76x2.h" -#include "mt76x2_mcu.h" -#include "mt76x2_eeprom.h" -#include "mt76x02_dma.h" +#include "mcu.h" +#include "eeprom.h" -int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw, +int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, u8 bw_index, bool scan) { struct sk_buff *skb; @@ -57,10 +56,9 @@ int mt76x2_mcu_set_channel(struct mt76x2_dev *dev, u8 channel, u8 bw, } EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel); -int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level, +int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, u8 channel) { - struct mt76_dev *mdev = &dev->mt76; struct sk_buff *skb; struct { u8 cr_mode; @@ -77,8 +75,8 @@ int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level, u32 val; val = BIT(31); - val |= (mt76x02_eeprom_get(mdev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff; - val |= (mt76x02_eeprom_get(mdev, MT_EE_NIC_CONF_1) << 8) & 0xff00; + val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff; + val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) << 8) & 0xff00; msg.cfg = cpu_to_le32(val); /* first set the channel without the extension channel info */ @@ -87,7 +85,7 @@ int mt76x2_mcu_load_cr(struct mt76x2_dev *dev, u8 type, u8 temp_level, } EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr); -int mt76x2_mcu_init_gain(struct mt76x2_dev *dev, u8 channel, u32 gain, +int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain, bool force) { struct sk_buff *skb; @@ -107,7 +105,7 @@ int mt76x2_mcu_init_gain(struct mt76x2_dev *dev, u8 channel, u32 gain, } EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain); -int mt76x2_mcu_tssi_comp(struct mt76x2_dev *dev, +int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev, struct mt76x2_tssi_comp *tssi_data) { struct sk_buff *skb; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h index fa72d5a5ecad..acfa2b570c7c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h @@ -17,7 +17,7 @@ #ifndef __MT76x2_MCU_H #define __MT76x2_MCU_H -#include "mt76x02_mcu.h" +#include "../mt76x02_mcu.h" /* Register definitions */ #define MT_MCU_CPU_CTL 0x0704 @@ -94,8 +94,8 @@ struct mt76x2_tssi_comp { u8 offset1; } __packed __aligned(4); -int mt76x2_mcu_tssi_comp(struct mt76x2_dev *dev, struct mt76x2_tssi_comp *tssi_data); -int mt76x2_mcu_init_gain(struct mt76x2_dev *dev, u8 channel, u32 gain, +int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev, struct mt76x2_tssi_comp *tssi_data); +int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain, bool force); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h new file mode 100644 index 000000000000..ab93125f46de --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __MT76x2_H +#define __MT76x2_H + +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/spinlock.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/mutex.h> +#include <linux/bitops.h> + +#define MT7662_FIRMWARE "mt7662.bin" +#define MT7662_ROM_PATCH "mt7662_rom_patch.bin" +#define MT7662_EEPROM_SIZE 512 + +#define MT7662U_FIRMWARE "mediatek/mt7662u.bin" +#define MT7662U_ROM_PATCH "mediatek/mt7662u_rom_patch.bin" + +#define MT_CALIBRATE_INTERVAL HZ + +#include "../mt76x02.h" +#include "mac.h" +#include "dfs.h" + +static inline bool is_mt7612(struct mt76x02_dev *dev) +{ + return mt76_chip(&dev->mt76) == 0x7612; +} + +static inline bool mt76x2_channel_silent(struct mt76x02_dev *dev) +{ + struct ieee80211_channel *chan = dev->mt76.chandef.chan; + + return ((chan->flags & IEEE80211_CHAN_RADAR) && + chan->dfs_state != NL80211_DFS_AVAILABLE); +} + +extern const struct ieee80211_ops mt76x2_ops; + +struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev); +int mt76x2_register_device(struct mt76x02_dev *dev); +void mt76x2_init_debugfs(struct mt76x02_dev *dev); +void mt76x2_init_device(struct mt76x02_dev *dev); + +void mt76x2_phy_power_on(struct mt76x02_dev *dev); +int mt76x2_init_hardware(struct mt76x02_dev *dev); +void mt76x2_stop_hardware(struct mt76x02_dev *dev); +int mt76x2_eeprom_init(struct mt76x02_dev *dev); +int mt76x2_apply_calibration_data(struct mt76x02_dev *dev, int channel); +void mt76x2_set_tx_ackto(struct mt76x02_dev *dev); + +void mt76x2_phy_set_antenna(struct mt76x02_dev *dev); +int mt76x2_phy_start(struct mt76x02_dev *dev); +int mt76x2_phy_set_channel(struct mt76x02_dev *dev, + struct cfg80211_chan_def *chandef); +void mt76x2_phy_calibrate(struct work_struct *work); +void mt76x2_phy_set_txpower(struct mt76x02_dev *dev); + +int mt76x2_mcu_init(struct mt76x02_dev *dev); +int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, + u8 bw_index, bool scan); +int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, + u8 channel); + +void mt76x2_cleanup(struct mt76x02_dev *dev); + +void mt76x2_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val); + +void mt76x2_pre_tbtt_tasklet(unsigned long arg); + +void mt76x2_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps); + +void mt76x2_update_channel(struct mt76_dev *mdev); + +void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable); +void mt76x2_init_txpower(struct mt76x02_dev *dev, + struct ieee80211_supported_band *sband); +void mt76_write_mac_initvals(struct mt76x02_dev *dev); + +void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait); +void mt76x2_phy_set_txpower_regs(struct mt76x02_dev *dev, + enum nl80211_band band); +void mt76x2_configure_tx_delay(struct mt76x02_dev *dev, + enum nl80211_band band, u8 bw); +void mt76x2_apply_gain_adj(struct mt76x02_dev *dev); + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h index 5d2ebdf42c63..6e932b5010ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2u.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h @@ -20,8 +20,7 @@ #include <linux/device.h> #include "mt76x2.h" -#include "mt76x2_mcu.h" -#include "mt76x02_dma.h" +#include "mcu.h" #define MT7612U_EEPROM_SIZE 512 @@ -30,35 +29,31 @@ extern const struct ieee80211_ops mt76x2u_ops; -struct mt76x2_dev *mt76x2u_alloc_device(struct device *pdev); -int mt76x2u_register_device(struct mt76x2_dev *dev); -int mt76x2u_init_hardware(struct mt76x2_dev *dev); -void mt76x2u_cleanup(struct mt76x2_dev *dev); -void mt76x2u_stop_hw(struct mt76x2_dev *dev); +struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev); +int mt76x2u_register_device(struct mt76x02_dev *dev); +int mt76x2u_init_hardware(struct mt76x02_dev *dev); +void mt76x2u_cleanup(struct mt76x02_dev *dev); +void mt76x2u_stop_hw(struct mt76x02_dev *dev); -int mt76x2u_mac_reset(struct mt76x2_dev *dev); -void mt76x2u_mac_resume(struct mt76x2_dev *dev); -int mt76x2u_mac_start(struct mt76x2_dev *dev); -int mt76x2u_mac_stop(struct mt76x2_dev *dev); +int mt76x2u_mac_reset(struct mt76x02_dev *dev); +void mt76x2u_mac_resume(struct mt76x02_dev *dev); +int mt76x2u_mac_start(struct mt76x02_dev *dev); +int mt76x2u_mac_stop(struct mt76x02_dev *dev); -int mt76x2u_phy_set_channel(struct mt76x2_dev *dev, +int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef); void mt76x2u_phy_calibrate(struct work_struct *work); -void mt76x2u_phy_channel_calibrate(struct mt76x2_dev *dev); +void mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev); void mt76x2u_mcu_complete_urb(struct urb *urb); -int mt76x2u_mcu_set_dynamic_vga(struct mt76x2_dev *dev, u8 channel, bool ap, +int mt76x2u_mcu_set_dynamic_vga(struct mt76x02_dev *dev, u8 channel, bool ap, bool ext, int rssi, u32 false_cca); -int mt76x2u_mcu_init(struct mt76x2_dev *dev); -int mt76x2u_mcu_fw_init(struct mt76x2_dev *dev); +int mt76x2u_mcu_init(struct mt76x02_dev *dev); +int mt76x2u_mcu_fw_init(struct mt76x02_dev *dev); -int mt76x2u_alloc_queues(struct mt76x2_dev *dev); -void mt76x2u_queues_deinit(struct mt76x2_dev *dev); -void mt76x2u_stop_queues(struct mt76x2_dev *dev); -int mt76x2u_tx_prepare_skb(struct mt76_dev *mdev, void *data, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info); +int mt76x2u_alloc_queues(struct mt76x02_dev *dev); +void mt76x2u_queues_deinit(struct mt76x02_dev *dev); +void mt76x2u_stop_queues(struct mt76x02_dev *dev); int mt76x2u_skb_dma_info(struct sk_buff *skb, enum dma_msg_port port, u32 flags); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index 26cfda24ce08..92432fe97312 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -19,7 +19,6 @@ #include <linux/pci.h> #include "mt76x2.h" -#include "mt76x2_trace.h" static const struct pci_device_id mt76pci_device_table[] = { { PCI_DEVICE(0x14c3, 0x7662) }, @@ -31,7 +30,7 @@ static const struct pci_device_id mt76pci_device_table[] = { static int mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct mt76x2_dev *dev; + struct mt76x02_dev *dev; int ret; ret = pcim_enable_device(pdev); @@ -58,7 +57,7 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); - ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x2_irq_handler, + ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto error; @@ -89,7 +88,7 @@ static void mt76pci_remove(struct pci_dev *pdev) { struct mt76_dev *mdev = pci_get_drvdata(pdev); - struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76); + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); mt76_unregister_device(mdev); mt76x2_cleanup(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_dfs.c index 8cfa3a063bda..b56febae8945 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_dfs.c @@ -15,7 +15,6 @@ */ #include "mt76x2.h" -#include "mt76x02_util.h" #define RADAR_SPEC(m, len, el, eh, wl, wh, \ w_tolerance, tl, th, t_tolerance, \ @@ -37,7 +36,7 @@ .pwr_jmp = power_jmp \ } -static const struct mt76x2_radar_specs etsi_radar_specs[] = { +static const struct mt76x02_radar_specs etsi_radar_specs[] = { /* 20MHz */ RADAR_SPEC(0, 8, 2, 15, 106, 150, 10, 4900, 100096, 10, 0, 0x7fffffff, 0x155cc0, 0x19cc), @@ -67,7 +66,7 @@ static const struct mt76x2_radar_specs etsi_radar_specs[] = { 0x7fffffff, 0x2191c0, 0x15cc) }; -static const struct mt76x2_radar_specs fcc_radar_specs[] = { +static const struct mt76x02_radar_specs fcc_radar_specs[] = { /* 20MHz */ RADAR_SPEC(0, 8, 2, 12, 106, 150, 5, 2900, 80100, 5, 0, 0x7fffffff, 0xfe808, 0x13dc), @@ -97,7 +96,7 @@ static const struct mt76x2_radar_specs fcc_radar_specs[] = { 0x3938700, 0x57bcf00, 0x1289) }; -static const struct mt76x2_radar_specs jp_w56_radar_specs[] = { +static const struct mt76x02_radar_specs jp_w56_radar_specs[] = { /* 20MHz */ RADAR_SPEC(0, 8, 2, 7, 106, 150, 5, 2900, 80100, 5, 0, 0x7fffffff, 0x14c080, 0x13dc), @@ -127,7 +126,7 @@ static const struct mt76x2_radar_specs jp_w56_radar_specs[] = { 0x3938700, 0X57bcf00, 0x1289) }; -static const struct mt76x2_radar_specs jp_w53_radar_specs[] = { +static const struct mt76x02_radar_specs jp_w53_radar_specs[] = { /* 20MHz */ RADAR_SPEC(0, 8, 2, 9, 106, 150, 20, 28400, 77000, 20, 0, 0x7fffffff, 0x14c080, 0x16cc), @@ -151,8 +150,9 @@ static const struct mt76x2_radar_specs jp_w53_radar_specs[] = { { 0 } }; -static void mt76x2_dfs_set_capture_mode_ctrl(struct mt76x2_dev *dev, - u8 enable) +static void +mt76x2_dfs_set_capture_mode_ctrl(struct mt76x02_dev *dev, + u8 enable) { u32 data; @@ -160,10 +160,10 @@ static void mt76x2_dfs_set_capture_mode_ctrl(struct mt76x2_dev *dev, mt76_wr(dev, MT_BBP(DFS, 36), data); } -static void mt76x2_dfs_seq_pool_put(struct mt76x2_dev *dev, - struct mt76x2_dfs_sequence *seq) +static void mt76x2_dfs_seq_pool_put(struct mt76x02_dev *dev, + struct mt76x02_dfs_sequence *seq) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; list_add(&seq->head, &dfs_pd->seq_pool); @@ -171,17 +171,17 @@ static void mt76x2_dfs_seq_pool_put(struct mt76x2_dev *dev, dfs_pd->seq_stats.seq_len--; } -static -struct mt76x2_dfs_sequence *mt76x2_dfs_seq_pool_get(struct mt76x2_dev *dev) +static struct mt76x02_dfs_sequence * +mt76x2_dfs_seq_pool_get(struct mt76x02_dev *dev) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x2_dfs_sequence *seq; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_sequence *seq; if (list_empty(&dfs_pd->seq_pool)) { seq = devm_kzalloc(dev->mt76.dev, sizeof(*seq), GFP_ATOMIC); } else { seq = list_first_entry(&dfs_pd->seq_pool, - struct mt76x2_dfs_sequence, + struct mt76x02_dfs_sequence, head); list_del(&seq->head); dfs_pd->seq_stats.seq_pool_len--; @@ -214,10 +214,10 @@ static int mt76x2_dfs_get_multiple(int val, int frac, int margin) return factor; } -static void mt76x2_dfs_detector_reset(struct mt76x2_dev *dev) +static void mt76x2_dfs_detector_reset(struct mt76x02_dev *dev) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x2_dfs_sequence *seq, *tmp_seq; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_sequence *seq, *tmp_seq; int i; /* reset hw detector */ @@ -235,11 +235,11 @@ static void mt76x2_dfs_detector_reset(struct mt76x2_dev *dev) } } -static bool mt76x2_dfs_check_chirp(struct mt76x2_dev *dev) +static bool mt76x2_dfs_check_chirp(struct mt76x02_dev *dev) { bool ret = false; u32 current_ts, delta_ts; - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; current_ts = mt76_rr(dev, MT_PBF_LIFE_TIMER); delta_ts = current_ts - dfs_pd->chirp_pulse_ts; @@ -256,8 +256,8 @@ static bool mt76x2_dfs_check_chirp(struct mt76x2_dev *dev) return ret; } -static void mt76x2_dfs_get_hw_pulse(struct mt76x2_dev *dev, - struct mt76x2_dfs_hw_pulse *pulse) +static void mt76x2_dfs_get_hw_pulse(struct mt76x02_dev *dev, + struct mt76x02_dfs_hw_pulse *pulse) { u32 data; @@ -276,8 +276,8 @@ static void mt76x2_dfs_get_hw_pulse(struct mt76x2_dev *dev, pulse->burst = mt76_rr(dev, MT_BBP(DFS, 22)); } -static bool mt76x2_dfs_check_hw_pulse(struct mt76x2_dev *dev, - struct mt76x2_dfs_hw_pulse *pulse) +static bool mt76x2_dfs_check_hw_pulse(struct mt76x02_dev *dev, + struct mt76x02_dfs_hw_pulse *pulse) { bool ret = false; @@ -371,8 +371,8 @@ static bool mt76x2_dfs_check_hw_pulse(struct mt76x2_dev *dev, return ret; } -static bool mt76x2_dfs_fetch_event(struct mt76x2_dev *dev, - struct mt76x2_dfs_event *event) +static bool mt76x2_dfs_fetch_event(struct mt76x02_dev *dev, + struct mt76x02_dfs_event *event) { u32 data; @@ -398,12 +398,12 @@ static bool mt76x2_dfs_fetch_event(struct mt76x2_dev *dev, return true; } -static bool mt76x2_dfs_check_event(struct mt76x2_dev *dev, - struct mt76x2_dfs_event *event) +static bool mt76x2_dfs_check_event(struct mt76x02_dev *dev, + struct mt76x02_dfs_event *event) { if (event->engine == 2) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x2_dfs_event_rb *event_buff = &dfs_pd->event_rb[1]; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_event_rb *event_buff = &dfs_pd->event_rb[1]; u16 last_event_idx; u32 delta_ts; @@ -417,11 +417,11 @@ static bool mt76x2_dfs_check_event(struct mt76x2_dev *dev, return true; } -static void mt76x2_dfs_queue_event(struct mt76x2_dev *dev, - struct mt76x2_dfs_event *event) +static void mt76x2_dfs_queue_event(struct mt76x02_dev *dev, + struct mt76x02_dfs_event *event) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x2_dfs_event_rb *event_buff; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_event_rb *event_buff; /* add radar event to ring buffer */ event_buff = event->engine == 2 ? &dfs_pd->event_rb[1] @@ -435,16 +435,16 @@ static void mt76x2_dfs_queue_event(struct mt76x2_dev *dev, MT_DFS_EVENT_BUFLEN); } -static int mt76x2_dfs_create_sequence(struct mt76x2_dev *dev, - struct mt76x2_dfs_event *event, +static int mt76x2_dfs_create_sequence(struct mt76x02_dev *dev, + struct mt76x02_dfs_event *event, u16 cur_len) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x2_dfs_sw_detector_params *sw_params; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_sw_detector_params *sw_params; u32 width_delta, with_sum, factor, cur_pri; - struct mt76x2_dfs_sequence seq, *seq_p; - struct mt76x2_dfs_event_rb *event_rb; - struct mt76x2_dfs_event *cur_event; + struct mt76x02_dfs_sequence seq, *seq_p; + struct mt76x02_dfs_event_rb *event_rb; + struct mt76x02_dfs_event *cur_event; int i, j, end, pri; event_rb = event->engine == 2 ? &dfs_pd->event_rb[1] @@ -522,12 +522,12 @@ next: return 0; } -static u16 mt76x2_dfs_add_event_to_sequence(struct mt76x2_dev *dev, - struct mt76x2_dfs_event *event) +static u16 mt76x2_dfs_add_event_to_sequence(struct mt76x02_dev *dev, + struct mt76x02_dfs_event *event) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x2_dfs_sw_detector_params *sw_params; - struct mt76x2_dfs_sequence *seq, *tmp_seq; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_sw_detector_params *sw_params; + struct mt76x02_dfs_sequence *seq, *tmp_seq; u16 max_seq_len = 0; u32 factor, pri; @@ -554,10 +554,10 @@ static u16 mt76x2_dfs_add_event_to_sequence(struct mt76x2_dev *dev, return max_seq_len; } -static bool mt76x2_dfs_check_detection(struct mt76x2_dev *dev) +static bool mt76x2_dfs_check_detection(struct mt76x02_dev *dev) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x2_dfs_sequence *seq; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_sequence *seq; if (list_empty(&dfs_pd->sequences)) return false; @@ -571,10 +571,10 @@ static bool mt76x2_dfs_check_detection(struct mt76x2_dev *dev) return false; } -static void mt76x2_dfs_add_events(struct mt76x2_dev *dev) +static void mt76x2_dfs_add_events(struct mt76x02_dev *dev) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x2_dfs_event event; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_event event; int i, seq_len; /* disable debug mode */ @@ -598,11 +598,11 @@ static void mt76x2_dfs_add_events(struct mt76x2_dev *dev) mt76x2_dfs_set_capture_mode_ctrl(dev, true); } -static void mt76x2_dfs_check_event_window(struct mt76x2_dev *dev) +static void mt76x2_dfs_check_event_window(struct mt76x02_dev *dev) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; - struct mt76x2_dfs_event_rb *event_buff; - struct mt76x2_dfs_event *event; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_event_rb *event_buff; + struct mt76x02_dfs_event *event; int i; for (i = 0; i < ARRAY_SIZE(dfs_pd->event_rb); i++) { @@ -623,8 +623,8 @@ static void mt76x2_dfs_check_event_window(struct mt76x2_dev *dev) static void mt76x2_dfs_tasklet(unsigned long arg) { - struct mt76x2_dev *dev = (struct mt76x2_dev *)arg; - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dev *dev = (struct mt76x02_dev *)arg; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; u32 engine_mask; int i; @@ -654,7 +654,7 @@ static void mt76x2_dfs_tasklet(unsigned long arg) goto out; for (i = 0; i < MT_DFS_NUM_ENGINES; i++) { - struct mt76x2_dfs_hw_pulse pulse; + struct mt76x02_dfs_hw_pulse pulse; if (!(engine_mask & (1 << i))) continue; @@ -679,12 +679,12 @@ static void mt76x2_dfs_tasklet(unsigned long arg) mt76_wr(dev, MT_BBP(DFS, 1), 0xf); out: - mt76x02_irq_enable(&dev->mt76, MT_INT_GPTIMER); + mt76x02_irq_enable(dev, MT_INT_GPTIMER); } -static void mt76x2_dfs_init_sw_detector(struct mt76x2_dev *dev) +static void mt76x2_dfs_init_sw_detector(struct mt76x02_dev *dev) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; switch (dev->dfs_pd.region) { case NL80211_DFS_FCC: @@ -708,11 +708,11 @@ static void mt76x2_dfs_init_sw_detector(struct mt76x2_dev *dev) } } -static void mt76x2_dfs_set_bbp_params(struct mt76x2_dev *dev) +static void mt76x2_dfs_set_bbp_params(struct mt76x02_dev *dev) { - u32 data; + const struct mt76x02_radar_specs *radar_specs; u8 i, shift; - const struct mt76x2_radar_specs *radar_specs; + u32 data; switch (dev->mt76.chandef.width) { case NL80211_CHAN_WIDTH_40: @@ -803,7 +803,7 @@ static void mt76x2_dfs_set_bbp_params(struct mt76x2_dev *dev) mt76_wr(dev, 0x212c, 0x0c350001); } -void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev) +void mt76x2_dfs_adjust_agc(struct mt76x02_dev *dev) { u32 agc_r8, agc_r4, val_r8, val_r4, dfs_r31; @@ -824,7 +824,7 @@ void mt76x2_dfs_adjust_agc(struct mt76x2_dev *dev) mt76_wr(dev, MT_BBP(DFS, 32), 0x00040071); } -void mt76x2_dfs_init_params(struct mt76x2_dev *dev) +void mt76x2_dfs_init_params(struct mt76x02_dev *dev) { struct cfg80211_chan_def *chandef = &dev->mt76.chandef; @@ -835,7 +835,7 @@ void mt76x2_dfs_init_params(struct mt76x2_dev *dev) /* enable debug mode */ mt76x2_dfs_set_capture_mode_ctrl(dev, true); - mt76x02_irq_enable(&dev->mt76, MT_INT_GPTIMER); + mt76x02_irq_enable(dev, MT_INT_GPTIMER); mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_GP_TIMER_EN, 1); } else { @@ -845,15 +845,15 @@ void mt76x2_dfs_init_params(struct mt76x2_dev *dev) mt76_wr(dev, MT_BBP(DFS, 1), 0xf); mt76_wr(dev, 0x212c, 0); - mt76x02_irq_disable(&dev->mt76, MT_INT_GPTIMER); + mt76x02_irq_disable(dev, MT_INT_GPTIMER); mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_GP_TIMER_EN, 0); } } -void mt76x2_dfs_init_detector(struct mt76x2_dev *dev) +void mt76x2_dfs_init_detector(struct mt76x02_dev *dev) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; INIT_LIST_HEAD(&dfs_pd->sequences); INIT_LIST_HEAD(&dfs_pd->seq_pool); @@ -863,10 +863,10 @@ void mt76x2_dfs_init_detector(struct mt76x2_dev *dev) (unsigned long)dev); } -void mt76x2_dfs_set_domain(struct mt76x2_dev *dev, +void mt76x2_dfs_set_domain(struct mt76x02_dev *dev, enum nl80211_dfs_regions region) { - struct mt76x2_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; if (dfs_pd->region != region) { tasklet_disable(&dfs_pd->dfs_tasklet); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 3f77c13a6d54..3824290b219d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -16,13 +16,11 @@ #include <linux/delay.h> #include "mt76x2.h" -#include "mt76x2_eeprom.h" -#include "mt76x2_mcu.h" -#include "mt76x02_util.h" -#include "mt76x02_dma.h" +#include "eeprom.h" +#include "mcu.h" static void -mt76x2_mac_pbf_init(struct mt76x2_dev *dev) +mt76x2_mac_pbf_init(struct mt76x02_dev *dev) { u32 val; @@ -40,12 +38,12 @@ mt76x2_mac_pbf_init(struct mt76x2_dev *dev) } static void -mt76x2_fixup_xtal(struct mt76x2_dev *dev) +mt76x2_fixup_xtal(struct mt76x02_dev *dev) { u16 eep_val; s8 offset = 0; - eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_2); + eep_val = mt76x02_eeprom_get(dev, MT_EE_XTAL_TRIM_2); offset = eep_val & 0x7f; if ((eep_val & 0xff) == 0xff) @@ -55,7 +53,7 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev) eep_val >>= 8; if (eep_val == 0x00 || eep_val == 0xff) { - eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_1); + eep_val = mt76x02_eeprom_get(dev, MT_EE_XTAL_TRIM_1); eep_val &= 0xff; if (eep_val == 0x00 || eep_val == 0xff) @@ -66,7 +64,7 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev) mt76_rmw_field(dev, MT_XO_CTRL5, MT_XO_CTRL5_C2_VAL, eep_val + offset); mt76_set(dev, MT_XO_CTRL6, MT_XO_CTRL6_C2_CTRL); - eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_2); + eep_val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2); switch (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, eep_val)) { case 0: mt76_wr(dev, MT_XO_CTRL7, 0x5c1fee80); @@ -79,7 +77,7 @@ mt76x2_fixup_xtal(struct mt76x2_dev *dev) } } -static int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard) +static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) { static const u8 null_addr[ETH_ALEN] = {}; const u8 *macaddr = dev->mt76.macaddr; @@ -145,14 +143,14 @@ static int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard) mt76_wr(dev, MT_WCID_DROP_BASE + i * 4, 0); for (i = 0; i < 256; i++) - mt76x02_mac_wcid_setup(&dev->mt76, i, 0, NULL); + mt76x02_mac_wcid_setup(dev, i, 0, NULL); for (i = 0; i < MT_MAX_VIFS; i++) - mt76x02_mac_wcid_setup(&dev->mt76, MT_VIF_WCID(i), i, NULL); + mt76x02_mac_wcid_setup(dev, MT_VIF_WCID(i), i, NULL); for (i = 0; i < 16; i++) for (k = 0; k < 4; k++) - mt76x02_mac_shared_key_setup(&dev->mt76, i, k, NULL); + mt76x02_mac_shared_key_setup(dev, i, k, NULL); for (i = 0; i < 8; i++) { mt76x2_mac_set_bssid(dev, i, null_addr); @@ -170,14 +168,14 @@ static int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard) MT_CH_TIME_CFG_EIFS_AS_BUSY | FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1)); - mt76x02_set_beacon_offsets(&dev->mt76); + mt76x02_set_beacon_offsets(dev); mt76x2_set_tx_ackto(dev); return 0; } -int mt76x2_mac_start(struct mt76x2_dev *dev) +int mt76x2_mac_start(struct mt76x02_dev *dev) { int i; @@ -188,12 +186,12 @@ int mt76x2_mac_start(struct mt76x2_dev *dev) mt76_rr(dev, MT_TX_STAT_FIFO); memset(dev->aggr_stats, 0, sizeof(dev->aggr_stats)); - mt76x02_mac_start(&dev->mt76); + mt76x02_mac_start(dev); return 0; } -void mt76x2_mac_resume(struct mt76x2_dev *dev) +void mt76x2_mac_resume(struct mt76x02_dev *dev) { mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX | @@ -201,7 +199,7 @@ void mt76x2_mac_resume(struct mt76x2_dev *dev) } static void -mt76x2_power_on_rf_patch(struct mt76x2_dev *dev) +mt76x2_power_on_rf_patch(struct mt76x02_dev *dev) { mt76_set(dev, 0x10130, BIT(0) | BIT(16)); udelay(1); @@ -222,7 +220,7 @@ mt76x2_power_on_rf_patch(struct mt76x2_dev *dev) } static void -mt76x2_power_on_rf(struct mt76x2_dev *dev, int unit) +mt76x2_power_on_rf(struct mt76x02_dev *dev, int unit) { int shift = unit ? 8 : 0; @@ -244,7 +242,7 @@ mt76x2_power_on_rf(struct mt76x2_dev *dev, int unit) } static void -mt76x2_power_on(struct mt76x2_dev *dev) +mt76x2_power_on(struct mt76x02_dev *dev) { u32 val; @@ -279,7 +277,7 @@ mt76x2_power_on(struct mt76x2_dev *dev) mt76x2_power_on_rf(dev, 1); } -void mt76x2_set_tx_ackto(struct mt76x2_dev *dev) +void mt76x2_set_tx_ackto(struct mt76x02_dev *dev) { u8 ackto, sifs, slottime = dev->slottime; @@ -296,14 +294,14 @@ void mt76x2_set_tx_ackto(struct mt76x2_dev *dev) MT_TX_TIMEOUT_CFG_ACKTO, ackto); } -int mt76x2_init_hardware(struct mt76x2_dev *dev) +int mt76x2_init_hardware(struct mt76x02_dev *dev) { int ret; tasklet_init(&dev->pre_tbtt_tasklet, mt76x2_pre_tbtt_tasklet, (unsigned long) dev); - mt76x02_dma_disable(&dev->mt76); + mt76x02_dma_disable(dev); mt76x2_reset_wlan(dev, true); mt76x2_power_on(dev); @@ -317,7 +315,7 @@ int mt76x2_init_hardware(struct mt76x2_dev *dev) dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG); - ret = mt76x02_dma_init(&dev->mt76); + ret = mt76x02_dma_init(dev); if (ret) return ret; @@ -335,43 +333,42 @@ int mt76x2_init_hardware(struct mt76x2_dev *dev) return 0; } -void mt76x2_stop_hardware(struct mt76x2_dev *dev) +void mt76x2_stop_hardware(struct mt76x02_dev *dev) { cancel_delayed_work_sync(&dev->cal_work); cancel_delayed_work_sync(&dev->mac_work); - mt76x02_mcu_set_radio_state(&dev->mt76, false, true); + mt76x02_mcu_set_radio_state(dev, false, true); mt76x2_mac_stop(dev, false); } -void mt76x2_cleanup(struct mt76x2_dev *dev) +void mt76x2_cleanup(struct mt76x02_dev *dev) { tasklet_disable(&dev->dfs_pd.dfs_tasklet); tasklet_disable(&dev->pre_tbtt_tasklet); mt76x2_stop_hardware(dev); - mt76x2_dma_cleanup(dev); - mt76x02_mcu_cleanup(&dev->mt76); + mt76x02_dma_cleanup(dev); + mt76x02_mcu_cleanup(dev); } -struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev) +struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev) { static const struct mt76_driver_ops drv_ops = { .txwi_size = sizeof(struct mt76x02_txwi), .update_survey = mt76x2_update_channel, - .tx_prepare_skb = mt76x2_tx_prepare_skb, - .tx_complete_skb = mt76x2_tx_complete_skb, - .rx_skb = mt76x2_queue_rx_skb, - .rx_poll_complete = mt76x2_rx_poll_complete, + .tx_prepare_skb = mt76x02_tx_prepare_skb, + .tx_complete_skb = mt76x02_tx_complete_skb, + .rx_skb = mt76x02_queue_rx_skb, + .rx_poll_complete = mt76x02_rx_poll_complete, .sta_ps = mt76x2_sta_ps, - .get_max_txpwr_adj = mt76x2_tx_get_max_txpwr_adj, }; - struct mt76x2_dev *dev; + struct mt76x02_dev *dev; struct mt76_dev *mdev; mdev = mt76_alloc_device(sizeof(*dev), &mt76x2_ops); if (!mdev) return NULL; - dev = container_of(mdev, struct mt76x2_dev, mt76); + dev = container_of(mdev, struct mt76x02_dev, mt76); mdev->dev = pdev; mdev->drv = &drv_ops; @@ -382,7 +379,7 @@ static void mt76x2_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mt76x2_dfs_set_domain(dev, request->dfs_region); } @@ -418,8 +415,8 @@ static const struct ieee80211_iface_combination if_comb[] = { static void mt76x2_led_set_config(struct mt76_dev *mt76, u8 delay_on, u8 delay_off) { - struct mt76x2_dev *dev = container_of(mt76, struct mt76x2_dev, - mt76); + struct mt76x02_dev *dev = container_of(mt76, struct mt76x02_dev, + mt76); u32 val; val = MT_LED_STATUS_DURATION(0xff) | @@ -463,21 +460,12 @@ static void mt76x2_led_set_brightness(struct led_classdev *led_cdev, mt76x2_led_set_config(mt76, 0xff, 0); } -int mt76x2_register_device(struct mt76x2_dev *dev) +int mt76x2_register_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); struct wiphy *wiphy = hw->wiphy; - void *status_fifo; - int fifo_size; int i, ret; - fifo_size = roundup_pow_of_two(32 * sizeof(struct mt76x02_tx_status)); - status_fifo = devm_kzalloc(dev->mt76.dev, fifo_size, GFP_KERNEL); - if (!status_fifo) - return -ENOMEM; - - tasklet_init(&dev->tx_tasklet, mt76x2_tx_tasklet, (unsigned long)dev); - kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size); INIT_DELAYED_WORK(&dev->cal_work, mt76x2_phy_calibrate); INIT_DELAYED_WORK(&dev->mac_work, mt76x2_mac_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mac.c index bb9c0a059a6e..4b331ed14bb2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mac.c @@ -16,12 +16,10 @@ #include <linux/delay.h> #include "mt76x2.h" -#include "mt76x2_mcu.h" -#include "mt76x2_eeprom.h" -#include "mt76x2_trace.h" -#include "mt76x02_util.h" +#include "mcu.h" +#include "eeprom.h" -void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr) +void mt76x2_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr) { idx &= 7; mt76_wr(dev, MT_MAC_APC_BSSID_L(idx), get_unaligned_le32(addr)); @@ -29,76 +27,8 @@ void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr) get_unaligned_le16(addr + 4)); } -void mt76x2_mac_poll_tx_status(struct mt76x2_dev *dev, bool irq) -{ - struct mt76x02_tx_status stat = {}; - unsigned long flags; - u8 update = 1; - bool ret; - - if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) - return; - - trace_mac_txstat_poll(dev); - - while (!irq || !kfifo_is_full(&dev->txstatus_fifo)) { - spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags); - ret = mt76x02_mac_load_tx_status(&dev->mt76, &stat); - spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags); - - if (!ret) - break; - - trace_mac_txstat_fetch(dev, &stat); - - if (!irq) { - mt76x02_send_tx_status(&dev->mt76, &stat, &update); - continue; - } - - kfifo_put(&dev->txstatus_fifo, stat); - } -} - -static void -mt76x2_mac_queue_txdone(struct mt76x2_dev *dev, struct sk_buff *skb, - void *txwi_ptr) -{ - struct mt76x2_tx_info *txi = mt76x2_skb_tx_info(skb); - struct mt76x02_txwi *txwi = txwi_ptr; - - mt76x2_mac_poll_tx_status(dev, false); - - txi->tries = 0; - txi->jiffies = jiffies; - txi->wcid = txwi->wcid; - txi->pktid = txwi->pktid; - trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid); - mt76x02_tx_complete(&dev->mt76, skb); -} - -void mt76x2_mac_process_tx_status_fifo(struct mt76x2_dev *dev) -{ - struct mt76x02_tx_status stat; - u8 update = 1; - - while (kfifo_get(&dev->txstatus_fifo, &stat)) - mt76x02_send_tx_status(&dev->mt76, &stat, &update); -} - -void mt76x2_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, - struct mt76_queue_entry *e, bool flush) -{ - struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76); - - if (e->txwi) - mt76x2_mac_queue_txdone(dev, e->skb, &e->txwi->txwi); - else - dev_kfree_skb_any(e->skb); -} - static int -mt76_write_beacon(struct mt76x2_dev *dev, int offset, struct sk_buff *skb) +mt76_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) { int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0]; struct mt76x02_txwi txwi; @@ -106,7 +36,7 @@ mt76_write_beacon(struct mt76x2_dev *dev, int offset, struct sk_buff *skb) if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi))) return -ENOSPC; - mt76x2_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); + mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); mt76_wr_copy(dev, offset, &txwi, sizeof(txwi)); offset += sizeof(txwi); @@ -116,7 +46,7 @@ mt76_write_beacon(struct mt76x2_dev *dev, int offset, struct sk_buff *skb) } static int -__mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 bcn_idx, struct sk_buff *skb) +__mt76x2_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx, struct sk_buff *skb) { int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0]; int beacon_addr = mt76x02_beacon_offsets[bcn_idx]; @@ -141,7 +71,7 @@ __mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 bcn_idx, struct sk_buff *skb) return ret; } -int mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 vif_idx, +int mt76x2_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, struct sk_buff *skb) { bool force_update = false; @@ -176,7 +106,8 @@ int mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 vif_idx, return 0; } -void mt76x2_mac_set_beacon_enable(struct mt76x2_dev *dev, u8 vif_idx, bool val) +void mt76x2_mac_set_beacon_enable(struct mt76x02_dev *dev, + u8 vif_idx, bool val) { u8 old_mask = dev->beacon_mask; bool en; @@ -201,14 +132,14 @@ void mt76x2_mac_set_beacon_enable(struct mt76x2_dev *dev, u8 vif_idx, bool val) mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en); if (en) - mt76x02_irq_enable(&dev->mt76, MT_INT_PRE_TBTT | MT_INT_TBTT); + mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); else - mt76x02_irq_disable(&dev->mt76, MT_INT_PRE_TBTT | MT_INT_TBTT); + mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); } void mt76x2_update_channel(struct mt76_dev *mdev) { - struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76); + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); struct mt76_channel_state *state; u32 active, busy; @@ -225,8 +156,8 @@ void mt76x2_update_channel(struct mt76_dev *mdev) void mt76x2_mac_work(struct work_struct *work) { - struct mt76x2_dev *dev = container_of(work, struct mt76x2_dev, - mac_work.work); + struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, + mac_work.work); int i, idx; mt76x2_update_channel(&dev->mt76); @@ -241,7 +172,7 @@ void mt76x2_mac_work(struct work_struct *work) MT_CALIBRATE_INTERVAL); } -void mt76x2_mac_set_tx_protection(struct mt76x2_dev *dev, u32 val) +void mt76x2_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val) { u32 data = 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 63691b68a436..034a06295668 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -15,12 +15,11 @@ */ #include "mt76x2.h" -#include "mt76x02_util.h" static int mt76x2_start(struct ieee80211_hw *hw) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; int ret; mutex_lock(&dev->mt76.mutex); @@ -46,7 +45,7 @@ out: static void mt76x2_stop(struct ieee80211_hw *hw) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); @@ -55,7 +54,7 @@ mt76x2_stop(struct ieee80211_hw *hw) } static int -mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef) +mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) { int ret; @@ -91,7 +90,7 @@ mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef) static int mt76x2_config(struct ieee80211_hw *hw, u32 changed) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; int ret = 0; mutex_lock(&dev->mt76.mutex); @@ -113,7 +112,7 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed) if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) { mt76x2_phy_set_txpower(dev); - mt76x2_tx_set_txpwr_auto(dev, dev->mt76.txpower_conf); + mt76x02_tx_set_txpwr_auto(dev, dev->mt76.txpower_conf); } } @@ -132,7 +131,7 @@ static void mt76x2_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv; mutex_lock(&dev->mt76.mutex); @@ -169,18 +168,18 @@ void mt76x2_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) { struct mt76x02_sta *msta = (struct mt76x02_sta *) sta->drv_priv; - struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76); + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); int idx = msta->wcid.idx; mt76_stop_tx_queues(&dev->mt76, sta, true); - mt76x02_mac_wcid_set_drop(&dev->mt76, idx, ps); + mt76x02_mac_wcid_set_drop(dev, idx, ps); } static void mt76x2_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; tasklet_disable(&dev->pre_tbtt_tasklet); set_bit(MT76_SCANNING, &dev->mt76.state); @@ -189,7 +188,7 @@ mt76x2_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static void mt76x2_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; clear_bit(MT76_SCANNING, &dev->mt76.state); tasklet_enable(&dev->pre_tbtt_tasklet); @@ -204,7 +203,7 @@ mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static int mt76x2_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; *dbm = dev->mt76.txpower_cur / 2; @@ -217,7 +216,7 @@ mt76x2_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) static void mt76x2_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); dev->coverage_class = coverage_class; @@ -234,7 +233,7 @@ mt76x2_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; if (!tx_ant || tx_ant > 3 || tx_ant != rx_ant) return -EINVAL; @@ -255,7 +254,7 @@ static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); *tx_ant = dev->mt76.antenna_mask; @@ -268,7 +267,7 @@ static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, static int mt76x2_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; if (val != ~0 && val > 0xffff) return -EINVAL; @@ -281,7 +280,7 @@ mt76x2_set_rts_threshold(struct ieee80211_hw *hw, u32 val) } const struct ieee80211_ops mt76x2_ops = { - .tx = mt76x2_tx, + .tx = mt76x02_tx, .start = mt76x2_start, .stop = mt76x2_stop, .add_interface = mt76x02_add_interface, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c index 55716fd7e01d..d8fa9ba56437 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c @@ -19,12 +19,11 @@ #include <linux/delay.h> #include "mt76x2.h" -#include "mt76x2_mcu.h" -#include "mt76x2_eeprom.h" -#include "mt76x02_dma.h" +#include "mcu.h" +#include "eeprom.h" static int -mt76pci_load_rom_patch(struct mt76x2_dev *dev) +mt76pci_load_rom_patch(struct mt76x02_dev *dev) { const struct firmware *fw = NULL; struct mt76x02_patch_header *hdr; @@ -90,7 +89,7 @@ out: } static int -mt76pci_load_firmware(struct mt76x2_dev *dev) +mt76pci_load_firmware(struct mt76x02_dev *dev) { const struct firmware *fw; const struct mt76x02_fw_header *hdr; @@ -141,7 +140,7 @@ mt76pci_load_firmware(struct mt76x2_dev *dev) mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0); - val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_2); + val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2); if (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, val) == 1) mt76_set(dev, MT_MCU_COM_REG0, BIT(30)); @@ -153,8 +152,8 @@ mt76pci_load_firmware(struct mt76x2_dev *dev) return -ETIMEDOUT; } + mt76x02_set_ethtool_fwver(dev, hdr); dev_info(dev->mt76.dev, "Firmware running!\n"); - mt76x02_set_ethtool_fwver(&dev->mt76, hdr); release_firmware(fw); @@ -166,7 +165,7 @@ error: return -ENOENT; } -int mt76x2_mcu_init(struct mt76x2_dev *dev) +int mt76x2_mcu_init(struct mt76x02_dev *dev) { static const struct mt76_mcu_ops mt76x2_mcu_ops = { .mcu_msg_alloc = mt76x02_mcu_msg_alloc, @@ -184,6 +183,6 @@ int mt76x2_mcu_init(struct mt76x2_dev *dev) if (ret) return ret; - mt76x02_mcu_function_select(&dev->mt76, Q_SELECT, 1, true); + mt76x02_mcu_function_select(dev, Q_SELECT, 1, true); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 22e66006a5f8..5bda44540225 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -16,16 +16,17 @@ #include <linux/delay.h> #include "mt76x2.h" -#include "mt76x2_mcu.h" -#include "mt76x2_eeprom.h" +#include "mcu.h" +#include "eeprom.h" +#include "../mt76x02_phy.h" static bool -mt76x2_phy_tssi_init_cal(struct mt76x2_dev *dev) +mt76x2_phy_tssi_init_cal(struct mt76x02_dev *dev) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; u32 flag = 0; - if (!mt76x02_tssi_enabled(&dev->mt76)) + if (!mt76x2_tssi_enabled(dev)) return false; if (mt76x2_channel_silent(dev)) @@ -34,16 +35,16 @@ mt76x2_phy_tssi_init_cal(struct mt76x2_dev *dev) if (chan->band == NL80211_BAND_5GHZ) flag |= BIT(0); - if (mt76x02_ext_pa_enabled(&dev->mt76, chan->band)) + if (mt76x02_ext_pa_enabled(dev, chan->band)) flag |= BIT(8); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TSSI, flag, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_TSSI, flag, true); dev->cal.tssi_cal_done = true; return true; } static void -mt76x2_phy_channel_calibrate(struct mt76x2_dev *dev, bool mac_stopped) +mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; bool is_5ghz = chan->band == NL80211_BAND_5GHZ; @@ -61,13 +62,13 @@ mt76x2_phy_channel_calibrate(struct mt76x2_dev *dev, bool mac_stopped) mt76x2_mac_stop(dev, false); if (is_5ghz) - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_LC, 0, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 0, true); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TX_LOFT, is_5ghz, true); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TXIQ, is_5ghz, true); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXIQC_FI, is_5ghz, true); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TEMP_SENSOR, 0, true); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TX_SHAPING, 0, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_TX_LOFT, is_5ghz, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQC_FI, is_5ghz, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_TEMP_SENSOR, 0, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_TX_SHAPING, 0, true); if (!mac_stopped) mt76x2_mac_resume(dev); @@ -77,7 +78,7 @@ mt76x2_phy_channel_calibrate(struct mt76x2_dev *dev, bool mac_stopped) dev->cal.channel_cal_done = true; } -void mt76x2_phy_set_antenna(struct mt76x2_dev *dev) +void mt76x2_phy_set_antenna(struct mt76x02_dev *dev) { u32 val; @@ -124,40 +125,7 @@ void mt76x2_phy_set_antenna(struct mt76x2_dev *dev) } static void -mt76x2_get_agc_gain(struct mt76x2_dev *dev, u8 *dest) -{ - dest[0] = mt76_get_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN); - dest[1] = mt76_get_field(dev, MT_BBP(AGC, 9), MT_BBP_AGC_GAIN); -} - -static int -mt76x2_get_rssi_gain_thresh(struct mt76x2_dev *dev) -{ - switch (dev->mt76.chandef.width) { - case NL80211_CHAN_WIDTH_80: - return -62; - case NL80211_CHAN_WIDTH_40: - return -65; - default: - return -68; - } -} - -static int -mt76x2_get_low_rssi_gain_thresh(struct mt76x2_dev *dev) -{ - switch (dev->mt76.chandef.width) { - case NL80211_CHAN_WIDTH_80: - return -76; - case NL80211_CHAN_WIDTH_40: - return -79; - default: - return -82; - } -} - -static void -mt76x2_phy_set_gain_val(struct mt76x2_dev *dev) +mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) { u32 val; u8 gain_val[2]; @@ -182,26 +150,7 @@ mt76x2_phy_set_gain_val(struct mt76x2_dev *dev) } static void -mt76x2_phy_adjust_vga_gain(struct mt76x2_dev *dev) -{ - u32 false_cca; - u8 limit = dev->cal.low_gain > 0 ? 16 : 4; - - false_cca = FIELD_GET(MT_RX_STAT_1_CCA_ERRORS, mt76_rr(dev, MT_RX_STAT_1)); - dev->cal.false_cca = false_cca; - if (false_cca > 800 && dev->cal.agc_gain_adjust < limit) - dev->cal.agc_gain_adjust += 2; - else if ((false_cca < 10 && dev->cal.agc_gain_adjust > 0) || - (dev->cal.agc_gain_adjust >= limit && false_cca < 500)) - dev->cal.agc_gain_adjust -= 2; - else - return; - - mt76x2_phy_set_gain_val(dev); -} - -static void -mt76x2_phy_update_channel_gain(struct mt76x2_dev *dev) +mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) { u8 *gain = dev->cal.agc_gain_init; u8 low_gain_delta, gain_delta; @@ -209,16 +158,17 @@ mt76x2_phy_update_channel_gain(struct mt76x2_dev *dev) int low_gain; u32 val; - dev->cal.avg_rssi_all = mt76x2_phy_get_min_avg_rssi(dev); + dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev); - low_gain = (dev->cal.avg_rssi_all > mt76x2_get_rssi_gain_thresh(dev)) + - (dev->cal.avg_rssi_all > mt76x2_get_low_rssi_gain_thresh(dev)); + low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) + + (dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev)); gain_change = (dev->cal.low_gain & 2) ^ (low_gain & 2); dev->cal.low_gain = low_gain; if (!gain_change) { - mt76x2_phy_adjust_vga_gain(dev); + if (mt76x02_phy_adjust_vga_gain(dev)) + mt76x2_phy_set_gain_val(dev); return; } @@ -264,7 +214,7 @@ mt76x2_phy_update_channel_gain(struct mt76x2_dev *dev) mt76_rr(dev, MT_RX_STAT_1); } -int mt76x2_phy_set_channel(struct mt76x2_dev *dev, +int mt76x2_phy_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) { struct ieee80211_channel *chan = chandef->chan; @@ -336,8 +286,8 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev, mt76x2_configure_tx_delay(dev, band, bw); mt76x2_phy_set_txpower(dev); - mt76x2_phy_set_band(dev, chan->band, ch_group_index & 1); - mt76x2_phy_set_bw(dev, chandef->width, ch_group_index); + mt76x02_phy_set_band(dev, chan->band, ch_group_index & 1); + mt76x02_phy_set_bw(dev, chandef->width, ch_group_index); mt76_rmw(dev, MT_EXT_CCA_CFG, (MT_EXT_CCA_CFG_CCA0 | @@ -360,17 +310,17 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev, mt76_set(dev, MT_BBP(RXO, 13), BIT(10)); if (!dev->cal.init_cal_done) { - u8 val = mt76x02_eeprom_get(&dev->mt76, MT_EE_BT_RCAL_RESULT); + u8 val = mt76x02_eeprom_get(dev, MT_EE_BT_RCAL_RESULT); if (val != 0xff) - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_R, 0, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, true); } - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, channel, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, channel, true); /* Rx LPF calibration */ if (!dev->cal.init_cal_done) - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RC, 0, true); + mt76x02_mcu_calibrate(dev, MCU_CAL_RC, 0, true); dev->cal.init_cal_done = true; @@ -383,14 +333,11 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev, if (scan) return 0; - dev->cal.low_gain = -1; mt76x2_phy_channel_calibrate(dev, true); - mt76x2_get_agc_gain(dev, dev->cal.agc_gain_init); - memcpy(dev->cal.agc_gain_cur, dev->cal.agc_gain_init, - sizeof(dev->cal.agc_gain_cur)); + mt76x02_init_agc_gain(dev); /* init default values for temp compensation */ - if (mt76x02_tssi_enabled(&dev->mt76)) { + if (mt76x2_tssi_enabled(dev)) { mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, 0x38); mt76_rmw_field(dev, MT_TX_ALC_CFG_2, MT_TX_ALC_CFG_2_TEMP_COMP, @@ -404,7 +351,7 @@ int mt76x2_phy_set_channel(struct mt76x2_dev *dev, } static void -mt76x2_phy_temp_compensate(struct mt76x2_dev *dev) +mt76x2_phy_temp_compensate(struct mt76x02_dev *dev) { struct mt76x2_temp_comp t; int temp, db_diff; @@ -433,9 +380,9 @@ mt76x2_phy_temp_compensate(struct mt76x2_dev *dev) void mt76x2_phy_calibrate(struct work_struct *work) { - struct mt76x2_dev *dev; + struct mt76x02_dev *dev; - dev = container_of(work, struct mt76x2_dev, cal_work.work); + dev = container_of(work, struct mt76x02_dev, cal_work.work); mt76x2_phy_channel_calibrate(dev, false); mt76x2_phy_tssi_compensate(dev, true); mt76x2_phy_temp_compensate(dev); @@ -444,11 +391,11 @@ void mt76x2_phy_calibrate(struct work_struct *work) MT_CALIBRATE_INTERVAL); } -int mt76x2_phy_start(struct mt76x2_dev *dev) +int mt76x2_phy_start(struct mt76x02_dev *dev) { int ret; - ret = mt76x02_mcu_set_radio_state(&dev->mt76, true, true); + ret = mt76x02_mcu_set_radio_state(dev, true, true); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_tx.c index fcdf1879162e..3a2ec86d3e88 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_tx.c @@ -15,50 +15,17 @@ */ #include "mt76x2.h" -#include "mt76x02_util.h" -#include "mt76x02_dma.h" struct beacon_bc_data { - struct mt76x2_dev *dev; + struct mt76x02_dev *dev; struct sk_buff_head q; struct sk_buff *tail[8]; }; -int mt76x2_tx_prepare_skb(struct mt76_dev *mdev, void *txwi, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info) -{ - struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int qsel = MT_QSEL_EDCA; - int ret; - - if (q == &dev->mt76.q_tx[MT_TXQ_PSD] && wcid && wcid->idx < 128) - mt76x02_mac_wcid_set_drop(&dev->mt76, wcid->idx, false); - - mt76x2_mac_write_txwi(dev, txwi, skb, wcid, sta, skb->len); - - ret = mt76x02_insert_hdr_pad(skb); - if (ret < 0) - return ret; - - if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) - qsel = MT_QSEL_MGMT; - - *tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) | - MT_TXD_INFO_80211; - - if (!wcid || wcid->hw_key_idx == 0xff || wcid->sw_iv) - *tx_info |= MT_TXD_INFO_WIV; - - return 0; -} - static void mt76x2_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt76x2_dev *dev = (struct mt76x2_dev *) priv; + struct mt76x02_dev *dev = (struct mt76x02_dev *) priv; struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv; struct sk_buff *skb = NULL; @@ -76,7 +43,7 @@ static void mt76x2_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct beacon_bc_data *data = priv; - struct mt76x2_dev *dev = data->dev; + struct mt76x02_dev *dev = data->dev; struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv; struct ieee80211_tx_info *info; struct sk_buff *skb; @@ -97,7 +64,7 @@ mt76x2_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) } static void -mt76x2_resync_beacon_timer(struct mt76x2_dev *dev) +mt76x2_resync_beacon_timer(struct mt76x02_dev *dev) { u32 timer_val = dev->beacon_int << 4; @@ -129,7 +96,7 @@ mt76x2_resync_beacon_timer(struct mt76x2_dev *dev) void mt76x2_pre_tbtt_tasklet(unsigned long arg) { - struct mt76x2_dev *dev = (struct mt76x2_dev *) arg; + struct mt76x02_dev *dev = (struct mt76x02_dev *) arg; struct mt76_queue *q = &dev->mt76.q_tx[MT_TXQ_PSD]; struct beacon_bc_data data = {}; struct sk_buff *skb; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_phy_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index dd32e756d8b7..e9fff5b7f125 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_phy_common.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -16,12 +16,12 @@ */ #include "mt76x2.h" -#include "mt76x2_eeprom.h" -#include "mt76x2_mcu.h" -#include "mt76x02_phy.h" +#include "eeprom.h" +#include "mcu.h" +#include "../mt76x02_phy.h" static void -mt76x2_adjust_high_lna_gain(struct mt76x2_dev *dev, int reg, s8 offset) +mt76x2_adjust_high_lna_gain(struct mt76x02_dev *dev, int reg, s8 offset) { s8 gain; @@ -31,7 +31,7 @@ mt76x2_adjust_high_lna_gain(struct mt76x2_dev *dev, int reg, s8 offset) } static void -mt76x2_adjust_agc_gain(struct mt76x2_dev *dev, int reg, s8 offset) +mt76x2_adjust_agc_gain(struct mt76x02_dev *dev, int reg, s8 offset) { s8 gain; @@ -40,7 +40,7 @@ mt76x2_adjust_agc_gain(struct mt76x2_dev *dev, int reg, s8 offset) mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_GAIN, gain); } -void mt76x2_apply_gain_adj(struct mt76x2_dev *dev) +void mt76x2_apply_gain_adj(struct mt76x02_dev *dev) { s8 *gain_adj = dev->cal.rx.high_gain; @@ -52,7 +52,7 @@ void mt76x2_apply_gain_adj(struct mt76x2_dev *dev) } EXPORT_SYMBOL_GPL(mt76x2_apply_gain_adj); -void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev, +void mt76x2_phy_set_txpower_regs(struct mt76x02_dev *dev, enum nl80211_band band) { u32 pa_mode[2]; @@ -65,7 +65,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev, mt76_wr(dev, MT_TX_ALC_CFG_2, 0x35160a00); mt76_wr(dev, MT_TX_ALC_CFG_3, 0x35160a06); - if (mt76x02_ext_pa_enabled(&dev->mt76, band)) { + if (mt76x02_ext_pa_enabled(dev, band)) { mt76_wr(dev, MT_RF_PA_MODE_ADJ0, 0x0000ec00); mt76_wr(dev, MT_RF_PA_MODE_ADJ1, 0x0000ec00); } else { @@ -76,7 +76,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev, pa_mode[0] = 0x0000ffff; pa_mode[1] = 0x00ff00ff; - if (mt76x02_ext_pa_enabled(&dev->mt76, band)) { + if (mt76x02_ext_pa_enabled(dev, band)) { mt76_wr(dev, MT_TX_ALC_CFG_2, 0x2f0f0400); mt76_wr(dev, MT_TX_ALC_CFG_3, 0x2f0f0476); } else { @@ -84,7 +84,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev, mt76_wr(dev, MT_TX_ALC_CFG_3, 0x1b0f0476); } - if (mt76x02_ext_pa_enabled(&dev->mt76, band)) + if (mt76x02_ext_pa_enabled(dev, band)) pa_mode_adj = 0x04000000; else pa_mode_adj = 0; @@ -98,7 +98,7 @@ void mt76x2_phy_set_txpower_regs(struct mt76x2_dev *dev, mt76_wr(dev, MT_RF_PA_MODE_CFG0, pa_mode[0]); mt76_wr(dev, MT_RF_PA_MODE_CFG1, pa_mode[1]); - if (mt76x02_ext_pa_enabled(&dev->mt76, band)) { + if (mt76x02_ext_pa_enabled(dev, band)) { u32 val; if (band == NL80211_BAND_2GHZ) @@ -144,7 +144,7 @@ mt76x2_get_min_rate_power(struct mt76_rate_power *r) return ret; } -void mt76x2_phy_set_txpower(struct mt76x2_dev *dev) +void mt76x2_phy_set_txpower(struct mt76x02_dev *dev) { enum nl80211_chan_width width = dev->mt76.chandef.width; struct ieee80211_channel *chan = dev->mt76.chandef.chan; @@ -187,16 +187,16 @@ void mt76x2_phy_set_txpower(struct mt76x2_dev *dev) dev->target_power_delta[1] = txp_1 - txp.chain[0].target_power; dev->mt76.rate_power = t; - mt76x02_phy_set_txpower(&dev->mt76, txp_0, txp_1); + mt76x02_phy_set_txpower(dev, txp_0, txp_1); } EXPORT_SYMBOL_GPL(mt76x2_phy_set_txpower); -void mt76x2_configure_tx_delay(struct mt76x2_dev *dev, +void mt76x2_configure_tx_delay(struct mt76x02_dev *dev, enum nl80211_band band, u8 bw) { u32 cfg0, cfg1; - if (mt76x02_ext_pa_enabled(&dev->mt76, band)) { + if (mt76x02_ext_pa_enabled(dev, band)) { cfg0 = bw ? 0x000b0c01 : 0x00101101; cfg1 = 0x00011414; } else { @@ -210,98 +210,7 @@ void mt76x2_configure_tx_delay(struct mt76x2_dev *dev, } EXPORT_SYMBOL_GPL(mt76x2_configure_tx_delay); -void mt76x2_phy_set_bw(struct mt76x2_dev *dev, int width, u8 ctrl) -{ - int core_val, agc_val; - - switch (width) { - case NL80211_CHAN_WIDTH_80: - core_val = 3; - agc_val = 7; - break; - case NL80211_CHAN_WIDTH_40: - core_val = 2; - agc_val = 3; - break; - default: - core_val = 0; - agc_val = 1; - break; - } - - mt76_rmw_field(dev, MT_BBP(CORE, 1), MT_BBP_CORE_R1_BW, core_val); - mt76_rmw_field(dev, MT_BBP(AGC, 0), MT_BBP_AGC_R0_BW, agc_val); - mt76_rmw_field(dev, MT_BBP(AGC, 0), MT_BBP_AGC_R0_CTRL_CHAN, ctrl); - mt76_rmw_field(dev, MT_BBP(TXBE, 0), MT_BBP_TXBE_R0_CTRL_CHAN, ctrl); -} -EXPORT_SYMBOL_GPL(mt76x2_phy_set_bw); - -void mt76x2_phy_set_band(struct mt76x2_dev *dev, int band, bool primary_upper) -{ - switch (band) { - case NL80211_BAND_2GHZ: - mt76_set(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_2G); - mt76_clear(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_5G); - break; - case NL80211_BAND_5GHZ: - mt76_clear(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_2G); - mt76_set(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_5G); - break; - } - - mt76_rmw_field(dev, MT_TX_BAND_CFG, MT_TX_BAND_CFG_UPPER_40M, - primary_upper); -} -EXPORT_SYMBOL_GPL(mt76x2_phy_set_band); - -int mt76x2_phy_get_min_avg_rssi(struct mt76x2_dev *dev) -{ - struct mt76x02_sta *sta; - struct mt76_wcid *wcid; - int i, j, min_rssi = 0; - s8 cur_rssi; - - local_bh_disable(); - rcu_read_lock(); - - for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid_mask); i++) { - unsigned long mask = dev->mt76.wcid_mask[i]; - - if (!mask) - continue; - - for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) { - if (!(mask & 1)) - continue; - - wcid = rcu_dereference(dev->mt76.wcid[j]); - if (!wcid) - continue; - - sta = container_of(wcid, struct mt76x02_sta, wcid); - spin_lock(&dev->mt76.rx_lock); - if (sta->inactive_count++ < 5) - cur_rssi = ewma_signal_read(&sta->rssi); - else - cur_rssi = 0; - spin_unlock(&dev->mt76.rx_lock); - - if (cur_rssi < min_rssi) - min_rssi = cur_rssi; - } - } - - rcu_read_unlock(); - local_bh_enable(); - - if (!min_rssi) - return -75; - - return min_rssi; -} -EXPORT_SYMBOL_GPL(mt76x2_phy_get_min_avg_rssi); - -void mt76x2_phy_tssi_compensate(struct mt76x2_dev *dev, bool wait) +void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; struct mt76x2_tx_power_info txp; @@ -322,7 +231,7 @@ void mt76x2_phy_tssi_compensate(struct mt76x2_dev *dev, bool wait) dev->cal.tssi_comp_pending = false; mt76x2_get_power_info(dev, &txp, chan); - if (mt76x02_ext_pa_enabled(&dev->mt76, chan->band)) + if (mt76x02_ext_pa_enabled(dev, chan->band)) t.pa_mode = 1; t.cal_mode = BIT(1); @@ -336,8 +245,7 @@ void mt76x2_phy_tssi_compensate(struct mt76x2_dev *dev, bool wait) return; usleep_range(10000, 20000); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_DPD, - chan->hw_value, wait); + mt76x02_mcu_calibrate(dev, MCU_CAL_DPD, chan->hw_value, wait); dev->cal.dpd_cal_done = true; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index feb5cec66c67..57baf8d1c830 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -17,7 +17,7 @@ #include <linux/kernel.h> #include <linux/module.h> -#include "mt76x02_usb.h" +#include "../mt76x02_usb.h" #include "mt76x2u.h" static const struct usb_device_id mt76x2u_device_table[] = { @@ -37,7 +37,7 @@ static int mt76x2u_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); - struct mt76x2_dev *dev; + struct mt76x02_dev *dev; int err; dev = mt76x2u_alloc_device(&intf->dev); @@ -72,7 +72,7 @@ err: static void mt76x2u_disconnect(struct usb_interface *intf) { struct usb_device *udev = interface_to_usbdev(intf); - struct mt76x2_dev *dev = usb_get_intfdata(intf); + struct mt76x02_dev *dev = usb_get_intfdata(intf); struct ieee80211_hw *hw = mt76_hw(dev); set_bit(MT76_REMOVED, &dev->mt76.state); @@ -87,7 +87,7 @@ static void mt76x2u_disconnect(struct usb_interface *intf) static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf, pm_message_t state) { - struct mt76x2_dev *dev = usb_get_intfdata(intf); + struct mt76x02_dev *dev = usb_get_intfdata(intf); struct mt76_usb *usb = &dev->mt76.usb; mt76u_stop_queues(&dev->mt76); @@ -99,7 +99,7 @@ static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf, static int __maybe_unused mt76x2u_resume(struct usb_interface *intf) { - struct mt76x2_dev *dev = usb_get_intfdata(intf); + struct mt76x02_dev *dev = usb_get_intfdata(intf); struct mt76_usb *usb = &dev->mt76.usb; int err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 5759a72d7ef6..13cce2937573 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2u_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -17,11 +17,11 @@ #include <linux/delay.h> #include "mt76x2u.h" -#include "mt76x02_util.h" -#include "mt76x02_phy.h" -#include "mt76x2_eeprom.h" +#include "eeprom.h" +#include "../mt76x02_phy.h" +#include "../mt76x02_usb.h" -static void mt76x2u_init_dma(struct mt76x2_dev *dev) +static void mt76x2u_init_dma(struct mt76x02_dev *dev) { u32 val = mt76_rr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG)); @@ -36,7 +36,7 @@ static void mt76x2u_init_dma(struct mt76x2_dev *dev) mt76_wr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG), val); } -static void mt76x2u_power_on_rf_patch(struct mt76x2_dev *dev) +static void mt76x2u_power_on_rf_patch(struct mt76x02_dev *dev) { mt76_set(dev, MT_VEND_ADDR(CFG, 0x130), BIT(0) | BIT(16)); udelay(1); @@ -56,7 +56,7 @@ static void mt76x2u_power_on_rf_patch(struct mt76x2_dev *dev) mt76_set(dev, MT_VEND_ADDR(CFG, 0x14c), BIT(19) | BIT(20)); } -static void mt76x2u_power_on_rf(struct mt76x2_dev *dev, int unit) +static void mt76x2u_power_on_rf(struct mt76x02_dev *dev, int unit) { int shift = unit ? 8 : 0; u32 val = (BIT(1) | BIT(3) | BIT(4) | BIT(5)) << shift; @@ -78,7 +78,7 @@ static void mt76x2u_power_on_rf(struct mt76x2_dev *dev, int unit) mt76_set(dev, 0x530, 0xf); } -static void mt76x2u_power_on(struct mt76x2_dev *dev) +static void mt76x2u_power_on(struct mt76x02_dev *dev) { u32 val; @@ -114,7 +114,7 @@ static void mt76x2u_power_on(struct mt76x2_dev *dev) mt76x2u_power_on_rf(dev, 1); } -static int mt76x2u_init_eeprom(struct mt76x2_dev *dev) +static int mt76x2u_init_eeprom(struct mt76x02_dev *dev) { u32 val, i; @@ -130,33 +130,33 @@ static int mt76x2u_init_eeprom(struct mt76x2_dev *dev) put_unaligned_le32(val, dev->mt76.eeprom.data + i); } - mt76x02_eeprom_parse_hw_cap(&dev->mt76); + mt76x02_eeprom_parse_hw_cap(dev); return 0; } -struct mt76x2_dev *mt76x2u_alloc_device(struct device *pdev) +struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev) { static const struct mt76_driver_ops drv_ops = { - .tx_prepare_skb = mt76x2u_tx_prepare_skb, - .tx_complete_skb = mt76x02_tx_complete_skb, + .tx_prepare_skb = mt76x02u_tx_prepare_skb, + .tx_complete_skb = mt76x02u_tx_complete_skb, .tx_status_data = mt76x02_tx_status_data, - .rx_skb = mt76x2_queue_rx_skb, + .rx_skb = mt76x02_queue_rx_skb, }; - struct mt76x2_dev *dev; + struct mt76x02_dev *dev; struct mt76_dev *mdev; mdev = mt76_alloc_device(sizeof(*dev), &mt76x2u_ops); if (!mdev) return NULL; - dev = container_of(mdev, struct mt76x2_dev, mt76); + dev = container_of(mdev, struct mt76x02_dev, mt76); mdev->dev = pdev; mdev->drv = &drv_ops; return dev; } -static void mt76x2u_init_beacon_offsets(struct mt76x2_dev *dev) +static void mt76x2u_init_beacon_offsets(struct mt76x02_dev *dev) { mt76_wr(dev, MT_BCN_OFFSET(0), 0x18100800); mt76_wr(dev, MT_BCN_OFFSET(1), 0x38302820); @@ -164,7 +164,7 @@ static void mt76x2u_init_beacon_offsets(struct mt76x2_dev *dev) mt76_wr(dev, MT_BCN_OFFSET(3), 0x78706860); } -int mt76x2u_init_hardware(struct mt76x2_dev *dev) +int mt76x2u_init_hardware(struct mt76x02_dev *dev) { const struct mt76_wcid_addr addr = { .macaddr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, @@ -204,8 +204,7 @@ int mt76x2u_init_hardware(struct mt76x2_dev *dev) if (err < 0) return err; - mt76x02_mac_setaddr(&dev->mt76, - dev->mt76.eeprom.data + MT_EE_MAC_ADDR); + mt76x02_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR); dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG); mt76x2u_init_beacon_offsets(dev); @@ -237,13 +236,13 @@ int mt76x2u_init_hardware(struct mt76x2_dev *dev) if (err < 0) return err; - mt76x02_phy_set_rxpath(&dev->mt76); - mt76x02_phy_set_txdac(&dev->mt76); + mt76x02_phy_set_rxpath(dev); + mt76x02_phy_set_txdac(dev); return mt76x2u_mac_stop(dev); } -int mt76x2u_register_device(struct mt76x2_dev *dev) +int mt76x2u_register_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); struct wiphy *wiphy = hw->wiphy; @@ -262,7 +261,7 @@ int mt76x2u_register_device(struct mt76x2_dev *dev) err = mt76u_mcu_init_rx(&dev->mt76); if (err < 0) - return err; + goto fail; err = mt76x2u_init_hardware(dev); if (err < 0) @@ -294,16 +293,16 @@ fail: return err; } -void mt76x2u_stop_hw(struct mt76x2_dev *dev) +void mt76x2u_stop_hw(struct mt76x02_dev *dev) { mt76u_stop_stat_wk(&dev->mt76); cancel_delayed_work_sync(&dev->cal_work); mt76x2u_mac_stop(dev); } -void mt76x2u_cleanup(struct mt76x2_dev *dev) +void mt76x2u_cleanup(struct mt76x02_dev *dev) { - mt76x02_mcu_set_radio_state(&dev->mt76, false, false); + mt76x02_mcu_set_radio_state(dev, false, false); mt76x2u_stop_hw(dev); mt76u_queues_deinit(&dev->mt76); mt76u_mcu_deinit(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c index f28c6fbcc305..db2194a92e67 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2u_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c @@ -15,9 +15,9 @@ */ #include "mt76x2u.h" -#include "mt76x2_eeprom.h" +#include "eeprom.h" -static void mt76x2u_mac_reset_counters(struct mt76x2_dev *dev) +static void mt76x2u_mac_reset_counters(struct mt76x02_dev *dev) { mt76_rr(dev, MT_RX_STAT_0); mt76_rr(dev, MT_RX_STAT_1); @@ -27,12 +27,12 @@ static void mt76x2u_mac_reset_counters(struct mt76x2_dev *dev) mt76_rr(dev, MT_TX_STA_2); } -static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev) +static void mt76x2u_mac_fixup_xtal(struct mt76x02_dev *dev) { s8 offset = 0; u16 eep_val; - eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_2); + eep_val = mt76x02_eeprom_get(dev, MT_EE_XTAL_TRIM_2); offset = eep_val & 0x7f; if ((eep_val & 0xff) == 0xff) @@ -42,7 +42,7 @@ static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev) eep_val >>= 8; if (eep_val == 0x00 || eep_val == 0xff) { - eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_XTAL_TRIM_1); + eep_val = mt76x02_eeprom_get(dev, MT_EE_XTAL_TRIM_1); eep_val &= 0xff; if (eep_val == 0x00 || eep_val == 0xff) @@ -67,7 +67,7 @@ static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev) /* init fce */ mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN); - eep_val = mt76x02_eeprom_get(&dev->mt76, MT_EE_NIC_CONF_2); + eep_val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2); switch (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, eep_val)) { case 0: mt76_wr(dev, MT_XO_CTRL7, 0x5c1fee80); @@ -80,7 +80,7 @@ static void mt76x2u_mac_fixup_xtal(struct mt76x2_dev *dev) } } -int mt76x2u_mac_reset(struct mt76x2_dev *dev) +int mt76x2u_mac_reset(struct mt76x02_dev *dev) { mt76_wr(dev, MT_WPDMA_GLO_CFG, BIT(4) | BIT(5)); @@ -114,7 +114,7 @@ int mt76x2u_mac_reset(struct mt76x2_dev *dev) return 0; } -int mt76x2u_mac_start(struct mt76x2_dev *dev) +int mt76x2u_mac_start(struct mt76x02_dev *dev) { mt76x2u_mac_reset_counters(dev); @@ -131,7 +131,7 @@ int mt76x2u_mac_start(struct mt76x2_dev *dev) return 0; } -int mt76x2u_mac_stop(struct mt76x2_dev *dev) +int mt76x2u_mac_stop(struct mt76x02_dev *dev) { int i, count = 0, val; bool stopped = false; @@ -212,7 +212,7 @@ int mt76x2u_mac_stop(struct mt76x2_dev *dev) return 0; } -void mt76x2u_mac_resume(struct mt76x2_dev *dev) +void mt76x2u_mac_resume(struct mt76x02_dev *dev) { mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX | diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index a80704568780..1971a1b00038 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2u_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -15,11 +15,10 @@ */ #include "mt76x2u.h" -#include "mt76x02_util.h" static int mt76x2u_start(struct ieee80211_hw *hw) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; int ret; mutex_lock(&dev->mt76.mutex); @@ -37,7 +36,7 @@ out: static void mt76x2u_stop(struct ieee80211_hw *hw) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); @@ -48,17 +47,17 @@ static void mt76x2u_stop(struct ieee80211_hw *hw) static int mt76x2u_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; if (!ether_addr_equal(dev->mt76.macaddr, vif->addr)) - mt76x02_mac_setaddr(&dev->mt76, vif->addr); + mt76x02_mac_setaddr(dev, vif->addr); - mt76x02_vif_init(&dev->mt76, vif, 0); + mt76x02_vif_init(dev, vif, 0); return 0; } static int -mt76x2u_set_channel(struct mt76x2_dev *dev, +mt76x2u_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) { int err; @@ -86,7 +85,7 @@ static void mt76x2u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); @@ -108,7 +107,7 @@ mt76x2u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static int mt76x2u_config(struct ieee80211_hw *hw, u32 changed) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; int err = 0; mutex_lock(&dev->mt76.mutex); @@ -146,7 +145,7 @@ static void mt76x2u_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; set_bit(MT76_SCANNING, &dev->mt76.state); } @@ -154,13 +153,13 @@ mt76x2u_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static void mt76x2u_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt76x2_dev *dev = hw->priv; + struct mt76x02_dev *dev = hw->priv; clear_bit(MT76_SCANNING, &dev->mt76.state); } const struct ieee80211_ops mt76x2u_ops = { - .tx = mt76x2_tx, + .tx = mt76x02_tx, .start = mt76x2u_start, .stop = mt76x2u_stop, .add_interface = mt76x2u_add_interface, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c index fdd94cad7b66..3f1e558e5e6d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2u_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c @@ -17,8 +17,8 @@ #include <linux/firmware.h> #include "mt76x2u.h" -#include "mt76x2_eeprom.h" -#include "mt76x02_usb.h" +#include "eeprom.h" +#include "../mt76x02_usb.h" #define MT_CMD_HDR_LEN 4 @@ -29,7 +29,7 @@ #define MT76U_MCU_DLM_OFFSET 0x110000 #define MT76U_MCU_ROM_PATCH_OFFSET 0x90000 -int mt76x2u_mcu_set_dynamic_vga(struct mt76x2_dev *dev, u8 channel, bool ap, +int mt76x2u_mcu_set_dynamic_vga(struct mt76x02_dev *dev, u8 channel, bool ap, bool ext, int rssi, u32 false_cca) { struct { @@ -53,14 +53,14 @@ int mt76x2u_mcu_set_dynamic_vga(struct mt76x2_dev *dev, u8 channel, bool ap, return mt76_mcu_send_msg(dev, skb, CMD_DYNC_VGA_OP, true); } -static void mt76x2u_mcu_load_ivb(struct mt76x2_dev *dev) +static void mt76x2u_mcu_load_ivb(struct mt76x02_dev *dev) { mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE, USB_DIR_OUT | USB_TYPE_VENDOR, 0x12, 0, NULL, 0); } -static void mt76x2u_mcu_enable_patch(struct mt76x2_dev *dev) +static void mt76x2u_mcu_enable_patch(struct mt76x02_dev *dev) { struct mt76_usb *usb = &dev->mt76.usb; const u8 data[] = { @@ -75,7 +75,7 @@ static void mt76x2u_mcu_enable_patch(struct mt76x2_dev *dev) 0x12, 0, usb->data, sizeof(data)); } -static void mt76x2u_mcu_reset_wmt(struct mt76x2_dev *dev) +static void mt76x2u_mcu_reset_wmt(struct mt76x02_dev *dev) { struct mt76_usb *usb = &dev->mt76.usb; u8 data[] = { @@ -89,7 +89,7 @@ static void mt76x2u_mcu_reset_wmt(struct mt76x2_dev *dev) 0x12, 0, usb->data, sizeof(data)); } -static int mt76x2u_mcu_load_rom_patch(struct mt76x2_dev *dev) +static int mt76x2u_mcu_load_rom_patch(struct mt76x02_dev *dev) { bool rom_protect = !is_mt7612(dev); struct mt76x02_patch_header *hdr; @@ -137,7 +137,7 @@ static int mt76x2u_mcu_load_rom_patch(struct mt76x2_dev *dev) mt76_wr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG), val); /* vendor reset */ - mt76x02u_mcu_fw_reset(&dev->mt76); + mt76x02u_mcu_fw_reset(dev); usleep_range(5000, 10000); /* enable FCE to send in-band cmd */ @@ -151,7 +151,7 @@ static int mt76x2u_mcu_load_rom_patch(struct mt76x2_dev *dev) /* FCE skip_fs_en */ mt76_wr(dev, MT_FCE_SKIP_FS, 0x3); - err = mt76x02u_mcu_fw_send_data(&dev->mt76, fw->data + sizeof(*hdr), + err = mt76x02u_mcu_fw_send_data(dev, fw->data + sizeof(*hdr), fw->size - sizeof(*hdr), MCU_ROM_PATCH_MAX_PAYLOAD, MT76U_MCU_ROM_PATCH_OFFSET); @@ -176,7 +176,7 @@ out: return err; } -static int mt76x2u_mcu_load_firmware(struct mt76x2_dev *dev) +static int mt76x2u_mcu_load_firmware(struct mt76x02_dev *dev) { u32 val, dlm_offset = MT76U_MCU_DLM_OFFSET; const struct mt76x02_fw_header *hdr; @@ -210,7 +210,7 @@ static int mt76x2u_mcu_load_firmware(struct mt76x2_dev *dev) dev_info(dev->mt76.dev, "Build Time: %.16s\n", hdr->build_time); /* vendor reset */ - mt76x02u_mcu_fw_reset(&dev->mt76); + mt76x02u_mcu_fw_reset(dev); usleep_range(5000, 10000); /* enable USB_DMA_CFG */ @@ -230,7 +230,7 @@ static int mt76x2u_mcu_load_firmware(struct mt76x2_dev *dev) mt76_wr(dev, MT_FCE_SKIP_FS, 0x3); /* load ILM */ - err = mt76x02u_mcu_fw_send_data(&dev->mt76, fw->data + sizeof(*hdr), + err = mt76x02u_mcu_fw_send_data(dev, fw->data + sizeof(*hdr), ilm_len, MCU_FW_URB_MAX_PAYLOAD, MT76U_MCU_ILM_OFFSET); if (err < 0) { @@ -241,8 +241,7 @@ static int mt76x2u_mcu_load_firmware(struct mt76x2_dev *dev) /* load DLM */ if (mt76xx_rev(dev) >= MT76XX_REV_E3) dlm_offset += 0x800; - err = mt76x02u_mcu_fw_send_data(&dev->mt76, - fw->data + sizeof(*hdr) + ilm_len, + err = mt76x02u_mcu_fw_send_data(dev, fw->data + sizeof(*hdr) + ilm_len, dlm_len, MCU_FW_URB_MAX_PAYLOAD, dlm_offset); if (err < 0) { @@ -260,15 +259,15 @@ static int mt76x2u_mcu_load_firmware(struct mt76x2_dev *dev) mt76_set(dev, MT_MCU_COM_REG0, BIT(1)); /* enable FCE to send in-band cmd */ mt76_wr(dev, MT_FCE_PSE_CTRL, 0x1); + mt76x02_set_ethtool_fwver(dev, hdr); dev_dbg(dev->mt76.dev, "firmware running\n"); - mt76x02_set_ethtool_fwver(&dev->mt76, hdr); out: release_firmware(fw); return err; } -int mt76x2u_mcu_fw_init(struct mt76x2_dev *dev) +int mt76x2u_mcu_fw_init(struct mt76x02_dev *dev) { int err; @@ -279,14 +278,13 @@ int mt76x2u_mcu_fw_init(struct mt76x2_dev *dev) return mt76x2u_mcu_load_firmware(dev); } -int mt76x2u_mcu_init(struct mt76x2_dev *dev) +int mt76x2u_mcu_init(struct mt76x02_dev *dev) { int err; - err = mt76x02_mcu_function_select(&dev->mt76, Q_SELECT, - 1, false); + err = mt76x02_mcu_function_select(dev, Q_SELECT, 1, false); if (err < 0) return err; - return mt76x02_mcu_set_radio_state(&dev->mt76, true, false); + return mt76x02_mcu_set_radio_state(dev, true, false); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index 06362d3487be..ca96ba60510e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2u_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -15,9 +15,10 @@ */ #include "mt76x2u.h" -#include "mt76x2_eeprom.h" +#include "eeprom.h" +#include "../mt76x02_phy.h" -void mt76x2u_phy_channel_calibrate(struct mt76x2_dev *dev) +void mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; bool is_5ghz = chan->band == NL80211_BAND_5GHZ; @@ -28,18 +29,18 @@ void mt76x2u_phy_channel_calibrate(struct mt76x2_dev *dev) mt76x2u_mac_stop(dev); if (is_5ghz) - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_LC, 0, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 0, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TX_LOFT, is_5ghz, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TXIQ, is_5ghz, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXIQC_FI, is_5ghz, false); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TEMP_SENSOR, 0, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_TX_LOFT, is_5ghz, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_TXIQ, is_5ghz, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXIQC_FI, is_5ghz, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_TEMP_SENSOR, 0, false); mt76x2u_mac_resume(dev); } static void -mt76x2u_phy_update_channel_gain(struct mt76x2_dev *dev) +mt76x2u_phy_update_channel_gain(struct mt76x02_dev *dev) { u8 channel = dev->mt76.chandef.chan->hw_value; int freq, freq1; @@ -68,7 +69,7 @@ mt76x2u_phy_update_channel_gain(struct mt76x2_dev *dev) break; } - dev->cal.avg_rssi_all = mt76x2_phy_get_min_avg_rssi(dev); + dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev); false_cca = FIELD_GET(MT_RX_STAT_1_CCA_ERRORS, mt76_rr(dev, MT_RX_STAT_1)); @@ -78,9 +79,9 @@ mt76x2u_phy_update_channel_gain(struct mt76x2_dev *dev) void mt76x2u_phy_calibrate(struct work_struct *work) { - struct mt76x2_dev *dev; + struct mt76x02_dev *dev; - dev = container_of(work, struct mt76x2_dev, cal_work.work); + dev = container_of(work, struct mt76x02_dev, cal_work.work); mt76x2_phy_tssi_compensate(dev, false); mt76x2u_phy_update_channel_gain(dev); @@ -88,7 +89,7 @@ void mt76x2u_phy_calibrate(struct work_struct *work) MT_CALIBRATE_INTERVAL); } -int mt76x2u_phy_set_channel(struct mt76x2_dev *dev, +int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) { u32 ext_cca_chan[4] = { @@ -154,8 +155,8 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev, mt76x2_configure_tx_delay(dev, chan->band, bw); mt76x2_phy_set_txpower(dev); - mt76x2_phy_set_band(dev, chan->band, ch_group_index & 1); - mt76x2_phy_set_bw(dev, chandef->width, ch_group_index); + mt76x02_phy_set_band(dev, chan->band, ch_group_index & 1); + mt76x02_phy_set_bw(dev, chandef->width, ch_group_index); mt76_rmw(dev, MT_EXT_CCA_CFG, (MT_EXT_CCA_CFG_CCA0 | @@ -176,18 +177,17 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev, mt76_set(dev, MT_BBP(RXO, 13), BIT(10)); if (!dev->cal.init_cal_done) { - u8 val = mt76x02_eeprom_get(&dev->mt76, MT_EE_BT_RCAL_RESULT); + u8 val = mt76x02_eeprom_get(dev, MT_EE_BT_RCAL_RESULT); if (val != 0xff) - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_R, - 0, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, false); } - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RXDCOC, channel, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, channel, false); /* Rx LPF calibration */ if (!dev->cal.init_cal_done) - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_RC, 0, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_RC, 0, false); dev->cal.init_cal_done = true; mt76_wr(dev, MT_BBP(AGC, 61), 0xff64a4e2); @@ -202,7 +202,7 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev, if (scan) return 0; - if (mt76x02_tssi_enabled(&dev->mt76)) { + if (mt76x2_tssi_enabled(dev)) { /* init default values for temp compensation */ mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, 0x38); @@ -217,10 +217,9 @@ int mt76x2u_phy_set_channel(struct mt76x2_dev *dev, chan = dev->mt76.chandef.chan; if (chan->band == NL80211_BAND_5GHZ) flag |= BIT(0); - if (mt76x02_ext_pa_enabled(&dev->mt76, chan->band)) + if (mt76x02_ext_pa_enabled(dev, chan->band)) flag |= BIT(8); - mt76x02_mcu_calibrate(&dev->mt76, MCU_CAL_TSSI, - flag, false); + mt76x02_mcu_calibrate(dev, MCU_CAL_TSSI, flag, false); dev->cal.tssi_cal_done = true; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_core.c b/drivers/net/wireless/mediatek/mt76/mt76x2_core.c deleted file mode 100644 index 06e47f960f9a..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_core.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <linux/delay.h> -#include "mt76x2.h" -#include "mt76x2_trace.h" -#include "mt76x02_util.h" - -void mt76x2_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) -{ - mt76x02_irq_enable(mdev, MT_INT_RX_DONE(q)); -} - -irqreturn_t mt76x2_irq_handler(int irq, void *dev_instance) -{ - struct mt76x2_dev *dev = dev_instance; - u32 intr; - - intr = mt76_rr(dev, MT_INT_SOURCE_CSR); - mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) - return IRQ_NONE; - - trace_dev_irq(dev, intr, dev->mt76.mmio.irqmask); - - intr &= dev->mt76.mmio.irqmask; - - if (intr & MT_INT_TX_DONE_ALL) { - mt76x02_irq_disable(&dev->mt76, MT_INT_TX_DONE_ALL); - tasklet_schedule(&dev->tx_tasklet); - } - - if (intr & MT_INT_RX_DONE(0)) { - mt76x02_irq_disable(&dev->mt76, MT_INT_RX_DONE(0)); - napi_schedule(&dev->mt76.napi[0]); - } - - if (intr & MT_INT_RX_DONE(1)) { - mt76x02_irq_disable(&dev->mt76, MT_INT_RX_DONE(1)); - napi_schedule(&dev->mt76.napi[1]); - } - - if (intr & MT_INT_PRE_TBTT) - tasklet_schedule(&dev->pre_tbtt_tasklet); - - /* send buffered multicast frames now */ - if (intr & MT_INT_TBTT) - mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]); - - if (intr & MT_INT_TX_STAT) { - mt76x2_mac_poll_tx_status(dev, true); - tasklet_schedule(&dev->tx_tasklet); - } - - if (intr & MT_INT_GPTIMER) { - mt76x02_irq_disable(&dev->mt76, MT_INT_GPTIMER); - tasklet_schedule(&dev->dfs_pd.dfs_tasklet); - } - - return IRQ_HANDLED; -} - diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.h deleted file mode 100644 index 66a57294fcfc..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __MT76x2_MAC_H -#define __MT76x2_MAC_H - -#include "mt76.h" -#include "mt76x02_mac.h" - -struct mt76x2_dev; -struct mt76x2_sta; -struct mt76x02_vif; - -struct mt76x2_tx_info { - unsigned long jiffies; - u8 tries; - - u8 wcid; - u8 pktid; - u8 retry; -}; - -static inline struct mt76x2_tx_info * -mt76x2_skb_tx_info(struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - return (void *) info->status.status_driver_data; -} - -int mt76x2_mac_start(struct mt76x2_dev *dev); -void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force); -void mt76x2_mac_resume(struct mt76x2_dev *dev); -void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr); - -int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, - void *rxi); -void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x02_txwi *txwi, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_sta *sta, int len); - -int mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 vif_idx, - struct sk_buff *skb); -void mt76x2_mac_set_beacon_enable(struct mt76x2_dev *dev, u8 vif_idx, bool val); - -void mt76x2_mac_poll_tx_status(struct mt76x2_dev *dev, bool irq); -void mt76x2_mac_process_tx_status_fifo(struct mt76x2_dev *dev); - -void mt76x2_mac_work(struct work_struct *work); - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c deleted file mode 100644 index ed4f56a3aae9..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> - * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "mt76x2.h" -#include "mt76x02_util.h" - -void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force) -{ - bool stopped = false; - u32 rts_cfg; - int i; - - mt76_wr(dev, MT_MAC_SYS_CTRL, 0); - - rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); - mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); - - /* Wait for MAC to become idle */ - for (i = 0; i < 300; i++) { - if ((mt76_rr(dev, MT_MAC_STATUS) & - (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) || - mt76_rr(dev, MT_BBP(IBI, 12))) { - udelay(1); - continue; - } - - stopped = true; - break; - } - - if (force && !stopped) { - mt76_set(dev, MT_BBP(CORE, 4), BIT(1)); - mt76_clear(dev, MT_BBP(CORE, 4), BIT(1)); - - mt76_set(dev, MT_BBP(CORE, 4), BIT(0)); - mt76_clear(dev, MT_BBP(CORE, 4), BIT(0)); - } - - mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg); -} -EXPORT_SYMBOL_GPL(mt76x2_mac_stop); - -void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x02_txwi *txwi, - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_sta *sta, int len) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rate = &info->control.rates[0]; - struct ieee80211_key_conf *key = info->control.hw_key; - u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2)); - u8 nss; - s8 txpwr_adj, max_txpwr_adj; - u8 ccmp_pn[8]; - - memset(txwi, 0, sizeof(*txwi)); - - if (wcid) - txwi->wcid = wcid->idx; - else - txwi->wcid = 0xff; - - txwi->pktid = 1; - - if (wcid && wcid->sw_iv && key) { - u64 pn = atomic64_inc_return(&key->tx_pn); - ccmp_pn[0] = pn; - ccmp_pn[1] = pn >> 8; - ccmp_pn[2] = 0; - ccmp_pn[3] = 0x20 | (key->keyidx << 6); - ccmp_pn[4] = pn >> 16; - ccmp_pn[5] = pn >> 24; - ccmp_pn[6] = pn >> 32; - ccmp_pn[7] = pn >> 40; - txwi->iv = *((__le32 *)&ccmp_pn[0]); - txwi->eiv = *((__le32 *)&ccmp_pn[1]); - } - - spin_lock_bh(&dev->mt76.lock); - if (wcid && (rate->idx < 0 || !rate->count)) { - txwi->rate = wcid->tx_rate; - max_txpwr_adj = wcid->max_txpwr_adj; - nss = wcid->tx_rate_nss; - } else { - txwi->rate = mt76x02_mac_tx_rate_val(&dev->mt76, rate, &nss); - max_txpwr_adj = mt76x2_tx_get_max_txpwr_adj(&dev->mt76, rate); - } - spin_unlock_bh(&dev->mt76.lock); - - txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, dev->mt76.txpower_conf, - max_txpwr_adj); - txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj); - - if (mt76xx_rev(dev) >= MT76XX_REV_E4) - txwi->txstream = 0x13; - else if (mt76xx_rev(dev) >= MT76XX_REV_E3 && - !(txwi->rate & cpu_to_le16(rate_ht_mask))) - txwi->txstream = 0x93; - - mt76x02_mac_fill_txwi(txwi, skb, sta, len, nss); -} -EXPORT_SYMBOL_GPL(mt76x2_mac_write_txwi); - -int mt76x2_mac_get_rssi(struct mt76x2_dev *dev, s8 rssi, int chain) -{ - struct mt76x2_rx_freq_cal *cal = &dev->cal.rx; - - rssi += cal->rssi_offset[chain]; - rssi -= cal->lna_gain; - - return rssi; -} - -static struct mt76x02_sta * -mt76x2_rx_get_sta(struct mt76x2_dev *dev, u8 idx) -{ - struct mt76_wcid *wcid; - - if (idx >= ARRAY_SIZE(dev->mt76.wcid)) - return NULL; - - wcid = rcu_dereference(dev->mt76.wcid[idx]); - if (!wcid) - return NULL; - - return container_of(wcid, struct mt76x02_sta, wcid); -} - -static struct mt76_wcid * -mt76x2_rx_get_sta_wcid(struct mt76x2_dev *dev, struct mt76x02_sta *sta, - bool unicast) -{ - if (!sta) - return NULL; - - if (unicast) - return &sta->wcid; - else - return &sta->vif->group_wcid; -} - -int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, - void *rxi) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb; - struct mt76x02_rxwi *rxwi = rxi; - struct mt76x02_sta *sta; - u32 rxinfo = le32_to_cpu(rxwi->rxinfo); - u32 ctl = le32_to_cpu(rxwi->ctl); - u16 rate = le16_to_cpu(rxwi->rate); - u16 tid_sn = le16_to_cpu(rxwi->tid_sn); - bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST); - int pad_len = 0; - u8 pn_len; - u8 wcid; - int len; - - if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) - return -EINVAL; - - if (rxinfo & MT_RXINFO_L2PAD) - pad_len += 2; - - if (rxinfo & MT_RXINFO_DECRYPT) { - status->flag |= RX_FLAG_DECRYPTED; - status->flag |= RX_FLAG_MMIC_STRIPPED; - status->flag |= RX_FLAG_MIC_STRIPPED; - status->flag |= RX_FLAG_IV_STRIPPED; - } - - wcid = FIELD_GET(MT_RXWI_CTL_WCID, ctl); - sta = mt76x2_rx_get_sta(dev, wcid); - status->wcid = mt76x2_rx_get_sta_wcid(dev, sta, unicast); - - len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl); - pn_len = FIELD_GET(MT_RXINFO_PN_LEN, rxinfo); - if (pn_len) { - int offset = ieee80211_get_hdrlen_from_skb(skb) + pad_len; - u8 *data = skb->data + offset; - - status->iv[0] = data[7]; - status->iv[1] = data[6]; - status->iv[2] = data[5]; - status->iv[3] = data[4]; - status->iv[4] = data[1]; - status->iv[5] = data[0]; - - /* - * Driver CCMP validation can't deal with fragments. - * Let mac80211 take care of it. - */ - if (rxinfo & MT_RXINFO_FRAG) { - status->flag &= ~RX_FLAG_IV_STRIPPED; - } else { - pad_len += pn_len << 2; - len -= pn_len << 2; - } - } - - mt76x02_remove_hdr_pad(skb, pad_len); - - if ((rxinfo & MT_RXINFO_BA) && !(rxinfo & MT_RXINFO_NULL)) - status->aggr = true; - - if (WARN_ON_ONCE(len > skb->len)) - return -EINVAL; - - pskb_trim(skb, len); - status->chains = BIT(0) | BIT(1); - status->chain_signal[0] = mt76x2_mac_get_rssi(dev, rxwi->rssi[0], 0); - status->chain_signal[1] = mt76x2_mac_get_rssi(dev, rxwi->rssi[1], 1); - status->signal = max(status->chain_signal[0], status->chain_signal[1]); - status->freq = dev->mt76.chandef.chan->center_freq; - status->band = dev->mt76.chandef.chan->band; - - status->tid = FIELD_GET(MT_RXWI_TID, tid_sn); - status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn); - - if (sta) { - ewma_signal_add(&sta->rssi, status->signal); - sta->inactive_count = 0; - } - - return mt76x02_mac_process_rate(status, rate); -} -EXPORT_SYMBOL_GPL(mt76x2_mac_process_rx); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c deleted file mode 100644 index 1ec3c293e2c4..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> - * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "mt76x2.h" -#include "dma.h" - -void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct mt76x2_dev *dev = hw->priv; - struct ieee80211_vif *vif = info->control.vif; - struct mt76_wcid *wcid = &dev->mt76.global_wcid; - - if (control->sta) { - struct mt76x02_sta *msta; - - msta = (struct mt76x02_sta *)control->sta->drv_priv; - wcid = &msta->wcid; - /* sw encrypted frames */ - if (!info->control.hw_key && wcid->hw_key_idx != 0xff) - control->sta = NULL; - } - - if (vif && !control->sta) { - struct mt76x02_vif *mvif; - - mvif = (struct mt76x02_vif *)vif->drv_priv; - wcid = &mvif->group_wcid; - } - - mt76_tx(&dev->mt76, control->sta, wcid, skb); -} -EXPORT_SYMBOL_GPL(mt76x2_tx); - -s8 mt76x2_tx_get_max_txpwr_adj(struct mt76_dev *mdev, - const struct ieee80211_tx_rate *rate) -{ - struct mt76x2_dev *dev = (struct mt76x2_dev *) mdev; - s8 max_txpwr; - - if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { - u8 mcs = ieee80211_rate_get_vht_mcs(rate); - - if (mcs == 8 || mcs == 9) { - max_txpwr = mdev->rate_power.vht[8]; - } else { - u8 nss, idx; - - nss = ieee80211_rate_get_vht_nss(rate); - idx = ((nss - 1) << 3) + mcs; - max_txpwr = mdev->rate_power.ht[idx & 0xf]; - } - } else if (rate->flags & IEEE80211_TX_RC_MCS) { - max_txpwr = mdev->rate_power.ht[rate->idx & 0xf]; - } else { - enum nl80211_band band = dev->mt76.chandef.chan->band; - - if (band == NL80211_BAND_2GHZ) { - const struct ieee80211_rate *r; - struct wiphy *wiphy = mt76_hw(dev)->wiphy; - struct mt76_rate_power *rp = &mdev->rate_power; - - r = &wiphy->bands[band]->bitrates[rate->idx]; - if (r->flags & IEEE80211_RATE_SHORT_PREAMBLE) - max_txpwr = rp->cck[r->hw_value & 0x3]; - else - max_txpwr = rp->ofdm[r->hw_value & 0x7]; - } else { - max_txpwr = mdev->rate_power.ofdm[rate->idx & 0x7]; - } - } - - return max_txpwr; -} -EXPORT_SYMBOL_GPL(mt76x2_tx_get_max_txpwr_adj); - -s8 mt76x2_tx_get_txpwr_adj(struct mt76x2_dev *dev, s8 txpwr, s8 max_txpwr_adj) -{ - txpwr = min_t(s8, txpwr, dev->mt76.txpower_conf); - txpwr -= (dev->target_power + dev->target_power_delta[0]); - txpwr = min_t(s8, txpwr, max_txpwr_adj); - - if (!dev->enable_tpc) - return 0; - else if (txpwr >= 0) - return min_t(s8, txpwr, 7); - else - return (txpwr < -16) ? 8 : (txpwr + 32) / 2; -} -EXPORT_SYMBOL_GPL(mt76x2_tx_get_txpwr_adj); - -void mt76x2_tx_set_txpwr_auto(struct mt76x2_dev *dev, s8 txpwr) -{ - s8 txpwr_adj; - - txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, txpwr, - dev->mt76.rate_power.ofdm[4]); - mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG, - MT_PROT_AUTO_TX_CFG_PROT_PADJ, txpwr_adj); - mt76_rmw_field(dev, MT_PROT_AUTO_TX_CFG, - MT_PROT_AUTO_TX_CFG_AUTO_PADJ, txpwr_adj); -} -EXPORT_SYMBOL_GPL(mt76x2_tx_set_txpwr_auto); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c b/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c deleted file mode 100644 index c2ccdebca470..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "mt76x2u.h" -#include "dma.h" -#include "mt76x02_util.h" -#include "mt76x02_usb.h" - -static int -mt76x2u_check_skb_rooms(struct sk_buff *skb) -{ - int hdr_len = ieee80211_get_hdrlen_from_skb(skb); - u32 need_head; - - need_head = sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN; - if (hdr_len % 4) - need_head += 2; - return skb_cow(skb, need_head); -} - -int mt76x2u_tx_prepare_skb(struct mt76_dev *mdev, void *data, - struct sk_buff *skb, struct mt76_queue *q, - struct mt76_wcid *wcid, struct ieee80211_sta *sta, - u32 *tx_info) -{ - struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76); - struct mt76x02_txwi *txwi; - int err, len = skb->len; - - err = mt76x2u_check_skb_rooms(skb); - if (err < 0) - return -ENOMEM; - - mt76x02_insert_hdr_pad(skb); - - txwi = skb_push(skb, sizeof(struct mt76x02_txwi)); - mt76x2_mac_write_txwi(dev, txwi, skb, wcid, sta, len); - - return mt76x02u_set_txinfo(skb, wcid, q2ep(q->hw_idx)); -} diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index bf0e9e666bc4..7cbce03aa65b 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -96,7 +96,8 @@ mt76_check_agg_ssn(struct mt76_txq *mtxq, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - if (!ieee80211_is_data_qos(hdr->frame_control)) + if (!ieee80211_is_data_qos(hdr->frame_control) || + !ieee80211_is_data_present(hdr->frame_control)) return; mtxq->agg_ssn = le16_to_cpu(hdr->seq_ctrl) + 0x10; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index de7785c4f6af..5f0faf07c346 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -286,7 +286,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, void *data; int offset; - data = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC); + data = page_frag_alloc(&q->rx_page, len, GFP_ATOMIC); if (!data) break; @@ -318,7 +318,7 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, if (!buf->urb) return -ENOMEM; - buf->urb->sg = devm_kzalloc(dev->dev, nsgs * sizeof(*buf->urb->sg), + buf->urb->sg = devm_kcalloc(dev->dev, nsgs, sizeof(*buf->urb->sg), gfp); if (!buf->urb->sg) return -ENOMEM; @@ -525,8 +525,8 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) spin_lock_init(&q->rx_page_lock); spin_lock_init(&q->lock); - q->entry = devm_kzalloc(dev->dev, - MT_NUM_RX_ENTRIES * sizeof(*q->entry), + q->entry = devm_kcalloc(dev->dev, + MT_NUM_RX_ENTRIES, sizeof(*q->entry), GFP_KERNEL); if (!q->entry) return -ENOMEM; @@ -755,8 +755,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) INIT_LIST_HEAD(&q->swq); q->hw_idx = mt76_ac_to_hwq(i); - q->entry = devm_kzalloc(dev->dev, - MT_NUM_TX_ENTRIES * sizeof(*q->entry), + q->entry = devm_kcalloc(dev->dev, + MT_NUM_TX_ENTRIES, sizeof(*q->entry), GFP_KERNEL); if (!q->entry) return -ENOMEM; @@ -862,6 +862,7 @@ int mt76u_init(struct mt76_dev *dev, .copy = mt76u_copy, .wr_rp = mt76u_wr_rp, .rd_rp = mt76u_rd_rp, + .type = MT76_BUS_USB, }; struct mt76_usb *usb = &dev->usb; diff --git a/drivers/net/wireless/quantenna/Kconfig b/drivers/net/wireless/quantenna/Kconfig index de84ce125c26..7628d9c1ea6a 100644 --- a/drivers/net/wireless/quantenna/Kconfig +++ b/drivers/net/wireless/quantenna/Kconfig @@ -1,7 +1,7 @@ config WLAN_VENDOR_QUANTENNA bool "Quantenna wireless cards support" default y - ---help--- + help If you have a wireless card belonging to this class, say Y. Note that the answer to this question doesn't directly affect the diff --git a/drivers/net/wireless/quantenna/qtnfmac/Kconfig b/drivers/net/wireless/quantenna/qtnfmac/Kconfig index 8d1492a90bd1..6cf5202c3666 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/Kconfig +++ b/drivers/net/wireless/quantenna/qtnfmac/Kconfig @@ -1,19 +1,20 @@ config QTNFMAC tristate - depends on QTNFMAC_PEARL_PCIE - default m if QTNFMAC_PEARL_PCIE=m - default y if QTNFMAC_PEARL_PCIE=y + depends on QTNFMAC_PCIE + default m if QTNFMAC_PCIE=m + default y if QTNFMAC_PCIE=y -config QTNFMAC_PEARL_PCIE - tristate "Quantenna QSR10g PCIe support" +config QTNFMAC_PCIE + tristate "Quantenna QSR1000/QSR2000/QSR10g PCIe support" default n depends on PCI && CFG80211 select QTNFMAC select FW_LOADER select CRC32 - ---help--- + help This option adds support for wireless adapters based on Quantenna - 802.11ac QSR10g (aka Pearl) FullMAC chipset running over PCIe. + 802.11ac QSR10g (aka Pearl) and QSR1000/QSR2000 (aka Topaz) + FullMAC chipsets running over PCIe. If you choose to build it as a module, two modules will be built: - qtnfmac.ko and qtnfmac_pearl_pcie.ko. + qtnfmac.ko and qtnfmac_pcie.ko. diff --git a/drivers/net/wireless/quantenna/qtnfmac/Makefile b/drivers/net/wireless/quantenna/qtnfmac/Makefile index 17cd7adb4109..40dffbd2ea47 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/Makefile +++ b/drivers/net/wireless/quantenna/qtnfmac/Makefile @@ -19,11 +19,12 @@ qtnfmac-objs += \ # -obj-$(CONFIG_QTNFMAC_PEARL_PCIE) += qtnfmac_pearl_pcie.o +obj-$(CONFIG_QTNFMAC_PCIE) += qtnfmac_pcie.o -qtnfmac_pearl_pcie-objs += \ +qtnfmac_pcie-objs += \ shm_ipc.o \ pcie/pcie.o \ - pcie/pearl_pcie.o + pcie/pearl_pcie.o \ + pcie/topaz_pcie.o -qtnfmac_pearl_pcie-$(CONFIG_DEBUG_FS) += debug.o +qtnfmac_pcie-$(CONFIG_DEBUG_FS) += debug.o diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 452d4b7c832d..51b33ec78fac 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -141,8 +141,8 @@ qtnf_change_virtual_intf(struct wiphy *wiphy, ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr); if (ret) { - pr_err("VIF%u.%u: failed to change VIF type: %d\n", - vif->mac->macid, vif->vifid, ret); + pr_err("VIF%u.%u: failed to change type to %d\n", + vif->mac->macid, vif->vifid, type); return ret; } @@ -216,7 +216,6 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy, eth_zero_addr(vif->mac_addr); eth_zero_addr(vif->bssid); vif->bss_priority = QTNF_DEF_BSS_PRIORITY; - vif->sta_state = QTNF_STA_DISCONNECTED; memset(&vif->wdev, 0, sizeof(vif->wdev)); vif->wdev.wiphy = wiphy; vif->wdev.iftype = type; @@ -229,18 +228,22 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy, if (params) mac_addr = params->macaddr; - if (qtnf_cmd_send_add_intf(vif, type, mac_addr)) { - pr_err("VIF%u.%u: failed to add VIF\n", mac->macid, vif->vifid); + ret = qtnf_cmd_send_add_intf(vif, type, mac_addr); + if (ret) { + pr_err("VIF%u.%u: failed to add VIF %pM\n", + mac->macid, vif->vifid, mac_addr); goto err_cmd; } if (!is_valid_ether_addr(vif->mac_addr)) { pr_err("VIF%u.%u: FW reported bad MAC: %pM\n", mac->macid, vif->vifid, vif->mac_addr); + ret = -EINVAL; goto err_mac; } - if (qtnf_core_net_attach(mac, vif, name, name_assign_t)) { + ret = qtnf_core_net_attach(mac, vif, name, name_assign_t); + if (ret) { pr_err("VIF%u.%u: failed to attach netdev\n", mac->macid, vif->vifid); goto err_net; @@ -256,7 +259,7 @@ err_mac: err_cmd: vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; - return ERR_PTR(-EFAULT); + return ERR_PTR(ret); } static int qtnf_mgmt_set_appie(struct qtnf_vif *vif, @@ -335,12 +338,11 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev) qtnf_scan_done(vif->mac, true); ret = qtnf_cmd_send_stop_ap(vif); - if (ret) { + if (ret) pr_err("VIF%u.%u: failed to stop AP operation in FW\n", vif->mac->macid, vif->vifid); - netif_carrier_off(vif->netdev); - } + netif_carrier_off(vif->netdev); return ret; } @@ -478,19 +480,31 @@ qtnf_dump_station(struct wiphy *wiphy, struct net_device *dev, const struct qtnf_sta_node *sta_node; int ret; - sta_node = qtnf_sta_list_lookup_index(&vif->sta_list, idx); + switch (vif->wdev.iftype) { + case NL80211_IFTYPE_STATION: + if (idx != 0 || !vif->wdev.current_bss) + return -ENOENT; - if (unlikely(!sta_node)) - return -ENOENT; + ether_addr_copy(mac, vif->bssid); + break; + case NL80211_IFTYPE_AP: + sta_node = qtnf_sta_list_lookup_index(&vif->sta_list, idx); + if (unlikely(!sta_node)) + return -ENOENT; - ether_addr_copy(mac, sta_node->mac_addr); + ether_addr_copy(mac, sta_node->mac_addr); + break; + default: + return -ENOTSUPP; + } - ret = qtnf_cmd_get_sta_info(vif, sta_node->mac_addr, sinfo); + ret = qtnf_cmd_get_sta_info(vif, mac, sinfo); - if (unlikely(ret == -ENOENT)) { - qtnf_sta_list_del(vif, mac); - cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL); - sinfo->filled = 0; + if (vif->wdev.iftype == NL80211_IFTYPE_AP) { + if (ret == -ENOENT) { + cfg80211_del_sta(vif->netdev, mac, GFP_KERNEL); + sinfo->filled = 0; + } } sinfo->generation = vif->generation; @@ -521,9 +535,16 @@ static int qtnf_del_key(struct wiphy *wiphy, struct net_device *dev, int ret; ret = qtnf_cmd_send_del_key(vif, key_index, pairwise, mac_addr); - if (ret) - pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n", - vif->mac->macid, vif->vifid, key_index, pairwise); + if (ret) { + if (ret == -ENOENT) { + pr_debug("VIF%u.%u: key index %d out of bounds\n", + vif->mac->macid, vif->vifid, key_index); + } else { + pr_err("VIF%u.%u: failed to delete key: idx=%u pw=%u\n", + vif->mac->macid, vif->vifid, + key_index, pairwise); + } + } return ret; } @@ -590,6 +611,7 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device *dev, if (ret) pr_err("VIF%u.%u: failed to delete STA %pM\n", vif->mac->macid, vif->vifid, params->mac); + return ret; } @@ -597,21 +619,25 @@ static int qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { struct qtnf_wmac *mac = wiphy_priv(wiphy); + int ret; cancel_delayed_work_sync(&mac->scan_timeout); mac->scan_req = request; - if (qtnf_cmd_send_scan(mac)) { + ret = qtnf_cmd_send_scan(mac); + if (ret) { pr_err("MAC%u: failed to start scan\n", mac->macid); mac->scan_req = NULL; - return -EFAULT; + goto out; } + pr_debug("MAC%u: scan started\n", mac->macid); queue_delayed_work(mac->bus->workqueue, &mac->scan_timeout, QTNF_SCAN_TIMEOUT_SEC * HZ); - return 0; +out: + return ret; } static int @@ -624,9 +650,6 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev, if (vif->wdev.iftype != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; - if (vif->sta_state != QTNF_STA_DISCONNECTED) - return -EBUSY; - if (sme->bssid) ether_addr_copy(vif->bssid, sme->bssid); else @@ -634,13 +657,13 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev, ret = qtnf_cmd_send_connect(vif, sme); if (ret) { - pr_err("VIF%u.%u: failed to connect\n", vif->mac->macid, - vif->vifid); - return ret; + pr_err("VIF%u.%u: failed to connect\n", + vif->mac->macid, vif->vifid); + goto out; } - vif->sta_state = QTNF_STA_CONNECTING; - return 0; +out: + return ret; } static int @@ -662,22 +685,18 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev, goto out; } - qtnf_scan_done(mac, true); - - if (vif->sta_state == QTNF_STA_DISCONNECTED) - goto out; - ret = qtnf_cmd_send_disconnect(vif, reason_code); - if (ret) { - pr_err("VIF%u.%u: failed to disconnect\n", mac->macid, - vif->vifid); - goto out; + if (ret) + pr_err("VIF%u.%u: failed to disconnect\n", + mac->macid, vif->vifid); + + if (vif->wdev.current_bss) { + netif_carrier_off(vif->netdev); + cfg80211_disconnected(vif->netdev, reason_code, + NULL, 0, true, GFP_KERNEL); } out: - if (vif->sta_state == QTNF_STA_CONNECTING) - vif->sta_state = QTNF_STA_DISCONNECTED; - return ret; } @@ -747,7 +766,6 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, default: pr_debug("failed to get chan(%d) stats from card\n", chan->hw_value); - ret = -EINVAL; break; } @@ -770,6 +788,7 @@ qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, ret = qtnf_cmd_get_channel(vif, chandef); if (ret) { pr_err("%s: failed to get channel: %d\n", ndev->name, ret); + ret = -ENODATA; goto out; } @@ -779,6 +798,7 @@ qtnf_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, chandef->center_freq1, chandef->center_freq2, chandef->width); ret = -ENODATA; + goto out; } out: @@ -848,10 +868,8 @@ static int qtnf_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, ret = qtnf_cmd_send_pm_set(vif, enabled ? QLINK_PM_AUTO_STANDBY : QLINK_PM_OFF, timeout); - if (ret) { + if (ret) pr_err("%s: failed to set PM mode ret=%d\n", dev->name, ret); - return ret; - } return ret; } @@ -971,9 +989,16 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in, ret = qtnf_cmd_reg_notify(bus, req); if (ret) { - if (ret != -EOPNOTSUPP && ret != -EALREADY) + if (ret == -EOPNOTSUPP) { + pr_warn("reg update not supported\n"); + } else if (ret == -EALREADY) { + pr_info("regulatory domain is already set to %c%c", + req->alpha2[0], req->alpha2[1]); + } else { pr_err("failed to update reg domain to %c%c\n", req->alpha2[0], req->alpha2[1]); + } + return; } @@ -1088,6 +1113,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD); + if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_DWELL) + wiphy_ext_feature_set(wiphy, + NL80211_EXT_FEATURE_SET_SCAN_DWELL); + wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2; @@ -1106,6 +1135,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR) wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; + if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN)) + wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN; + #ifdef CONFIG_PM if (macinfo->wowlan) wiphy->wowlan = macinfo->wowlan; @@ -1120,6 +1152,15 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; } + if (mac->macinfo.extended_capabilities_len) { + wiphy->extended_capabilities = + mac->macinfo.extended_capabilities; + wiphy->extended_capabilities_mask = + mac->macinfo.extended_capabilities_mask; + wiphy->extended_capabilities_len = + mac->macinfo.extended_capabilities_len; + } + strlcpy(wiphy->fw_version, hw_info->fw_version, sizeof(wiphy->fw_version)); wiphy->hw_version = hw_info->hw_version; @@ -1143,7 +1184,8 @@ void qtnf_netdev_updown(struct net_device *ndev, bool up) struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev); if (qtnf_cmd_send_updown_intf(vif, up)) - pr_err("failed to send up/down command to FW\n"); + pr_err("failed to send %s command to VIF%u.%u\n", + up ? "UP" : "DOWN", vif->mac->macid, vif->vifid); } void qtnf_virtual_intf_cleanup(struct net_device *ndev) @@ -1151,57 +1193,20 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev) struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev); struct qtnf_wmac *mac = wiphy_priv(vif->wdev.wiphy); - if (vif->wdev.iftype == NL80211_IFTYPE_STATION) { - switch (vif->sta_state) { - case QTNF_STA_DISCONNECTED: - break; - case QTNF_STA_CONNECTING: - cfg80211_connect_result(vif->netdev, - vif->bssid, NULL, 0, - NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); - qtnf_disconnect(vif->wdev.wiphy, ndev, - WLAN_REASON_DEAUTH_LEAVING); - break; - case QTNF_STA_CONNECTED: - cfg80211_disconnected(vif->netdev, - WLAN_REASON_DEAUTH_LEAVING, - NULL, 0, 1, GFP_KERNEL); - qtnf_disconnect(vif->wdev.wiphy, ndev, - WLAN_REASON_DEAUTH_LEAVING); - break; - } - - vif->sta_state = QTNF_STA_DISCONNECTED; - } + if (vif->wdev.iftype == NL80211_IFTYPE_STATION) + qtnf_disconnect(vif->wdev.wiphy, ndev, + WLAN_REASON_DEAUTH_LEAVING); qtnf_scan_done(mac, true); } void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif) { - if (vif->wdev.iftype == NL80211_IFTYPE_STATION) { - switch (vif->sta_state) { - case QTNF_STA_CONNECTING: - cfg80211_connect_result(vif->netdev, - vif->bssid, NULL, 0, - NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); - break; - case QTNF_STA_CONNECTED: - cfg80211_disconnected(vif->netdev, - WLAN_REASON_DEAUTH_LEAVING, - NULL, 0, 1, GFP_KERNEL); - break; - case QTNF_STA_DISCONNECTED: - break; - } - } + if (vif->wdev.iftype == NL80211_IFTYPE_STATION) + cfg80211_disconnected(vif->netdev, WLAN_REASON_DEAUTH_LEAVING, + NULL, 0, 1, GFP_KERNEL); cfg80211_shutdown_all_interfaces(vif->wdev.wiphy); - vif->sta_state = QTNF_STA_DISCONNECTED; } void qtnf_band_init_rates(struct ieee80211_supported_band *band) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index ae9e77300533..659e7649fe22 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -80,15 +80,15 @@ static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result qcode) static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus, struct sk_buff *cmd_skb, struct sk_buff **response_skb, - u16 *result_code, size_t const_resp_size, size_t *var_resp_size) { struct qlink_cmd *cmd; - const struct qlink_resp *resp; + struct qlink_resp *resp = NULL; struct sk_buff *resp_skb = NULL; u16 cmd_id; - u8 mac_id, vif_id; + u8 mac_id; + u8 vif_id; int ret; cmd = (struct qlink_cmd *)cmd_skb->data; @@ -97,8 +97,11 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus, vif_id = cmd->vifid; cmd->mhdr.len = cpu_to_le16(cmd_skb->len); - if (unlikely(bus->fw_state != QTNF_FW_STATE_ACTIVE && - le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT)) { + pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, + le16_to_cpu(cmd->cmd_id)); + + if (bus->fw_state != QTNF_FW_STATE_ACTIVE && + le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT) { pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n", mac_id, vif_id, le16_to_cpu(cmd->cmd_id), bus->fw_state); @@ -106,24 +109,21 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus, return -ENODEV; } - pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, - le16_to_cpu(cmd->cmd_id)); - ret = qtnf_trans_send_cmd_with_resp(bus, cmd_skb, &resp_skb); + if (ret) + goto out; - if (unlikely(ret)) + if (WARN_ON(!resp_skb || !resp_skb->data)) { + ret = -EFAULT; goto out; + } - resp = (const struct qlink_resp *)resp_skb->data; + resp = (struct qlink_resp *)resp_skb->data; ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id, const_resp_size); - - if (unlikely(ret)) + if (ret) goto out; - if (likely(result_code)) - *result_code = le16_to_cpu(resp->result); - /* Return length of variable part of response */ if (response_skb && var_resp_size) *var_resp_size = le16_to_cpu(resp->mhdr.len) - const_resp_size; @@ -134,14 +134,18 @@ out: else consume_skb(resp_skb); + if (!ret && resp) + return qtnf_cmd_resp_result_decode(le16_to_cpu(resp->result)); + + pr_warn("VIF%u.%u: cmd 0x%.4X failed: %d\n", + mac_id, vif_id, le16_to_cpu(cmd->cmd_id), ret); + return ret; } -static inline int qtnf_cmd_send(struct qtnf_bus *bus, - struct sk_buff *cmd_skb, - u16 *result_code) +static inline int qtnf_cmd_send(struct qtnf_bus *bus, struct sk_buff *cmd_skb) { - return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL, result_code, + return qtnf_cmd_send_with_reply(bus, cmd_skb, NULL, sizeof(struct qlink_resp), NULL); } @@ -228,7 +232,6 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, struct sk_buff *cmd_skb; struct qlink_cmd_start_ap *cmd; struct qlink_auth_encr *aen; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; int i; @@ -329,30 +332,21 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, } qtnf_bus_lock(vif->mac->bus); - - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } netif_carrier_on(vif->netdev); out: qtnf_bus_unlock(vif->mac->bus); + return ret; } int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif) { struct sk_buff *cmd_skb; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -362,23 +356,13 @@ int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif) return -ENOMEM; qtnf_bus_lock(vif->mac->bus); - - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } - - netif_carrier_off(vif->netdev); out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -386,7 +370,6 @@ int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg) { struct sk_buff *cmd_skb; struct qlink_cmd_mgmt_frame_register *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -401,20 +384,13 @@ int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg) cmd->frame_type = cpu_to_le16(frame_type); cmd->do_register = reg; - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -423,7 +399,6 @@ int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, { struct sk_buff *cmd_skb; struct qlink_cmd_mgmt_frame_tx *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) { @@ -448,20 +423,13 @@ int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags, if (len && buf) qtnf_cmd_skb_put_buffer(cmd_skb, buf, len); - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -469,7 +437,6 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type, const u8 *buf, size_t len) { struct sk_buff *cmd_skb; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; if (len > QTNF_MAX_CMD_BUF_SIZE) { @@ -487,21 +454,13 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type, qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len); qtnf_bus_lock(vif->mac->bus); - - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u frame %u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, frame_type, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -544,6 +503,9 @@ qtnf_sta_info_parse_rate(struct rate_info *rate_dst, rate_dst->flags |= RATE_INFO_FLAGS_MCS; else if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_VHT_MCS) rate_dst->flags |= RATE_INFO_FLAGS_VHT_MCS; + + if (rate_src->flags & QLINK_STA_INFO_RATE_FLAG_SHORT_GI) + rate_dst->flags |= RATE_INFO_FLAGS_SHORT_GI; } static void @@ -729,8 +691,7 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac, struct sk_buff *cmd_skb, *resp_skb = NULL; struct qlink_cmd_get_sta_info *cmd; const struct qlink_resp_get_sta_info *resp; - size_t var_resp_len; - u16 res_code = QLINK_CMD_RESULT_OK; + size_t var_resp_len = 0; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -745,31 +706,13 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac, ether_addr_copy(cmd->sta_addr, sta_mac); ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb, - &res_code, sizeof(*resp), - &var_resp_len); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - switch (res_code) { - case QLINK_CMD_RESULT_ENOTFOUND: - pr_warn("VIF%u.%u: %pM STA not found\n", - vif->mac->macid, vif->vifid, sta_mac); - ret = -ENOENT; - break; - default: - pr_err("VIF%u.%u: can't get info for %pM: %u\n", - vif->mac->macid, vif->vifid, sta_mac, res_code); - ret = -EFAULT; - break; - } + sizeof(*resp), &var_resp_len); + if (ret) goto out; - } resp = (const struct qlink_resp_get_sta_info *)resp_skb->data; - if (unlikely(!ether_addr_equal(sta_mac, resp->sta_addr))) { + if (!ether_addr_equal(sta_mac, resp->sta_addr)) { pr_err("VIF%u.%u: wrong mac in reply: %pM != %pM\n", vif->mac->macid, vif->vifid, resp->sta_addr, sta_mac); ret = -EINVAL; @@ -795,7 +738,6 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif, struct sk_buff *cmd_skb, *resp_skb = NULL; struct qlink_cmd_manage_intf *cmd; const struct qlink_resp_manage_intf *resp; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -828,17 +770,9 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif, eth_zero_addr(cmd->intf_info.mac_addr); ret = qtnf_cmd_send_with_reply(vif->mac->bus, cmd_skb, &resp_skb, - &res_code, sizeof(*resp), NULL); - - if (unlikely(ret)) - goto out; - - ret = qtnf_cmd_resp_result_decode(res_code); - if (ret) { - pr_err("VIF%u.%u: CMD %d failed: %u\n", vif->mac->macid, - vif->vifid, cmd_type, res_code); + sizeof(*resp), NULL); + if (ret) goto out; - } resp = (const struct qlink_resp_manage_intf *)resp_skb->data; ether_addr_copy(vif->mac_addr, resp->intf_info.mac_addr); @@ -868,7 +802,6 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif) { struct sk_buff *cmd_skb; struct qlink_cmd_manage_intf *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -897,17 +830,9 @@ int qtnf_cmd_send_del_intf(struct qtnf_vif *vif) eth_zero_addr(cmd->intf_info.mac_addr); - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); @@ -1353,8 +1278,7 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, ext_capa_mask = NULL; } - kfree(mac->macinfo.extended_capabilities); - kfree(mac->macinfo.extended_capabilities_mask); + qtnf_mac_ext_caps_free(mac); mac->macinfo.extended_capabilities = ext_capa; mac->macinfo.extended_capabilities_mask = ext_capa_mask; mac->macinfo.extended_capabilities_len = ext_capa_len; @@ -1731,8 +1655,7 @@ int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac) { struct sk_buff *cmd_skb, *resp_skb = NULL; const struct qlink_resp_get_mac_info *resp; - size_t var_data_len; - u16 res_code = QLINK_CMD_RESULT_OK; + size_t var_data_len = 0; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD, @@ -1742,17 +1665,10 @@ int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac) return -ENOMEM; qtnf_bus_lock(mac->bus); - - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code, + ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, sizeof(*resp), &var_data_len); - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); - ret = -EFAULT; + if (ret) goto out; - } resp = (const struct qlink_resp_get_mac_info *)resp_skb->data; qtnf_cmd_resp_proc_mac_info(mac, resp); @@ -1769,9 +1685,8 @@ int qtnf_cmd_get_hw_info(struct qtnf_bus *bus) { struct sk_buff *cmd_skb, *resp_skb = NULL; const struct qlink_resp_get_hw_info *resp; - u16 res_code = QLINK_CMD_RESULT_OK; + size_t info_len = 0; int ret = 0; - size_t info_len; cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD, QLINK_CMD_GET_HW_INFO, @@ -1780,18 +1695,10 @@ int qtnf_cmd_get_hw_info(struct qtnf_bus *bus) return -ENOMEM; qtnf_bus_lock(bus); - - ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code, + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, sizeof(*resp), &info_len); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("cmd exec failed: 0x%.4X\n", res_code); - ret = -EFAULT; + if (ret) goto out; - } resp = (const struct qlink_resp_get_hw_info *)resp_skb->data; ret = qtnf_cmd_resp_proc_hw_info(bus, resp, info_len); @@ -1807,10 +1714,9 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac, struct ieee80211_supported_band *band) { struct sk_buff *cmd_skb, *resp_skb = NULL; - size_t info_len; struct qlink_cmd_band_info_get *cmd; struct qlink_resp_band_info_get *resp; - u16 res_code = QLINK_CMD_RESULT_OK; + size_t info_len = 0; int ret = 0; u8 qband; @@ -1838,18 +1744,10 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac, cmd->band = qband; qtnf_bus_lock(mac->bus); - - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code, + ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, sizeof(*resp), &info_len); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); - ret = -EFAULT; + if (ret) goto out; - } resp = (struct qlink_resp_band_info_get *)resp_skb->data; if (resp->band != qband) { @@ -1871,9 +1769,8 @@ out: int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac) { struct sk_buff *cmd_skb, *resp_skb = NULL; - size_t response_size; struct qlink_resp_phy_params *resp; - u16 res_code = QLINK_CMD_RESULT_OK; + size_t response_size = 0; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, @@ -1883,18 +1780,10 @@ int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac) return -ENOMEM; qtnf_bus_lock(mac->bus); - - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code, + ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, sizeof(*resp), &response_size); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); - ret = -EFAULT; + if (ret) goto out; - } resp = (struct qlink_resp_phy_params *)resp_skb->data; ret = qtnf_cmd_resp_proc_phy_params(mac, resp->info, response_size); @@ -1910,7 +1799,6 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) { struct wiphy *wiphy = priv_to_wiphy(mac); struct sk_buff *cmd_skb; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, @@ -1931,26 +1819,19 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS, wiphy->coverage_class); - ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(mac->bus); + return ret; } int qtnf_cmd_send_init_fw(struct qtnf_bus *bus) { struct sk_buff *cmd_skb; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD, @@ -1960,20 +1841,13 @@ int qtnf_cmd_send_init_fw(struct qtnf_bus *bus) return -ENOMEM; qtnf_bus_lock(bus); - - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("cmd exec failed: 0x%.4X\n", res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(bus); + return ret; } @@ -1988,9 +1862,7 @@ void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus) return; qtnf_bus_lock(bus); - - qtnf_cmd_send(bus, cmd_skb, NULL); - + qtnf_cmd_send(bus, cmd_skb); qtnf_bus_unlock(bus); } @@ -1999,7 +1871,6 @@ int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise, { struct sk_buff *cmd_skb; struct qlink_cmd_add_key *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2031,19 +1902,13 @@ int qtnf_cmd_send_add_key(struct qtnf_vif *vif, u8 key_index, bool pairwise, params->seq, params->seq_len); - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", - vif->mac->macid, vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -2052,7 +1917,6 @@ int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise, { struct sk_buff *cmd_skb; struct qlink_cmd_del_key *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2072,19 +1936,14 @@ int qtnf_cmd_send_del_key(struct qtnf_vif *vif, u8 key_index, bool pairwise, cmd->key_index = key_index; cmd->pairwise = pairwise; - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - if (unlikely(ret)) - goto out; - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", - vif->mac->macid, vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -2093,7 +1952,6 @@ int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index, { struct sk_buff *cmd_skb; struct qlink_cmd_set_def_key *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2108,19 +1966,14 @@ int qtnf_cmd_send_set_default_key(struct qtnf_vif *vif, u8 key_index, cmd->key_index = key_index; cmd->unicast = unicast; cmd->multicast = multicast; - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - if (unlikely(ret)) - goto out; - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -2128,7 +1981,6 @@ int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index) { struct sk_buff *cmd_skb; struct qlink_cmd_set_def_mgmt_key *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2141,19 +1993,14 @@ int qtnf_cmd_send_set_default_mgmt_key(struct qtnf_vif *vif, u8 key_index) cmd = (struct qlink_cmd_set_def_mgmt_key *)cmd_skb->data; cmd->key_index = key_index; - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - if (unlikely(ret)) - goto out; - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -2183,7 +2030,6 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac, { struct sk_buff *cmd_skb; struct qlink_cmd_change_sta *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2214,19 +2060,13 @@ int qtnf_cmd_send_change_sta(struct qtnf_vif *vif, const u8 *mac, goto out; } - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -2235,7 +2075,6 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif, { struct sk_buff *cmd_skb; struct qlink_cmd_del_sta *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2256,19 +2095,13 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif, cmd->subtype = params->subtype; cmd->reason_code = cpu_to_le16(params->reason_code); - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -2312,7 +2145,6 @@ static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb, int qtnf_cmd_send_scan(struct qtnf_wmac *mac) { struct sk_buff *cmd_skb; - u16 res_code = QLINK_CMD_RESULT_OK; struct ieee80211_channel *sc; struct cfg80211_scan_request *scan_req = mac->scan_req; int n_channels; @@ -2370,20 +2202,28 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac) scan_req->mac_addr_mask); } - ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code); + if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) { + pr_debug("MAC%u: flush cache before scan\n", mac->macid); - if (unlikely(ret)) - goto out; + qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH); + } - pr_debug("MAC%u: scan started\n", mac->macid); + if (scan_req->duration) { + pr_debug("MAC%u: %s scan duration %u\n", mac->macid, + scan_req->duration_mandatory ? "mandatory" : "max", + scan_req->duration); - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("MAC%u: CMD failed: %u\n", mac->macid, res_code); - ret = -EFAULT; - goto out; + qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_SCAN_DWELL, + scan_req->duration); } + + ret = qtnf_cmd_send(mac->bus, cmd_skb); + if (ret) + goto out; + out: qtnf_bus_unlock(mac->bus); + return ret; } @@ -2393,7 +2233,6 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, struct sk_buff *cmd_skb; struct qlink_cmd_connect *cmd; struct qlink_auth_encr *aen; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; int i; u32 connect_flags = 0; @@ -2474,20 +2313,13 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel); qtnf_bus_lock(vif->mac->bus); - - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; - goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -2495,7 +2327,6 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code) { struct sk_buff *cmd_skb; struct qlink_cmd_disconnect *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2509,19 +2340,13 @@ int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code) cmd = (struct qlink_cmd_disconnect *)cmd_skb->data; cmd->reason = cpu_to_le16(reason_code); - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; - goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -2529,7 +2354,6 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up) { struct sk_buff *cmd_skb; struct qlink_cmd_updown *cmd; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2542,20 +2366,13 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up) cmd->if_up = !!up; qtnf_bus_lock(vif->mac->bus); - - ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) goto out; - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, - vif->vifid, res_code); - ret = -EFAULT; - goto out; - } out: qtnf_bus_unlock(vif->mac->bus); + return ret; } @@ -2563,7 +2380,6 @@ int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req) { struct sk_buff *cmd_skb; int ret; - u16 res_code; struct qlink_cmd_reg_notify *cmd; cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD, @@ -2604,29 +2420,10 @@ int qtnf_cmd_reg_notify(struct qtnf_bus *bus, struct regulatory_request *req) } qtnf_bus_lock(bus); - - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); + ret = qtnf_cmd_send(bus, cmd_skb); if (ret) goto out; - switch (res_code) { - case QLINK_CMD_RESULT_ENOTSUPP: - pr_warn("reg update not supported\n"); - ret = -EOPNOTSUPP; - break; - case QLINK_CMD_RESULT_EALREADY: - pr_info("regulatory domain is already set to %c%c", - req->alpha2[0], req->alpha2[1]); - ret = -EALREADY; - break; - case QLINK_CMD_RESULT_OK: - ret = 0; - break; - default: - ret = -EFAULT; - break; - } - out: qtnf_bus_unlock(bus); @@ -2639,8 +2436,7 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, struct sk_buff *cmd_skb, *resp_skb = NULL; struct qlink_cmd_get_chan_stats *cmd; struct qlink_resp_get_chan_stats *resp; - size_t var_data_len; - u16 res_code = QLINK_CMD_RESULT_OK; + size_t var_data_len = 0; int ret = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD, @@ -2654,25 +2450,10 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, cmd = (struct qlink_cmd_get_chan_stats *)cmd_skb->data; cmd->channel = cpu_to_le16(channel); - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, &res_code, + ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, sizeof(*resp), &var_data_len); - if (unlikely(ret)) { - qtnf_bus_unlock(mac->bus); - return ret; - } - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - switch (res_code) { - case QLINK_CMD_RESULT_ENOTFOUND: - ret = -ENOENT; - break; - default: - pr_err("cmd exec failed: 0x%.4X\n", res_code); - ret = -EFAULT; - break; - } + if (ret) goto out; - } resp = (struct qlink_resp_get_chan_stats *)resp_skb->data; ret = qtnf_cmd_resp_proc_chan_stat_info(stats, resp->info, @@ -2681,6 +2462,7 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, out: qtnf_bus_unlock(mac->bus); consume_skb(resp_skb); + return ret; } @@ -2690,7 +2472,6 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, struct qtnf_wmac *mac = vif->mac; struct qlink_cmd_chan_switch *cmd; struct sk_buff *cmd_skb; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid, @@ -2707,32 +2488,13 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, cmd->block_tx = params->block_tx; cmd->beacon_count = params->count; - ret = qtnf_cmd_send(mac->bus, cmd_skb, &res_code); - - if (unlikely(ret)) + ret = qtnf_cmd_send(mac->bus, cmd_skb); + if (ret) goto out; - switch (res_code) { - case QLINK_CMD_RESULT_OK: - ret = 0; - break; - case QLINK_CMD_RESULT_ENOTFOUND: - ret = -ENOENT; - break; - case QLINK_CMD_RESULT_ENOTSUPP: - ret = -EOPNOTSUPP; - break; - case QLINK_CMD_RESULT_EALREADY: - ret = -EALREADY; - break; - case QLINK_CMD_RESULT_INVALID: - default: - ret = -EFAULT; - break; - } - out: qtnf_bus_unlock(mac->bus); + return ret; } @@ -2742,7 +2504,6 @@ int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef) const struct qlink_resp_channel_get *resp; struct sk_buff *cmd_skb; struct sk_buff *resp_skb = NULL; - u16 res_code = QLINK_CMD_RESULT_OK; int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2752,25 +2513,18 @@ int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef) return -ENOMEM; qtnf_bus_lock(bus); - - ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, &res_code, + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, sizeof(*resp), NULL); - - qtnf_bus_unlock(bus); - - if (unlikely(ret)) - goto out; - - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - ret = -ENODATA; + if (ret) goto out; - } resp = (const struct qlink_resp_channel_get *)resp_skb->data; qlink_chandef_q2cfg(priv_to_wiphy(vif->mac), &resp->chan, chdef); out: + qtnf_bus_unlock(bus); consume_skb(resp_skb); + return ret; } @@ -2782,7 +2536,6 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif, struct sk_buff *cmd_skb; struct qlink_cmd_start_cac *cmd; int ret; - u16 res_code; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, QLINK_CMD_START_CAC, @@ -2795,19 +2548,12 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif, qlink_chandef_cfg2q(chdef, &cmd->chan); qtnf_bus_lock(bus); - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); - qtnf_bus_unlock(bus); - + ret = qtnf_cmd_send(bus, cmd_skb); if (ret) - return ret; + goto out; - switch (res_code) { - case QLINK_CMD_RESULT_OK: - break; - default: - ret = -EOPNOTSUPP; - break; - } +out: + qtnf_bus_unlock(bus); return ret; } @@ -2819,7 +2565,6 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif, struct sk_buff *cmd_skb; struct qlink_tlv_hdr *tlv; size_t acl_size = qtnf_cmd_acl_data_size(params); - u16 res_code; int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2834,22 +2579,12 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif, qlink_acl_data_cfg2q(params, (struct qlink_acl_data *)tlv->val); qtnf_bus_lock(bus); - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); - qtnf_bus_unlock(bus); - - if (unlikely(ret)) - return ret; + ret = qtnf_cmd_send(bus, cmd_skb); + if (ret) + goto out; - switch (res_code) { - case QLINK_CMD_RESULT_OK: - break; - case QLINK_CMD_RESULT_INVALID: - ret = -EINVAL; - break; - default: - ret = -EOPNOTSUPP; - break; - } +out: + qtnf_bus_unlock(bus); return ret; } @@ -2858,7 +2593,6 @@ int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 pm_mode, int timeout) { struct qtnf_bus *bus = vif->mac->bus; struct sk_buff *cmd_skb; - u16 res_code = QLINK_CMD_RESULT_OK; struct qlink_cmd_pm_set *cmd; int ret = 0; @@ -2873,18 +2607,13 @@ int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 pm_mode, int timeout) qtnf_bus_lock(bus); - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); - - if (unlikely(ret)) + ret = qtnf_cmd_send(bus, cmd_skb); + if (ret) goto out; - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("cmd exec failed: 0x%.4X\n", res_code); - ret = -EFAULT; - } - out: qtnf_bus_unlock(bus); + return ret; } @@ -2893,7 +2622,6 @@ int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif, { struct qtnf_bus *bus = vif->mac->bus; struct sk_buff *cmd_skb; - u16 res_code = QLINK_CMD_RESULT_OK; struct qlink_cmd_wowlan_set *cmd; u32 triggers = 0; int count = 0; @@ -2929,16 +2657,10 @@ int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif, cmd->triggers = cpu_to_le32(triggers); - ret = qtnf_cmd_send(bus, cmd_skb, &res_code); - - if (unlikely(ret)) + ret = qtnf_cmd_send(bus, cmd_skb); + if (ret) goto out; - if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { - pr_err("cmd exec failed: 0x%.4X\n", res_code); - ret = -EFAULT; - } - out: qtnf_bus_unlock(bus); return ret; diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 19abbc4e23e0..5d18a4a917c9 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -304,6 +304,19 @@ void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac) } } +void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac) +{ + if (mac->macinfo.extended_capabilities_len) { + kfree(mac->macinfo.extended_capabilities); + mac->macinfo.extended_capabilities = NULL; + + kfree(mac->macinfo.extended_capabilities_mask); + mac->macinfo.extended_capabilities_mask = NULL; + + mac->macinfo.extended_capabilities_len = 0; + } +} + static void qtnf_vif_reset_handler(struct work_struct *work) { struct qtnf_vif *vif = container_of(work, struct qtnf_vif, reset_work); @@ -370,6 +383,7 @@ static void qtnf_mac_scan_timeout(struct work_struct *work) static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus, unsigned int macid) { + struct qtnf_vif *vif; struct wiphy *wiphy; struct qtnf_wmac *mac; unsigned int i; @@ -382,18 +396,20 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus, mac->macid = macid; mac->bus = bus; + mutex_init(&mac->mac_lock); + INIT_DELAYED_WORK(&mac->scan_timeout, qtnf_mac_scan_timeout); for (i = 0; i < QTNF_MAX_INTF; i++) { - memset(&mac->iflist[i], 0, sizeof(struct qtnf_vif)); - mac->iflist[i].wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; - mac->iflist[i].mac = mac; - mac->iflist[i].vifid = i; - qtnf_sta_list_init(&mac->iflist[i].sta_list); - mutex_init(&mac->mac_lock); - INIT_DELAYED_WORK(&mac->scan_timeout, qtnf_mac_scan_timeout); - mac->iflist[i].stats64 = - netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); - if (!mac->iflist[i].stats64) + vif = &mac->iflist[i]; + + memset(vif, 0, sizeof(*vif)); + vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; + vif->mac = mac; + vif->vifid = i; + qtnf_sta_list_init(&vif->sta_list); + + vif->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!vif->stats64) pr_warn("VIF%u.%u: per cpu stats allocation failed\n", macid, i); } @@ -493,8 +509,7 @@ static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid) } qtnf_mac_iface_comb_free(mac); - kfree(mac->macinfo.extended_capabilities); - kfree(mac->macinfo.extended_capabilities_mask); + qtnf_mac_ext_caps_free(mac); kfree(mac->macinfo.wowlan); wiphy_free(wiphy); bus->mac[macid] = NULL; diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index a1e338a1f055..293055049caa 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -64,12 +64,6 @@ struct qtnf_sta_list { atomic_t size; }; -enum qtnf_sta_state { - QTNF_STA_DISCONNECTED, - QTNF_STA_CONNECTING, - QTNF_STA_CONNECTED -}; - struct qtnf_vif { struct wireless_dev wdev; u8 bssid[ETH_ALEN]; @@ -77,7 +71,6 @@ struct qtnf_vif { u8 vifid; u8 bss_priority; u8 bss_status; - enum qtnf_sta_state sta_state; u16 mgmt_frames_bitmask; struct net_device *netdev; struct qtnf_wmac *mac; @@ -151,6 +144,7 @@ struct qtnf_hw_info { struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac); struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac); void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac); +void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac); struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus); int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv, const char *name, unsigned char name_assign_type); diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 68da81bec4e9..8b542b431b75 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -171,24 +171,14 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, return -EPROTO; } - if (vif->sta_state != QTNF_STA_CONNECTING) { - pr_err("VIF%u.%u: BSS_JOIN event when STA is not connecting\n", - vif->mac->macid, vif->vifid); - return -EPROTO; - } - pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid, join_info->bssid); cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL, 0, le16_to_cpu(join_info->status), GFP_KERNEL); - if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) { - vif->sta_state = QTNF_STA_CONNECTED; + if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) netif_carrier_on(vif->netdev); - } else { - vif->sta_state = QTNF_STA_DISCONNECTED; - } return 0; } @@ -211,16 +201,10 @@ qtnf_event_handle_bss_leave(struct qtnf_vif *vif, return -EPROTO; } - if (vif->sta_state != QTNF_STA_CONNECTED) - pr_warn("VIF%u.%u: BSS_LEAVE event when STA is not connected\n", - vif->mac->macid, vif->vifid); - pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid); cfg80211_disconnected(vif->netdev, le16_to_cpu(leave_info->reason), NULL, 0, 0, GFP_KERNEL); - - vif->sta_state = QTNF_STA_DISCONNECTED; netif_carrier_off(vif->netdev); return 0; diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c index d1637f2354a6..c3a32effa6f0 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* Copyright (c) 2018 Quantenna Communications, Inc. All rights reserved. */ +#include <linux/module.h> #include <linux/printk.h> #include <linux/pci.h> #include <linux/spinlock.h> @@ -15,14 +16,37 @@ #include "shm_ipc.h" #include "core.h" #include "debug.h" - -#undef pr_fmt -#define pr_fmt(fmt) "qtnf_pcie: %s: " fmt, __func__ +#include "util.h" +#include "qtn_hw_ids.h" #define QTN_SYSCTL_BAR 0 #define QTN_SHMEM_BAR 2 #define QTN_DMA_BAR 3 +#define QTN_PCIE_MAX_FW_BUFSZ (1 * 1024 * 1024) + +static bool use_msi = true; +module_param(use_msi, bool, 0644); +MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt"); + +static unsigned int tx_bd_size_param; +module_param(tx_bd_size_param, uint, 0644); +MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size"); + +static unsigned int rx_bd_size_param = 256; +module_param(rx_bd_size_param, uint, 0644); +MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size"); + +static u8 flashboot = 1; +module_param(flashboot, byte, 0644); +MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS"); + +static unsigned int fw_blksize_param = QTN_PCIE_MAX_FW_BUFSZ; +module_param(fw_blksize_param, uint, 0644); +MODULE_PARM_DESC(fw_blksize_param, "firmware loading block size in bytes"); + +#define DRV_NAME "qtnfmac_pcie" + int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb) { struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); @@ -58,7 +82,7 @@ int qtnf_pcie_alloc_skb_array(struct qtnf_pcie_bus_priv *priv) return 0; } -void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus) +static void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus) { struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); struct pci_dev *pdev = priv->pdev; @@ -72,7 +96,7 @@ static int qtnf_dbg_mps_show(struct seq_file *s, void *data) struct qtnf_bus *bus = dev_get_drvdata(s->private); struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); - seq_printf(s, "%d\n", priv->mps); + seq_printf(s, "%d\n", pcie_get_mps(priv->pdev)); return 0; } @@ -104,8 +128,7 @@ static int qtnf_dbg_shm_stats(struct seq_file *s, void *data) return 0; } -void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success, - const char *drv_name) +void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success) { struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus); struct pci_dev *pdev = priv->pdev; @@ -122,7 +145,7 @@ void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success, } if (boot_success) { - qtnf_debugfs_init(bus, drv_name); + qtnf_debugfs_init(bus, DRV_NAME); qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show); qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show); qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats); @@ -133,9 +156,8 @@ void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success, put_device(&pdev->dev); } -static void qtnf_tune_pcie_mps(struct qtnf_pcie_bus_priv *priv) +static void qtnf_tune_pcie_mps(struct pci_dev *pdev) { - struct pci_dev *pdev = priv->pdev; struct pci_dev *parent; int mps_p, mps_o, mps_m, mps; int ret; @@ -163,12 +185,10 @@ static void qtnf_tune_pcie_mps(struct qtnf_pcie_bus_priv *priv) if (ret) { pr_err("failed to set mps to %d, keep using current %d\n", mps, mps_o); - priv->mps = mps_o; return; } pr_debug("set mps to %d (was %d, max %d)\n", mps, mps_o, mps_m); - priv->mps = mps; } static void qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv, bool use_msi) @@ -194,20 +214,20 @@ static void qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv, bool use_msi) } } -static void __iomem *qtnf_map_bar(struct qtnf_pcie_bus_priv *priv, u8 index) +static void __iomem *qtnf_map_bar(struct pci_dev *pdev, u8 index) { void __iomem *vaddr; dma_addr_t busaddr; size_t len; int ret; - ret = pcim_iomap_regions(priv->pdev, 1 << index, "qtnfmac_pcie"); + ret = pcim_iomap_regions(pdev, 1 << index, "qtnfmac_pcie"); if (ret) return IOMEM_ERR_PTR(ret); - busaddr = pci_resource_start(priv->pdev, index); - len = pci_resource_len(priv->pdev, index); - vaddr = pcim_iomap_table(priv->pdev)[index]; + busaddr = pci_resource_start(pdev, index); + len = pci_resource_len(pdev, index); + vaddr = pcim_iomap_table(pdev)[index]; if (!vaddr) return IOMEM_ERR_PTR(-ENOMEM); @@ -217,32 +237,8 @@ static void __iomem *qtnf_map_bar(struct qtnf_pcie_bus_priv *priv, u8 index) return vaddr; } -static int qtnf_pcie_init_memory(struct qtnf_pcie_bus_priv *priv) -{ - int ret = -ENOMEM; - - priv->sysctl_bar = qtnf_map_bar(priv, QTN_SYSCTL_BAR); - if (IS_ERR(priv->sysctl_bar)) { - pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR); - return ret; - } - - priv->dmareg_bar = qtnf_map_bar(priv, QTN_DMA_BAR); - if (IS_ERR(priv->dmareg_bar)) { - pr_err("failed to map BAR%u\n", QTN_DMA_BAR); - return ret; - } - - priv->epmem_bar = qtnf_map_bar(priv, QTN_SHMEM_BAR); - if (IS_ERR(priv->epmem_bar)) { - pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR); - return ret; - } - - return 0; -} - -static void qtnf_pcie_control_rx_callback(void *arg, const u8 *buf, size_t len) +static void qtnf_pcie_control_rx_callback(void *arg, const u8 __iomem *buf, + size_t len) { struct qtnf_pcie_bus_priv *priv = arg; struct qtnf_bus *bus = pci_get_drvdata(priv->pdev); @@ -260,7 +256,7 @@ static void qtnf_pcie_control_rx_callback(void *arg, const u8 *buf, size_t len) return; } - skb_put_data(skb, buf, len); + memcpy_fromio(skb_put(skb, len), buf, len); qtnf_trans_handle_rx_ctl_packet(bus, skb); } @@ -281,27 +277,83 @@ void qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv, ipc_int, &rx_callback); } -int qtnf_pcie_probe(struct pci_dev *pdev, size_t priv_size, - const struct qtnf_bus_ops *bus_ops, u64 dma_mask, - bool use_msi) +static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct qtnf_pcie_bus_priv *pcie_priv; struct qtnf_bus *bus; + void __iomem *sysctl_bar; + void __iomem *epmem_bar; + void __iomem *dmareg_bar; + unsigned int chipid; int ret; - bus = devm_kzalloc(&pdev->dev, - sizeof(*bus) + priv_size, GFP_KERNEL); + if (!pci_is_pcie(pdev)) { + pr_err("device %s is not PCI Express\n", pci_name(pdev)); + return -EIO; + } + + qtnf_tune_pcie_mps(pdev); + + ret = pcim_enable_device(pdev); + if (ret) { + pr_err("failed to init PCI device %x\n", pdev->device); + return ret; + } + + pci_set_master(pdev); + + sysctl_bar = qtnf_map_bar(pdev, QTN_SYSCTL_BAR); + if (IS_ERR(sysctl_bar)) { + pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR); + return ret; + } + + dmareg_bar = qtnf_map_bar(pdev, QTN_DMA_BAR); + if (IS_ERR(dmareg_bar)) { + pr_err("failed to map BAR%u\n", QTN_DMA_BAR); + return ret; + } + + epmem_bar = qtnf_map_bar(pdev, QTN_SHMEM_BAR); + if (IS_ERR(epmem_bar)) { + pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR); + return ret; + } + + chipid = qtnf_chip_id_get(sysctl_bar); + + pr_info("identified device: %s\n", qtnf_chipid_to_string(chipid)); + + switch (chipid) { + case QTN_CHIP_ID_PEARL: + case QTN_CHIP_ID_PEARL_B: + case QTN_CHIP_ID_PEARL_C: + bus = qtnf_pcie_pearl_alloc(pdev); + break; + case QTN_CHIP_ID_TOPAZ: + bus = qtnf_pcie_topaz_alloc(pdev); + break; + default: + pr_err("unsupported chip ID 0x%x\n", chipid); + return -ENOTSUPP; + } + if (!bus) return -ENOMEM; pcie_priv = get_bus_priv(bus); - pci_set_drvdata(pdev, bus); - bus->bus_ops = bus_ops; bus->dev = &pdev->dev; bus->fw_state = QTNF_FW_STATE_RESET; pcie_priv->pdev = pdev; pcie_priv->tx_stopped = 0; + pcie_priv->rx_bd_num = rx_bd_size_param; + pcie_priv->flashboot = flashboot; + + if (fw_blksize_param > QTN_PCIE_MAX_FW_BUFSZ) + pcie_priv->fw_blksize = QTN_PCIE_MAX_FW_BUFSZ; + else + pcie_priv->fw_blksize = fw_blksize_param; mutex_init(&bus->bus_lock); spin_lock_init(&pcie_priv->tx_lock); @@ -316,53 +368,35 @@ int qtnf_pcie_probe(struct pci_dev *pdev, size_t priv_size, pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PCIE"); if (!pcie_priv->workqueue) { pr_err("failed to alloc bus workqueue\n"); - ret = -ENODEV; - goto err_init; - } - - init_dummy_netdev(&bus->mux_dev); - - if (!pci_is_pcie(pdev)) { - pr_err("device %s is not PCI Express\n", pci_name(pdev)); - ret = -EIO; - goto err_base; - } - - qtnf_tune_pcie_mps(pcie_priv); - - ret = pcim_enable_device(pdev); - if (ret) { - pr_err("failed to init PCI device %x\n", pdev->device); - goto err_base; - } else { - pr_debug("successful init of PCI device %x\n", pdev->device); + return -ENODEV; } - ret = dma_set_mask_and_coherent(&pdev->dev, dma_mask); + ret = dma_set_mask_and_coherent(&pdev->dev, + pcie_priv->dma_mask_get_cb()); if (ret) { - pr_err("PCIE DMA coherent mask init failed\n"); - goto err_base; + pr_err("PCIE DMA coherent mask init failed 0x%llx\n", + pcie_priv->dma_mask_get_cb()); + goto error; } - pci_set_master(pdev); + init_dummy_netdev(&bus->mux_dev); qtnf_pcie_init_irq(pcie_priv, use_msi); - - ret = qtnf_pcie_init_memory(pcie_priv); - if (ret < 0) { - pr_err("PCIE memory init failed\n"); - goto err_base; - } - + pcie_priv->sysctl_bar = sysctl_bar; + pcie_priv->dmareg_bar = dmareg_bar; + pcie_priv->epmem_bar = epmem_bar; pci_save_state(pdev); + ret = pcie_priv->probe_cb(bus, tx_bd_size_param); + if (ret) + goto error; + + qtnf_pcie_bringup_fw_async(bus); return 0; -err_base: +error: flush_workqueue(pcie_priv->workqueue); destroy_workqueue(pcie_priv->workqueue); -err_init: pci_set_drvdata(pdev, NULL); - return ret; } @@ -372,8 +406,17 @@ static void qtnf_pcie_free_shm_ipc(struct qtnf_pcie_bus_priv *priv) qtnf_shm_ipc_free(&priv->shm_ipc_ep_out); } -void qtnf_pcie_remove(struct qtnf_bus *bus, struct qtnf_pcie_bus_priv *priv) +static void qtnf_pcie_remove(struct pci_dev *dev) { + struct qtnf_pcie_bus_priv *priv; + struct qtnf_bus *bus; + + bus = pci_get_drvdata(dev); + if (!bus) + return; + + priv = get_bus_priv(bus); + cancel_work_sync(&bus->fw_work); if (bus->fw_state == QTNF_FW_STATE_ACTIVE || @@ -387,5 +430,77 @@ void qtnf_pcie_remove(struct qtnf_bus *bus, struct qtnf_pcie_bus_priv *priv) qtnf_pcie_free_shm_ipc(priv); qtnf_debugfs_remove(bus); + priv->remove_cb(bus); pci_set_drvdata(priv->pdev, NULL); } + +#ifdef CONFIG_PM_SLEEP +static int qtnf_pcie_suspend(struct device *dev) +{ + struct qtnf_pcie_bus_priv *priv; + struct qtnf_bus *bus; + + bus = pci_get_drvdata(to_pci_dev(dev)); + if (!bus) + return -EFAULT; + + priv = get_bus_priv(bus); + return priv->suspend_cb(bus); +} + +static int qtnf_pcie_resume(struct device *dev) +{ + struct qtnf_pcie_bus_priv *priv; + struct qtnf_bus *bus; + + bus = pci_get_drvdata(to_pci_dev(dev)); + if (!bus) + return -EFAULT; + + priv = get_bus_priv(bus); + return priv->resume_cb(bus); +} + +/* Power Management Hooks */ +static SIMPLE_DEV_PM_OPS(qtnf_pcie_pm_ops, qtnf_pcie_suspend, + qtnf_pcie_resume); +#endif + +static const struct pci_device_id qtnf_pcie_devid_table[] = { + { + PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QSR, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + }, + { }, +}; + +MODULE_DEVICE_TABLE(pci, qtnf_pcie_devid_table); + +static struct pci_driver qtnf_pcie_drv_data = { + .name = DRV_NAME, + .id_table = qtnf_pcie_devid_table, + .probe = qtnf_pcie_probe, + .remove = qtnf_pcie_remove, +#ifdef CONFIG_PM_SLEEP + .driver = { + .pm = &qtnf_pcie_pm_ops, + }, +#endif +}; + +static int __init qtnf_pcie_register(void) +{ + return pci_register_driver(&qtnf_pcie_drv_data); +} + +static void __exit qtnf_pcie_exit(void) +{ + pci_unregister_driver(&qtnf_pcie_drv_data); +} + +module_init(qtnf_pcie_register); +module_exit(qtnf_pcie_exit); + +MODULE_AUTHOR("Quantenna Communications"); +MODULE_DESCRIPTION("Quantenna PCIe bus driver for 802.11 wireless LAN."); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h index 5c70fb4c0f92..bbc074e1f34d 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie_priv.h @@ -23,9 +23,14 @@ struct qtnf_pcie_bus_priv { struct pci_dev *pdev; + int (*probe_cb)(struct qtnf_bus *bus, unsigned int tx_bd_size); + void (*remove_cb)(struct qtnf_bus *bus); + int (*suspend_cb)(struct qtnf_bus *bus); + int (*resume_cb)(struct qtnf_bus *bus); + u64 (*dma_mask_get_cb)(void); + spinlock_t tx_reclaim_lock; spinlock_t tx_lock; - int mps; struct workqueue_struct *workqueue; struct tasklet_struct reclaim_tq; @@ -43,6 +48,8 @@ struct qtnf_pcie_bus_priv { struct sk_buff **tx_skb; struct sk_buff **rx_skb; + unsigned int fw_blksize; + u32 rx_bd_w_index; u32 rx_bd_r_index; @@ -58,21 +65,18 @@ struct qtnf_pcie_bus_priv { u8 msi_enabled; u8 tx_stopped; + bool flashboot; }; int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb); int qtnf_pcie_alloc_skb_array(struct qtnf_pcie_bus_priv *priv); -void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus); -void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success, - const char *drv_name); +void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success); void qtnf_pcie_init_shm_ipc(struct qtnf_pcie_bus_priv *priv, struct qtnf_shm_ipc_region __iomem *ipc_tx_reg, struct qtnf_shm_ipc_region __iomem *ipc_rx_reg, const struct qtnf_shm_ipc_int *ipc_int); -int qtnf_pcie_probe(struct pci_dev *pdev, size_t priv_size, - const struct qtnf_bus_ops *bus_ops, u64 dma_mask, - bool use_msi); -void qtnf_pcie_remove(struct qtnf_bus *bus, struct qtnf_pcie_bus_priv *priv); +struct qtnf_bus *qtnf_pcie_pearl_alloc(struct pci_dev *pdev); +struct qtnf_bus *qtnf_pcie_topaz_alloc(struct pci_dev *pdev); static inline void qtnf_non_posted_write(u32 val, void __iomem *basereg) { diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c index 5aca12a51fe3..1f5facbb8905 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c @@ -1,21 +1,7 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2018 Quantenna Communications */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/firmware.h> #include <linux/pci.h> #include <linux/vmalloc.h> @@ -37,23 +23,7 @@ #include "shm_ipc.h" #include "debug.h" -static bool use_msi = true; -module_param(use_msi, bool, 0644); -MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt"); - -static unsigned int tx_bd_size_param = 32; -module_param(tx_bd_size_param, uint, 0644); -MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size, power of two"); - -static unsigned int rx_bd_size_param = 256; -module_param(rx_bd_size_param, uint, 0644); -MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size, power of two"); - -static u8 flashboot = 1; -module_param(flashboot, byte, 0644); -MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS"); - -#define DRV_NAME "qtnfmac_pearl_pcie" +#define PEARL_TX_BD_SIZE_DEFAULT 32 struct qtnf_pearl_bda { __le16 bda_len; @@ -428,30 +398,28 @@ static int pearl_hhbm_init(struct qtnf_pcie_pearl_state *ps) return 0; } -static int qtnf_pcie_pearl_init_xfer(struct qtnf_pcie_pearl_state *ps) +static int qtnf_pcie_pearl_init_xfer(struct qtnf_pcie_pearl_state *ps, + unsigned int tx_bd_size) { struct qtnf_pcie_bus_priv *priv = &ps->base; int ret; u32 val; - priv->tx_bd_num = tx_bd_size_param; - priv->rx_bd_num = rx_bd_size_param; - priv->rx_bd_w_index = 0; - priv->rx_bd_r_index = 0; + if (tx_bd_size == 0) + tx_bd_size = PEARL_TX_BD_SIZE_DEFAULT; - if (!priv->tx_bd_num || !is_power_of_2(priv->tx_bd_num)) { - pr_err("tx_bd_size_param %u is not power of two\n", - priv->tx_bd_num); - return -EINVAL; - } + val = tx_bd_size * sizeof(struct qtnf_pearl_tx_bd); - val = priv->tx_bd_num * sizeof(struct qtnf_pearl_tx_bd); - if (val > PCIE_HHBM_MAX_SIZE) { - pr_err("tx_bd_size_param %u is too large\n", - priv->tx_bd_num); - return -EINVAL; + if (!is_power_of_2(tx_bd_size) || val > PCIE_HHBM_MAX_SIZE) { + pr_warn("bad tx_bd_size value %u\n", tx_bd_size); + priv->tx_bd_num = PEARL_TX_BD_SIZE_DEFAULT; + } else { + priv->tx_bd_num = tx_bd_size; } + priv->rx_bd_w_index = 0; + priv->rx_bd_r_index = 0; + if (!priv->rx_bd_num || !is_power_of_2(priv->rx_bd_num)) { pr_err("rx_bd_size_param %u is not power of two\n", priv->rx_bd_num); @@ -1019,7 +987,7 @@ static void qtnf_pearl_fw_work_handler(struct work_struct *work) const char *fwname = QTN_PCI_PEARL_FW_NAME; bool fw_boot_success = false; - if (flashboot) { + if (ps->base.flashboot) { state |= QTN_RC_FW_FLASHBOOT; } else { ret = request_firmware(&fw, fwname, &pdev->dev); @@ -1035,7 +1003,7 @@ static void qtnf_pearl_fw_work_handler(struct work_struct *work) QTN_FW_DL_TIMEOUT_MS)) { pr_err("card is not ready\n"); - if (!flashboot) + if (!ps->base.flashboot) release_firmware(fw); goto fw_load_exit; @@ -1043,7 +1011,7 @@ static void qtnf_pearl_fw_work_handler(struct work_struct *work) qtnf_clear_state(&ps->bda->bda_ep_state, QTN_EP_FW_LOADRDY); - if (flashboot) { + if (ps->base.flashboot) { pr_info("booting firmware from flash\n"); } else { @@ -1074,7 +1042,7 @@ static void qtnf_pearl_fw_work_handler(struct work_struct *work) fw_boot_success = true; fw_load_exit: - qtnf_pcie_fw_boot_done(bus, fw_boot_success, DRV_NAME); + qtnf_pcie_fw_boot_done(bus, fw_boot_success); if (fw_boot_success) { qtnf_debugfs_add_entry(bus, "hdp_stats", qtnf_dbg_hdp_stats); @@ -1090,74 +1058,34 @@ static void qtnf_pearl_reclaim_tasklet_fn(unsigned long data) qtnf_en_txdone_irq(ps); } -static int qtnf_pearl_check_chip_id(struct qtnf_pcie_pearl_state *ps) +static u64 qtnf_pearl_dma_mask_get(void) { - unsigned int chipid; - - chipid = qtnf_chip_id_get(ps->base.sysctl_bar); - - switch (chipid) { - case QTN_CHIP_ID_PEARL: - case QTN_CHIP_ID_PEARL_B: - case QTN_CHIP_ID_PEARL_C: - pr_info("chip ID is 0x%x\n", chipid); - break; - default: - pr_err("incorrect chip ID 0x%x\n", chipid); - return -ENODEV; - } - - return 0; +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + return DMA_BIT_MASK(64); +#else + return DMA_BIT_MASK(32); +#endif } -static int qtnf_pcie_pearl_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int qtnf_pcie_pearl_probe(struct qtnf_bus *bus, unsigned int tx_bd_size) { struct qtnf_shm_ipc_int ipc_int; - struct qtnf_pcie_pearl_state *ps; - struct qtnf_bus *bus; + struct qtnf_pcie_pearl_state *ps = get_bus_priv(bus); + struct pci_dev *pdev = ps->base.pdev; int ret; - u64 dma_mask; - -#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT - dma_mask = DMA_BIT_MASK(64); -#else - dma_mask = DMA_BIT_MASK(32); -#endif - - ret = qtnf_pcie_probe(pdev, sizeof(*ps), &qtnf_pcie_pearl_bus_ops, - dma_mask, use_msi); - if (ret) - return ret; - - bus = pci_get_drvdata(pdev); - ps = get_bus_priv(bus); + bus->bus_ops = &qtnf_pcie_pearl_bus_ops; spin_lock_init(&ps->irq_lock); - - tasklet_init(&ps->base.reclaim_tq, qtnf_pearl_reclaim_tasklet_fn, - (unsigned long)ps); - netif_napi_add(&bus->mux_dev, &bus->mux_napi, - qtnf_pcie_pearl_rx_poll, 10); INIT_WORK(&bus->fw_work, qtnf_pearl_fw_work_handler); ps->pcie_reg_base = ps->base.dmareg_bar; ps->bda = ps->base.epmem_bar; writel(ps->base.msi_enabled, &ps->bda->bda_rc_msi_enabled); - ipc_int.fn = qtnf_pcie_pearl_ipc_gen_ep_int; - ipc_int.arg = ps; - qtnf_pcie_init_shm_ipc(&ps->base, &ps->bda->bda_shm_reg1, - &ps->bda->bda_shm_reg2, &ipc_int); - - ret = qtnf_pearl_check_chip_id(ps); - if (ret) - goto error; - - ret = qtnf_pcie_pearl_init_xfer(ps); + ret = qtnf_pcie_pearl_init_xfer(ps, tx_bd_size); if (ret) { pr_err("PCIE xfer init failed\n"); - goto error; + return ret; } /* init default irq settings */ @@ -1168,95 +1096,63 @@ static int qtnf_pcie_pearl_probe(struct pci_dev *pdev, ret = devm_request_irq(&pdev->dev, pdev->irq, &qtnf_pcie_pearl_interrupt, 0, - "qtnf_pcie_irq", (void *)bus); + "qtnf_pearl_irq", (void *)bus); if (ret) { pr_err("failed to request pcie irq %d\n", pdev->irq); - goto err_xfer; + qtnf_pearl_free_xfer_buffers(ps); + return ret; } - qtnf_pcie_bringup_fw_async(bus); - - return 0; + tasklet_init(&ps->base.reclaim_tq, qtnf_pearl_reclaim_tasklet_fn, + (unsigned long)ps); + netif_napi_add(&bus->mux_dev, &bus->mux_napi, + qtnf_pcie_pearl_rx_poll, 10); -err_xfer: - qtnf_pearl_free_xfer_buffers(ps); -error: - qtnf_pcie_remove(bus, &ps->base); + ipc_int.fn = qtnf_pcie_pearl_ipc_gen_ep_int; + ipc_int.arg = ps; + qtnf_pcie_init_shm_ipc(&ps->base, &ps->bda->bda_shm_reg1, + &ps->bda->bda_shm_reg2, &ipc_int); - return ret; + return 0; } -static void qtnf_pcie_pearl_remove(struct pci_dev *pdev) +static void qtnf_pcie_pearl_remove(struct qtnf_bus *bus) { - struct qtnf_pcie_pearl_state *ps; - struct qtnf_bus *bus; - - bus = pci_get_drvdata(pdev); - if (!bus) - return; - - ps = get_bus_priv(bus); + struct qtnf_pcie_pearl_state *ps = get_bus_priv(bus); - qtnf_pcie_remove(bus, &ps->base); qtnf_pearl_reset_ep(ps); qtnf_pearl_free_xfer_buffers(ps); } #ifdef CONFIG_PM_SLEEP -static int qtnf_pcie_pearl_suspend(struct device *dev) +static int qtnf_pcie_pearl_suspend(struct qtnf_bus *bus) { return -EOPNOTSUPP; } -static int qtnf_pcie_pearl_resume(struct device *dev) +static int qtnf_pcie_pearl_resume(struct qtnf_bus *bus) { return 0; } -#endif /* CONFIG_PM_SLEEP */ - -#ifdef CONFIG_PM_SLEEP -/* Power Management Hooks */ -static SIMPLE_DEV_PM_OPS(qtnf_pcie_pearl_pm_ops, qtnf_pcie_pearl_suspend, - qtnf_pcie_pearl_resume); #endif -static const struct pci_device_id qtnf_pcie_devid_table[] = { - { - PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QTN_PEARL, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - }, - { }, -}; +struct qtnf_bus *qtnf_pcie_pearl_alloc(struct pci_dev *pdev) +{ + struct qtnf_bus *bus; + struct qtnf_pcie_pearl_state *ps; -MODULE_DEVICE_TABLE(pci, qtnf_pcie_devid_table); + bus = devm_kzalloc(&pdev->dev, sizeof(*bus) + sizeof(*ps), GFP_KERNEL); + if (!bus) + return NULL; -static struct pci_driver qtnf_pcie_pearl_drv_data = { - .name = DRV_NAME, - .id_table = qtnf_pcie_devid_table, - .probe = qtnf_pcie_pearl_probe, - .remove = qtnf_pcie_pearl_remove, + ps = get_bus_priv(bus); + ps->base.probe_cb = qtnf_pcie_pearl_probe; + ps->base.remove_cb = qtnf_pcie_pearl_remove; + ps->base.dma_mask_get_cb = qtnf_pearl_dma_mask_get; #ifdef CONFIG_PM_SLEEP - .driver = { - .pm = &qtnf_pcie_pearl_pm_ops, - }, + ps->base.resume_cb = qtnf_pcie_pearl_resume; + ps->base.suspend_cb = qtnf_pcie_pearl_suspend; #endif -}; - -static int __init qtnf_pcie_pearl_register(void) -{ - pr_info("register Quantenna QSR10g FullMAC PCIE driver\n"); - return pci_register_driver(&qtnf_pcie_pearl_drv_data); -} -static void __exit qtnf_pcie_pearl_exit(void) -{ - pr_info("unregister Quantenna QSR10g FullMAC PCIE driver\n"); - pci_unregister_driver(&qtnf_pcie_pearl_drv_data); + return bus; } - -module_init(qtnf_pcie_pearl_register); -module_exit(qtnf_pcie_pearl_exit); - -MODULE_AUTHOR("Quantenna Communications"); -MODULE_DESCRIPTION("Quantenna QSR10g PCIe bus driver for 802.11 wireless LAN."); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h index f21e97ede090..634480fe6a64 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_ipc.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications */ #ifndef _QTN_FMAC_PCIE_IPC_H_ #define _QTN_FMAC_PCIE_IPC_H_ @@ -85,11 +72,6 @@ #define QTN_EP_LHOST_TQE_PORT 4 -enum qtnf_pcie_bda_ipc_flags { - QTN_PCIE_IPC_FLAG_HBM_MAGIC = BIT(0), - QTN_PCIE_IPC_FLAG_SHM_PIO = BIT(1), -}; - enum qtnf_fw_loadtype { QTN_FW_DBEGIN, QTN_FW_DSUB, diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h index 0bfe285b6b48..6e9a5c61d46f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie_regs.h @@ -1,28 +1,10 @@ -/* - * Copyright (c) 2015 Quantenna Communications, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015 Quantenna Communications */ #ifndef __PEARL_PCIE_H #define __PEARL_PCIE_H -#define PCIE_GEN2_BASE (0xe9000000) -#define PCIE_GEN3_BASE (0xe7000000) - -#define PEARL_CUR_PCIE_BASE (PCIE_GEN2_BASE) -#define PCIE_HDP_OFFSET (0x2000) - +/* Pearl PCIe HDP registers */ #define PCIE_HDP_CTRL(base) ((base) + 0x2c00) #define PCIE_HDP_AXI_CTRL(base) ((base) + 0x2c04) #define PCIE_HDP_HOST_WR_DESC0(base) ((base) + 0x2c10) @@ -86,7 +68,7 @@ #define PCIE_HDP_TX_HOST_Q_RD_PTR(base) ((base) + 0x2d3c) #define PCIE_HDP_TX_HOST_Q_STS(base) ((base) + 0x2d40) -/* Host HBM pool registers */ +/* Pearl PCIe HBM pool registers */ #define PCIE_HHBM_CSR_REG(base) ((base) + 0x2e00) #define PCIE_HHBM_Q_BASE_REG(base) ((base) + 0x2e04) #define PCIE_HHBM_Q_LIMIT_REG(base) ((base) + 0x2e08) @@ -104,230 +86,13 @@ #define HBM_INT_STATUS(base) ((base) + 0x2f9c) #define PCIE_HHBM_POOL_CNFIG(base) ((base) + 0x2f9c) -/* host HBM bit field definition */ +/* Pearl PCIe HBM bit field definitions */ #define HHBM_CONFIG_SOFT_RESET (BIT(8)) #define HHBM_WR_REQ (BIT(0)) #define HHBM_RD_REQ (BIT(1)) #define HHBM_DONE (BIT(31)) #define HHBM_64BIT (BIT(10)) -/* offsets for dual PCIE */ -#define PCIE_PORT_LINK_CTL(base) ((base) + 0x0710) -#define PCIE_GEN2_CTL(base) ((base) + 0x080C) -#define PCIE_GEN3_OFF(base) ((base) + 0x0890) -#define PCIE_ATU_CTRL1(base) ((base) + 0x0904) -#define PCIE_ATU_CTRL2(base) ((base) + 0x0908) -#define PCIE_ATU_BASE_LOW(base) ((base) + 0x090C) -#define PCIE_ATU_BASE_HIGH(base) ((base) + 0x0910) -#define PCIE_ATU_BASE_LIMIT(base) ((base) + 0x0914) -#define PCIE_ATU_TGT_LOW(base) ((base) + 0x0918) -#define PCIE_ATU_TGT_HIGH(base) ((base) + 0x091C) -#define PCIE_DMA_WR_ENABLE(base) ((base) + 0x097C) -#define PCIE_DMA_WR_CHWTLOW(base) ((base) + 0x0988) -#define PCIE_DMA_WR_CHWTHIG(base) ((base) + 0x098C) -#define PCIE_DMA_WR_INTSTS(base) ((base) + 0x09BC) -#define PCIE_DMA_WR_INTMASK(base) ((base) + 0x09C4) -#define PCIE_DMA_WR_INTCLER(base) ((base) + 0x09C8) -#define PCIE_DMA_WR_DONE_IMWR_ADDR_L(base) ((base) + 0x09D0) -#define PCIE_DMA_WR_DONE_IMWR_ADDR_H(base) ((base) + 0x09D4) -#define PCIE_DMA_WR_ABORT_IMWR_ADDR_L(base) ((base) + 0x09D8) -#define PCIE_DMA_WR_ABORT_IMWR_ADDR_H(base) ((base) + 0x09DC) -#define PCIE_DMA_WR_IMWR_DATA(base) ((base) + 0x09E0) -#define PCIE_DMA_WR_LL_ERR_EN(base) ((base) + 0x0A00) -#define PCIE_DMA_WR_DOORBELL(base) ((base) + 0x0980) -#define PCIE_DMA_RD_ENABLE(base) ((base) + 0x099C) -#define PCIE_DMA_RD_DOORBELL(base) ((base) + 0x09A0) -#define PCIE_DMA_RD_CHWTLOW(base) ((base) + 0x09A8) -#define PCIE_DMA_RD_CHWTHIG(base) ((base) + 0x09AC) -#define PCIE_DMA_RD_INTSTS(base) ((base) + 0x0A10) -#define PCIE_DMA_RD_INTMASK(base) ((base) + 0x0A18) -#define PCIE_DMA_RD_INTCLER(base) ((base) + 0x0A1C) -#define PCIE_DMA_RD_ERR_STS_L(base) ((base) + 0x0A24) -#define PCIE_DMA_RD_ERR_STS_H(base) ((base) + 0x0A28) -#define PCIE_DMA_RD_LL_ERR_EN(base) ((base) + 0x0A34) -#define PCIE_DMA_RD_DONE_IMWR_ADDR_L(base) ((base) + 0x0A3C) -#define PCIE_DMA_RD_DONE_IMWR_ADDR_H(base) ((base) + 0x0A40) -#define PCIE_DMA_RD_ABORT_IMWR_ADDR_L(base) ((base) + 0x0A44) -#define PCIE_DMA_RD_ABORT_IMWR_ADDR_H(base) ((base) + 0x0A48) -#define PCIE_DMA_RD_IMWR_DATA(base) ((base) + 0x0A4C) -#define PCIE_DMA_CHNL_CONTEXT(base) ((base) + 0x0A6C) -#define PCIE_DMA_CHNL_CNTRL(base) ((base) + 0x0A70) -#define PCIE_DMA_XFR_SIZE(base) ((base) + 0x0A78) -#define PCIE_DMA_SAR_LOW(base) ((base) + 0x0A7C) -#define PCIE_DMA_SAR_HIGH(base) ((base) + 0x0A80) -#define PCIE_DMA_DAR_LOW(base) ((base) + 0x0A84) -#define PCIE_DMA_DAR_HIGH(base) ((base) + 0x0A88) -#define PCIE_DMA_LLPTR_LOW(base) ((base) + 0x0A8C) -#define PCIE_DMA_LLPTR_HIGH(base) ((base) + 0x0A90) -#define PCIE_DMA_WRLL_ERR_ENB(base) ((base) + 0x0A00) -#define PCIE_DMA_RDLL_ERR_ENB(base) ((base) + 0x0A34) -#define PCIE_DMABD_CHNL_CNTRL(base) ((base) + 0x8000) -#define PCIE_DMABD_XFR_SIZE(base) ((base) + 0x8004) -#define PCIE_DMABD_SAR_LOW(base) ((base) + 0x8008) -#define PCIE_DMABD_SAR_HIGH(base) ((base) + 0x800c) -#define PCIE_DMABD_DAR_LOW(base) ((base) + 0x8010) -#define PCIE_DMABD_DAR_HIGH(base) ((base) + 0x8014) -#define PCIE_DMABD_LLPTR_LOW(base) ((base) + 0x8018) -#define PCIE_DMABD_LLPTR_HIGH(base) ((base) + 0x801c) -#define PCIE_WRDMA0_CHNL_CNTRL(base) ((base) + 0x8000) -#define PCIE_WRDMA0_XFR_SIZE(base) ((base) + 0x8004) -#define PCIE_WRDMA0_SAR_LOW(base) ((base) + 0x8008) -#define PCIE_WRDMA0_SAR_HIGH(base) ((base) + 0x800c) -#define PCIE_WRDMA0_DAR_LOW(base) ((base) + 0x8010) -#define PCIE_WRDMA0_DAR_HIGH(base) ((base) + 0x8014) -#define PCIE_WRDMA0_LLPTR_LOW(base) ((base) + 0x8018) -#define PCIE_WRDMA0_LLPTR_HIGH(base) ((base) + 0x801c) -#define PCIE_WRDMA1_CHNL_CNTRL(base) ((base) + 0x8020) -#define PCIE_WRDMA1_XFR_SIZE(base) ((base) + 0x8024) -#define PCIE_WRDMA1_SAR_LOW(base) ((base) + 0x8028) -#define PCIE_WRDMA1_SAR_HIGH(base) ((base) + 0x802c) -#define PCIE_WRDMA1_DAR_LOW(base) ((base) + 0x8030) -#define PCIE_WRDMA1_DAR_HIGH(base) ((base) + 0x8034) -#define PCIE_WRDMA1_LLPTR_LOW(base) ((base) + 0x8038) -#define PCIE_WRDMA1_LLPTR_HIGH(base) ((base) + 0x803c) -#define PCIE_RDDMA0_CHNL_CNTRL(base) ((base) + 0x8040) -#define PCIE_RDDMA0_XFR_SIZE(base) ((base) + 0x8044) -#define PCIE_RDDMA0_SAR_LOW(base) ((base) + 0x8048) -#define PCIE_RDDMA0_SAR_HIGH(base) ((base) + 0x804c) -#define PCIE_RDDMA0_DAR_LOW(base) ((base) + 0x8050) -#define PCIE_RDDMA0_DAR_HIGH(base) ((base) + 0x8054) -#define PCIE_RDDMA0_LLPTR_LOW(base) ((base) + 0x8058) -#define PCIE_RDDMA0_LLPTR_HIGH(base) ((base) + 0x805c) -#define PCIE_RDDMA1_CHNL_CNTRL(base) ((base) + 0x8060) -#define PCIE_RDDMA1_XFR_SIZE(base) ((base) + 0x8064) -#define PCIE_RDDMA1_SAR_LOW(base) ((base) + 0x8068) -#define PCIE_RDDMA1_SAR_HIGH(base) ((base) + 0x806c) -#define PCIE_RDDMA1_DAR_LOW(base) ((base) + 0x8070) -#define PCIE_RDDMA1_DAR_HIGH(base) ((base) + 0x8074) -#define PCIE_RDDMA1_LLPTR_LOW(base) ((base) + 0x8078) -#define PCIE_RDDMA1_LLPTR_HIGH(base) ((base) + 0x807c) - -#define PCIE_ID(base) ((base) + 0x0000) -#define PCIE_CMD(base) ((base) + 0x0004) -#define PCIE_BAR(base, n) ((base) + 0x0010 + ((n) << 2)) -#define PCIE_CAP_PTR(base) ((base) + 0x0034) -#define PCIE_MSI_LBAR(base) ((base) + 0x0054) -#define PCIE_MSI_CTRL(base) ((base) + 0x0050) -#define PCIE_MSI_ADDR_L(base) ((base) + 0x0054) -#define PCIE_MSI_ADDR_H(base) ((base) + 0x0058) -#define PCIE_MSI_DATA(base) ((base) + 0x005C) -#define PCIE_MSI_MASK_BIT(base) ((base) + 0x0060) -#define PCIE_MSI_PEND_BIT(base) ((base) + 0x0064) -#define PCIE_DEVCAP(base) ((base) + 0x0074) -#define PCIE_DEVCTLSTS(base) ((base) + 0x0078) - -#define PCIE_CMDSTS(base) ((base) + 0x0004) -#define PCIE_LINK_STAT(base) ((base) + 0x80) -#define PCIE_LINK_CTL2(base) ((base) + 0xa0) -#define PCIE_ASPM_L1_CTRL(base) ((base) + 0x70c) -#define PCIE_ASPM_LINK_CTRL(base) (PCIE_LINK_STAT) -#define PCIE_ASPM_L1_SUBSTATE_TIMING(base) ((base) + 0xB44) -#define PCIE_L1SUB_CTRL1(base) ((base) + 0x150) -#define PCIE_PMCSR(base) ((base) + 0x44) -#define PCIE_CFG_SPACE_LIMIT(base) ((base) + 0x100) - -/* PCIe link defines */ -#define PEARL_PCIE_LINKUP (0x7) -#define PEARL_PCIE_DATA_LINK (BIT(0)) -#define PEARL_PCIE_PHY_LINK (BIT(1)) -#define PEARL_PCIE_LINK_RST (BIT(3)) -#define PEARL_PCIE_FATAL_ERR (BIT(5)) -#define PEARL_PCIE_NONFATAL_ERR (BIT(6)) - -/* PCIe Lane defines */ -#define PCIE_G2_LANE_X1 ((BIT(0)) << 16) -#define PCIE_G2_LANE_X2 ((BIT(0) | BIT(1)) << 16) - -/* PCIe DLL link enable */ -#define PCIE_DLL_LINK_EN ((BIT(0)) << 5) - -#define PCIE_LINK_GEN1 (BIT(0)) -#define PCIE_LINK_GEN2 (BIT(1)) -#define PCIE_LINK_GEN3 (BIT(2)) -#define PCIE_LINK_MODE(x) (((x) >> 16) & 0x7) - -#define MSI_EN (BIT(0)) -#define MSI_64_EN (BIT(7)) -#define PCIE_MSI_ADDR_OFFSET(a) ((a) & 0xFFFF) -#define PCIE_MSI_ADDR_ALIGN(a) ((a) & (~0xFFFF)) - -#define PCIE_BAR_MASK(base, n) ((base) + 0x1010 + ((n) << 2)) -#define PCIE_MAX_BAR (6) - -#define PCIE_ATU_VIEW(base) ((base) + 0x0900) -#define PCIE_ATU_CTL1(base) ((base) + 0x0904) -#define PCIE_ATU_CTL2(base) ((base) + 0x0908) -#define PCIE_ATU_LBAR(base) ((base) + 0x090c) -#define PCIE_ATU_UBAR(base) ((base) + 0x0910) -#define PCIE_ATU_LAR(base) ((base) + 0x0914) -#define PCIE_ATU_LTAR(base) ((base) + 0x0918) -#define PCIE_ATU_UTAR(base) ((base) + 0x091c) - -#define PCIE_MSI_ADDR_LOWER(base) ((base) + 0x0820) -#define PCIE_MSI_ADDR_UPPER(base) ((base) + 0x0824) -#define PCIE_MSI_ENABLE(base) ((base) + 0x0828) -#define PCIE_MSI_MASK_RC(base) ((base) + 0x082c) -#define PCIE_MSI_STATUS(base) ((base) + 0x0830) -#define PEARL_PCIE_MSI_REGION (0xce000000) -#define PEARL_PCIE_MSI_DATA (0) -#define PCIE_MSI_GPIO(base) ((base) + 0x0888) - -#define PCIE_HDP_HOST_QUEUE_FULL (BIT(17)) -#define USE_BAR_MATCH_MODE -#define PCIE_ATU_OB_REGION (BIT(0)) -#define PCIE_ATU_EN_REGION (BIT(31)) -#define PCIE_ATU_EN_MATCH (BIT(30)) -#define PCIE_BASE_REGION (0xb0000000) -#define PCIE_MEM_MAP_SIZE (512 * 1024) - -#define PCIE_OB_REG_REGION (0xcf000000) -#define PCIE_CONFIG_REGION (0xcf000000) -#define PCIE_CONFIG_SIZE (4096) -#define PCIE_CONFIG_CH (1) - -/* inbound mapping */ -#define PCIE_IB_BAR0 (0x00000000) /* ddr */ -#define PCIE_IB_BAR0_CH (0) -#define PCIE_IB_BAR3 (0xe0000000) /* sys_reg */ -#define PCIE_IB_BAR3_CH (1) - -/* outbound mapping */ -#define PCIE_MEM_CH (0) -#define PCIE_REG_CH (1) -#define PCIE_MEM_REGION (0xc0000000) -#define PCIE_MEM_SIZE (0x000fffff) -#define PCIE_MEM_TAR (0x80000000) - -#define PCIE_MSI_REGION (0xce000000) -#define PCIE_MSI_SIZE (KBYTE(4) - 1) -#define PCIE_MSI_CH (1) - -/* size of config region */ -#define PCIE_CFG_SIZE (0x0000ffff) - -#define PCIE_ATU_DIR_IB (BIT(31)) -#define PCIE_ATU_DIR_OB (0) -#define PCIE_ATU_DIR_CFG (2) -#define PCIE_ATU_DIR_MATCH_IB (BIT(31) | BIT(30)) - -#define PCIE_DMA_WR_0 (0) -#define PCIE_DMA_WR_1 (1) -#define PCIE_DMA_RD_0 (2) -#define PCIE_DMA_RD_1 (3) - -#define PCIE_DMA_CHNL_CNTRL_CB (BIT(0)) -#define PCIE_DMA_CHNL_CNTRL_TCB (BIT(1)) -#define PCIE_DMA_CHNL_CNTRL_LLP (BIT(2)) -#define PCIE_DMA_CHNL_CNTRL_LIE (BIT(3)) -#define PCIE_DMA_CHNL_CNTRL_RIE (BIT(4)) -#define PCIE_DMA_CHNL_CNTRL_CSS (BIT(8)) -#define PCIE_DMA_CHNL_CNTRL_LLE (BIT(9)) -#define PCIE_DMA_CHNL_CNTRL_TLP (BIT(26)) - -#define PCIE_DMA_CHNL_CONTEXT_RD (BIT(31)) -#define PCIE_DMA_CHNL_CONTEXT_WR (0) -#define PCIE_MAX_BAR (6) - /* PCIe HDP interrupt status definition */ #define PCIE_HDP_INT_EP_RXDMA (BIT(0)) #define PCIE_HDP_INT_HBM_UF (BIT(1)) diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c new file mode 100644 index 000000000000..598edb814421 --- /dev/null +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c @@ -0,0 +1,1219 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2018 Quantenna Communications */ + +#include <linux/kernel.h> +#include <linux/firmware.h> +#include <linux/pci.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/crc32.h> +#include <linux/completion.h> +#include <linux/spinlock.h> +#include <linux/circ_buf.h> + +#include "pcie_priv.h" +#include "topaz_pcie_regs.h" +#include "topaz_pcie_ipc.h" +#include "qtn_hw_ids.h" +#include "core.h" +#include "bus.h" +#include "shm_ipc.h" +#include "debug.h" + +#define TOPAZ_TX_BD_SIZE_DEFAULT 128 + +struct qtnf_topaz_tx_bd { + __le32 addr; + __le32 info; +} __packed; + +struct qtnf_topaz_rx_bd { + __le32 addr; + __le32 info; +} __packed; + +struct qtnf_extra_bd_params { + __le32 param1; + __le32 param2; + __le32 param3; + __le32 param4; +} __packed; + +#define QTNF_BD_PARAM_OFFSET(n) offsetof(struct qtnf_extra_bd_params, param##n) + +struct vmac_pkt_info { + __le32 addr; + __le32 info; +}; + +struct qtnf_topaz_bda { + __le16 bda_len; + __le16 bda_version; + __le32 bda_bootstate; + __le32 bda_dma_mask; + __le32 bda_dma_offset; + __le32 bda_flags; + __le32 bda_img; + __le32 bda_img_size; + __le32 bda_ep2h_irqstatus; + __le32 bda_h2ep_irqstatus; + __le32 bda_msi_addr; + u8 reserved1[56]; + __le32 bda_flashsz; + u8 bda_boardname[PCIE_BDA_NAMELEN]; + __le32 bda_pci_pre_status; + __le32 bda_pci_endian; + __le32 bda_pci_post_status; + __le32 bda_h2ep_txd_budget; + __le32 bda_ep2h_txd_budget; + __le32 bda_rc_rx_bd_base; + __le32 bda_rc_rx_bd_num; + __le32 bda_rc_tx_bd_base; + __le32 bda_rc_tx_bd_num; + u8 bda_ep_link_state; + u8 bda_rc_link_state; + u8 bda_rc_msi_enabled; + u8 reserved2; + __le32 bda_ep_next_pkt; + struct vmac_pkt_info request[QTN_PCIE_RC_TX_QUEUE_LEN]; + struct qtnf_shm_ipc_region bda_shm_reg1 __aligned(4096); + struct qtnf_shm_ipc_region bda_shm_reg2 __aligned(4096); +} __packed; + +struct qtnf_pcie_topaz_state { + struct qtnf_pcie_bus_priv base; + struct qtnf_topaz_bda __iomem *bda; + + dma_addr_t dma_msi_dummy; + u32 dma_msi_imwr; + + struct qtnf_topaz_tx_bd *tx_bd_vbase; + struct qtnf_topaz_rx_bd *rx_bd_vbase; + + __le32 __iomem *ep_next_rx_pkt; + __le32 __iomem *txqueue_wake; + __le32 __iomem *ep_pmstate; + + unsigned long rx_pkt_count; +}; + +static void qtnf_deassert_intx(struct qtnf_pcie_topaz_state *ts) +{ + void __iomem *reg = ts->base.sysctl_bar + TOPAZ_PCIE_CFG0_OFFSET; + u32 cfg; + + cfg = readl(reg); + cfg &= ~TOPAZ_ASSERT_INTX; + qtnf_non_posted_write(cfg, reg); +} + +static inline int qtnf_topaz_intx_asserted(struct qtnf_pcie_topaz_state *ts) +{ + void __iomem *reg = ts->base.sysctl_bar + TOPAZ_PCIE_CFG0_OFFSET; + u32 cfg = readl(reg); + + return !!(cfg & TOPAZ_ASSERT_INTX); +} + +static void qtnf_topaz_reset_ep(struct qtnf_pcie_topaz_state *ts) +{ + writel(TOPAZ_IPC_IRQ_WORD(TOPAZ_RC_RST_EP_IRQ), + TOPAZ_LH_IPC4_INT(ts->base.sysctl_bar)); + msleep(QTN_EP_RESET_WAIT_MS); + pci_restore_state(ts->base.pdev); +} + +static void setup_rx_irqs(struct qtnf_pcie_topaz_state *ts) +{ + void __iomem *reg = PCIE_DMA_WR_DONE_IMWR_ADDR_LOW(ts->base.dmareg_bar); + + ts->dma_msi_imwr = readl(reg); +} + +static void enable_rx_irqs(struct qtnf_pcie_topaz_state *ts) +{ + void __iomem *reg = PCIE_DMA_WR_DONE_IMWR_ADDR_LOW(ts->base.dmareg_bar); + + qtnf_non_posted_write(ts->dma_msi_imwr, reg); +} + +static void disable_rx_irqs(struct qtnf_pcie_topaz_state *ts) +{ + void __iomem *reg = PCIE_DMA_WR_DONE_IMWR_ADDR_LOW(ts->base.dmareg_bar); + + qtnf_non_posted_write(QTN_HOST_LO32(ts->dma_msi_dummy), reg); +} + +static void qtnf_topaz_ipc_gen_ep_int(void *arg) +{ + struct qtnf_pcie_topaz_state *ts = arg; + + writel(TOPAZ_IPC_IRQ_WORD(TOPAZ_RC_CTRL_IRQ), + TOPAZ_CTL_M2L_INT(ts->base.sysctl_bar)); +} + +static int qtnf_is_state(__le32 __iomem *reg, u32 state) +{ + u32 s = readl(reg); + + return (s == state); +} + +static void qtnf_set_state(__le32 __iomem *reg, u32 state) +{ + qtnf_non_posted_write(state, reg); +} + +static int qtnf_poll_state(__le32 __iomem *reg, u32 state, u32 delay_in_ms) +{ + u32 timeout = 0; + + while ((qtnf_is_state(reg, state) == 0)) { + usleep_range(1000, 1200); + if (++timeout > delay_in_ms) + return -1; + } + + return 0; +} + +static int topaz_alloc_bd_table(struct qtnf_pcie_topaz_state *ts, + struct qtnf_topaz_bda __iomem *bda) +{ + struct qtnf_extra_bd_params __iomem *extra_params; + struct qtnf_pcie_bus_priv *priv = &ts->base; + dma_addr_t paddr; + void *vaddr; + int len; + int i; + + /* bd table */ + + len = priv->tx_bd_num * sizeof(struct qtnf_topaz_tx_bd) + + priv->rx_bd_num * sizeof(struct qtnf_topaz_rx_bd) + + sizeof(struct qtnf_extra_bd_params); + + vaddr = dmam_alloc_coherent(&priv->pdev->dev, len, &paddr, GFP_KERNEL); + if (!vaddr) + return -ENOMEM; + + memset(vaddr, 0, len); + + /* tx bd */ + + ts->tx_bd_vbase = vaddr; + qtnf_non_posted_write(paddr, &bda->bda_rc_tx_bd_base); + + for (i = 0; i < priv->tx_bd_num; i++) + ts->tx_bd_vbase[i].info |= cpu_to_le32(QTN_BD_EMPTY); + + pr_debug("TX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr); + + priv->tx_bd_r_index = 0; + priv->tx_bd_w_index = 0; + + /* rx bd */ + + vaddr = ((struct qtnf_topaz_tx_bd *)vaddr) + priv->tx_bd_num; + paddr += priv->tx_bd_num * sizeof(struct qtnf_topaz_tx_bd); + + ts->rx_bd_vbase = vaddr; + qtnf_non_posted_write(paddr, &bda->bda_rc_rx_bd_base); + + pr_debug("RX descriptor table: vaddr=0x%p paddr=%pad\n", vaddr, &paddr); + + /* extra shared params */ + + vaddr = ((struct qtnf_topaz_rx_bd *)vaddr) + priv->rx_bd_num; + paddr += priv->rx_bd_num * sizeof(struct qtnf_topaz_rx_bd); + + extra_params = (struct qtnf_extra_bd_params __iomem *)vaddr; + + ts->ep_next_rx_pkt = &extra_params->param1; + qtnf_non_posted_write(paddr + QTNF_BD_PARAM_OFFSET(1), + &bda->bda_ep_next_pkt); + ts->txqueue_wake = &extra_params->param2; + ts->ep_pmstate = &extra_params->param3; + ts->dma_msi_dummy = paddr + QTNF_BD_PARAM_OFFSET(4); + + return 0; +} + +static int +topaz_skb2rbd_attach(struct qtnf_pcie_topaz_state *ts, u16 index, u32 wrap) +{ + struct qtnf_topaz_rx_bd *rxbd = &ts->rx_bd_vbase[index]; + struct sk_buff *skb; + dma_addr_t paddr; + + skb = __netdev_alloc_skb_ip_align(NULL, SKB_BUF_SIZE, GFP_ATOMIC); + if (!skb) { + ts->base.rx_skb[index] = NULL; + return -ENOMEM; + } + + ts->base.rx_skb[index] = skb; + + paddr = pci_map_single(ts->base.pdev, skb->data, + SKB_BUF_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(ts->base.pdev, paddr)) { + pr_err("skb mapping error: %pad\n", &paddr); + return -ENOMEM; + } + + rxbd->addr = cpu_to_le32(QTN_HOST_LO32(paddr)); + rxbd->info = cpu_to_le32(QTN_BD_EMPTY | wrap); + + ts->base.rx_bd_w_index = index; + + return 0; +} + +static int topaz_alloc_rx_buffers(struct qtnf_pcie_topaz_state *ts) +{ + u16 i; + int ret = 0; + + memset(ts->rx_bd_vbase, 0x0, + ts->base.rx_bd_num * sizeof(struct qtnf_topaz_rx_bd)); + + for (i = 0; i < ts->base.rx_bd_num; i++) { + ret = topaz_skb2rbd_attach(ts, i, 0); + if (ret) + break; + } + + ts->rx_bd_vbase[ts->base.rx_bd_num - 1].info |= + cpu_to_le32(QTN_BD_WRAP); + + return ret; +} + +/* all rx/tx activity should have ceased before calling this function */ +static void qtnf_topaz_free_xfer_buffers(struct qtnf_pcie_topaz_state *ts) +{ + struct qtnf_pcie_bus_priv *priv = &ts->base; + struct qtnf_topaz_rx_bd *rxbd; + struct qtnf_topaz_tx_bd *txbd; + struct sk_buff *skb; + dma_addr_t paddr; + int i; + + /* free rx buffers */ + for (i = 0; i < priv->rx_bd_num; i++) { + if (priv->rx_skb && priv->rx_skb[i]) { + rxbd = &ts->rx_bd_vbase[i]; + skb = priv->rx_skb[i]; + paddr = QTN_HOST_ADDR(0x0, le32_to_cpu(rxbd->addr)); + pci_unmap_single(priv->pdev, paddr, SKB_BUF_SIZE, + PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + priv->rx_skb[i] = NULL; + rxbd->addr = 0; + rxbd->info = 0; + } + } + + /* free tx buffers */ + for (i = 0; i < priv->tx_bd_num; i++) { + if (priv->tx_skb && priv->tx_skb[i]) { + txbd = &ts->tx_bd_vbase[i]; + skb = priv->tx_skb[i]; + paddr = QTN_HOST_ADDR(0x0, le32_to_cpu(txbd->addr)); + pci_unmap_single(priv->pdev, paddr, SKB_BUF_SIZE, + PCI_DMA_TODEVICE); + dev_kfree_skb_any(skb); + priv->tx_skb[i] = NULL; + txbd->addr = 0; + txbd->info = 0; + } + } +} + +static int qtnf_pcie_topaz_init_xfer(struct qtnf_pcie_topaz_state *ts, + unsigned int tx_bd_size) +{ + struct qtnf_topaz_bda __iomem *bda = ts->bda; + struct qtnf_pcie_bus_priv *priv = &ts->base; + int ret; + + if (tx_bd_size == 0) + tx_bd_size = TOPAZ_TX_BD_SIZE_DEFAULT; + + /* check TX BD queue max length according to struct qtnf_topaz_bda */ + if (tx_bd_size > QTN_PCIE_RC_TX_QUEUE_LEN) { + pr_warn("TX BD queue cannot exceed %d\n", + QTN_PCIE_RC_TX_QUEUE_LEN); + tx_bd_size = QTN_PCIE_RC_TX_QUEUE_LEN; + } + + priv->tx_bd_num = tx_bd_size; + qtnf_non_posted_write(priv->tx_bd_num, &bda->bda_rc_tx_bd_num); + qtnf_non_posted_write(priv->rx_bd_num, &bda->bda_rc_rx_bd_num); + + priv->rx_bd_w_index = 0; + priv->rx_bd_r_index = 0; + + ret = qtnf_pcie_alloc_skb_array(priv); + if (ret) { + pr_err("failed to allocate skb array\n"); + return ret; + } + + ret = topaz_alloc_bd_table(ts, bda); + if (ret) { + pr_err("failed to allocate bd table\n"); + return ret; + } + + ret = topaz_alloc_rx_buffers(ts); + if (ret) { + pr_err("failed to allocate rx buffers\n"); + return ret; + } + + return ret; +} + +static void qtnf_topaz_data_tx_reclaim(struct qtnf_pcie_topaz_state *ts) +{ + struct qtnf_pcie_bus_priv *priv = &ts->base; + struct qtnf_topaz_tx_bd *txbd; + struct sk_buff *skb; + unsigned long flags; + dma_addr_t paddr; + u32 tx_done_index; + int count = 0; + int i; + + spin_lock_irqsave(&priv->tx_reclaim_lock, flags); + + tx_done_index = readl(ts->ep_next_rx_pkt); + i = priv->tx_bd_r_index; + + if (CIRC_CNT(priv->tx_bd_w_index, tx_done_index, priv->tx_bd_num)) + writel(TOPAZ_IPC_IRQ_WORD(TOPAZ_RC_TX_DONE_IRQ), + TOPAZ_LH_IPC4_INT(priv->sysctl_bar)); + + while (CIRC_CNT(tx_done_index, i, priv->tx_bd_num)) { + skb = priv->tx_skb[i]; + + if (likely(skb)) { + txbd = &ts->tx_bd_vbase[i]; + paddr = QTN_HOST_ADDR(0x0, le32_to_cpu(txbd->addr)); + pci_unmap_single(priv->pdev, paddr, skb->len, + PCI_DMA_TODEVICE); + + if (skb->dev) { + qtnf_update_tx_stats(skb->dev, skb); + if (unlikely(priv->tx_stopped)) { + qtnf_wake_all_queues(skb->dev); + priv->tx_stopped = 0; + } + } + + dev_kfree_skb_any(skb); + } + + priv->tx_skb[i] = NULL; + count++; + + if (++i >= priv->tx_bd_num) + i = 0; + } + + priv->tx_reclaim_done += count; + priv->tx_reclaim_req++; + priv->tx_bd_r_index = i; + + spin_unlock_irqrestore(&priv->tx_reclaim_lock, flags); +} + +static void qtnf_try_stop_xmit(struct qtnf_bus *bus, struct net_device *ndev) +{ + struct qtnf_pcie_topaz_state *ts = (void *)get_bus_priv(bus); + + if (ndev) { + netif_tx_stop_all_queues(ndev); + ts->base.tx_stopped = 1; + } + + writel(0x0, ts->txqueue_wake); + + /* sync up tx queue status before generating interrupt */ + dma_wmb(); + + /* send irq to card: tx stopped */ + writel(TOPAZ_IPC_IRQ_WORD(TOPAZ_RC_TX_STOP_IRQ), + TOPAZ_LH_IPC4_INT(ts->base.sysctl_bar)); + + /* schedule reclaim attempt */ + tasklet_hi_schedule(&ts->base.reclaim_tq); +} + +static void qtnf_try_wake_xmit(struct qtnf_bus *bus, struct net_device *ndev) +{ + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + int ready; + + ready = readl(ts->txqueue_wake); + if (ready) { + netif_wake_queue(ndev); + } else { + /* re-send irq to card: tx stopped */ + writel(TOPAZ_IPC_IRQ_WORD(TOPAZ_RC_TX_STOP_IRQ), + TOPAZ_LH_IPC4_INT(ts->base.sysctl_bar)); + } +} + +static int qtnf_tx_queue_ready(struct qtnf_pcie_topaz_state *ts) +{ + struct qtnf_pcie_bus_priv *priv = &ts->base; + + if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, + priv->tx_bd_num)) { + qtnf_topaz_data_tx_reclaim(ts); + + if (!CIRC_SPACE(priv->tx_bd_w_index, priv->tx_bd_r_index, + priv->tx_bd_num)) { + priv->tx_full_count++; + return 0; + } + } + + return 1; +} + +static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb) +{ + struct qtnf_pcie_topaz_state *ts = (void *)get_bus_priv(bus); + struct qtnf_pcie_bus_priv *priv = &ts->base; + struct qtnf_topaz_bda __iomem *bda = ts->bda; + struct qtnf_topaz_tx_bd *txbd; + dma_addr_t skb_paddr; + unsigned long flags; + int ret = 0; + int len; + int i; + + spin_lock_irqsave(&priv->tx_lock, flags); + + if (!qtnf_tx_queue_ready(ts)) { + qtnf_try_stop_xmit(bus, skb->dev); + spin_unlock_irqrestore(&priv->tx_lock, flags); + return NETDEV_TX_BUSY; + } + + i = priv->tx_bd_w_index; + priv->tx_skb[i] = skb; + len = skb->len; + + skb_paddr = pci_map_single(priv->pdev, skb->data, + skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pdev, skb_paddr)) { + ret = -ENOMEM; + goto tx_done; + } + + txbd = &ts->tx_bd_vbase[i]; + txbd->addr = cpu_to_le32(QTN_HOST_LO32(skb_paddr)); + + writel(QTN_HOST_LO32(skb_paddr), &bda->request[i].addr); + writel(len | QTN_PCIE_TX_VALID_PKT, &bda->request[i].info); + + /* sync up descriptor updates before generating interrupt */ + dma_wmb(); + + /* generate irq to card: tx done */ + writel(TOPAZ_IPC_IRQ_WORD(TOPAZ_RC_TX_DONE_IRQ), + TOPAZ_LH_IPC4_INT(priv->sysctl_bar)); + + if (++i >= priv->tx_bd_num) + i = 0; + + priv->tx_bd_w_index = i; + +tx_done: + if (ret) { + if (skb->dev) + skb->dev->stats.tx_dropped++; + dev_kfree_skb_any(skb); + } + + priv->tx_done_count++; + spin_unlock_irqrestore(&priv->tx_lock, flags); + + qtnf_topaz_data_tx_reclaim(ts); + + return NETDEV_TX_OK; +} + +static irqreturn_t qtnf_pcie_topaz_interrupt(int irq, void *data) +{ + struct qtnf_bus *bus = (struct qtnf_bus *)data; + struct qtnf_pcie_topaz_state *ts = (void *)get_bus_priv(bus); + struct qtnf_pcie_bus_priv *priv = &ts->base; + + if (!priv->msi_enabled && !qtnf_topaz_intx_asserted(ts)) + return IRQ_NONE; + + priv->pcie_irq_count++; + + qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in); + qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_out); + + if (napi_schedule_prep(&bus->mux_napi)) { + disable_rx_irqs(ts); + __napi_schedule(&bus->mux_napi); + } + + tasklet_hi_schedule(&priv->reclaim_tq); + + if (!priv->msi_enabled) + qtnf_deassert_intx(ts); + + return IRQ_HANDLED; +} + +static int qtnf_rx_data_ready(struct qtnf_pcie_topaz_state *ts) +{ + u16 index = ts->base.rx_bd_r_index; + struct qtnf_topaz_rx_bd *rxbd; + u32 descw; + + rxbd = &ts->rx_bd_vbase[index]; + descw = le32_to_cpu(rxbd->info); + + if (descw & QTN_BD_EMPTY) + return 0; + + return 1; +} + +static int qtnf_topaz_rx_poll(struct napi_struct *napi, int budget) +{ + struct qtnf_bus *bus = container_of(napi, struct qtnf_bus, mux_napi); + struct qtnf_pcie_topaz_state *ts = (void *)get_bus_priv(bus); + struct qtnf_pcie_bus_priv *priv = &ts->base; + struct net_device *ndev = NULL; + struct sk_buff *skb = NULL; + int processed = 0; + struct qtnf_topaz_rx_bd *rxbd; + dma_addr_t skb_paddr; + int consume; + u32 descw; + u32 poffset; + u32 psize; + u16 r_idx; + u16 w_idx; + int ret; + + while (processed < budget) { + if (!qtnf_rx_data_ready(ts)) + goto rx_out; + + r_idx = priv->rx_bd_r_index; + rxbd = &ts->rx_bd_vbase[r_idx]; + descw = le32_to_cpu(rxbd->info); + + skb = priv->rx_skb[r_idx]; + poffset = QTN_GET_OFFSET(descw); + psize = QTN_GET_LEN(descw); + consume = 1; + + if (descw & QTN_BD_EMPTY) { + pr_warn("skip invalid rxbd[%d]\n", r_idx); + consume = 0; + } + + if (!skb) { + pr_warn("skip missing rx_skb[%d]\n", r_idx); + consume = 0; + } + + if (skb && (skb_tailroom(skb) < psize)) { + pr_err("skip packet with invalid length: %u > %u\n", + psize, skb_tailroom(skb)); + consume = 0; + } + + if (skb) { + skb_paddr = QTN_HOST_ADDR(0x0, le32_to_cpu(rxbd->addr)); + pci_unmap_single(priv->pdev, skb_paddr, SKB_BUF_SIZE, + PCI_DMA_FROMDEVICE); + } + + if (consume) { + skb_reserve(skb, poffset); + skb_put(skb, psize); + ndev = qtnf_classify_skb(bus, skb); + if (likely(ndev)) { + qtnf_update_rx_stats(ndev, skb); + skb->protocol = eth_type_trans(skb, ndev); + netif_receive_skb(skb); + } else { + pr_debug("drop untagged skb\n"); + bus->mux_dev.stats.rx_dropped++; + dev_kfree_skb_any(skb); + } + } else { + if (skb) { + bus->mux_dev.stats.rx_dropped++; + dev_kfree_skb_any(skb); + } + } + + /* notify card about recv packets once per several packets */ + if (((++ts->rx_pkt_count) & RX_DONE_INTR_MSK) == 0) + writel(TOPAZ_IPC_IRQ_WORD(TOPAZ_RC_RX_DONE_IRQ), + TOPAZ_LH_IPC4_INT(priv->sysctl_bar)); + + priv->rx_skb[r_idx] = NULL; + if (++r_idx >= priv->rx_bd_num) + r_idx = 0; + + priv->rx_bd_r_index = r_idx; + + /* repalce processed buffer by a new one */ + w_idx = priv->rx_bd_w_index; + while (CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, + priv->rx_bd_num) > 0) { + if (++w_idx >= priv->rx_bd_num) + w_idx = 0; + + ret = topaz_skb2rbd_attach(ts, w_idx, + descw & QTN_BD_WRAP); + if (ret) { + pr_err("failed to allocate new rx_skb[%d]\n", + w_idx); + break; + } + } + + processed++; + } + +rx_out: + if (processed < budget) { + napi_complete(napi); + enable_rx_irqs(ts); + } + + return processed; +} + +static void +qtnf_pcie_data_tx_timeout(struct qtnf_bus *bus, struct net_device *ndev) +{ + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + + qtnf_try_wake_xmit(bus, ndev); + tasklet_hi_schedule(&ts->base.reclaim_tq); +} + +static void qtnf_pcie_data_rx_start(struct qtnf_bus *bus) +{ + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + + napi_enable(&bus->mux_napi); + enable_rx_irqs(ts); +} + +static void qtnf_pcie_data_rx_stop(struct qtnf_bus *bus) +{ + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + + disable_rx_irqs(ts); + napi_disable(&bus->mux_napi); +} + +static const struct qtnf_bus_ops qtnf_pcie_topaz_bus_ops = { + /* control path methods */ + .control_tx = qtnf_pcie_control_tx, + + /* data path methods */ + .data_tx = qtnf_pcie_data_tx, + .data_tx_timeout = qtnf_pcie_data_tx_timeout, + .data_rx_start = qtnf_pcie_data_rx_start, + .data_rx_stop = qtnf_pcie_data_rx_stop, +}; + +static int qtnf_dbg_irq_stats(struct seq_file *s, void *data) +{ + struct qtnf_bus *bus = dev_get_drvdata(s->private); + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + + seq_printf(s, "pcie_irq_count(%u)\n", ts->base.pcie_irq_count); + + return 0; +} + +static int qtnf_dbg_pkt_stats(struct seq_file *s, void *data) +{ + struct qtnf_bus *bus = dev_get_drvdata(s->private); + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + struct qtnf_pcie_bus_priv *priv = &ts->base; + u32 tx_done_index = readl(ts->ep_next_rx_pkt); + + seq_printf(s, "tx_full_count(%u)\n", priv->tx_full_count); + seq_printf(s, "tx_done_count(%u)\n", priv->tx_done_count); + seq_printf(s, "tx_reclaim_done(%u)\n", priv->tx_reclaim_done); + seq_printf(s, "tx_reclaim_req(%u)\n", priv->tx_reclaim_req); + + seq_printf(s, "tx_bd_r_index(%u)\n", priv->tx_bd_r_index); + seq_printf(s, "tx_done_index(%u)\n", tx_done_index); + seq_printf(s, "tx_bd_w_index(%u)\n", priv->tx_bd_w_index); + + seq_printf(s, "tx host queue len(%u)\n", + CIRC_CNT(priv->tx_bd_w_index, priv->tx_bd_r_index, + priv->tx_bd_num)); + seq_printf(s, "tx reclaim queue len(%u)\n", + CIRC_CNT(tx_done_index, priv->tx_bd_r_index, + priv->tx_bd_num)); + seq_printf(s, "tx card queue len(%u)\n", + CIRC_CNT(priv->tx_bd_w_index, tx_done_index, + priv->tx_bd_num)); + + seq_printf(s, "rx_bd_r_index(%u)\n", priv->rx_bd_r_index); + seq_printf(s, "rx_bd_w_index(%u)\n", priv->rx_bd_w_index); + seq_printf(s, "rx alloc queue len(%u)\n", + CIRC_SPACE(priv->rx_bd_w_index, priv->rx_bd_r_index, + priv->rx_bd_num)); + + return 0; +} + +static void qtnf_reset_dma_offset(struct qtnf_pcie_topaz_state *ts) +{ + struct qtnf_topaz_bda __iomem *bda = ts->bda; + u32 offset = readl(&bda->bda_dma_offset); + + if ((offset & PCIE_DMA_OFFSET_ERROR_MASK) != PCIE_DMA_OFFSET_ERROR) + return; + + writel(0x0, &bda->bda_dma_offset); +} + +static int qtnf_pcie_endian_detect(struct qtnf_pcie_topaz_state *ts) +{ + struct qtnf_topaz_bda __iomem *bda = ts->bda; + u32 timeout = 0; + u32 endian; + int ret = 0; + + writel(QTN_PCI_ENDIAN_DETECT_DATA, &bda->bda_pci_endian); + + /* flush endian modifications before status update */ + dma_wmb(); + + writel(QTN_PCI_ENDIAN_VALID_STATUS, &bda->bda_pci_pre_status); + + while (readl(&bda->bda_pci_post_status) != + QTN_PCI_ENDIAN_VALID_STATUS) { + usleep_range(1000, 1200); + if (++timeout > QTN_FW_DL_TIMEOUT_MS) { + pr_err("card endianness detection timed out\n"); + ret = -ETIMEDOUT; + goto endian_out; + } + } + + /* do not read before status is updated */ + dma_rmb(); + + endian = readl(&bda->bda_pci_endian); + WARN(endian != QTN_PCI_LITTLE_ENDIAN, + "%s: unexpected card endianness", __func__); + +endian_out: + writel(0, &bda->bda_pci_pre_status); + writel(0, &bda->bda_pci_post_status); + writel(0, &bda->bda_pci_endian); + + return ret; +} + +static int qtnf_pre_init_ep(struct qtnf_bus *bus) +{ + struct qtnf_pcie_topaz_state *ts = (void *)get_bus_priv(bus); + struct qtnf_topaz_bda __iomem *bda = ts->bda; + u32 flags; + int ret; + + ret = qtnf_pcie_endian_detect(ts); + if (ret < 0) { + pr_err("failed to detect card endianness\n"); + return ret; + } + + writeb(ts->base.msi_enabled, &ts->bda->bda_rc_msi_enabled); + qtnf_reset_dma_offset(ts); + + /* notify card about driver type and boot mode */ + flags = readl(&bda->bda_flags) | QTN_BDA_HOST_QLINK_DRV; + + if (ts->base.flashboot) + flags |= QTN_BDA_FLASH_BOOT; + else + flags &= ~QTN_BDA_FLASH_BOOT; + + writel(flags, &bda->bda_flags); + + qtnf_set_state(&ts->bda->bda_bootstate, QTN_BDA_FW_HOST_RDY); + if (qtnf_poll_state(&ts->bda->bda_bootstate, QTN_BDA_FW_TARGET_RDY, + QTN_FW_DL_TIMEOUT_MS)) { + pr_err("card is not ready to boot...\n"); + return -ETIMEDOUT; + } + + return ret; +} + +static int qtnf_post_init_ep(struct qtnf_pcie_topaz_state *ts) +{ + struct pci_dev *pdev = ts->base.pdev; + + setup_rx_irqs(ts); + disable_rx_irqs(ts); + + if (qtnf_poll_state(&ts->bda->bda_bootstate, QTN_BDA_FW_QLINK_DONE, + QTN_FW_QLINK_TIMEOUT_MS)) + return -ETIMEDOUT; + + enable_irq(pdev->irq); + return 0; +} + +static int +qtnf_ep_fw_load(struct qtnf_pcie_topaz_state *ts, const u8 *fw, u32 fw_size) +{ + struct qtnf_topaz_bda __iomem *bda = ts->bda; + struct pci_dev *pdev = ts->base.pdev; + u32 remaining = fw_size; + u8 *curr = (u8 *)fw; + u32 blksize; + u32 nblocks; + u32 offset; + u32 count; + u32 size; + dma_addr_t paddr; + void *data; + int ret = 0; + + pr_debug("FW upload started: fw_addr = 0x%p, size=%d\n", fw, fw_size); + + blksize = ts->base.fw_blksize; + + if (blksize < PAGE_SIZE) + blksize = PAGE_SIZE; + + while (blksize >= PAGE_SIZE) { + pr_debug("allocating %u bytes to upload FW\n", blksize); + data = dma_alloc_coherent(&pdev->dev, blksize, + &paddr, GFP_KERNEL); + if (data) + break; + blksize /= 2; + } + + if (!data) { + pr_err("failed to allocate DMA buffer for FW upload\n"); + ret = -ENOMEM; + goto fw_load_out; + } + + nblocks = NBLOCKS(fw_size, blksize); + offset = readl(&bda->bda_dma_offset); + + qtnf_set_state(&ts->bda->bda_bootstate, QTN_BDA_FW_HOST_LOAD); + if (qtnf_poll_state(&ts->bda->bda_bootstate, QTN_BDA_FW_EP_RDY, + QTN_FW_DL_TIMEOUT_MS)) { + pr_err("card is not ready to download FW\n"); + ret = -ETIMEDOUT; + goto fw_load_map; + } + + for (count = 0 ; count < nblocks; count++) { + size = (remaining > blksize) ? blksize : remaining; + + memcpy(data, curr, size); + qtnf_non_posted_write(paddr + offset, &bda->bda_img); + qtnf_non_posted_write(size, &bda->bda_img_size); + + pr_debug("chunk[%u] VA[0x%p] PA[%pad] sz[%u]\n", + count, (void *)curr, &paddr, size); + + qtnf_set_state(&ts->bda->bda_bootstate, QTN_BDA_FW_BLOCK_RDY); + if (qtnf_poll_state(&ts->bda->bda_bootstate, + QTN_BDA_FW_BLOCK_DONE, + QTN_FW_DL_TIMEOUT_MS)) { + pr_err("confirmation for block #%d timed out\n", count); + ret = -ETIMEDOUT; + goto fw_load_map; + } + + remaining = (remaining < size) ? remaining : (remaining - size); + curr += size; + } + + /* upload completion mark: zero-sized block */ + qtnf_non_posted_write(0, &bda->bda_img); + qtnf_non_posted_write(0, &bda->bda_img_size); + + qtnf_set_state(&ts->bda->bda_bootstate, QTN_BDA_FW_BLOCK_RDY); + if (qtnf_poll_state(&ts->bda->bda_bootstate, QTN_BDA_FW_BLOCK_DONE, + QTN_FW_DL_TIMEOUT_MS)) { + pr_err("confirmation for the last block timed out\n"); + ret = -ETIMEDOUT; + goto fw_load_map; + } + + /* RC is done */ + qtnf_set_state(&ts->bda->bda_bootstate, QTN_BDA_FW_BLOCK_END); + if (qtnf_poll_state(&ts->bda->bda_bootstate, QTN_BDA_FW_LOAD_DONE, + QTN_FW_DL_TIMEOUT_MS)) { + pr_err("confirmation for FW upload completion timed out\n"); + ret = -ETIMEDOUT; + goto fw_load_map; + } + + pr_debug("FW upload completed: totally sent %d blocks\n", count); + +fw_load_map: + dma_free_coherent(&pdev->dev, blksize, data, paddr); + +fw_load_out: + return ret; +} + +static int qtnf_topaz_fw_upload(struct qtnf_pcie_topaz_state *ts, + const char *fwname) +{ + const struct firmware *fw; + struct pci_dev *pdev = ts->base.pdev; + int ret; + + if (qtnf_poll_state(&ts->bda->bda_bootstate, + QTN_BDA_FW_LOAD_RDY, + QTN_FW_DL_TIMEOUT_MS)) { + pr_err("%s: card is not ready\n", fwname); + return -1; + } + + pr_info("starting firmware upload: %s\n", fwname); + + ret = request_firmware(&fw, fwname, &pdev->dev); + if (ret < 0) { + pr_err("%s: request_firmware error %d\n", fwname, ret); + return -1; + } + + ret = qtnf_ep_fw_load(ts, fw->data, fw->size); + release_firmware(fw); + + if (ret) + pr_err("%s: FW upload error\n", fwname); + + return ret; +} + +static void qtnf_topaz_fw_work_handler(struct work_struct *work) +{ + struct qtnf_bus *bus = container_of(work, struct qtnf_bus, fw_work); + struct qtnf_pcie_topaz_state *ts = (void *)get_bus_priv(bus); + int ret; + int bootloader_needed = readl(&ts->bda->bda_flags) & QTN_BDA_XMIT_UBOOT; + + qtnf_set_state(&ts->bda->bda_bootstate, QTN_BDA_FW_TARGET_BOOT); + + if (bootloader_needed) { + ret = qtnf_topaz_fw_upload(ts, QTN_PCI_TOPAZ_BOOTLD_NAME); + if (ret) + goto fw_load_exit; + + ret = qtnf_pre_init_ep(bus); + if (ret) + goto fw_load_exit; + + qtnf_set_state(&ts->bda->bda_bootstate, + QTN_BDA_FW_TARGET_BOOT); + } + + if (ts->base.flashboot) { + pr_info("booting firmware from flash\n"); + + ret = qtnf_poll_state(&ts->bda->bda_bootstate, + QTN_BDA_FW_FLASH_BOOT, + QTN_FW_DL_TIMEOUT_MS); + if (ret) + goto fw_load_exit; + } else { + ret = qtnf_topaz_fw_upload(ts, QTN_PCI_TOPAZ_FW_NAME); + if (ret) + goto fw_load_exit; + + qtnf_set_state(&ts->bda->bda_bootstate, QTN_BDA_FW_START); + ret = qtnf_poll_state(&ts->bda->bda_bootstate, + QTN_BDA_FW_CONFIG, + QTN_FW_QLINK_TIMEOUT_MS); + if (ret) { + pr_err("FW bringup timed out\n"); + goto fw_load_exit; + } + + qtnf_set_state(&ts->bda->bda_bootstate, QTN_BDA_FW_RUN); + ret = qtnf_poll_state(&ts->bda->bda_bootstate, + QTN_BDA_FW_RUNNING, + QTN_FW_QLINK_TIMEOUT_MS); + if (ret) { + pr_err("card bringup timed out\n"); + goto fw_load_exit; + } + } + + pr_info("firmware is up and running\n"); + + ret = qtnf_post_init_ep(ts); + if (ret) + pr_err("FW runtime failure\n"); + +fw_load_exit: + qtnf_pcie_fw_boot_done(bus, ret ? false : true); + + if (ret == 0) { + qtnf_debugfs_add_entry(bus, "pkt_stats", qtnf_dbg_pkt_stats); + qtnf_debugfs_add_entry(bus, "irq_stats", qtnf_dbg_irq_stats); + } +} + +static void qtnf_reclaim_tasklet_fn(unsigned long data) +{ + struct qtnf_pcie_topaz_state *ts = (void *)data; + + qtnf_topaz_data_tx_reclaim(ts); +} + +static u64 qtnf_topaz_dma_mask_get(void) +{ + return DMA_BIT_MASK(32); +} + +static int qtnf_pcie_topaz_probe(struct qtnf_bus *bus, unsigned int tx_bd_num) +{ + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + struct pci_dev *pdev = ts->base.pdev; + struct qtnf_shm_ipc_int ipc_int; + unsigned long irqflags; + int ret; + + bus->bus_ops = &qtnf_pcie_topaz_bus_ops; + INIT_WORK(&bus->fw_work, qtnf_topaz_fw_work_handler); + ts->bda = ts->base.epmem_bar; + + /* assign host msi irq before card init */ + if (ts->base.msi_enabled) + irqflags = IRQF_NOBALANCING; + else + irqflags = IRQF_NOBALANCING | IRQF_SHARED; + + ret = devm_request_irq(&pdev->dev, pdev->irq, + &qtnf_pcie_topaz_interrupt, + irqflags, "qtnf_topaz_irq", (void *)bus); + if (ret) { + pr_err("failed to request pcie irq %d\n", pdev->irq); + return ret; + } + + disable_irq(pdev->irq); + + ret = qtnf_pre_init_ep(bus); + if (ret) { + pr_err("failed to init card\n"); + return ret; + } + + ret = qtnf_pcie_topaz_init_xfer(ts, tx_bd_num); + if (ret) { + pr_err("PCIE xfer init failed\n"); + return ret; + } + + tasklet_init(&ts->base.reclaim_tq, qtnf_reclaim_tasklet_fn, + (unsigned long)ts); + netif_napi_add(&bus->mux_dev, &bus->mux_napi, + qtnf_topaz_rx_poll, 10); + + ipc_int.fn = qtnf_topaz_ipc_gen_ep_int; + ipc_int.arg = ts; + qtnf_pcie_init_shm_ipc(&ts->base, &ts->bda->bda_shm_reg1, + &ts->bda->bda_shm_reg2, &ipc_int); + + return 0; +} + +static void qtnf_pcie_topaz_remove(struct qtnf_bus *bus) +{ + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + + qtnf_topaz_reset_ep(ts); + qtnf_topaz_free_xfer_buffers(ts); +} + +#ifdef CONFIG_PM_SLEEP +static int qtnf_pcie_topaz_suspend(struct qtnf_bus *bus) +{ + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + struct pci_dev *pdev = ts->base.pdev; + + writel((u32 __force)PCI_D3hot, ts->ep_pmstate); + dma_wmb(); + writel(TOPAZ_IPC_IRQ_WORD(TOPAZ_RC_PM_EP_IRQ), + TOPAZ_LH_IPC4_INT(ts->base.sysctl_bar)); + + pci_save_state(pdev); + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int qtnf_pcie_topaz_resume(struct qtnf_bus *bus) +{ + struct qtnf_pcie_topaz_state *ts = get_bus_priv(bus); + struct pci_dev *pdev = ts->base.pdev; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_wake(pdev, PCI_D0, 0); + + writel((u32 __force)PCI_D0, ts->ep_pmstate); + dma_wmb(); + writel(TOPAZ_IPC_IRQ_WORD(TOPAZ_RC_PM_EP_IRQ), + TOPAZ_LH_IPC4_INT(ts->base.sysctl_bar)); + + return 0; +} +#endif + +struct qtnf_bus *qtnf_pcie_topaz_alloc(struct pci_dev *pdev) +{ + struct qtnf_bus *bus; + struct qtnf_pcie_topaz_state *ts; + + bus = devm_kzalloc(&pdev->dev, sizeof(*bus) + sizeof(*ts), GFP_KERNEL); + if (!bus) + return NULL; + + ts = get_bus_priv(bus); + ts->base.probe_cb = qtnf_pcie_topaz_probe; + ts->base.remove_cb = qtnf_pcie_topaz_remove; + ts->base.dma_mask_get_cb = qtnf_topaz_dma_mask_get; +#ifdef CONFIG_PM_SLEEP + ts->base.resume_cb = qtnf_pcie_topaz_resume; + ts->base.suspend_cb = qtnf_pcie_topaz_suspend; +#endif + + return bus; +} diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_ipc.h new file mode 100644 index 000000000000..eb30e9d08de2 --- /dev/null +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_ipc.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2018 Quantenna Communications */ + +#ifndef _QTN_FMAC_PCIE_IPC_H_ +#define _QTN_FMAC_PCIE_IPC_H_ + +#include <linux/types.h> + +#include "shm_ipc_defs.h" + +/* EP/RC status and flags */ +#define QTN_BDA_PCIE_INIT 0x01 +#define QTN_BDA_PCIE_RDY 0x02 +#define QTN_BDA_FW_LOAD_RDY 0x03 +#define QTN_BDA_FW_LOAD_DONE 0x04 +#define QTN_BDA_FW_START 0x05 +#define QTN_BDA_FW_RUN 0x06 +#define QTN_BDA_FW_HOST_RDY 0x07 +#define QTN_BDA_FW_TARGET_RDY 0x11 +#define QTN_BDA_FW_TARGET_BOOT 0x12 +#define QTN_BDA_FW_FLASH_BOOT 0x13 +#define QTN_BDA_FW_QLINK_DONE 0x14 +#define QTN_BDA_FW_HOST_LOAD 0x08 +#define QTN_BDA_FW_BLOCK_DONE 0x09 +#define QTN_BDA_FW_BLOCK_RDY 0x0A +#define QTN_BDA_FW_EP_RDY 0x0B +#define QTN_BDA_FW_BLOCK_END 0x0C +#define QTN_BDA_FW_CONFIG 0x0D +#define QTN_BDA_FW_RUNNING 0x0E +#define QTN_BDA_PCIE_FAIL 0x82 +#define QTN_BDA_FW_LOAD_FAIL 0x85 + +#define QTN_BDA_RCMODE BIT(1) +#define QTN_BDA_MSI BIT(2) +#define QTN_BDA_HOST_CALCMD BIT(3) +#define QTN_BDA_FLASH_PRESENT BIT(4) +#define QTN_BDA_FLASH_BOOT BIT(5) +#define QTN_BDA_XMIT_UBOOT BIT(6) +#define QTN_BDA_HOST_QLINK_DRV BIT(7) +#define QTN_BDA_TARGET_FBOOT_ERR BIT(8) +#define QTN_BDA_TARGET_FWLOAD_ERR BIT(9) +#define QTN_BDA_HOST_NOFW_ERR BIT(12) +#define QTN_BDA_HOST_MEMALLOC_ERR BIT(13) +#define QTN_BDA_HOST_MEMMAP_ERR BIT(14) +#define QTN_BDA_VER(x) (((x) >> 4) & 0xFF) +#define QTN_BDA_ERROR_MASK 0xFF00 + +/* registers and shmem address macros */ +#if BITS_PER_LONG == 64 +#define QTN_HOST_HI32(a) ((u32)(((u64)a) >> 32)) +#define QTN_HOST_LO32(a) ((u32)(((u64)a) & 0xffffffffUL)) +#define QTN_HOST_ADDR(h, l) ((((u64)h) << 32) | ((u64)l)) +#elif BITS_PER_LONG == 32 +#define QTN_HOST_HI32(a) 0 +#define QTN_HOST_LO32(a) ((u32)(((u32)a) & 0xffffffffUL)) +#define QTN_HOST_ADDR(h, l) ((u32)l) +#else +#error Unexpected BITS_PER_LONG value +#endif + +#define QTN_PCIE_BDA_VERSION 0x1001 + +#define PCIE_BDA_NAMELEN 32 + +#define QTN_PCIE_RC_TX_QUEUE_LEN 256 +#define QTN_PCIE_TX_VALID_PKT 0x80000000 +#define QTN_PCIE_PKT_LEN_MASK 0xffff + +#define QTN_BD_EMPTY ((uint32_t)0x00000001) +#define QTN_BD_WRAP ((uint32_t)0x00000002) +#define QTN_BD_MASK_LEN ((uint32_t)0xFFFF0000) +#define QTN_BD_MASK_OFFSET ((uint32_t)0x0000FF00) + +#define QTN_GET_LEN(x) (((x) >> 16) & 0xFFFF) +#define QTN_GET_OFFSET(x) (((x) >> 8) & 0xFF) +#define QTN_SET_LEN(len) (((len) & 0xFFFF) << 16) +#define QTN_SET_OFFSET(of) (((of) & 0xFF) << 8) + +#define RX_DONE_INTR_MSK ((0x1 << 6) - 1) + +#define PCIE_DMA_OFFSET_ERROR 0xFFFF +#define PCIE_DMA_OFFSET_ERROR_MASK 0xFFFF + +#define QTN_PCI_ENDIAN_DETECT_DATA 0x12345678 +#define QTN_PCI_ENDIAN_REVERSE_DATA 0x78563412 +#define QTN_PCI_ENDIAN_VALID_STATUS 0x3c3c3c3c +#define QTN_PCI_ENDIAN_INVALID_STATUS 0 +#define QTN_PCI_LITTLE_ENDIAN 0 +#define QTN_PCI_BIG_ENDIAN 0xffffffff + +#define NBLOCKS(size, blksize) \ + ((size) / (blksize) + (((size) % (blksize) > 0) ? 1 : 0)) + +#endif /* _QTN_FMAC_PCIE_IPC_H_ */ diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_regs.h b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_regs.h new file mode 100644 index 000000000000..4782e1ed3c2c --- /dev/null +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie_regs.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2018 Quantenna Communications */ + +#ifndef __TOPAZ_PCIE_H +#define __TOPAZ_PCIE_H + +/* Topaz PCIe DMA registers */ +#define PCIE_DMA_WR_INTR_STATUS(base) ((base) + 0x9bc) +#define PCIE_DMA_WR_INTR_MASK(base) ((base) + 0x9c4) +#define PCIE_DMA_WR_INTR_CLR(base) ((base) + 0x9c8) +#define PCIE_DMA_WR_ERR_STATUS(base) ((base) + 0x9cc) +#define PCIE_DMA_WR_DONE_IMWR_ADDR_LOW(base) ((base) + 0x9D0) +#define PCIE_DMA_WR_DONE_IMWR_ADDR_HIGH(base) ((base) + 0x9d4) + +#define PCIE_DMA_RD_INTR_STATUS(base) ((base) + 0x310) +#define PCIE_DMA_RD_INTR_MASK(base) ((base) + 0x319) +#define PCIE_DMA_RD_INTR_CLR(base) ((base) + 0x31c) +#define PCIE_DMA_RD_ERR_STATUS_LOW(base) ((base) + 0x324) +#define PCIE_DMA_RD_ERR_STATUS_HIGH(base) ((base) + 0x328) +#define PCIE_DMA_RD_DONE_IMWR_ADDR_LOW(base) ((base) + 0x33c) +#define PCIE_DMA_RD_DONE_IMWR_ADDR_HIGH(base) ((base) + 0x340) + +/* Topaz LHost IPC4 interrupt */ +#define TOPAZ_LH_IPC4_INT(base) ((base) + 0x13C) +#define TOPAZ_LH_IPC4_INT_MASK(base) ((base) + 0x140) + +#define TOPAZ_RC_TX_DONE_IRQ (0) +#define TOPAZ_RC_RST_EP_IRQ (1) +#define TOPAZ_RC_TX_STOP_IRQ (2) +#define TOPAZ_RC_RX_DONE_IRQ (3) +#define TOPAZ_RC_PM_EP_IRQ (4) + +/* Topaz LHost M2L interrupt */ +#define TOPAZ_CTL_M2L_INT(base) ((base) + 0x2C) +#define TOPAZ_CTL_M2L_INT_MASK(base) ((base) + 0x30) + +#define TOPAZ_RC_CTRL_IRQ (6) + +#define TOPAZ_IPC_IRQ_WORD(irq) (BIT(irq) | BIT(irq + 16)) + +/* PCIe legacy INTx */ +#define TOPAZ_PCIE_CFG0_OFFSET (0x6C) +#define TOPAZ_ASSERT_INTX BIT(9) + +#endif /* __TOPAZ_PCIE_H */ diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 99d37e3efba6..8d62addea895 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -71,6 +71,7 @@ struct qlink_msg_header { * @QLINK_HW_CAPAB_DFS_OFFLOAD: device implements DFS offload functionality * @QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR: device supports MAC Address * Randomization in probe requests. + * @QLINK_HW_CAPAB_OBSS_SCAN: device can perform OBSS scanning. */ enum qlink_hw_capab { QLINK_HW_CAPAB_REG_UPDATE = BIT(0), @@ -78,6 +79,8 @@ enum qlink_hw_capab { QLINK_HW_CAPAB_DFS_OFFLOAD = BIT(2), QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3), QLINK_HW_CAPAB_PWR_MGMT = BIT(4), + QLINK_HW_CAPAB_OBSS_SCAN = BIT(5), + QLINK_HW_CAPAB_SCAN_DWELL = BIT(6), }; enum qlink_iface_type { @@ -1149,6 +1152,8 @@ enum qlink_tlv_id { QTN_TLV_ID_MAX_SCAN_SSIDS = 0x0409, QTN_TLV_ID_WOWLAN_CAPAB = 0x0410, QTN_TLV_ID_WOWLAN_PATTERN = 0x0411, + QTN_TLV_ID_SCAN_FLUSH = 0x0412, + QTN_TLV_ID_SCAN_DWELL = 0x0413, }; struct qlink_tlv_hdr { diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index 54caeb38917c..960d5d97492f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -40,6 +40,14 @@ static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff *skb, memcpy(hdr->val, arr, arr_len); } +static inline void qtnf_cmd_skb_put_tlv_tag(struct sk_buff *skb, u16 tlv_id) +{ + struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr)); + + hdr->type = cpu_to_le16(tlv_id); + hdr->len = cpu_to_le16(0); +} + static inline void qtnf_cmd_skb_put_tlv_u8(struct sk_buff *skb, u16 tlv_id, u8 value) { diff --git a/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h index 1fe798a9a667..40295a511224 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h @@ -23,7 +23,7 @@ /* PCIE Device IDs */ -#define PCIE_DEVICE_ID_QTN_PEARL (0x0008) +#define PCIE_DEVICE_ID_QSR (0x0008) #define QTN_REG_SYS_CTRL_CSR 0x14 #define QTN_CHIP_ID_MASK 0xF0 @@ -35,6 +35,8 @@ /* FW names */ #define QTN_PCI_PEARL_FW_NAME "qtn/fmac_qsr10g.img" +#define QTN_PCI_TOPAZ_FW_NAME "qtn/fmac_qsr1000.img" +#define QTN_PCI_TOPAZ_BOOTLD_NAME "qtn/uboot_qsr1000.img" static inline unsigned int qtnf_chip_id_get(const void __iomem *regs_base) { diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c index aa106dd0a14b..2ec334199c2b 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c +++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c @@ -42,19 +42,18 @@ static void qtnf_shm_handle_new_data(struct qtnf_shm_ipc *ipc) if (unlikely(size == 0 || size > QTN_IPC_MAX_DATA_SZ)) { pr_err("wrong rx packet size: %zu\n", size); rx_buff_ok = false; - } else { - memcpy_fromio(ipc->rx_data, ipc->shm_region->data, size); + } + + if (likely(rx_buff_ok)) { + ipc->rx_packet_count++; + ipc->rx_callback.fn(ipc->rx_callback.arg, + ipc->shm_region->data, size); } writel(QTNF_SHM_IPC_ACK, &shm_reg_hdr->flags); readl(&shm_reg_hdr->flags); /* flush PCIe write */ ipc->interrupt.fn(ipc->interrupt.arg); - - if (likely(rx_buff_ok)) { - ipc->rx_packet_count++; - ipc->rx_callback.fn(ipc->rx_callback.arg, ipc->rx_data, size); - } } static void qtnf_shm_ipc_irq_work(struct work_struct *work) diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h index 453dd6477b12..c2a3702a9ee7 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h +++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h @@ -32,7 +32,7 @@ struct qtnf_shm_ipc_int { }; struct qtnf_shm_ipc_rx_callback { - void (*fn)(void *arg, const u8 *buf, size_t len); + void (*fn)(void *arg, const u8 __iomem *buf, size_t len); void *arg; }; @@ -51,8 +51,6 @@ struct qtnf_shm_ipc { u8 waiting_for_ack; - u8 rx_data[QTN_IPC_MAX_DATA_SZ] __aligned(sizeof(u32)); - struct qtnf_shm_ipc_int interrupt; struct qtnf_shm_ipc_rx_callback rx_callback; diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.c b/drivers/net/wireless/quantenna/qtnfmac/util.c index e745733ba417..3bc96b264769 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/util.c +++ b/drivers/net/wireless/quantenna/qtnfmac/util.c @@ -15,6 +15,7 @@ */ #include "util.h" +#include "qtn_hw_ids.h" void qtnf_sta_list_init(struct qtnf_sta_list *list) { @@ -116,3 +117,20 @@ void qtnf_sta_list_free(struct qtnf_sta_list *list) INIT_LIST_HEAD(&list->head); } + +const char *qtnf_chipid_to_string(unsigned long chip_id) +{ + switch (chip_id) { + case QTN_CHIP_ID_TOPAZ: + return "Topaz"; + case QTN_CHIP_ID_PEARL: + return "Pearl revA"; + case QTN_CHIP_ID_PEARL_B: + return "Pearl revB"; + case QTN_CHIP_ID_PEARL_C: + return "Pearl revC"; + default: + return "unknown"; + } +} +EXPORT_SYMBOL_GPL(qtnf_chipid_to_string); diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.h b/drivers/net/wireless/quantenna/qtnfmac/util.h index 0d4d92b11540..b8744baac332 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/util.h @@ -20,6 +20,8 @@ #include <linux/kernel.h> #include "core.h" +const char *qtnf_chipid_to_string(unsigned long chip_id); + void qtnf_sta_list_init(struct qtnf_sta_list *list); struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list, diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c index 0bc8b0249c57..49a732798395 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c @@ -1302,7 +1302,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, break; case 2: /* Failure, excessive retries */ __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags); - /* Don't break, this is a failed frame! */ + /* Fall through - this is a failed frame! */ default: /* Failure */ __set_bit(TXDONE_FAILURE, &txdesc.flags); } diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c index 1ff5434798ec..e8e7bfe1ba9b 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c @@ -1430,7 +1430,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, break; case 2: /* Failure, excessive retries */ __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags); - /* Don't break, this is a failed frame! */ + /* Fall through - this is a failed frame! */ default: /* Failure */ __set_bit(TXDONE_FAILURE, &txdesc.flags); } diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 9e7b8933d30c..0e95555aec62 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -2482,6 +2482,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, switch (rt2x00dev->default_ant.tx_chain_num) { case 1: rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); + /* fall through */ case 2: rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); break; @@ -2490,6 +2491,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, switch (rt2x00dev->default_ant.rx_chain_num) { case 1: rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); + /* fall through */ case 2: rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); break; @@ -9457,8 +9459,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) switch (rx_chains) { case 3: spec->ht.mcs.rx_mask[2] = 0xff; + /* fall through */ case 2: spec->ht.mcs.rx_mask[1] = 0xff; + /* fall through */ case 1: spec->ht.mcs.rx_mask[0] = 0xff; spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */ diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c index cb0e1196f2c2..4c5de8fc8f12 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c @@ -2226,7 +2226,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) break; case 6: /* Failure, excessive retries */ __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags); - /* Don't break, this is a failed frame! */ + /* Fall through - this is a failed frame! */ default: /* Failure */ __set_bit(TXDONE_FAILURE, &txdesc.flags); } diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 08c607c031bc..33ad87528d9a 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -889,8 +889,10 @@ static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev, switch (ccsindex = get_free_tx_ccs(local)) { case ECCSBUSY: pr_debug("ray_hw_xmit tx_ccs table busy\n"); + /* fall through */ case ECCSFULL: pr_debug("ray_hw_xmit No free tx ccs\n"); + /* fall through */ case ECARDGONE: netif_stop_queue(dev); return XMIT_NO_CCS; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 73f6fc0d4a01..2bd43057dda3 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -1153,6 +1153,7 @@ void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw) switch (hw->conf.chandef.width) { case NL80211_CHAN_WIDTH_20_NOHT: ht = false; + /* fall through */ case NL80211_CHAN_WIDTH_20: opmode |= BW_OPMODE_20MHZ; rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); @@ -1280,6 +1281,7 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw) switch (hw->conf.chandef.width) { case NL80211_CHAN_WIDTH_20_NOHT: ht = false; + /* fall through */ case NL80211_CHAN_WIDTH_20: rf_mode_bw |= WMAC_TRXPTCL_CTL_BW_20; subchannel = 0; @@ -1748,9 +1750,11 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) case 3: priv->ep_tx_low_queue = 1; priv->ep_tx_count++; + /* fall through */ case 2: priv->ep_tx_normal_queue = 1; priv->ep_tx_count++; + /* fall through */ case 1: priv->ep_tx_high_queue = 1; priv->ep_tx_count++; @@ -4918,11 +4922,10 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, struct device *dev = &priv->udev->dev; u32 queue, rts_rate; u16 pktlen = skb->len; - u16 seq_number; u16 rate_flag = tx_info->control.rates[0].flags; int tx_desc_size = priv->fops->tx_desc_size; int ret; - bool usedesc40, ampdu_enable, sgi = false, short_preamble = false; + bool ampdu_enable, sgi = false, short_preamble = false; if (skb_headroom(skb) < tx_desc_size) { dev_warn(dev, @@ -4946,7 +4949,6 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, if (ieee80211_is_action(hdr->frame_control)) rtl8xxxu_dump_action(dev, hdr); - usedesc40 = (tx_desc_size == 40); tx_info->rate_driver_data[0] = hw; if (control && control->sta) @@ -5013,7 +5015,6 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, else rts_rate = 0; - seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble, ampdu_enable, rts_rate); @@ -5691,6 +5692,7 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; case WLAN_CIPHER_SUITE_TKIP: key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + break; default: return -EOPNOTSUPP; } diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c index 6fbf8845a2ab..d748aab66aa2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c @@ -292,11 +292,9 @@ bool halbtc_send_bt_mp_operation(struct btc_coexist *btcoexist, u8 op_code, static void halbtc_leave_lps(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv; - struct rtl_ps_ctl *ppsc; bool ap_enable = false; rtlpriv = btcoexist->adapter; - ppsc = rtl_psc(rtlpriv); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, &ap_enable); @@ -315,11 +313,9 @@ static void halbtc_leave_lps(struct btc_coexist *btcoexist) static void halbtc_enter_lps(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv; - struct rtl_ps_ctl *ppsc; bool ap_enable = false; rtlpriv = btcoexist->adapter; - ppsc = rtl_psc(rtlpriv); btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, &ap_enable); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 4c1f8b08fc10..14dcb0816bc0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -29,7 +29,6 @@ #include "../stats.h" #include "reg.h" #include "def.h" -#include "phy.h" #include "trx.h" #include "led.h" #include "dm.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c index 85cedd083d2b..75bfa9dfef4a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c @@ -173,7 +173,7 @@ static int _rtl92d_fw_init(struct ieee80211_hw *hw) rtl_read_byte(rtlpriv, FW_MAC1_READY)); } RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Polling FW ready fail!! REG_MCUFWDL:0x%08ul\n", + "Polling FW ready fail!! REG_MCUFWDL:0x%08x\n", rtl_read_dword(rtlpriv, REG_MCUFWDL)); return -1; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c index 5cf29f5a4b54..3f3327878b51 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c @@ -509,13 +509,10 @@ bool rtl8723e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, int i; bool rtstatus = true; u32 *radioa_array_table; - u32 *radiob_array_table; - u16 radioa_arraylen, radiob_arraylen; + u16 radioa_arraylen; radioa_arraylen = RTL8723ERADIOA_1TARRAYLENGTH; radioa_array_table = RTL8723E_RADIOA_1TARRAY; - radiob_arraylen = RTL8723E_RADIOB_1TARRAYLENGTH; - radiob_array_table = RTL8723E_RADIOB_1TARRAY; rtstatus = true; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c index 61e86045f15c..1bbee0bfac23 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c @@ -475,10 +475,6 @@ u32 RTL8723E_RADIOA_1TARRAY[RTL8723ERADIOA_1TARRAYLENGTH] = { 0x000, 0x00030159, }; -u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH] = { - 0x0, -}; - u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH] = { 0x420, 0x00000080, 0x423, 0x00000000, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h index 57a548ceba7d..a044f3c456fa 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h @@ -36,8 +36,6 @@ extern u32 RTL8723EPHY_REG_1TARRAY[RTL8723E_PHY_REG_1TARRAY_LENGTH]; extern u32 RTL8723EPHY_REG_ARRAY_PG[RTL8723E_PHY_REG_ARRAY_PGLENGTH]; #define RTL8723ERADIOA_1TARRAYLENGTH 282 extern u32 RTL8723E_RADIOA_1TARRAY[RTL8723ERADIOA_1TARRAYLENGTH]; -#define RTL8723E_RADIOB_1TARRAYLENGTH 1 -extern u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH]; #define RTL8723E_MACARRAYLENGTH 172 extern u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH]; #define RTL8723E_AGCTAB_1TARRAYLENGTH 320 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index 317c1b3101da..ba258318ee9f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -3404,75 +3404,6 @@ static void rtl8821ae_update_hal_rate_table(struct ieee80211_hw *hw, "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); } -static u8 _rtl8821ae_mrate_idx_to_arfr_id( - struct ieee80211_hw *hw, u8 rate_index, - enum wireless_mode wirelessmode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 ret = 0; - switch (rate_index) { - case RATR_INX_WIRELESS_NGB: - if (rtlphy->rf_type == RF_1T1R) - ret = 1; - else - ret = 0; - ; break; - case RATR_INX_WIRELESS_N: - case RATR_INX_WIRELESS_NG: - if (rtlphy->rf_type == RF_1T1R) - ret = 5; - else - ret = 4; - ; break; - case RATR_INX_WIRELESS_NB: - if (rtlphy->rf_type == RF_1T1R) - ret = 3; - else - ret = 2; - ; break; - case RATR_INX_WIRELESS_GB: - ret = 6; - break; - case RATR_INX_WIRELESS_G: - ret = 7; - break; - case RATR_INX_WIRELESS_B: - ret = 8; - break; - case RATR_INX_WIRELESS_MC: - if ((wirelessmode == WIRELESS_MODE_B) - || (wirelessmode == WIRELESS_MODE_G) - || (wirelessmode == WIRELESS_MODE_N_24G) - || (wirelessmode == WIRELESS_MODE_AC_24G)) - ret = 6; - else - ret = 7; - case RATR_INX_WIRELESS_AC_5N: - if (rtlphy->rf_type == RF_1T1R) - ret = 10; - else - ret = 9; - break; - case RATR_INX_WIRELESS_AC_24N: - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { - if (rtlphy->rf_type == RF_1T1R) - ret = 10; - else - ret = 9; - } else { - if (rtlphy->rf_type == RF_1T1R) - ret = 11; - else - ret = 12; - } - break; - default: - ret = 0; break; - } - return ret; -} - static u32 _rtl8821ae_rate_to_bitmap_2ssvht(__le16 vht_rate) { u8 i, j, tmp_rate; @@ -3761,7 +3692,7 @@ static void rtl8821ae_update_hal_rate_mask(struct ieee80211_hw *hw, break; } - ratr_index = _rtl8821ae_mrate_idx_to_arfr_id(hw, ratr_index, wirelessmode); + ratr_index = rtl_mrate_idx_to_arfr_id(hw, ratr_index, wirelessmode); sta_entry->ratr_index = ratr_index; ratr_bitmap = _rtl8821ae_set_ra_vht_ratr_bitmap(hw, wirelessmode, ratr_bitmap); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index 176deb2b5386..a75451c246fd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -394,6 +394,7 @@ static void _rtl8812ae_phy_set_rfe_reg_24g(struct ieee80211_hw *hw) rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); break; } + /* fall through */ case 0: case 2: default: diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c index d7960dd5bf1a..b01c3c5e21c7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c @@ -29,7 +29,6 @@ #include "../stats.h" #include "reg.h" #include "def.h" -#include "phy.h" #include "trx.h" #include "led.h" #include "dm.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 0f3b98c5227f..87bc21bb5e8b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -1905,10 +1905,6 @@ struct rtl_efuse { u8 efuse_map[2][EFUSE_MAX_LOGICAL_SIZE]; u16 efuse_usedbytes; u8 efuse_usedpercentage; -#ifdef EFUSE_REPG_WORKAROUND - bool efuse_re_pg_sec1flag; - u8 efuse_re_pg_data[8]; -#endif u8 autoload_failflag; u8 autoload_status; diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c index 612c211e21a1..449f6d23c5e3 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c @@ -210,7 +210,7 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter) } /* This tells SDIO FIFO when to start read to host */ - rsi_dbg(INIT_ZONE, "%s: Initialzing SDIO read start level\n", __func__); + rsi_dbg(INIT_ZONE, "%s: Initializing SDIO read start level\n", __func__); byte = 0x24; status = rsi_sdio_write_register(adapter, @@ -223,7 +223,7 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter) return -1; } - rsi_dbg(INIT_ZONE, "%s: Initialzing FIFO ctrl registers\n", __func__); + rsi_dbg(INIT_ZONE, "%s: Initializing FIFO ctrl registers\n", __func__); byte = (128 - 32); status = rsi_sdio_write_register(adapter, diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c index 38678e9a0562..8dae92a79fe1 100644 --- a/drivers/net/wireless/st/cw1200/sta.c +++ b/drivers/net/wireless/st/cw1200/sta.c @@ -1123,7 +1123,7 @@ int cw1200_setup_mac(struct cw1200_common *priv) * * NOTE2: RSSI based reports have been switched to RCPI, since * FW has a bug and RSSI reported values are not stable, - * what can leads to signal level oscilations in user-end applications + * what can lead to signal level oscilations in user-end applications */ struct wsm_rcpi_rssi_threshold threshold = { .rssiRcpiMode = WSM_RCPI_RSSI_THRESHOLD_ENABLE | diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 89b0d0fade9f..26b187336875 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -27,6 +27,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/pm_runtime.h> +#include <linux/pm_wakeirq.h> #include "wlcore.h" #include "debug.h" @@ -957,6 +958,8 @@ static void wl1271_recovery_work(struct work_struct *work) BUG_ON(wl->conf.recovery.bug_on_recovery && !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); + clear_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); + if (wl->conf.recovery.no_recovery) { wl1271_info("No recovery (chosen on module load). Fw will remain stuck."); goto out_unlock; @@ -6625,13 +6628,25 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) } #ifdef CONFIG_PM + device_init_wakeup(wl->dev, true); + ret = enable_irq_wake(wl->irq); if (!ret) { wl->irq_wake_enabled = true; - device_init_wakeup(wl->dev, 1); if (pdev_data->pwr_in_suspend) wl->hw->wiphy->wowlan = &wlcore_wowlan_support; } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); + if (res) { + wl->wakeirq = res->start; + wl->wakeirq_flags = res->flags & IRQF_TRIGGER_MASK; + ret = dev_pm_set_dedicated_wake_irq(wl->dev, wl->wakeirq); + if (ret) + wl->wakeirq = -ENODEV; + } else { + wl->wakeirq = -ENODEV; + } #endif disable_irq(wl->irq); wl1271_power_off(wl); @@ -6659,6 +6674,9 @@ out_unreg: wl1271_unregister_hw(wl); out_irq: + if (wl->wakeirq >= 0) + dev_pm_clear_wake_irq(wl->dev); + device_init_wakeup(wl->dev, false); free_irq(wl->irq, wl); out_free_nvs: @@ -6710,6 +6728,7 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) int ret; unsigned long start_time = jiffies; bool pending = false; + bool recovery = false; /* Nothing to do if no ELP mode requested */ if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) @@ -6726,7 +6745,7 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); if (ret < 0) { - wl12xx_queue_recovery_work(wl); + recovery = true; goto err; } @@ -6734,11 +6753,12 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) ret = wait_for_completion_timeout(&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); if (ret == 0) { - wl1271_error("ELP wakeup timeout!"); - wl12xx_queue_recovery_work(wl); + wl1271_warning("ELP wakeup timeout!"); /* Return no error for runtime PM for recovery */ - return 0; + ret = 0; + recovery = true; + goto err; } } @@ -6753,6 +6773,12 @@ err: spin_lock_irqsave(&wl->wl_lock, flags); wl->elp_compl = NULL; spin_unlock_irqrestore(&wl->wl_lock, flags); + + if (recovery) { + set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); + wl12xx_queue_recovery_work(wl); + } + return ret; } @@ -6815,10 +6841,16 @@ int wlcore_remove(struct platform_device *pdev) if (!wl->initialized) return 0; - if (wl->irq_wake_enabled) { - device_init_wakeup(wl->dev, 0); - disable_irq_wake(wl->irq); + if (wl->wakeirq >= 0) { + dev_pm_clear_wake_irq(wl->dev); + wl->wakeirq = -ENODEV; } + + device_init_wakeup(wl->dev, false); + + if (wl->irq_wake_enabled) + disable_irq_wake(wl->irq); + wl1271_unregister_hw(wl); pm_runtime_put_sync(wl->dev); diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 750bea3574ee..4c2154b9e6a3 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -241,7 +241,7 @@ static const struct of_device_id wlcore_sdio_of_match_table[] = { { } }; -static int wlcore_probe_of(struct device *dev, int *irq, +static int wlcore_probe_of(struct device *dev, int *irq, int *wakeirq, struct wlcore_platdev_data *pdev_data) { struct device_node *np = dev->of_node; @@ -259,6 +259,8 @@ static int wlcore_probe_of(struct device *dev, int *irq, return -EINVAL; } + *wakeirq = irq_of_parse_and_map(np, 1); + /* optional clock frequency params */ of_property_read_u32(np, "ref-clock-frequency", &pdev_data->ref_clock_freq); @@ -268,7 +270,7 @@ static int wlcore_probe_of(struct device *dev, int *irq, return 0; } #else -static int wlcore_probe_of(struct device *dev, int *irq, +static int wlcore_probe_of(struct device *dev, int *irq, int *wakeirq, struct wlcore_platdev_data *pdev_data) { return -ENODATA; @@ -280,10 +282,10 @@ static int wl1271_probe(struct sdio_func *func, { struct wlcore_platdev_data *pdev_data; struct wl12xx_sdio_glue *glue; - struct resource res[1]; + struct resource res[2]; mmc_pm_flag_t mmcflags; int ret = -ENOMEM; - int irq; + int irq, wakeirq; const char *chip_family; /* We are only able to handle the wlan function */ @@ -308,7 +310,7 @@ static int wl1271_probe(struct sdio_func *func, /* Use block mode for transferring over one block size of data */ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; - ret = wlcore_probe_of(&func->dev, &irq, pdev_data); + ret = wlcore_probe_of(&func->dev, &irq, &wakeirq, pdev_data); if (ret) goto out; @@ -351,6 +353,11 @@ static int wl1271_probe(struct sdio_func *func, irqd_get_trigger_type(irq_get_irq_data(irq)); res[0].name = "irq"; + res[1].start = wakeirq; + res[1].flags = IORESOURCE_IRQ | + irqd_get_trigger_type(irq_get_irq_data(wakeirq)); + res[1].name = "wakeirq"; + ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); if (ret) { dev_err(glue->dev, "can't add resources\n"); diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.c b/drivers/net/wireless/ti/wlcore/vendor_cmd.c index dbe78d8491ef..7f34ec077ee5 100644 --- a/drivers/net/wireless/ti/wlcore/vendor_cmd.c +++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.c @@ -70,7 +70,7 @@ wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy, out: mutex_unlock(&wl->mutex); - return 0; + return ret; } static int diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index d4b1f66ef457..dd14850b0603 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -199,8 +199,10 @@ struct wl1271 { struct wl1271_if_operations *if_ops; int irq; + int wakeirq; int irq_flags; + int wakeirq_flags; spinlock_t wl_lock; diff --git a/drivers/net/wireless/zydas/zd1201.c b/drivers/net/wireless/zydas/zd1201.c index 253403899fe9..22c70f1f568c 100644 --- a/drivers/net/wireless/zydas/zd1201.c +++ b/drivers/net/wireless/zydas/zd1201.c @@ -969,6 +969,7 @@ static int zd1201_set_mode(struct net_device *dev, */ zd1201_join(zd, "\0-*#\0", 5); /* Put port in pIBSS */ + /* Fall through */ case 8: /* No pseudo-IBSS in wireless extensions (yet) */ porttype = ZD1201_PORTTYPE_PSEUDOIBSS; break; diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c index 1f6d9f357e57..9ccd780695f0 100644 --- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c @@ -235,7 +235,7 @@ void zd_mac_clear(struct zd_mac *mac) { flush_workqueue(zd_workqueue); zd_chip_clear(&mac->chip); - ZD_ASSERT(!spin_is_locked(&mac->lock)); + lockdep_assert_held(&mac->lock); ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); } |