forked from luck/tmp_suning_uos_patched
wireless-drivers-next patches for 4.15
Last minute patches before the merge window. Not really anything special standing out, mostly fixes or cleanup and some minor new features. Major changes: iwlwifi * some new PCI IDs -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJaBk4+AAoJEG4XJFUm622bUD0H/1pm0KIhu73lpMrwLYcQLhKg 70VlXQbOfGGJShtUuRo9h04rXFDjlxb8nSATYomyOmh+vAyWmgMXlMCCt+es9a/H wqf6wPTZNGSo0boNjKXr21LP9OT0a9qSSpU3uEBlSZqWVEsb/cw2/vZeqPn76uQv //s7HkHDQviIuvaKu23RZXH8uSmrwvTeTAOw2Km1F4BSoQVkcBSuOTcFWD9FYumG DDYr5oTH+Y2VUooRli5l+eSC5Iw1VsSHIVKBZNSS140PKFEmLYyjAI3OTzApA+w3 UBnTq7qA5WfxxnTW+7ysLh5Zn4jh7yFqqBueVQP5CrgIu3OqgDMVOc0A+9qeYQE= =wWET -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-for-davem-2017-11-11' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== wireless-drivers-next patches for 4.15 Last minute patches before the merge window. Not really anything special standing out, mostly fixes or cleanup and some minor new features. Major changes: iwlwifi * some new PCI IDs ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
7c5556decd
|
@ -71,6 +71,7 @@ struct brcmf_bus_dcmd {
|
|||
* @wowl_config: specify if dongle is configured for wowl when going to suspend
|
||||
* @get_ramsize: obtain size of device memory.
|
||||
* @get_memdump: obtain device memory dump in provided buffer.
|
||||
* @get_fwname: obtain firmware name.
|
||||
*
|
||||
* This structure provides an abstract interface towards the
|
||||
* bus specific driver. For control messages to common driver
|
||||
|
@ -87,6 +88,8 @@ struct brcmf_bus_ops {
|
|||
void (*wowl_config)(struct device *dev, bool enabled);
|
||||
size_t (*get_ramsize)(struct device *dev);
|
||||
int (*get_memdump)(struct device *dev, void *data, size_t len);
|
||||
int (*get_fwname)(struct device *dev, uint chip, uint chiprev,
|
||||
unsigned char *fw_name);
|
||||
};
|
||||
|
||||
|
||||
|
@ -224,6 +227,13 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)
|
|||
return bus->ops->get_memdump(bus->dev, data, len);
|
||||
}
|
||||
|
||||
static inline
|
||||
int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev,
|
||||
unsigned char *fw_name)
|
||||
{
|
||||
return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* interface functions from common layer
|
||||
*/
|
||||
|
|
|
@ -472,47 +472,6 @@ send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key)
|
|||
return err;
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
|
||||
{
|
||||
s32 err;
|
||||
u32 mode;
|
||||
|
||||
if (enable)
|
||||
mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
|
||||
else
|
||||
mode = 0;
|
||||
|
||||
/* Try to set and enable ARP offload feature, this may fail, then it */
|
||||
/* is simply not supported and err 0 will be returned */
|
||||
err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
|
||||
mode, err);
|
||||
err = 0;
|
||||
} else {
|
||||
err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n",
|
||||
enable, err);
|
||||
err = 0;
|
||||
} else
|
||||
brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n",
|
||||
enable, mode);
|
||||
}
|
||||
|
||||
err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n",
|
||||
enable, err);
|
||||
err = 0;
|
||||
} else
|
||||
brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n",
|
||||
enable, mode);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
brcmf_cfg80211_update_proto_addr_mode(struct wireless_dev *wdev)
|
||||
{
|
||||
|
@ -1084,7 +1043,6 @@ brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request)
|
|||
{
|
||||
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
||||
s32 err;
|
||||
u32 passive_scan;
|
||||
struct brcmf_scan_results *results;
|
||||
struct escan_info *escan = &cfg->escan_info;
|
||||
|
||||
|
@ -1092,13 +1050,7 @@ brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request)
|
|||
escan->ifp = ifp;
|
||||
escan->wiphy = cfg->wiphy;
|
||||
escan->escan_state = WL_ESCAN_STATE_SCANNING;
|
||||
passive_scan = cfg->active_scan ? 0 : 1;
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
|
||||
passive_scan);
|
||||
if (err) {
|
||||
brcmf_err("error (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
brcmf_scan_config_mpc(ifp, 0);
|
||||
results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
|
||||
results->version = 0;
|
||||
|
@ -1112,21 +1064,16 @@ brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request)
|
|||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
|
||||
struct cfg80211_scan_request *request,
|
||||
struct cfg80211_ssid *this_ssid)
|
||||
brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
|
||||
{
|
||||
struct brcmf_if *ifp = vif->ifp;
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct cfg80211_ssid *ssids;
|
||||
u32 passive_scan;
|
||||
bool escan_req;
|
||||
bool spec_scan;
|
||||
s32 err;
|
||||
struct brcmf_ssid_le ssid_le;
|
||||
u32 SSID_len;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
s32 err = 0;
|
||||
|
||||
brcmf_dbg(SCAN, "START ESCAN\n");
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);
|
||||
if (!check_vif_up(vif))
|
||||
return -EIO;
|
||||
|
||||
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
|
||||
brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
|
||||
|
@ -1142,8 +1089,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
|
|||
cfg->scan_status);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
|
||||
brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state);
|
||||
if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) {
|
||||
brcmf_err("Connecting: status (%lu)\n", vif->sme_state);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
@ -1151,96 +1098,38 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
|
|||
if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
|
||||
vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
|
||||
|
||||
escan_req = false;
|
||||
if (request) {
|
||||
/* scan bss */
|
||||
ssids = request->ssids;
|
||||
escan_req = true;
|
||||
} else {
|
||||
/* scan in ibss */
|
||||
/* we don't do escan in ibss */
|
||||
ssids = this_ssid;
|
||||
}
|
||||
brcmf_dbg(SCAN, "START ESCAN\n");
|
||||
|
||||
cfg->scan_request = request;
|
||||
set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||
if (escan_req) {
|
||||
cfg->escan_info.run = brcmf_run_escan;
|
||||
err = brcmf_p2p_scan_prep(wiphy, request, vif);
|
||||
if (err)
|
||||
goto scan_out;
|
||||
|
||||
err = brcmf_do_escan(vif->ifp, request);
|
||||
if (err)
|
||||
goto scan_out;
|
||||
} else {
|
||||
brcmf_dbg(SCAN, "ssid \"%s\", ssid_len (%d)\n",
|
||||
ssids->ssid, ssids->ssid_len);
|
||||
memset(&ssid_le, 0, sizeof(ssid_le));
|
||||
SSID_len = min_t(u8, sizeof(ssid_le.SSID), ssids->ssid_len);
|
||||
ssid_le.SSID_len = cpu_to_le32(0);
|
||||
spec_scan = false;
|
||||
if (SSID_len) {
|
||||
memcpy(ssid_le.SSID, ssids->ssid, SSID_len);
|
||||
ssid_le.SSID_len = cpu_to_le32(SSID_len);
|
||||
spec_scan = true;
|
||||
} else
|
||||
brcmf_dbg(SCAN, "Broadcast scan\n");
|
||||
cfg->escan_info.run = brcmf_run_escan;
|
||||
err = brcmf_p2p_scan_prep(wiphy, request, vif);
|
||||
if (err)
|
||||
goto scan_out;
|
||||
|
||||
passive_scan = cfg->active_scan ? 0 : 1;
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
|
||||
passive_scan);
|
||||
if (err) {
|
||||
brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
|
||||
goto scan_out;
|
||||
}
|
||||
brcmf_scan_config_mpc(ifp, 0);
|
||||
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, &ssid_le,
|
||||
sizeof(ssid_le));
|
||||
if (err) {
|
||||
if (err == -EBUSY)
|
||||
brcmf_dbg(INFO, "BUSY: scan for \"%s\" canceled\n",
|
||||
ssid_le.SSID);
|
||||
else
|
||||
brcmf_err("WLC_SCAN error (%d)\n", err);
|
||||
err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
|
||||
request->ie, request->ie_len);
|
||||
if (err)
|
||||
goto scan_out;
|
||||
|
||||
brcmf_scan_config_mpc(ifp, 1);
|
||||
goto scan_out;
|
||||
}
|
||||
}
|
||||
err = brcmf_do_escan(vif->ifp, request);
|
||||
if (err)
|
||||
goto scan_out;
|
||||
|
||||
/* Arm scan timeout timer */
|
||||
mod_timer(&cfg->escan_timeout, jiffies +
|
||||
BRCMF_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
|
||||
mod_timer(&cfg->escan_timeout,
|
||||
jiffies + msecs_to_jiffies(BRCMF_ESCAN_TIMER_INTERVAL_MS));
|
||||
|
||||
return 0;
|
||||
|
||||
scan_out:
|
||||
brcmf_err("scan error (%d)\n", err);
|
||||
clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
|
||||
cfg->scan_request = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
|
||||
{
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
s32 err = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);
|
||||
if (!check_vif_up(vif))
|
||||
return -EIO;
|
||||
|
||||
err = brcmf_cfg80211_escan(wiphy, vif, request, NULL);
|
||||
|
||||
if (err)
|
||||
brcmf_err("scan error (%d)\n", err);
|
||||
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
|
||||
{
|
||||
s32 err = 0;
|
||||
|
@ -5876,7 +5765,6 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
|
|||
|
||||
cfg->scan_request = NULL;
|
||||
cfg->pwr_save = true;
|
||||
cfg->active_scan = true; /* we do active scan per default */
|
||||
cfg->dongle_up = false; /* dongle is not up yet */
|
||||
err = brcmf_init_priv_mem(cfg);
|
||||
if (err)
|
||||
|
|
|
@ -283,7 +283,6 @@ struct brcmf_cfg80211_wowl {
|
|||
* @scan_status: scan activity on the dongle.
|
||||
* @pub: common driver information.
|
||||
* @channel: current channel.
|
||||
* @active_scan: current scan mode.
|
||||
* @int_escan_map: bucket map for which internal e-scan is done.
|
||||
* @ibss_starter: indicates this sta is ibss starter.
|
||||
* @pwr_save: indicate whether dongle to support power save mode.
|
||||
|
@ -316,7 +315,6 @@ struct brcmf_cfg80211_info {
|
|||
unsigned long scan_status;
|
||||
struct brcmf_pub *pub;
|
||||
u32 channel;
|
||||
bool active_scan;
|
||||
u32 int_escan_map;
|
||||
bool ibss_starter;
|
||||
bool pwr_save;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include "core.h"
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include "tracepoint.h"
|
||||
#include "common.h"
|
||||
#include "of.h"
|
||||
#include "firmware.h"
|
||||
|
||||
MODULE_AUTHOR("Broadcom Corporation");
|
||||
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
|
||||
|
@ -104,12 +106,140 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
|
|||
brcmf_err("Set join_pref error (%d)\n", err);
|
||||
}
|
||||
|
||||
static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
|
||||
struct brcmf_dload_data_le *dload_buf,
|
||||
u32 len)
|
||||
{
|
||||
s32 err;
|
||||
|
||||
flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT);
|
||||
dload_buf->flag = cpu_to_le16(flag);
|
||||
dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM);
|
||||
dload_buf->len = cpu_to_le32(len);
|
||||
dload_buf->crc = cpu_to_le32(0);
|
||||
len = sizeof(*dload_buf) + len - 1;
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name)
|
||||
{
|
||||
struct brcmf_bus *bus = ifp->drvr->bus_if;
|
||||
struct brcmf_rev_info *ri = &ifp->drvr->revinfo;
|
||||
u8 fw_name[BRCMF_FW_NAME_LEN];
|
||||
u8 *ptr;
|
||||
size_t len;
|
||||
s32 err;
|
||||
|
||||
memset(fw_name, 0, BRCMF_FW_NAME_LEN);
|
||||
err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name);
|
||||
if (err) {
|
||||
brcmf_err("get firmware name failed (%d)\n", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* generate CLM blob file name */
|
||||
ptr = strrchr(fw_name, '.');
|
||||
if (!ptr) {
|
||||
err = -ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
len = ptr - fw_name + 1;
|
||||
if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) {
|
||||
err = -E2BIG;
|
||||
} else {
|
||||
strlcpy(clm_name, fw_name, len);
|
||||
strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN);
|
||||
}
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
|
||||
{
|
||||
struct device *dev = ifp->drvr->bus_if->dev;
|
||||
struct brcmf_dload_data_le *chunk_buf;
|
||||
const struct firmware *clm = NULL;
|
||||
u8 clm_name[BRCMF_FW_NAME_LEN];
|
||||
u32 chunk_len;
|
||||
u32 datalen;
|
||||
u32 cumulative_len;
|
||||
u16 dl_flag = DL_BEGIN;
|
||||
u32 status;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
memset(clm_name, 0, BRCMF_FW_NAME_LEN);
|
||||
err = brcmf_c_get_clm_name(ifp, clm_name);
|
||||
if (err) {
|
||||
brcmf_err("get CLM blob file name failed (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = request_firmware(&clm, clm_name, dev);
|
||||
if (err) {
|
||||
if (err == -ENOENT) {
|
||||
brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n");
|
||||
return 0;
|
||||
}
|
||||
brcmf_err("request CLM blob file failed (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL);
|
||||
if (!chunk_buf) {
|
||||
err = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
datalen = clm->size;
|
||||
cumulative_len = 0;
|
||||
do {
|
||||
if (datalen > MAX_CHUNK_LEN) {
|
||||
chunk_len = MAX_CHUNK_LEN;
|
||||
} else {
|
||||
chunk_len = datalen;
|
||||
dl_flag |= DL_END;
|
||||
}
|
||||
memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len);
|
||||
|
||||
err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len);
|
||||
|
||||
dl_flag &= ~DL_BEGIN;
|
||||
|
||||
cumulative_len += chunk_len;
|
||||
datalen -= chunk_len;
|
||||
} while ((datalen > 0) && (err == 0));
|
||||
|
||||
if (err) {
|
||||
brcmf_err("clmload (%zu byte file) failed (%d); ",
|
||||
clm->size, err);
|
||||
/* Retrieve clmload_status and print */
|
||||
err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status);
|
||||
if (err)
|
||||
brcmf_err("get clmload_status failed (%d)\n", err);
|
||||
else
|
||||
brcmf_dbg(INFO, "clmload_status=%d\n", status);
|
||||
err = -EIO;
|
||||
}
|
||||
|
||||
kfree(chunk_buf);
|
||||
done:
|
||||
release_firmware(clm);
|
||||
return err;
|
||||
}
|
||||
|
||||
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
||||
{
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
u8 buf[BRCMF_DCMD_SMLEN];
|
||||
struct brcmf_rev_info_le revinfo;
|
||||
struct brcmf_rev_info *ri;
|
||||
char *clmver;
|
||||
char *ptr;
|
||||
s32 err;
|
||||
|
||||
|
@ -148,6 +278,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|||
}
|
||||
ri->result = err;
|
||||
|
||||
/* Do any CLM downloading */
|
||||
err = brcmf_c_process_clm_blob(ifp);
|
||||
if (err < 0) {
|
||||
brcmf_err("download CLM blob file failed, %d\n", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* query for 'ver' to get version info from firmware */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
strcpy(buf, "ver");
|
||||
|
@ -167,6 +304,26 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|||
ptr = strrchr(buf, ' ') + 1;
|
||||
strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
|
||||
|
||||
/* Query for 'clmver' to get CLM version info from firmware */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf));
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err);
|
||||
} else {
|
||||
clmver = (char *)buf;
|
||||
/* store CLM version for adding it to revinfo debugfs file */
|
||||
memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver));
|
||||
|
||||
/* Replace all newline/linefeed characters with space
|
||||
* character
|
||||
*/
|
||||
ptr = clmver;
|
||||
while ((ptr = strnchr(ptr, '\n', sizeof(buf))) != NULL)
|
||||
*ptr = ' ';
|
||||
|
||||
brcmf_dbg(INFO, "CLM version = %s\n", clmver);
|
||||
}
|
||||
|
||||
/* set mpc */
|
||||
err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
|
||||
if (err) {
|
||||
|
|
|
@ -71,6 +71,43 @@ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
|
|||
return ifp;
|
||||
}
|
||||
|
||||
void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
|
||||
{
|
||||
s32 err;
|
||||
u32 mode;
|
||||
|
||||
if (enable)
|
||||
mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
|
||||
else
|
||||
mode = 0;
|
||||
|
||||
/* Try to set and enable ARP offload feature, this may fail, then it */
|
||||
/* is simply not supported and err 0 will be returned */
|
||||
err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
|
||||
mode, err);
|
||||
} else {
|
||||
err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n",
|
||||
enable, err);
|
||||
} else {
|
||||
brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n",
|
||||
enable, mode);
|
||||
}
|
||||
}
|
||||
|
||||
err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable);
|
||||
if (err) {
|
||||
brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n",
|
||||
enable, err);
|
||||
} else {
|
||||
brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n",
|
||||
enable, mode);
|
||||
}
|
||||
}
|
||||
|
||||
static void _brcmf_set_multicast_list(struct work_struct *work)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
|
@ -134,6 +171,7 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
|
|||
if (err < 0)
|
||||
brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
|
||||
err);
|
||||
brcmf_configure_arp_nd_offload(ifp, !cmd_value);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
@ -950,6 +988,8 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data)
|
|||
seq_printf(s, "anarev: %u\n", ri->anarev);
|
||||
seq_printf(s, "nvramrev: %08x\n", ri->nvramrev);
|
||||
|
||||
seq_printf(s, "clmver: %s\n", bus_if->drvr->clmver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,6 +141,8 @@ struct brcmf_pub {
|
|||
struct notifier_block inetaddr_notifier;
|
||||
struct notifier_block inet6addr_notifier;
|
||||
struct brcmf_mp_device *settings;
|
||||
|
||||
u8 clmver[BRCMF_DCMD_SMLEN];
|
||||
};
|
||||
|
||||
/* forward declarations */
|
||||
|
@ -203,6 +205,7 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
|
|||
/* Return pointer to interface name */
|
||||
char *brcmf_ifname(struct brcmf_if *ifp);
|
||||
struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
|
||||
void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable);
|
||||
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
|
||||
bool is_p2pdev, const char *name, u8 *mac_addr);
|
||||
|
|
|
@ -155,6 +155,21 @@
|
|||
#define BRCMF_MFP_CAPABLE 1
|
||||
#define BRCMF_MFP_REQUIRED 2
|
||||
|
||||
/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each
|
||||
* ioctl. It is relatively small because firmware has small maximum size input
|
||||
* playload restriction for ioctls.
|
||||
*/
|
||||
#define MAX_CHUNK_LEN 1400
|
||||
|
||||
#define DLOAD_HANDLER_VER 1 /* Downloader version */
|
||||
#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */
|
||||
#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */
|
||||
|
||||
#define DL_BEGIN 0x0002
|
||||
#define DL_END 0x0004
|
||||
|
||||
#define DL_TYPE_CLM 2
|
||||
|
||||
/* join preference types for join_pref iovar */
|
||||
enum brcmf_join_pref_types {
|
||||
BRCMF_JOIN_PREF_RSSI = 1,
|
||||
|
@ -826,6 +841,22 @@ struct brcmf_pno_macaddr_le {
|
|||
u8 mac[ETH_ALEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_dload_data_le - data passing to firmware for downloading
|
||||
* @flag: flags related to download data.
|
||||
* @dload_type: type of download data.
|
||||
* @len: length in bytes of download data.
|
||||
* @crc: crc of download data.
|
||||
* @data: download data.
|
||||
*/
|
||||
struct brcmf_dload_data_le {
|
||||
__le16 flag;
|
||||
__le16 dload_type;
|
||||
__le32 len;
|
||||
__le32 crc;
|
||||
u8 data[1];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_pno_bssid_le - bssid configuration for PNO scan.
|
||||
*
|
||||
|
|
|
@ -692,10 +692,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
|
|||
|
||||
/* determine the scan engine parameters */
|
||||
sparams->bss_type = DOT11_BSSTYPE_ANY;
|
||||
if (p2p->cfg->active_scan)
|
||||
sparams->scan_type = 0;
|
||||
else
|
||||
sparams->scan_type = 1;
|
||||
sparams->scan_type = BRCMF_SCANTYPE_ACTIVE;
|
||||
|
||||
eth_broadcast_addr(sparams->bssid);
|
||||
sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS);
|
||||
|
@ -884,7 +881,7 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
|
|||
{
|
||||
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
|
||||
struct brcmf_p2p_info *p2p = &cfg->p2p;
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
if (brcmf_p2p_scan_is_p2p_request(request)) {
|
||||
/* find my listen channel */
|
||||
|
@ -907,9 +904,7 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy,
|
|||
/* override .run_escan() callback. */
|
||||
cfg->escan_info.run = brcmf_p2p_run_escan;
|
||||
}
|
||||
err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
|
||||
request->ie, request->ie_len);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1350,6 +1350,24 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int brcmf_pcie_get_fwname(struct device *dev, u32 chip, u32 chiprev,
|
||||
u8 *fw_name)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
|
||||
struct brcmf_pciedev_info *devinfo = buspub->devinfo;
|
||||
int ret = 0;
|
||||
|
||||
if (devinfo->fw_name[0] != '\0')
|
||||
strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
|
||||
else
|
||||
ret = brcmf_fw_map_chip_to_name(chip, chiprev,
|
||||
brcmf_pcie_fwnames,
|
||||
ARRAY_SIZE(brcmf_pcie_fwnames),
|
||||
fw_name, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
|
||||
.txdata = brcmf_pcie_tx,
|
||||
|
@ -1359,6 +1377,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
|
|||
.wowl_config = brcmf_pcie_wowl_config,
|
||||
.get_ramsize = brcmf_pcie_get_ramsize,
|
||||
.get_memdump = brcmf_pcie_get_memdump,
|
||||
.get_fwname = brcmf_pcie_get_fwname,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -260,10 +260,11 @@ struct rte_console {
|
|||
#define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */
|
||||
|
||||
/* tohostmailboxdata */
|
||||
#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */
|
||||
#define HMB_DATA_DEVREADY 2 /* talk to host after enable */
|
||||
#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */
|
||||
#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */
|
||||
#define HMB_DATA_NAKHANDLED 0x0001 /* retransmit NAK'd frame */
|
||||
#define HMB_DATA_DEVREADY 0x0002 /* talk to host after enable */
|
||||
#define HMB_DATA_FC 0x0004 /* per prio flowcontrol update flag */
|
||||
#define HMB_DATA_FWREADY 0x0008 /* fw ready for protocol activity */
|
||||
#define HMB_DATA_FWHALT 0x0010 /* firmware halted */
|
||||
|
||||
#define HMB_DATA_FCDATA_MASK 0xff000000
|
||||
#define HMB_DATA_FCDATA_SHIFT 24
|
||||
|
@ -1094,6 +1095,10 @@ static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
|
|||
offsetof(struct sdpcmd_regs, tosbmailbox));
|
||||
bus->sdcnt.f1regdata += 2;
|
||||
|
||||
/* dongle indicates the firmware has halted/crashed */
|
||||
if (hmb_data & HMB_DATA_FWHALT)
|
||||
brcmf_err("mailbox indicates firmware halted\n");
|
||||
|
||||
/* Dongle recomposed rx frames, accept them again */
|
||||
if (hmb_data & HMB_DATA_NAKHANDLED) {
|
||||
brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n",
|
||||
|
@ -1151,6 +1156,7 @@ static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
|
|||
HMB_DATA_NAKHANDLED |
|
||||
HMB_DATA_FC |
|
||||
HMB_DATA_FWREADY |
|
||||
HMB_DATA_FWHALT |
|
||||
HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK))
|
||||
brcmf_err("Unknown mailbox data content: 0x%02x\n",
|
||||
hmb_data);
|
||||
|
@ -3979,6 +3985,24 @@ brcmf_sdio_watchdog(unsigned long data)
|
|||
}
|
||||
}
|
||||
|
||||
static int brcmf_sdio_get_fwname(struct device *dev, u32 chip, u32 chiprev,
|
||||
u8 *fw_name)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||
int ret = 0;
|
||||
|
||||
if (sdiodev->fw_name[0] != '\0')
|
||||
strlcpy(fw_name, sdiodev->fw_name, BRCMF_FW_NAME_LEN);
|
||||
else
|
||||
ret = brcmf_fw_map_chip_to_name(chip, chiprev,
|
||||
brcmf_sdio_fwnames,
|
||||
ARRAY_SIZE(brcmf_sdio_fwnames),
|
||||
fw_name, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
|
||||
.stop = brcmf_sdio_bus_stop,
|
||||
.preinit = brcmf_sdio_bus_preinit,
|
||||
|
@ -3989,6 +4013,7 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
|
|||
.wowl_config = brcmf_sdio_wowl_config,
|
||||
.get_ramsize = brcmf_sdio_bus_get_ramsize,
|
||||
.get_memdump = brcmf_sdio_bus_get_memdump,
|
||||
.get_fwname = brcmf_sdio_get_fwname,
|
||||
};
|
||||
|
||||
static void brcmf_sdio_firmware_callback(struct device *dev, int err,
|
||||
|
|
|
@ -1128,12 +1128,30 @@ static void brcmf_usb_wowl_config(struct device *dev, bool enabled)
|
|||
device_set_wakeup_enable(devinfo->dev, false);
|
||||
}
|
||||
|
||||
static int brcmf_usb_get_fwname(struct device *dev, u32 chip, u32 chiprev,
|
||||
u8 *fw_name)
|
||||
{
|
||||
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (devinfo->fw_name[0] != '\0')
|
||||
strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
|
||||
else
|
||||
ret = brcmf_fw_map_chip_to_name(chip, chiprev,
|
||||
brcmf_usb_fwnames,
|
||||
ARRAY_SIZE(brcmf_usb_fwnames),
|
||||
fw_name, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
|
||||
.txdata = brcmf_usb_tx,
|
||||
.stop = brcmf_usb_down,
|
||||
.txctl = brcmf_usb_tx_ctlpkt,
|
||||
.rxctl = brcmf_usb_rx_ctlpkt,
|
||||
.wowl_config = brcmf_usb_wowl_config,
|
||||
.get_fwname = brcmf_usb_get_fwname,
|
||||
};
|
||||
|
||||
static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
|
||||
|
|
|
@ -2154,13 +2154,11 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
|
|||
u8 use_green;
|
||||
u8 active_tbl = 0;
|
||||
u8 valid_tx_ant;
|
||||
struct il_station_priv *sta_priv;
|
||||
|
||||
if (!sta || !lq_sta)
|
||||
return;
|
||||
|
||||
use_green = il4965_rs_use_green(il, sta);
|
||||
sta_priv = (void *)sta->drv_priv;
|
||||
|
||||
i = lq_sta->last_txrate_idx;
|
||||
|
||||
|
|
|
@ -100,14 +100,6 @@
|
|||
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
|
||||
#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
|
||||
|
||||
/* Max SDIO RX/TX aggregation sizes of the ADDBA request/response */
|
||||
#define MAX_RX_AGG_SIZE_8260_SDIO 21
|
||||
#define MAX_TX_AGG_SIZE_8260_SDIO 40
|
||||
|
||||
/* Max A-MPDU exponent for HT and VHT */
|
||||
#define MAX_HT_AMPDU_EXPONENT_8260_SDIO IEEE80211_HT_MAX_AMPDU_32K
|
||||
#define MAX_VHT_AMPDU_EXPONENT_8260_SDIO IEEE80211_VHT_MAX_AMPDU_32K
|
||||
|
||||
static const struct iwl_base_params iwl8000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
|
||||
.num_of_queues = 31,
|
||||
|
@ -234,48 +226,5 @@ const struct iwl_cfg iwl4165_2ac_cfg = {
|
|||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless-AC 8260",
|
||||
.fw_name_pre = IWL8000_FW_PRE,
|
||||
IWL_DEVICE_8260,
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
|
||||
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
|
||||
.max_tx_agg_size = MAX_TX_AGG_SIZE_8260_SDIO,
|
||||
.disable_dummy_notification = true,
|
||||
.max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
|
||||
.max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl8265_2ac_sdio_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless-AC 8265",
|
||||
.fw_name_pre = IWL8265_FW_PRE,
|
||||
IWL_DEVICE_8265,
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
|
||||
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
|
||||
.max_tx_agg_size = MAX_TX_AGG_SIZE_8260_SDIO,
|
||||
.disable_dummy_notification = true,
|
||||
.max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
|
||||
.max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless-AC 4165",
|
||||
.fw_name_pre = IWL8000_FW_PRE,
|
||||
IWL_DEVICE_8000,
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
|
||||
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
|
||||
.max_tx_agg_size = MAX_TX_AGG_SIZE_8260_SDIO,
|
||||
.bt_shared_single_ant = true,
|
||||
.disable_dummy_notification = true,
|
||||
.max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
|
||||
.max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_MAX));
|
||||
|
|
|
@ -81,28 +81,4 @@ struct iwl_fw_paging_cmd {
|
|||
__le32 device_phy_addr[NUM_OF_FW_PAGING_BLOCKS];
|
||||
} __packed; /* FW_PAGING_BLOCK_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* enum iwl_fw_item_id - FW item IDs
|
||||
*
|
||||
* @IWL_FW_ITEM_ID_PAGING: Address of the pages that the FW will upload
|
||||
* download
|
||||
*/
|
||||
enum iwl_fw_item_id {
|
||||
IWL_FW_ITEM_ID_PAGING = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_get_item_cmd - get an item from the fw
|
||||
* @item_id: ID of item to obtain, see &enum iwl_fw_item_id
|
||||
*/
|
||||
struct iwl_fw_get_item_cmd {
|
||||
__le32 item_id;
|
||||
} __packed; /* FW_GET_ITEM_CMD_API_S_VER_1 */
|
||||
|
||||
struct iwl_fw_get_item_resp {
|
||||
__le32 item_id;
|
||||
__le32 item_byte_cnt;
|
||||
__le32 item_val;
|
||||
} __packed; /* FW_GET_ITEM_RSP_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_paging_h__ */
|
||||
|
|
|
@ -136,7 +136,7 @@ enum iwl_ucode_tlv_type {
|
|||
IWL_UCODE_TLV_N_SCAN_CHANNELS = 31,
|
||||
IWL_UCODE_TLV_PAGING = 32,
|
||||
IWL_UCODE_TLV_SEC_RT_USNIFFER = 34,
|
||||
IWL_UCODE_TLV_SDIO_ADMA_ADDR = 35,
|
||||
/* 35 is unused */
|
||||
IWL_UCODE_TLV_FW_VERSION = 36,
|
||||
IWL_UCODE_TLV_FW_DBG_DEST = 38,
|
||||
IWL_UCODE_TLV_FW_DBG_CONF = 39,
|
||||
|
|
|
@ -138,11 +138,6 @@ struct fw_img {
|
|||
u32 paging_mem_size;
|
||||
};
|
||||
|
||||
struct iwl_sf_region {
|
||||
u32 addr;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
/*
|
||||
* Block paging calculations
|
||||
*/
|
||||
|
@ -257,7 +252,6 @@ enum iwl_fw_type {
|
|||
* @type: firmware type (&enum iwl_fw_type)
|
||||
* @cipher_scheme: optional external cipher scheme.
|
||||
* @human_readable: human readable version
|
||||
* @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until
|
||||
* 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
|
||||
|
@ -290,8 +284,6 @@ struct iwl_fw {
|
|||
struct iwl_fw_cipher_scheme cs[IWL_UCODE_MAX_CS];
|
||||
u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
|
||||
|
||||
u32 sdio_adma_addr;
|
||||
|
||||
struct iwl_fw_dbg_dest_tlv *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];
|
||||
|
|
|
@ -87,9 +87,6 @@ void iwl_free_fw_paging(struct iwl_fw_runtime *fwrt)
|
|||
get_order(paging->fw_paging_size));
|
||||
paging->fw_paging_block = NULL;
|
||||
}
|
||||
kfree(fwrt->trans->paging_download_buf);
|
||||
fwrt->trans->paging_download_buf = NULL;
|
||||
fwrt->trans->paging_db = NULL;
|
||||
|
||||
memset(fwrt->fw_paging_db, 0, sizeof(fwrt->fw_paging_db));
|
||||
}
|
||||
|
@ -100,13 +97,11 @@ static int iwl_alloc_fw_paging_mem(struct iwl_fw_runtime *fwrt,
|
|||
{
|
||||
struct page *block;
|
||||
dma_addr_t phys = 0;
|
||||
int blk_idx, order, num_of_pages, size, dma_enabled;
|
||||
int blk_idx, order, num_of_pages, size;
|
||||
|
||||
if (fwrt->fw_paging_db[0].fw_paging_block)
|
||||
return 0;
|
||||
|
||||
dma_enabled = is_device_dma_capable(fwrt->trans->dev);
|
||||
|
||||
/* ensure BLOCK_2_EXP_SIZE is power of 2 of PAGING_BLOCK_SIZE */
|
||||
BUILD_BUG_ON(BIT(BLOCK_2_EXP_SIZE) != PAGING_BLOCK_SIZE);
|
||||
|
||||
|
@ -139,24 +134,18 @@ static int iwl_alloc_fw_paging_mem(struct iwl_fw_runtime *fwrt,
|
|||
fwrt->fw_paging_db[blk_idx].fw_paging_block = block;
|
||||
fwrt->fw_paging_db[blk_idx].fw_paging_size = size;
|
||||
|
||||
if (dma_enabled) {
|
||||
phys = dma_map_page(fwrt->trans->dev, block, 0,
|
||||
PAGE_SIZE << order,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(fwrt->trans->dev, phys)) {
|
||||
/*
|
||||
* free the previous pages and the current one
|
||||
* since we failed to map_page.
|
||||
*/
|
||||
iwl_free_fw_paging(fwrt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
fwrt->fw_paging_db[blk_idx].fw_paging_phys = phys;
|
||||
} else {
|
||||
fwrt->fw_paging_db[blk_idx].fw_paging_phys =
|
||||
PAGING_ADDR_SIG |
|
||||
blk_idx << BLOCK_2_EXP_SIZE;
|
||||
phys = dma_map_page(fwrt->trans->dev, block, 0,
|
||||
PAGE_SIZE << order,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(fwrt->trans->dev, phys)) {
|
||||
/*
|
||||
* free the previous pages and the current one
|
||||
* since we failed to map_page.
|
||||
*/
|
||||
iwl_free_fw_paging(fwrt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
fwrt->fw_paging_db[blk_idx].fw_paging_phys = phys;
|
||||
|
||||
if (!blk_idx)
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
|
@ -312,60 +301,6 @@ static int iwl_send_paging_cmd(struct iwl_fw_runtime *fwrt,
|
|||
return iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send paging item cmd to FW in case CPU2 has paging image
|
||||
*/
|
||||
static int iwl_trans_get_paging_item(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_fw_get_item_cmd fw_get_item_cmd = {
|
||||
.item_id = cpu_to_le32(IWL_FW_ITEM_ID_PAGING),
|
||||
};
|
||||
struct iwl_fw_get_item_resp *item_resp;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = iwl_cmd_id(FW_GET_ITEM_CMD, IWL_ALWAYS_LONG_GROUP, 0),
|
||||
.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
|
||||
.data = { &fw_get_item_cmd, },
|
||||
.len = { sizeof(fw_get_item_cmd), },
|
||||
};
|
||||
|
||||
ret = iwl_trans_send_cmd(fwrt->trans, &cmd);
|
||||
if (ret) {
|
||||
IWL_ERR(fwrt,
|
||||
"Paging: Failed to send FW_GET_ITEM_CMD cmd (err = %d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
item_resp = (void *)((struct iwl_rx_packet *)cmd.resp_pkt)->data;
|
||||
if (item_resp->item_id != cpu_to_le32(IWL_FW_ITEM_ID_PAGING)) {
|
||||
IWL_ERR(fwrt,
|
||||
"Paging: got wrong item in FW_GET_ITEM_CMD resp (item_id = %u)\n",
|
||||
le32_to_cpu(item_resp->item_id));
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Add an extra page for headers */
|
||||
fwrt->trans->paging_download_buf = kzalloc(PAGING_BLOCK_SIZE +
|
||||
FW_PAGING_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (!fwrt->trans->paging_download_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
fwrt->trans->paging_req_addr = le32_to_cpu(item_resp->item_val);
|
||||
fwrt->trans->paging_db = fwrt->fw_paging_db;
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"Paging: got paging request address (paging_req_addr 0x%08x)\n",
|
||||
fwrt->trans->paging_req_addr);
|
||||
|
||||
exit:
|
||||
iwl_free_resp(&cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type)
|
||||
{
|
||||
const struct fw_img *fw = &fwrt->fw->img[type];
|
||||
|
@ -382,20 +317,6 @@ int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type)
|
|||
if (!fw->paging_mem_size)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* When dma is not enabled, the driver needs to copy / write
|
||||
* the downloaded / uploaded page to / from the smem.
|
||||
* This gets the location of the place were the pages are
|
||||
* stored.
|
||||
*/
|
||||
if (!is_device_dma_capable(fwrt->trans->dev)) {
|
||||
ret = iwl_trans_get_paging_item(fwrt);
|
||||
if (ret) {
|
||||
IWL_ERR(fwrt, "failed to get FW paging item\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_save_fw_paging(fwrt, fw);
|
||||
if (ret) {
|
||||
IWL_ERR(fwrt, "failed to save the FW paging image\n");
|
||||
|
|
|
@ -467,9 +467,6 @@ extern const struct iwl_cfg iwl8260_2ac_cfg;
|
|||
extern const struct iwl_cfg iwl8265_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl8275_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl4165_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
|
||||
extern const struct iwl_cfg iwl8265_2ac_sdio_cfg;
|
||||
extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
|
||||
extern const struct iwl_cfg iwl9160_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9270_2ac_cfg;
|
||||
|
|
|
@ -218,7 +218,6 @@
|
|||
#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
|
||||
#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
|
||||
#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
|
||||
#define CSR_INT_BIT_PAGING (1 << 24) /* SDIO PAGING */
|
||||
#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
|
||||
#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
|
||||
#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses */
|
||||
|
@ -229,7 +228,6 @@
|
|||
CSR_INT_BIT_HW_ERR | \
|
||||
CSR_INT_BIT_FH_TX | \
|
||||
CSR_INT_BIT_SW_ERR | \
|
||||
CSR_INT_BIT_PAGING | \
|
||||
CSR_INT_BIT_RF_KILL | \
|
||||
CSR_INT_BIT_SW_RX | \
|
||||
CSR_INT_BIT_WAKEUP | \
|
||||
|
|
|
@ -1039,12 +1039,6 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
|||
drv->fw.img[usniffer_img].paging_mem_size =
|
||||
paging_mem_size;
|
||||
break;
|
||||
case IWL_UCODE_TLV_SDIO_ADMA_ADDR:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
drv->fw.sdio_adma_addr =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_FW_GSCAN_CAPA:
|
||||
/*
|
||||
* Don't return an error in case of a shorter tlv_len
|
||||
|
|
|
@ -398,8 +398,6 @@ struct iwl_hcmd_arr {
|
|||
* @command_groups: array of command groups, each member is an array of the
|
||||
* commands in the group; for debugging only
|
||||
* @command_groups_size: number of command groups, to avoid illegal access
|
||||
* @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until
|
||||
* we get the ALIVE from the uCode
|
||||
* @cb_data_offs: offset inside skb->cb to store transport data at, must have
|
||||
* space for at least two pointers
|
||||
*/
|
||||
|
@ -419,8 +417,6 @@ struct iwl_trans_config {
|
|||
const struct iwl_hcmd_arr *command_groups;
|
||||
int command_groups_size;
|
||||
|
||||
u32 sdio_adma_addr;
|
||||
|
||||
u8 cb_data_offs;
|
||||
};
|
||||
|
||||
|
@ -524,6 +520,9 @@ struct iwl_trans_txq_scd_cfg {
|
|||
* @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last
|
||||
* TX'ed commands and similar. The buffer will be vfree'd by the caller.
|
||||
* Note that the transport must fill in the proper file headers.
|
||||
* @dump_regs: dump using IWL_ERR configuration space and memory mapped
|
||||
* registers of the device to diagnose failure, e.g., when HW becomes
|
||||
* inaccessible.
|
||||
*/
|
||||
struct iwl_trans_ops {
|
||||
|
||||
|
@ -531,8 +530,6 @@ struct iwl_trans_ops {
|
|||
void (*op_mode_leave)(struct iwl_trans *iwl_trans);
|
||||
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw,
|
||||
bool run_in_rfkill);
|
||||
int (*update_sf)(struct iwl_trans *trans,
|
||||
struct iwl_sf_region *st_fwrd_space);
|
||||
void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
|
||||
void (*stop_device)(struct iwl_trans *trans, bool low_power);
|
||||
|
||||
|
@ -593,6 +590,8 @@ struct iwl_trans_ops {
|
|||
struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans,
|
||||
const struct iwl_fw_dbg_trigger_tlv
|
||||
*trigger);
|
||||
|
||||
void (*dump_regs)(struct iwl_trans *trans);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -700,12 +699,6 @@ enum iwl_plat_pm_mode {
|
|||
* @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
|
||||
* @paging_req_addr: The location were the FW will upload / download the pages
|
||||
* from. The address is set by the opmode
|
||||
* @paging_db: Pointer to the opmode paging data base, the pointer is set by
|
||||
* the opmode.
|
||||
* @paging_download_buf: Buffer used for copying all of the pages before
|
||||
* downloading them to the FW. The buffer is allocated in the opmode
|
||||
* @system_pm_mode: the system-wide power management mode in use.
|
||||
* This mode is set dynamically, depending on the WoWLAN values
|
||||
* configured from the userspace at runtime.
|
||||
|
@ -754,14 +747,6 @@ struct iwl_trans {
|
|||
struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv;
|
||||
u8 dbg_dest_reg_num;
|
||||
|
||||
/*
|
||||
* Paging parameters - All of the parameters should be set by the
|
||||
* opmode when paging is enabled
|
||||
*/
|
||||
u32 paging_req_addr;
|
||||
struct iwl_fw_paging *paging_db;
|
||||
void *paging_download_buf;
|
||||
|
||||
enum iwl_plat_pm_mode system_pm_mode;
|
||||
enum iwl_plat_pm_mode runtime_pm_mode;
|
||||
bool suspending;
|
||||
|
@ -828,17 +813,6 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
|
|||
return trans->ops->start_fw(trans, fw, run_in_rfkill);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_update_sf(struct iwl_trans *trans,
|
||||
struct iwl_sf_region *st_fwrd_space)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (trans->ops->update_sf)
|
||||
return trans->ops->update_sf(trans, st_fwrd_space);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _iwl_trans_stop_device(struct iwl_trans *trans,
|
||||
bool low_power)
|
||||
{
|
||||
|
@ -896,6 +870,12 @@ iwl_trans_dump_data(struct iwl_trans *trans,
|
|||
return trans->ops->dump_data(trans, trigger);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_dump_regs(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->ops->dump_regs)
|
||||
trans->ops->dump_regs(trans);
|
||||
}
|
||||
|
||||
static inline struct iwl_device_cmd *
|
||||
iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
|
||||
{
|
||||
|
|
|
@ -196,8 +196,6 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
|||
mvm->error_event_table[1] =
|
||||
le32_to_cpu(lmac2->error_event_table_ptr);
|
||||
mvm->log_event_table = le32_to_cpu(lmac1->log_event_table_ptr);
|
||||
mvm->sf_space.addr = le32_to_cpu(lmac1->st_fwrd_addr);
|
||||
mvm->sf_space.size = le32_to_cpu(lmac1->st_fwrd_size);
|
||||
|
||||
umac_error_event_table = le32_to_cpu(umac->error_info_addr);
|
||||
|
||||
|
@ -266,7 +264,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
int ret, i;
|
||||
enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
|
||||
static const u16 alive_cmd[] = { MVM_ALIVE };
|
||||
struct iwl_sf_region st_fwrd_space;
|
||||
|
||||
if (ucode_type == IWL_UCODE_REGULAR &&
|
||||
iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
|
||||
|
@ -320,18 +317,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* update the sdio allocation according to the pointer we get in the
|
||||
* alive notification.
|
||||
*/
|
||||
st_fwrd_space.addr = mvm->sf_space.addr;
|
||||
st_fwrd_space.size = mvm->sf_space.size;
|
||||
ret = iwl_trans_update_sf(mvm->trans, &st_fwrd_space);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to update SF size. ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
|
||||
|
||||
/*
|
||||
|
|
|
@ -4002,39 +4002,36 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
|
|||
|
||||
static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
|
||||
{
|
||||
if (drop) {
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
/* TODO new tx api */
|
||||
WARN_ONCE(1,
|
||||
"Need to implement flush TX queue\n");
|
||||
else
|
||||
iwl_mvm_flush_tx_path(mvm,
|
||||
iwl_mvm_flushable_queues(mvm) & queues,
|
||||
0);
|
||||
} else {
|
||||
if (iwl_mvm_has_new_tx_api(mvm)) {
|
||||
struct ieee80211_sta *sta;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (!iwl_mvm_has_new_tx_api(mvm)) {
|
||||
if (drop) {
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
|
||||
sta = rcu_dereference_protected(
|
||||
mvm->fw_id_to_mac_id[i],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (IS_ERR_OR_NULL(sta))
|
||||
continue;
|
||||
|
||||
iwl_mvm_wait_sta_queues_empty(mvm,
|
||||
iwl_mvm_sta_from_mac80211(sta));
|
||||
}
|
||||
|
||||
iwl_mvm_flush_tx_path(mvm,
|
||||
iwl_mvm_flushable_queues(mvm) & queues, 0);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
} else {
|
||||
iwl_trans_wait_tx_queues_empty(mvm->trans,
|
||||
queues);
|
||||
iwl_trans_wait_tx_queues_empty(mvm->trans, queues);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
||||
lockdep_is_held(&mvm->mutex));
|
||||
if (IS_ERR_OR_NULL(sta))
|
||||
continue;
|
||||
|
||||
if (drop)
|
||||
iwl_mvm_flush_sta_tids(mvm, i, 0xFF, 0);
|
||||
else
|
||||
iwl_mvm_wait_sta_queues_empty(mvm,
|
||||
iwl_mvm_sta_from_mac80211(sta));
|
||||
}
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
|
||||
|
@ -4294,9 +4291,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
|
|||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* TODO - remove a000 disablement when we have RXQ config API */
|
||||
if (!iwl_mvm_has_new_rx_api(mvm) ||
|
||||
mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_A000)
|
||||
if (!iwl_mvm_has_new_rx_api(mvm))
|
||||
return;
|
||||
|
||||
notif->cookie = mvm->queue_sync_cookie;
|
||||
|
@ -4305,6 +4300,13 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
|
|||
atomic_set(&mvm->queue_sync_counter,
|
||||
mvm->trans->num_rx_queues);
|
||||
|
||||
/* TODO - remove this when we have RXQ config API */
|
||||
if (mvm->trans->cfg->device_family == IWL_DEVICE_FAMILY_A000) {
|
||||
qmask = BIT(0);
|
||||
if (notif->sync)
|
||||
atomic_set(&mvm->queue_sync_counter, 1);
|
||||
}
|
||||
|
||||
ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif, size);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
|
||||
|
|
|
@ -652,6 +652,7 @@ struct iwl_mvm_baid_data {
|
|||
u16 entries_per_queue;
|
||||
unsigned long last_rx;
|
||||
struct timer_list session_timer;
|
||||
struct iwl_mvm_baid_data __rcu **rcu_ptr;
|
||||
struct iwl_mvm *mvm;
|
||||
struct iwl_mvm_reorder_buffer reorder_buf[IWL_MAX_RX_HW_QUEUES];
|
||||
struct iwl_mvm_reorder_buf_entry entries[];
|
||||
|
@ -754,7 +755,6 @@ struct iwl_mvm {
|
|||
u32 log_event_table;
|
||||
u32 umac_error_event_table;
|
||||
bool support_umac_log;
|
||||
struct iwl_sf_region sf_space;
|
||||
|
||||
u32 ampdu_ref;
|
||||
bool ampdu_toggle;
|
||||
|
@ -1854,7 +1854,7 @@ void iwl_mvm_tdls_ch_switch_work(struct work_struct *work);
|
|||
void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_internal_rxq_notif *notif,
|
||||
u32 size);
|
||||
void iwl_mvm_reorder_timer_expired(unsigned long data);
|
||||
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);
|
||||
|
||||
|
|
|
@ -703,7 +703,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
trans_cfg.cb_data_offs = offsetof(struct ieee80211_tx_info,
|
||||
driver_data[2]);
|
||||
|
||||
trans_cfg.sdio_adma_addr = fw->sdio_adma_addr;
|
||||
trans_cfg.sw_csum_tx = IWL_MVM_SW_TX_CSUM_OFFLOAD;
|
||||
|
||||
/* Set a short watchdog for the command queue */
|
||||
|
|
|
@ -67,12 +67,8 @@ static u8 rs_ht_to_legacy[] = {
|
|||
static const u8 ant_toggle_lookup[] = {
|
||||
[ANT_NONE] = ANT_NONE,
|
||||
[ANT_A] = ANT_B,
|
||||
[ANT_B] = ANT_C,
|
||||
[ANT_AB] = ANT_BC,
|
||||
[ANT_C] = ANT_A,
|
||||
[ANT_AC] = ANT_AB,
|
||||
[ANT_BC] = ANT_AC,
|
||||
[ANT_ABC] = ANT_ABC,
|
||||
[ANT_B] = ANT_A,
|
||||
[ANT_AB] = ANT_AB,
|
||||
};
|
||||
|
||||
#define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \
|
||||
|
@ -975,7 +971,7 @@ static int rs_toggle_antenna(u32 valid_ant, struct rs_rate *rate)
|
|||
{
|
||||
u8 new_ant_type;
|
||||
|
||||
if (!rate->ant || rate->ant > ANT_ABC)
|
||||
if (!rate->ant || WARN_ON_ONCE(rate->ant & ANT_C))
|
||||
return 0;
|
||||
|
||||
if (!rs_is_valid_ant(valid_ant, rate->ant))
|
||||
|
|
|
@ -460,9 +460,9 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
|||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_reorder_timer_expired(unsigned long data)
|
||||
void iwl_mvm_reorder_timer_expired(struct timer_list *t)
|
||||
{
|
||||
struct iwl_mvm_reorder_buffer *buf = (void *)data;
|
||||
struct iwl_mvm_reorder_buffer *buf = from_timer(buf, t, reorder_timer);
|
||||
struct iwl_mvm_baid_data *baid_data =
|
||||
iwl_mvm_baid_data_from_reorder_buf(buf);
|
||||
struct iwl_mvm_reorder_buf_entry *entries =
|
||||
|
@ -719,6 +719,22 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* release immediately if there are no stored frames, and the sn is
|
||||
* equal to the head.
|
||||
* This can happen due to reorder timer, where NSSN is behind head_sn.
|
||||
* When we released everything, and we got the next frame in the
|
||||
* sequence, according to the NSSN we can't release immediately,
|
||||
* while technically there is no hole and we can move forward.
|
||||
*/
|
||||
if (!buffer->num_stored && sn == buffer->head_sn) {
|
||||
if (!amsdu || last_subframe)
|
||||
buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
|
||||
/* No need to update AMSDU last SN - we are moving the head */
|
||||
spin_unlock_bh(&buffer->lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
index = sn % buffer->buf_size;
|
||||
|
||||
/*
|
||||
|
@ -818,6 +834,9 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
struct sk_buff *skb;
|
||||
u8 crypt_len = 0;
|
||||
|
||||
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
|
||||
return;
|
||||
|
||||
/* Dont use dev_alloc_skb(), we'll have enough headroom once
|
||||
* ieee80211_hdr pulled.
|
||||
*/
|
||||
|
|
|
@ -252,9 +252,11 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mvm_rx_agg_session_expired(unsigned long data)
|
||||
static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)
|
||||
{
|
||||
struct iwl_mvm_baid_data __rcu **rcu_ptr = (void *)data;
|
||||
struct iwl_mvm_baid_data *data =
|
||||
from_timer(data, t, session_timer);
|
||||
struct iwl_mvm_baid_data __rcu **rcu_ptr = data->rcu_ptr;
|
||||
struct iwl_mvm_baid_data *ba_data;
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_mvm_sta *mvm_sta;
|
||||
|
@ -644,8 +646,7 @@ int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid,
|
|||
|
||||
/* Redirect to lower AC */
|
||||
iwl_mvm_reconfig_scd(mvm, queue, iwl_mvm_ac_to_tx_fifo[ac],
|
||||
cmd.sta_id, tid, LINK_QUAL_AGG_FRAME_LIMIT_DEF,
|
||||
ssn);
|
||||
cmd.sta_id, tid, IWL_FRAME_LIMIT, ssn);
|
||||
|
||||
/* Update AC marking of the queue */
|
||||
spin_lock_bh(&mvm->queue_info_lock);
|
||||
|
@ -1258,6 +1259,14 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
|
|||
mvm_sta->sta_id,
|
||||
i, wdg_timeout);
|
||||
tid_data->txq_id = txq_id;
|
||||
|
||||
/*
|
||||
* Since we don't set the seq number after reset, and HW
|
||||
* sets it now, FW reset will cause the seq num to start
|
||||
* at 0 again, so driver will need to update it
|
||||
* internally as well, so it keeps in sync with real val
|
||||
*/
|
||||
tid_data->seq_number = 0;
|
||||
} else {
|
||||
u16 seq = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
|
||||
|
||||
|
@ -2153,10 +2162,8 @@ static void iwl_mvm_init_reorder_buffer(struct iwl_mvm *mvm,
|
|||
reorder_buf->head_sn = ssn;
|
||||
reorder_buf->buf_size = buf_size;
|
||||
/* rx reorder timer */
|
||||
reorder_buf->reorder_timer.function =
|
||||
iwl_mvm_reorder_timer_expired;
|
||||
reorder_buf->reorder_timer.data = (unsigned long)reorder_buf;
|
||||
init_timer(&reorder_buf->reorder_timer);
|
||||
timer_setup(&reorder_buf->reorder_timer,
|
||||
iwl_mvm_reorder_timer_expired, 0);
|
||||
spin_lock_init(&reorder_buf->lock);
|
||||
reorder_buf->mvm = mvm;
|
||||
reorder_buf->queue = i;
|
||||
|
@ -2279,9 +2286,9 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
baid_data->baid = baid;
|
||||
baid_data->timeout = timeout;
|
||||
baid_data->last_rx = jiffies;
|
||||
setup_timer(&baid_data->session_timer,
|
||||
iwl_mvm_rx_agg_session_expired,
|
||||
(unsigned long)&mvm->baid_map[baid]);
|
||||
baid_data->rcu_ptr = &mvm->baid_map[baid];
|
||||
timer_setup(&baid_data->session_timer,
|
||||
iwl_mvm_rx_agg_session_expired, 0);
|
||||
baid_data->mvm = mvm;
|
||||
baid_data->tid = tid;
|
||||
baid_data->sta_id = mvm_sta->sta_id;
|
||||
|
@ -2544,12 +2551,6 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
BUILD_BUG_ON((sizeof(mvmsta->agg_tids) * BITS_PER_BYTE)
|
||||
!= IWL_MAX_TID_COUNT);
|
||||
|
||||
if (!mvm->trans->cfg->gen2)
|
||||
buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
|
||||
else
|
||||
buf_size = min_t(int, buf_size,
|
||||
LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF);
|
||||
|
||||
spin_lock_bh(&mvmsta->lock);
|
||||
ssn = tid_data->ssn;
|
||||
queue = tid_data->txq_id;
|
||||
|
@ -2561,10 +2562,17 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
|
||||
if (iwl_mvm_has_new_tx_api(mvm)) {
|
||||
/*
|
||||
* If no queue iwl_mvm_sta_tx_agg_start() would have failed so
|
||||
* no need to check queue's status
|
||||
* If there is no queue for this tid, iwl_mvm_sta_tx_agg_start()
|
||||
* would have failed, so if we are here there is no need to
|
||||
* allocate a queue.
|
||||
* However, if aggregation size is different than the default
|
||||
* size, the scheduler should be reconfigured.
|
||||
* We cannot do this with the new TX API, so return unsupported
|
||||
* for now, until it will be offloaded to firmware..
|
||||
* Note that if SCD default value changes - this condition
|
||||
* should be updated as well.
|
||||
*/
|
||||
if (buf_size < mvmsta->max_agg_bufsize)
|
||||
if (buf_size < IWL_FRAME_LIMIT)
|
||||
return -ENOTSUPP;
|
||||
|
||||
ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true);
|
||||
|
@ -2587,7 +2595,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
* Only reconfig the SCD for the queue if the window size has
|
||||
* changed from current (become smaller)
|
||||
*/
|
||||
if (!alloc_queue && buf_size < mvmsta->max_agg_bufsize) {
|
||||
if (!alloc_queue && buf_size < IWL_FRAME_LIMIT) {
|
||||
/*
|
||||
* If reconfiguring an existing queue, it first must be
|
||||
* drained
|
||||
|
|
|
@ -1594,8 +1594,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
|
|||
mvmsta->tid_data[tid].tx_time =
|
||||
le16_to_cpu(tx_resp->wireless_media_time);
|
||||
mvmsta->tid_data[tid].lq_color =
|
||||
(tx_resp->tlc_info & TX_RES_RATE_TABLE_COLOR_MSK) >>
|
||||
TX_RES_RATE_TABLE_COLOR_POS;
|
||||
TX_RES_RATE_TABLE_COL_GET(tx_resp->tlc_info);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
|
|
@ -467,6 +467,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
|||
{IWL_PCI_DEVICE(0x24F3, 0x9110, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F4, 0x8030, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F4, 0x9030, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F4, 0xC030, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F4, 0xD030, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F3, 0x8130, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F3, 0x9130, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F3, 0x8132, iwl8260_2ac_cfg)},
|
||||
|
@ -485,6 +487,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
|||
{IWL_PCI_DEVICE(0x24F3, 0x0950, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F3, 0x0930, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F3, 0x0000, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24F3, 0x4010, iwl8260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x0010, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x0110, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x1110, iwl8265_2ac_cfg)},
|
||||
|
@ -510,6 +513,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
|||
{IWL_PCI_DEVICE(0x24FD, 0x3E01, iwl8275_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x1012, iwl8275_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x0012, iwl8275_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x0014, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x9074, iwl8265_2ac_cfg)},
|
||||
|
||||
/* 9000 Series */
|
||||
{IWL_PCI_DEVICE(0x2526, 0x0000, iwl9260_2ac_cfg)},
|
||||
|
@ -581,6 +586,11 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
|||
{IWL_PCI_DEVICE(0x2720, 0x0070, iwla000_2ac_cfg_hr_cdb)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0030, iwla000_2ac_cfg_hr_cdb)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x1080, iwla000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0090, iwla000_2ac_cfg_hr_cdb)},
|
||||
{IWL_PCI_DEVICE(0x2720, 0x0310, iwla000_2ac_cfg_hr_cdb)},
|
||||
{IWL_PCI_DEVICE(0x40C0, 0x0000, iwla000_2ax_cfg_hr)},
|
||||
{IWL_PCI_DEVICE(0x40C0, 0x0A10, iwla000_2ax_cfg_hr)},
|
||||
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
{0}
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
#define IWL_FW_MEM_EXTENDED_START 0x40000
|
||||
#define IWL_FW_MEM_EXTENDED_END 0x57FFF
|
||||
|
||||
static void iwl_trans_pcie_err_dump(struct iwl_trans *trans)
|
||||
static void iwl_trans_pcie_dump_regs(struct iwl_trans *trans)
|
||||
{
|
||||
#define PCI_DUMP_SIZE 64
|
||||
#define PREFIX_LEN 32
|
||||
|
@ -736,7 +736,7 @@ static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans,
|
|||
trans_pcie->ucode_write_complete, 5 * HZ);
|
||||
if (!ret) {
|
||||
IWL_ERR(trans, "Failed to load firmware chunk!\n");
|
||||
iwl_trans_pcie_err_dump(trans);
|
||||
iwl_trans_pcie_dump_regs(trans);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
@ -1956,7 +1956,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans,
|
|||
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
|
||||
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
|
||||
if (unlikely(ret < 0)) {
|
||||
iwl_trans_pcie_err_dump(trans);
|
||||
iwl_trans_pcie_dump_regs(trans);
|
||||
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
|
||||
WARN_ONCE(1,
|
||||
"Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n",
|
||||
|
@ -3021,6 +3021,7 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans)
|
|||
.ref = iwl_trans_pcie_ref, \
|
||||
.unref = iwl_trans_pcie_unref, \
|
||||
.dump_data = iwl_trans_pcie_dump_data, \
|
||||
.dump_regs = iwl_trans_pcie_dump_regs, \
|
||||
.d3_suspend = iwl_trans_pcie_d3_suspend, \
|
||||
.d3_resume = iwl_trans_pcie_d3_resume
|
||||
|
||||
|
|
|
@ -1909,6 +1909,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
|
|||
}
|
||||
|
||||
if (test_bit(STATUS_FW_ERROR, &trans->status)) {
|
||||
iwl_trans_dump_regs(trans);
|
||||
IWL_ERR(trans, "FW error in SYNC CMD %s\n",
|
||||
iwl_get_cmd_string(trans, cmd->id));
|
||||
dump_stack();
|
||||
|
|
|
@ -1457,7 +1457,6 @@ static void ezusb_bulk_in_callback(struct urb *urb)
|
|||
|
||||
static inline void ezusb_delete(struct ezusb_priv *upriv)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct list_head *item;
|
||||
struct list_head *tmp_item;
|
||||
unsigned long flags;
|
||||
|
@ -1465,7 +1464,6 @@ static inline void ezusb_delete(struct ezusb_priv *upriv)
|
|||
BUG_ON(in_interrupt());
|
||||
BUG_ON(!upriv);
|
||||
|
||||
dev = upriv->dev;
|
||||
mutex_lock(&upriv->mtx);
|
||||
|
||||
upriv->udev = NULL; /* No timer will be rearmed from here */
|
||||
|
|
|
@ -217,10 +217,10 @@ static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,
|
|||
int ret = 0;
|
||||
|
||||
if (!info->beacon_ies || !info->beacon_ies_len) {
|
||||
ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_MGMT_FRAME_BEACON,
|
||||
ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_IE_SET_BEACON_IES,
|
||||
NULL, 0);
|
||||
} else {
|
||||
ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_MGMT_FRAME_BEACON,
|
||||
ret = qtnf_cmd_send_mgmt_set_appie(vif, QLINK_IE_SET_BEACON_IES,
|
||||
info->beacon_ies,
|
||||
info->beacon_ies_len);
|
||||
}
|
||||
|
@ -230,11 +230,11 @@ static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,
|
|||
|
||||
if (!info->proberesp_ies || !info->proberesp_ies_len) {
|
||||
ret = qtnf_cmd_send_mgmt_set_appie(vif,
|
||||
QLINK_MGMT_FRAME_PROBE_RESP,
|
||||
QLINK_IE_SET_PROBE_RESP_IES,
|
||||
NULL, 0);
|
||||
} else {
|
||||
ret = qtnf_cmd_send_mgmt_set_appie(vif,
|
||||
QLINK_MGMT_FRAME_PROBE_RESP,
|
||||
QLINK_IE_SET_PROBE_RESP_IES,
|
||||
info->proberesp_ies,
|
||||
info->proberesp_ies_len);
|
||||
}
|
||||
|
@ -244,11 +244,11 @@ static int qtnf_mgmt_set_appie(struct qtnf_vif *vif,
|
|||
|
||||
if (!info->assocresp_ies || !info->assocresp_ies_len) {
|
||||
ret = qtnf_cmd_send_mgmt_set_appie(vif,
|
||||
QLINK_MGMT_FRAME_ASSOC_RESP,
|
||||
QLINK_IE_SET_ASSOC_RESP,
|
||||
NULL, 0);
|
||||
} else {
|
||||
ret = qtnf_cmd_send_mgmt_set_appie(vif,
|
||||
QLINK_MGMT_FRAME_ASSOC_RESP,
|
||||
QLINK_IE_SET_ASSOC_RESP,
|
||||
info->assocresp_ies,
|
||||
info->assocresp_ies_len);
|
||||
}
|
||||
|
@ -271,26 +271,11 @@ static int qtnf_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = qtnf_cmd_send_config_ap(vif, settings);
|
||||
if (ret) {
|
||||
pr_err("VIF%u.%u: failed to push config to FW\n",
|
||||
vif->mac->macid, vif->vifid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qtnf_mgmt_set_appie(vif, &settings->beacon);
|
||||
if (ret) {
|
||||
pr_err("VIF%u.%u: failed to add IEs to beacon\n",
|
||||
vif->mac->macid, vif->vifid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qtnf_cmd_send_start_ap(vif);
|
||||
ret = qtnf_cmd_send_start_ap(vif, settings);
|
||||
if (ret)
|
||||
pr_err("VIF%u.%u: failed to start AP\n", vif->mac->macid,
|
||||
vif->vifid);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -823,8 +808,7 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
|
|||
if (!wiphy->bands[band])
|
||||
continue;
|
||||
|
||||
ret = qtnf_cmd_get_mac_chan_info(mac,
|
||||
wiphy->bands[band]);
|
||||
ret = qtnf_cmd_band_info_get(mac, wiphy->bands[band]);
|
||||
if (ret)
|
||||
pr_err("failed to get chan info for mac %u band %u\n",
|
||||
mac_idx, band);
|
||||
|
@ -832,33 +816,6 @@ static void qtnf_cfg80211_reg_notifier(struct wiphy *wiphy_in,
|
|||
}
|
||||
}
|
||||
|
||||
void qtnf_band_setup_htvht_caps(struct qtnf_mac_info *macinfo,
|
||||
struct ieee80211_supported_band *band)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap;
|
||||
|
||||
ht_cap = &band->ht_cap;
|
||||
ht_cap->ht_supported = true;
|
||||
memcpy(&ht_cap->cap, &macinfo->ht_cap.cap_info,
|
||||
sizeof(u16));
|
||||
ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||
ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
|
||||
memcpy(&ht_cap->mcs, &macinfo->ht_cap.mcs,
|
||||
sizeof(ht_cap->mcs));
|
||||
|
||||
if (macinfo->phymode_cap & QLINK_PHYMODE_AC) {
|
||||
vht_cap = &band->vht_cap;
|
||||
vht_cap->vht_supported = true;
|
||||
memcpy(&vht_cap->cap,
|
||||
&macinfo->vht_cap.vht_cap_info, sizeof(u32));
|
||||
/* Update MCS support for VHT */
|
||||
memcpy(&vht_cap->vht_mcs,
|
||||
&macinfo->vht_cap.supp_mcs,
|
||||
sizeof(struct ieee80211_vht_mcs_info));
|
||||
}
|
||||
}
|
||||
|
||||
struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus)
|
||||
{
|
||||
struct wiphy *wiphy;
|
||||
|
@ -919,9 +876,6 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
pr_info("MAC%u: phymode=%#x radar=%#x\n", mac->macid,
|
||||
mac->macinfo.phymode_cap, mac->macinfo.radar_detect_widths);
|
||||
|
||||
wiphy->frag_threshold = mac->macinfo.frag_thr;
|
||||
wiphy->rts_threshold = mac->macinfo.rts_thr;
|
||||
wiphy->retry_short = mac->macinfo.sretry_limit;
|
||||
|
@ -953,6 +907,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
|
|||
wiphy->available_antennas_rx = mac->macinfo.num_rx_chain;
|
||||
|
||||
wiphy->max_ap_assoc_sta = mac->macinfo.max_ap_assoc_sta;
|
||||
wiphy->ht_capa_mod_mask = &mac->macinfo.ht_cap_mod_mask;
|
||||
wiphy->vht_capa_mod_mask = &mac->macinfo.vht_cap_mod_mask;
|
||||
|
||||
ether_addr_copy(wiphy->perm_addr, mac->macaddr);
|
||||
|
||||
|
|
|
@ -147,56 +147,66 @@ static struct sk_buff *qtnf_cmd_alloc_new_cmdskb(u8 macid, u8 vifid, u16 cmd_no,
|
|||
return cmd_skb;
|
||||
}
|
||||
|
||||
int qtnf_cmd_send_start_ap(struct qtnf_vif *vif)
|
||||
static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type,
|
||||
const u8 *buf, size_t len)
|
||||
{
|
||||
struct sk_buff *cmd_skb;
|
||||
u16 res_code = QLINK_CMD_RESULT_OK;
|
||||
int ret;
|
||||
struct qlink_tlv_ie_set *tlv;
|
||||
|
||||
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
|
||||
QLINK_CMD_START_AP,
|
||||
sizeof(struct qlink_cmd));
|
||||
if (unlikely(!cmd_skb))
|
||||
return -ENOMEM;
|
||||
tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + len);
|
||||
tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET);
|
||||
tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr));
|
||||
tlv->type = frame_type;
|
||||
tlv->flags = 0;
|
||||
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
|
||||
netif_carrier_on(vif->netdev);
|
||||
|
||||
out:
|
||||
qtnf_bus_unlock(vif->mac->bus);
|
||||
return ret;
|
||||
if (len && buf)
|
||||
memcpy(tlv->ie_data, buf, len);
|
||||
}
|
||||
|
||||
int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
|
||||
const struct cfg80211_ap_settings *s)
|
||||
static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif,
|
||||
const struct cfg80211_ap_settings *s)
|
||||
{
|
||||
unsigned int len = sizeof(struct qlink_cmd_start_ap);
|
||||
|
||||
len += s->ssid_len;
|
||||
len += s->beacon.head_len;
|
||||
len += s->beacon.tail_len;
|
||||
len += s->beacon.beacon_ies_len;
|
||||
len += s->beacon.proberesp_ies_len;
|
||||
len += s->beacon.assocresp_ies_len;
|
||||
len += s->beacon.probe_resp_len;
|
||||
|
||||
if (cfg80211_chandef_valid(&s->chandef))
|
||||
len += sizeof(struct qlink_tlv_chandef);
|
||||
|
||||
if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) {
|
||||
pr_err("VIF%u.%u: can not fit AP settings: %u\n",
|
||||
vif->mac->macid, vif->vifid, len);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
|
||||
const struct cfg80211_ap_settings *s)
|
||||
{
|
||||
struct sk_buff *cmd_skb;
|
||||
struct qlink_cmd_config_ap *cmd;
|
||||
struct qlink_cmd_start_ap *cmd;
|
||||
struct qlink_auth_encr *aen;
|
||||
u16 res_code = QLINK_CMD_RESULT_OK;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (!qtnf_cmd_start_ap_can_fit(vif, s))
|
||||
return -E2BIG;
|
||||
|
||||
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
|
||||
QLINK_CMD_CONFIG_AP,
|
||||
QLINK_CMD_START_AP,
|
||||
sizeof(*cmd));
|
||||
if (unlikely(!cmd_skb))
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct qlink_cmd_config_ap *)cmd_skb->data;
|
||||
cmd = (struct qlink_cmd_start_ap *)cmd_skb->data;
|
||||
cmd->dtim_period = s->dtim_period;
|
||||
cmd->beacon_interval = cpu_to_le16(s->beacon_interval);
|
||||
cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid);
|
||||
|
@ -211,7 +221,6 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
|
|||
aen = &cmd->aen;
|
||||
aen->auth_type = s->auth_type;
|
||||
aen->privacy = !!s->privacy;
|
||||
aen->mfp = 0;
|
||||
aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions);
|
||||
aen->cipher_group = cpu_to_le32(s->crypto.cipher_group);
|
||||
aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise);
|
||||
|
@ -241,6 +250,39 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
|
|||
qlink_chandef_cfg2q(&s->chandef, &chtlv->chan);
|
||||
}
|
||||
|
||||
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_HEAD,
|
||||
s->beacon.head, s->beacon.head_len);
|
||||
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_TAIL,
|
||||
s->beacon.tail, s->beacon.tail_len);
|
||||
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_IES,
|
||||
s->beacon.beacon_ies, s->beacon.beacon_ies_len);
|
||||
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP,
|
||||
s->beacon.probe_resp, s->beacon.probe_resp_len);
|
||||
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP_IES,
|
||||
s->beacon.proberesp_ies,
|
||||
s->beacon.proberesp_ies_len);
|
||||
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_RESP,
|
||||
s->beacon.assocresp_ies,
|
||||
s->beacon.assocresp_ies_len);
|
||||
|
||||
if (s->ht_cap) {
|
||||
struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
|
||||
skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->ht_cap));
|
||||
|
||||
tlv->type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
|
||||
tlv->len = cpu_to_le16(sizeof(*s->ht_cap));
|
||||
memcpy(tlv->val, s->ht_cap, sizeof(*s->ht_cap));
|
||||
}
|
||||
|
||||
if (s->vht_cap) {
|
||||
struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *)
|
||||
skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->vht_cap));
|
||||
|
||||
tlv->type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
|
||||
tlv->len = cpu_to_le16(sizeof(*s->vht_cap));
|
||||
memcpy(tlv->val, s->vht_cap, sizeof(*s->vht_cap));
|
||||
}
|
||||
|
||||
qtnf_bus_lock(vif->mac->bus);
|
||||
|
||||
ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code);
|
||||
|
@ -255,6 +297,8 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
|
|||
goto out;
|
||||
}
|
||||
|
||||
netif_carrier_on(vif->netdev);
|
||||
|
||||
out:
|
||||
qtnf_bus_unlock(vif->mac->bus);
|
||||
return ret;
|
||||
|
@ -380,11 +424,10 @@ 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;
|
||||
struct qlink_cmd_mgmt_append_ie *cmd;
|
||||
u16 res_code = QLINK_CMD_RESULT_OK;
|
||||
int ret;
|
||||
|
||||
if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
|
||||
if (len > QTNF_MAX_CMD_BUF_SIZE) {
|
||||
pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid,
|
||||
vif->vifid, frame_type, len);
|
||||
return -E2BIG;
|
||||
|
@ -392,22 +435,14 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
|
|||
|
||||
cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
|
||||
QLINK_CMD_MGMT_SET_APPIE,
|
||||
sizeof(*cmd));
|
||||
sizeof(struct qlink_cmd));
|
||||
if (unlikely(!cmd_skb))
|
||||
return -ENOMEM;
|
||||
|
||||
qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len);
|
||||
|
||||
qtnf_bus_lock(vif->mac->bus);
|
||||
|
||||
cmd = (struct qlink_cmd_mgmt_append_ie *)cmd_skb->data;
|
||||
cmd->type = frame_type;
|
||||
cmd->flags = 0;
|
||||
|
||||
/* If len == 0 then IE buf for specified frame type
|
||||
* should be cleared on EP.
|
||||
*/
|
||||
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))
|
||||
|
@ -1090,7 +1125,6 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
|
|||
mac_info = &mac->macinfo;
|
||||
|
||||
mac_info->bands_cap = resp_info->bands_cap;
|
||||
mac_info->phymode_cap = resp_info->phymode_cap;
|
||||
memcpy(&mac_info->dev_mac, &resp_info->dev_mac,
|
||||
sizeof(mac_info->dev_mac));
|
||||
|
||||
|
@ -1110,24 +1144,56 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac,
|
|||
qlink_chan_width_mask_to_nl(le16_to_cpu(
|
||||
resp_info->radar_detect_widths));
|
||||
|
||||
memcpy(&mac_info->ht_cap, &resp_info->ht_cap, sizeof(mac_info->ht_cap));
|
||||
memcpy(&mac_info->vht_cap, &resp_info->vht_cap,
|
||||
sizeof(mac_info->vht_cap));
|
||||
memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask,
|
||||
sizeof(mac_info->ht_cap_mod_mask));
|
||||
memcpy(&mac_info->vht_cap_mod_mask, &resp_info->vht_cap_mod_mask,
|
||||
sizeof(mac_info->vht_cap_mod_mask));
|
||||
}
|
||||
|
||||
static void qtnf_cmd_resp_band_fill_htcap(const u8 *info,
|
||||
struct ieee80211_sta_ht_cap *bcap)
|
||||
{
|
||||
const struct ieee80211_ht_cap *ht_cap =
|
||||
(const struct ieee80211_ht_cap *)info;
|
||||
|
||||
bcap->ht_supported = true;
|
||||
bcap->cap = le16_to_cpu(ht_cap->cap_info);
|
||||
bcap->ampdu_factor =
|
||||
ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
|
||||
bcap->ampdu_density =
|
||||
(ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >>
|
||||
IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
|
||||
memcpy(&bcap->mcs, &ht_cap->mcs, sizeof(bcap->mcs));
|
||||
}
|
||||
|
||||
static void qtnf_cmd_resp_band_fill_vhtcap(const u8 *info,
|
||||
struct ieee80211_sta_vht_cap *bcap)
|
||||
{
|
||||
const struct ieee80211_vht_cap *vht_cap =
|
||||
(const struct ieee80211_vht_cap *)info;
|
||||
|
||||
bcap->vht_supported = true;
|
||||
bcap->cap = le32_to_cpu(vht_cap->vht_cap_info);
|
||||
memcpy(&bcap->vht_mcs, &vht_cap->supp_mcs, sizeof(bcap->vht_mcs));
|
||||
}
|
||||
|
||||
static int
|
||||
qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band,
|
||||
struct qlink_resp_get_chan_info *resp,
|
||||
size_t payload_len)
|
||||
qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band,
|
||||
struct qlink_resp_band_info_get *resp,
|
||||
size_t payload_len)
|
||||
{
|
||||
u16 tlv_type;
|
||||
size_t tlv_len;
|
||||
size_t tlv_dlen;
|
||||
const struct qlink_tlv_hdr *tlv;
|
||||
const struct qlink_tlv_channel *qchan;
|
||||
struct ieee80211_channel *chan;
|
||||
unsigned int chidx = 0;
|
||||
u32 qflags;
|
||||
|
||||
memset(&band->ht_cap, 0, sizeof(band->ht_cap));
|
||||
memset(&band->vht_cap, 0, sizeof(band->vht_cap));
|
||||
|
||||
if (band->channels) {
|
||||
if (band->n_channels == resp->num_chans) {
|
||||
memset(band->channels, 0,
|
||||
|
@ -1155,7 +1221,8 @@ qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band,
|
|||
|
||||
while (payload_len >= sizeof(*tlv)) {
|
||||
tlv_type = le16_to_cpu(tlv->type);
|
||||
tlv_len = le16_to_cpu(tlv->len) + sizeof(*tlv);
|
||||
tlv_dlen = le16_to_cpu(tlv->len);
|
||||
tlv_len = tlv_dlen + sizeof(*tlv);
|
||||
|
||||
if (tlv_len > payload_len) {
|
||||
pr_warn("malformed TLV 0x%.2X; LEN: %zu\n",
|
||||
|
@ -1241,13 +1308,32 @@ qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band,
|
|||
chan->hw_value, chan->flags, chan->max_power,
|
||||
chan->max_reg_power);
|
||||
break;
|
||||
case WLAN_EID_HT_CAPABILITY:
|
||||
if (unlikely(tlv_dlen !=
|
||||
sizeof(struct ieee80211_ht_cap))) {
|
||||
pr_err("bad HTCAP TLV len %zu\n", tlv_dlen);
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
qtnf_cmd_resp_band_fill_htcap(tlv->val, &band->ht_cap);
|
||||
break;
|
||||
case WLAN_EID_VHT_CAPABILITY:
|
||||
if (unlikely(tlv_dlen !=
|
||||
sizeof(struct ieee80211_vht_cap))) {
|
||||
pr_err("bad VHTCAP TLV len %zu\n", tlv_dlen);
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
qtnf_cmd_resp_band_fill_vhtcap(tlv->val,
|
||||
&band->vht_cap);
|
||||
break;
|
||||
default:
|
||||
pr_warn("unknown TLV type: %#x\n", tlv_type);
|
||||
break;
|
||||
}
|
||||
|
||||
payload_len -= tlv_len;
|
||||
tlv = (struct qlink_tlv_hdr *)((u8 *)tlv + tlv_len);
|
||||
tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_dlen);
|
||||
}
|
||||
|
||||
if (payload_len) {
|
||||
|
@ -1469,13 +1555,13 @@ int qtnf_cmd_get_hw_info(struct qtnf_bus *bus)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
|
||||
struct ieee80211_supported_band *band)
|
||||
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_chans_info_get *cmd;
|
||||
struct qlink_resp_get_chan_info *resp;
|
||||
struct qlink_cmd_band_info_get *cmd;
|
||||
struct qlink_resp_band_info_get *resp;
|
||||
u16 res_code = QLINK_CMD_RESULT_OK;
|
||||
int ret = 0;
|
||||
u8 qband;
|
||||
|
@ -1495,12 +1581,12 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
|
|||
}
|
||||
|
||||
cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0,
|
||||
QLINK_CMD_CHANS_INFO_GET,
|
||||
QLINK_CMD_BAND_INFO_GET,
|
||||
sizeof(*cmd));
|
||||
if (!cmd_skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct qlink_cmd_chans_info_get *)cmd_skb->data;
|
||||
cmd = (struct qlink_cmd_band_info_get *)cmd_skb->data;
|
||||
cmd->band = qband;
|
||||
|
||||
qtnf_bus_lock(mac->bus);
|
||||
|
@ -1517,7 +1603,7 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
|
|||
goto out;
|
||||
}
|
||||
|
||||
resp = (struct qlink_resp_get_chan_info *)resp_skb->data;
|
||||
resp = (struct qlink_resp_band_info_get *)resp_skb->data;
|
||||
if (resp->band != qband) {
|
||||
pr_err("MAC%u: reply band %u != cmd band %u\n", mac->macid,
|
||||
resp->band, qband);
|
||||
|
@ -1525,7 +1611,7 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = qtnf_cmd_resp_fill_channels_info(band, resp, info_len);
|
||||
ret = qtnf_cmd_resp_fill_band_info(band, resp, info_len);
|
||||
|
||||
out:
|
||||
qtnf_bus_unlock(mac->bus);
|
||||
|
@ -1942,17 +2028,36 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb,
|
||||
const struct ieee80211_channel *sc)
|
||||
{
|
||||
struct qlink_tlv_channel *qchan;
|
||||
u32 flags = 0;
|
||||
|
||||
qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
|
||||
qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
|
||||
qchan->hdr.len = cpu_to_le16(sizeof(*qchan) - sizeof(qchan->hdr));
|
||||
qchan->center_freq = cpu_to_le16(sc->center_freq);
|
||||
qchan->hw_value = cpu_to_le16(sc->hw_value);
|
||||
|
||||
if (sc->flags & IEEE80211_CHAN_NO_IR)
|
||||
flags |= QLINK_CHAN_NO_IR;
|
||||
|
||||
if (sc->flags & IEEE80211_CHAN_RADAR)
|
||||
flags |= QLINK_CHAN_RADAR;
|
||||
|
||||
qchan->flags = cpu_to_le32(flags);
|
||||
}
|
||||
|
||||
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;
|
||||
struct qlink_tlv_channel *qchan;
|
||||
int n_channels;
|
||||
int count = 0;
|
||||
int ret;
|
||||
u32 flags;
|
||||
|
||||
if (scan_req->n_ssids > QTNF_MAX_SSID_LIST_LENGTH) {
|
||||
pr_err("MAC%u: too many SSIDs in scan request\n", mac->macid);
|
||||
|
@ -1977,9 +2082,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
|
|||
}
|
||||
|
||||
if (scan_req->ie_len != 0)
|
||||
qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
|
||||
scan_req->ie,
|
||||
scan_req->ie_len);
|
||||
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ,
|
||||
scan_req->ie, scan_req->ie_len);
|
||||
|
||||
if (scan_req->n_channels) {
|
||||
n_channels = scan_req->n_channels;
|
||||
|
@ -1995,22 +2099,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac)
|
|||
pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n",
|
||||
mac->macid, sc->hw_value, sc->center_freq,
|
||||
sc->flags);
|
||||
qchan = skb_put_zero(cmd_skb, sizeof(*qchan));
|
||||
flags = 0;
|
||||
|
||||
qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL);
|
||||
qchan->hdr.len = cpu_to_le16(sizeof(*qchan) -
|
||||
sizeof(struct qlink_tlv_hdr));
|
||||
qchan->center_freq = cpu_to_le16(sc->center_freq);
|
||||
qchan->hw_value = cpu_to_le16(sc->hw_value);
|
||||
|
||||
if (sc->flags & IEEE80211_CHAN_NO_IR)
|
||||
flags |= QLINK_CHAN_NO_IR;
|
||||
|
||||
if (sc->flags & IEEE80211_CHAN_RADAR)
|
||||
flags |= QLINK_CHAN_RADAR;
|
||||
|
||||
qchan->flags = cpu_to_le32(flags);
|
||||
qtnf_cmd_channel_tlv_add(cmd_skb, sc);
|
||||
n_channels--;
|
||||
count++;
|
||||
}
|
||||
|
@ -2054,10 +2144,15 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
|
|||
|
||||
ether_addr_copy(cmd->bssid, vif->bssid);
|
||||
|
||||
if (sme->channel)
|
||||
cmd->channel = cpu_to_le16(sme->channel->hw_value);
|
||||
if (sme->bssid_hint)
|
||||
ether_addr_copy(cmd->bssid_hint, sme->bssid_hint);
|
||||
else
|
||||
cmd->channel = 0;
|
||||
eth_zero_addr(cmd->bssid_hint);
|
||||
|
||||
if (sme->prev_bssid)
|
||||
ether_addr_copy(cmd->prev_bssid, sme->prev_bssid);
|
||||
else
|
||||
eth_zero_addr(cmd->prev_bssid);
|
||||
|
||||
if ((sme->bg_scan_period > 0) &&
|
||||
(sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD))
|
||||
|
@ -2075,11 +2170,18 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
|
|||
connect_flags |= QLINK_STA_CONNECT_USE_RRM;
|
||||
|
||||
cmd->flags = cpu_to_le32(connect_flags);
|
||||
memcpy(&cmd->ht_capa, &sme->ht_capa, sizeof(cmd->ht_capa));
|
||||
memcpy(&cmd->ht_capa_mask, &sme->ht_capa_mask,
|
||||
sizeof(cmd->ht_capa_mask));
|
||||
memcpy(&cmd->vht_capa, &sme->vht_capa, sizeof(cmd->vht_capa));
|
||||
memcpy(&cmd->vht_capa_mask, &sme->vht_capa_mask,
|
||||
sizeof(cmd->vht_capa_mask));
|
||||
cmd->pbss = sme->pbss;
|
||||
|
||||
aen = &cmd->aen;
|
||||
aen->auth_type = sme->auth_type;
|
||||
aen->privacy = !!sme->privacy;
|
||||
aen->mfp = sme->mfp;
|
||||
cmd->mfp = sme->mfp;
|
||||
aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions);
|
||||
aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group);
|
||||
aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise);
|
||||
|
@ -2103,9 +2205,11 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif,
|
|||
sme->ssid_len);
|
||||
|
||||
if (sme->ie_len != 0)
|
||||
qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET,
|
||||
sme->ie,
|
||||
sme->ie_len);
|
||||
qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ,
|
||||
sme->ie, sme->ie_len);
|
||||
|
||||
if (sme->channel)
|
||||
qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel);
|
||||
|
||||
qtnf_bus_lock(vif->mac->bus);
|
||||
|
||||
|
|
|
@ -30,12 +30,11 @@ int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype,
|
|||
int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif,
|
||||
enum nl80211_iftype iftype, u8 *mac_addr);
|
||||
int qtnf_cmd_send_del_intf(struct qtnf_vif *vif);
|
||||
int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac,
|
||||
struct ieee80211_supported_band *band);
|
||||
int qtnf_cmd_band_info_get(struct qtnf_wmac *mac,
|
||||
struct ieee80211_supported_band *band);
|
||||
int qtnf_cmd_send_regulatory_config(struct qtnf_wmac *mac, const char *alpha2);
|
||||
int qtnf_cmd_send_config_ap(struct qtnf_vif *vif,
|
||||
const struct cfg80211_ap_settings *s);
|
||||
int qtnf_cmd_send_start_ap(struct qtnf_vif *vif);
|
||||
int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
|
||||
const struct cfg80211_ap_settings *s);
|
||||
int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif);
|
||||
int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg);
|
||||
int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
|
||||
|
|
|
@ -171,7 +171,7 @@ static int qtnf_mac_init_single_band(struct wiphy *wiphy,
|
|||
|
||||
wiphy->bands[band]->band = band;
|
||||
|
||||
ret = qtnf_cmd_get_mac_chan_info(mac, wiphy->bands[band]);
|
||||
ret = qtnf_cmd_band_info_get(mac, wiphy->bands[band]);
|
||||
if (ret) {
|
||||
pr_err("MAC%u: band %u: failed to get chans info: %d\n",
|
||||
mac->macid, band, ret);
|
||||
|
@ -179,7 +179,6 @@ static int qtnf_mac_init_single_band(struct wiphy *wiphy,
|
|||
}
|
||||
|
||||
qtnf_band_init_rates(wiphy->bands[band]);
|
||||
qtnf_band_setup_htvht_caps(&mac->macinfo, wiphy->bands[band]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,6 @@ struct qtnf_vif {
|
|||
|
||||
struct qtnf_mac_info {
|
||||
u8 bands_cap;
|
||||
u8 phymode_cap;
|
||||
u8 dev_mac[ETH_ALEN];
|
||||
u8 num_tx_chain;
|
||||
u8 num_rx_chain;
|
||||
|
@ -103,8 +102,8 @@ struct qtnf_mac_info {
|
|||
u8 sretry_limit;
|
||||
u8 coverage_class;
|
||||
u8 radar_detect_widths;
|
||||
struct ieee80211_ht_cap ht_cap;
|
||||
struct ieee80211_vht_cap vht_cap;
|
||||
struct ieee80211_ht_cap ht_cap_mod_mask;
|
||||
struct ieee80211_vht_cap vht_cap_mod_mask;
|
||||
struct ieee80211_iface_limit *limits;
|
||||
size_t n_limits;
|
||||
};
|
||||
|
|
|
@ -65,34 +65,39 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
|
|||
sinfo.assoc_req_ies_len = 0;
|
||||
|
||||
payload_len = len - sizeof(*sta_assoc);
|
||||
tlv = (struct qlink_tlv_hdr *)sta_assoc->ies;
|
||||
tlv = (const struct qlink_tlv_hdr *)sta_assoc->ies;
|
||||
|
||||
while (payload_len >= sizeof(struct qlink_tlv_hdr)) {
|
||||
while (payload_len >= sizeof(*tlv)) {
|
||||
tlv_type = le16_to_cpu(tlv->type);
|
||||
tlv_value_len = le16_to_cpu(tlv->len);
|
||||
tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
|
||||
|
||||
if (tlv_full_len > payload_len) {
|
||||
pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
|
||||
mac->macid, vif->vifid, tlv_type,
|
||||
tlv_value_len);
|
||||
if (tlv_full_len > payload_len)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tlv_type == QTN_TLV_ID_IE_SET) {
|
||||
sinfo.assoc_req_ies = tlv->val;
|
||||
sinfo.assoc_req_ies_len = tlv_value_len;
|
||||
const struct qlink_tlv_ie_set *ie_set;
|
||||
unsigned int ie_len;
|
||||
|
||||
if (payload_len < sizeof(*ie_set))
|
||||
return -EINVAL;
|
||||
|
||||
ie_set = (const struct qlink_tlv_ie_set *)tlv;
|
||||
ie_len = tlv_value_len -
|
||||
(sizeof(*ie_set) - sizeof(ie_set->hdr));
|
||||
|
||||
if (ie_set->type == QLINK_IE_SET_ASSOC_REQ && ie_len) {
|
||||
sinfo.assoc_req_ies = ie_set->ie_data;
|
||||
sinfo.assoc_req_ies_len = ie_len;
|
||||
}
|
||||
}
|
||||
|
||||
payload_len -= tlv_full_len;
|
||||
tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
|
||||
}
|
||||
|
||||
if (payload_len) {
|
||||
pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n",
|
||||
mac->macid, vif->vifid, payload_len);
|
||||
if (payload_len)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, &sinfo,
|
||||
GFP_KERNEL);
|
||||
|
@ -247,13 +252,12 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif,
|
|||
struct cfg80211_bss *bss;
|
||||
struct ieee80211_channel *channel;
|
||||
struct wiphy *wiphy = priv_to_wiphy(vif->mac);
|
||||
enum cfg80211_bss_frame_type frame_type;
|
||||
enum cfg80211_bss_frame_type frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
|
||||
size_t payload_len;
|
||||
u16 tlv_type;
|
||||
u16 tlv_value_len;
|
||||
size_t tlv_full_len;
|
||||
const struct qlink_tlv_hdr *tlv;
|
||||
|
||||
const u8 *ies = NULL;
|
||||
size_t ies_len = 0;
|
||||
|
||||
|
@ -270,17 +274,6 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (sr->frame_type) {
|
||||
case QLINK_BSS_FTYPE_BEACON:
|
||||
frame_type = CFG80211_BSS_FTYPE_BEACON;
|
||||
break;
|
||||
case QLINK_BSS_FTYPE_PRESP:
|
||||
frame_type = CFG80211_BSS_FTYPE_PRESP;
|
||||
break;
|
||||
default:
|
||||
frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
payload_len = len - sizeof(*sr);
|
||||
tlv = (struct qlink_tlv_hdr *)sr->payload;
|
||||
|
||||
|
@ -289,27 +282,43 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif,
|
|||
tlv_value_len = le16_to_cpu(tlv->len);
|
||||
tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr);
|
||||
|
||||
if (tlv_full_len > payload_len) {
|
||||
pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n",
|
||||
vif->mac->macid, vif->vifid, tlv_type,
|
||||
tlv_value_len);
|
||||
if (tlv_full_len > payload_len)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tlv_type == QTN_TLV_ID_IE_SET) {
|
||||
ies = tlv->val;
|
||||
ies_len = tlv_value_len;
|
||||
const struct qlink_tlv_ie_set *ie_set;
|
||||
unsigned int ie_len;
|
||||
|
||||
if (payload_len < sizeof(*ie_set))
|
||||
return -EINVAL;
|
||||
|
||||
ie_set = (const struct qlink_tlv_ie_set *)tlv;
|
||||
ie_len = tlv_value_len -
|
||||
(sizeof(*ie_set) - sizeof(ie_set->hdr));
|
||||
|
||||
switch (ie_set->type) {
|
||||
case QLINK_IE_SET_BEACON_IES:
|
||||
frame_type = CFG80211_BSS_FTYPE_BEACON;
|
||||
break;
|
||||
case QLINK_IE_SET_PROBE_RESP_IES:
|
||||
frame_type = CFG80211_BSS_FTYPE_PRESP;
|
||||
break;
|
||||
default:
|
||||
frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (ie_len) {
|
||||
ies = ie_set->ie_data;
|
||||
ies_len = ie_len;
|
||||
}
|
||||
}
|
||||
|
||||
payload_len -= tlv_full_len;
|
||||
tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
|
||||
}
|
||||
|
||||
if (payload_len) {
|
||||
pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n",
|
||||
vif->mac->macid, vif->vifid, payload_len);
|
||||
if (payload_len)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bss = cfg80211_inform_bss(wiphy, channel, frame_type,
|
||||
sr->bssid, get_unaligned_le64(&sr->tsf),
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include <linux/ieee80211.h>
|
||||
|
||||
#define QLINK_PROTO_VER 5
|
||||
#define QLINK_PROTO_VER 6
|
||||
|
||||
#define QLINK_MACID_RSVD 0xFF
|
||||
#define QLINK_VIFID_RSVD 0xFF
|
||||
|
@ -74,12 +74,6 @@ enum qlink_hw_capab {
|
|||
QLINK_HW_CAPAB_STA_INACT_TIMEOUT = BIT(1),
|
||||
};
|
||||
|
||||
enum qlink_phy_mode {
|
||||
QLINK_PHYMODE_BGN = BIT(0),
|
||||
QLINK_PHYMODE_AN = BIT(1),
|
||||
QLINK_PHYMODE_AC = BIT(2),
|
||||
};
|
||||
|
||||
enum qlink_iface_type {
|
||||
QLINK_IFTYPE_AP = 1,
|
||||
QLINK_IFTYPE_STATION = 2,
|
||||
|
@ -154,9 +148,9 @@ struct qlink_auth_encr {
|
|||
__le16 control_port_ethertype;
|
||||
u8 auth_type;
|
||||
u8 privacy;
|
||||
u8 mfp;
|
||||
u8 control_port;
|
||||
u8 control_port_no_encrypt;
|
||||
u8 rsvd[2];
|
||||
} __packed;
|
||||
|
||||
/* QLINK Command messages related definitions
|
||||
|
@ -168,11 +162,12 @@ struct qlink_auth_encr {
|
|||
* Commands are QLINK messages of type @QLINK_MSG_TYPE_CMD, sent by driver to
|
||||
* wireless network device for processing. Device is expected to send back a
|
||||
* reply message of type &QLINK_MSG_TYPE_CMDRSP, containing at least command
|
||||
* execution status (one of &enum qlink_cmd_result) at least. Reply message
|
||||
* execution status (one of &enum qlink_cmd_result). Reply message
|
||||
* may also contain data payload specific to the command type.
|
||||
*
|
||||
* @QLINK_CMD_CHANS_INFO_GET: for the specified MAC and specified band, get
|
||||
* number of operational channels and information on each of the channel.
|
||||
* @QLINK_CMD_BAND_INFO_GET: for the specified MAC and specified band, get
|
||||
* the band's description including number of operational channels and
|
||||
* info on each channel, HT/VHT capabilities, supported rates etc.
|
||||
* This command is generic to a specified MAC, interface index must be set
|
||||
* to QLINK_VIFID_RSVD in command header.
|
||||
* @QLINK_CMD_REG_NOTIFY: notify device about regulatory domain change. This
|
||||
|
@ -194,10 +189,9 @@ enum qlink_cmd_type {
|
|||
QLINK_CMD_CHANGE_INTF = 0x0017,
|
||||
QLINK_CMD_UPDOWN_INTF = 0x0018,
|
||||
QLINK_CMD_REG_NOTIFY = 0x0019,
|
||||
QLINK_CMD_CHANS_INFO_GET = 0x001A,
|
||||
QLINK_CMD_BAND_INFO_GET = 0x001A,
|
||||
QLINK_CMD_CHAN_SWITCH = 0x001B,
|
||||
QLINK_CMD_CHAN_GET = 0x001C,
|
||||
QLINK_CMD_CONFIG_AP = 0x0020,
|
||||
QLINK_CMD_START_AP = 0x0021,
|
||||
QLINK_CMD_STOP_AP = 0x0022,
|
||||
QLINK_CMD_GET_STA_INFO = 0x0030,
|
||||
|
@ -303,21 +297,6 @@ struct qlink_cmd_mgmt_frame_tx {
|
|||
u8 frame_data[0];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct qlink_cmd_mgmt_append_ie - data for QLINK_CMD_MGMT_SET_APPIE command
|
||||
*
|
||||
* @type: type of MGMT frame to appent requested IEs to, one of
|
||||
* &enum qlink_mgmt_frame_type.
|
||||
* @flags: for future use.
|
||||
* @ie_data: IEs data to append.
|
||||
*/
|
||||
struct qlink_cmd_mgmt_append_ie {
|
||||
struct qlink_cmd chdr;
|
||||
u8 type;
|
||||
u8 flags;
|
||||
u8 ie_data[0];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct qlink_cmd_get_sta_info - data for QLINK_CMD_GET_STA_INFO command
|
||||
*
|
||||
|
@ -425,20 +404,36 @@ enum qlink_sta_connect_flags {
|
|||
/**
|
||||
* struct qlink_cmd_connect - data for QLINK_CMD_CONNECT command
|
||||
*
|
||||
* @flags: for future use.
|
||||
* @channel: channel which should be used to connect.
|
||||
* @bg_scan_period: period of background scan.
|
||||
* @aen: authentication information.
|
||||
* @bssid: BSSID of the BSS to connect to.
|
||||
* @bssid_hint: recommended AP BSSID for initial connection to the BSS or
|
||||
* 00:00:00:00:00:00 if not specified.
|
||||
* @prev_bssid: previous BSSID, if specified (not 00:00:00:00:00:00) indicates
|
||||
* a request to reassociate.
|
||||
* @bg_scan_period: period of background scan.
|
||||
* @flags: one of &enum qlink_sta_connect_flags.
|
||||
* @ht_capa: HT Capabilities overrides.
|
||||
* @ht_capa_mask: The bits of ht_capa which are to be used.
|
||||
* @vht_capa: VHT Capability overrides
|
||||
* @vht_capa_mask: The bits of vht_capa which are to be used.
|
||||
* @aen: authentication information.
|
||||
* @mfp: whether to use management frame protection.
|
||||
* @payload: variable portion of connection request.
|
||||
*/
|
||||
struct qlink_cmd_connect {
|
||||
struct qlink_cmd chdr;
|
||||
__le32 flags;
|
||||
__le16 channel;
|
||||
__le16 bg_scan_period;
|
||||
struct qlink_auth_encr aen;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 bssid_hint[ETH_ALEN];
|
||||
u8 prev_bssid[ETH_ALEN];
|
||||
__le16 bg_scan_period;
|
||||
__le32 flags;
|
||||
struct ieee80211_ht_cap ht_capa;
|
||||
struct ieee80211_ht_cap ht_capa_mask;
|
||||
struct ieee80211_vht_cap vht_capa;
|
||||
struct ieee80211_vht_cap vht_capa_mask;
|
||||
struct qlink_auth_encr aen;
|
||||
u8 mfp;
|
||||
u8 pbss;
|
||||
u8 rsvd[2];
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
|
@ -477,11 +472,11 @@ enum qlink_band {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct qlink_cmd_chans_info_get - data for QLINK_CMD_CHANS_INFO_GET command
|
||||
* struct qlink_cmd_band_info_get - data for QLINK_CMD_BAND_INFO_GET command
|
||||
*
|
||||
* @band: a PHY band for which channels info is needed, one of @enum qlink_band
|
||||
* @band: a PHY band for which information is queried, one of @enum qlink_band
|
||||
*/
|
||||
struct qlink_cmd_chans_info_get {
|
||||
struct qlink_cmd_band_info_get {
|
||||
struct qlink_cmd chdr;
|
||||
u8 band;
|
||||
} __packed;
|
||||
|
@ -562,7 +557,7 @@ enum qlink_hidden_ssid {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct qlink_cmd_config_ap - data for QLINK_CMD_CONFIG_AP command
|
||||
* struct qlink_cmd_start_ap - data for QLINK_CMD_START_AP command
|
||||
*
|
||||
* @beacon_interval: beacon interval
|
||||
* @inactivity_timeout: station's inactivity period in seconds
|
||||
|
@ -574,7 +569,7 @@ enum qlink_hidden_ssid {
|
|||
* @aen: encryption info
|
||||
* @info: variable configurations
|
||||
*/
|
||||
struct qlink_cmd_config_ap {
|
||||
struct qlink_cmd_start_ap {
|
||||
struct qlink_cmd chdr;
|
||||
__le16 beacon_interval;
|
||||
__le16 inactivity_timeout;
|
||||
|
@ -635,10 +630,9 @@ struct qlink_resp {
|
|||
* specified WMAC).
|
||||
* @num_tx_chain: Number of transmit chains used by WMAC.
|
||||
* @num_rx_chain: Number of receive chains used by WMAC.
|
||||
* @vht_cap: VHT capabilities.
|
||||
* @ht_cap: HT capabilities.
|
||||
* @vht_cap_mod_mask: mask specifying which VHT capabilities can be altered.
|
||||
* @ht_cap_mod_mask: mask specifying which HT capabilities can be altered.
|
||||
* @bands_cap: wireless bands WMAC can operate in, bitmap of &enum qlink_band.
|
||||
* @phymode_cap: PHY modes WMAC can operate in, bitmap of &enum qlink_phy_mode.
|
||||
* @max_ap_assoc_sta: Maximum number of associations supported by WMAC.
|
||||
* @radar_detect_widths: bitmask of channels BW for which WMAC can detect radar.
|
||||
* @var_info: variable-length WMAC info data.
|
||||
|
@ -648,12 +642,12 @@ struct qlink_resp_get_mac_info {
|
|||
u8 dev_mac[ETH_ALEN];
|
||||
u8 num_tx_chain;
|
||||
u8 num_rx_chain;
|
||||
struct ieee80211_vht_cap vht_cap;
|
||||
struct ieee80211_ht_cap ht_cap;
|
||||
u8 bands_cap;
|
||||
u8 phymode_cap;
|
||||
struct ieee80211_vht_cap vht_cap_mod_mask;
|
||||
struct ieee80211_ht_cap ht_cap_mod_mask;
|
||||
__le16 max_ap_assoc_sta;
|
||||
__le16 radar_detect_widths;
|
||||
u8 bands_cap;
|
||||
u8 rsvd[1];
|
||||
u8 var_info[0];
|
||||
} __packed;
|
||||
|
||||
|
@ -730,17 +724,19 @@ struct qlink_resp_get_sta_info {
|
|||
} __packed;
|
||||
|
||||
/**
|
||||
* struct qlink_resp_get_chan_info - response for QLINK_CMD_CHANS_INFO_GET cmd
|
||||
* struct qlink_resp_band_info_get - response for QLINK_CMD_BAND_INFO_GET cmd
|
||||
*
|
||||
* @band: frequency band to which channels belong to, one of @enum qlink_band.
|
||||
* @num_chans: total number of channels info data contained in reply data.
|
||||
* @info: variable-length channels info.
|
||||
* @band: frequency band that the response describes, one of @enum qlink_band.
|
||||
* @num_chans: total number of channels info TLVs contained in reply.
|
||||
* @num_bitrates: total number of bitrate TLVs contained in reply.
|
||||
* @info: variable-length info portion.
|
||||
*/
|
||||
struct qlink_resp_get_chan_info {
|
||||
struct qlink_resp_band_info_get {
|
||||
struct qlink_resp rhdr;
|
||||
u8 band;
|
||||
u8 num_chans;
|
||||
u8 rsvd[2];
|
||||
u8 num_bitrates;
|
||||
u8 rsvd[1];
|
||||
u8 info[0];
|
||||
} __packed;
|
||||
|
||||
|
@ -885,12 +881,6 @@ struct qlink_event_rxmgmt {
|
|||
u8 frame_data[0];
|
||||
} __packed;
|
||||
|
||||
enum qlink_frame_type {
|
||||
QLINK_BSS_FTYPE_UNKNOWN,
|
||||
QLINK_BSS_FTYPE_BEACON,
|
||||
QLINK_BSS_FTYPE_PRESP,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qlink_event_scan_result - data for QLINK_EVENT_SCAN_RESULTS event
|
||||
*
|
||||
|
@ -900,7 +890,6 @@ enum qlink_frame_type {
|
|||
* @capab: capabilities field.
|
||||
* @bintval: beacon interval announced by discovered BSS.
|
||||
* @signal: signal strength.
|
||||
* @frame_type: frame type used to get scan result, see &enum qlink_frame_type.
|
||||
* @bssid: BSSID announced by discovered BSS.
|
||||
* @ssid_len: length of SSID announced by BSS.
|
||||
* @ssid: SSID announced by discovered BSS.
|
||||
|
@ -913,10 +902,10 @@ struct qlink_event_scan_result {
|
|||
__le16 capab;
|
||||
__le16 bintval;
|
||||
s8 signal;
|
||||
u8 frame_type;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 ssid_len;
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 rsvd[2];
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
|
@ -1151,6 +1140,33 @@ struct qlink_tlv_chandef {
|
|||
struct qlink_chandef chan;
|
||||
} __packed;
|
||||
|
||||
enum qlink_ie_set_type {
|
||||
QLINK_IE_SET_UNKNOWN,
|
||||
QLINK_IE_SET_ASSOC_REQ,
|
||||
QLINK_IE_SET_ASSOC_RESP,
|
||||
QLINK_IE_SET_PROBE_REQ,
|
||||
QLINK_IE_SET_SCAN,
|
||||
QLINK_IE_SET_BEACON_HEAD,
|
||||
QLINK_IE_SET_BEACON_TAIL,
|
||||
QLINK_IE_SET_BEACON_IES,
|
||||
QLINK_IE_SET_PROBE_RESP,
|
||||
QLINK_IE_SET_PROBE_RESP_IES,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qlink_tlv_ie_set - data for QTN_TLV_ID_IE_SET
|
||||
*
|
||||
* @type: type of MGMT frame IEs belong to, one of &enum qlink_ie_set_type.
|
||||
* @flags: for future use.
|
||||
* @ie_data: IEs data.
|
||||
*/
|
||||
struct qlink_tlv_ie_set {
|
||||
struct qlink_tlv_hdr hdr;
|
||||
u8 type;
|
||||
u8 flags;
|
||||
u8 ie_data[0];
|
||||
} __packed;
|
||||
|
||||
struct qlink_chan_stats {
|
||||
__le32 chan_num;
|
||||
__le32 cca_tx;
|
||||
|
|
|
@ -164,13 +164,13 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
|||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
struct sk_buff *skbcopy;
|
||||
struct rt2x00dump_hdr *dump_hdr;
|
||||
struct timeval timestamp;
|
||||
struct timespec64 timestamp;
|
||||
u32 data_len;
|
||||
|
||||
if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)))
|
||||
return;
|
||||
|
||||
do_gettimeofday(×tamp);
|
||||
ktime_get_ts64(×tamp);
|
||||
|
||||
if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
|
||||
rt2x00_dbg(rt2x00dev, "txrx dump queue length exceeded\n");
|
||||
|
@ -200,7 +200,8 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
|||
dump_hdr->queue_index = entry->queue->qid;
|
||||
dump_hdr->entry_index = entry->entry_idx;
|
||||
dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
|
||||
dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
|
||||
dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_nsec /
|
||||
NSEC_PER_USEC);
|
||||
|
||||
if (!(skbdesc->flags & SKBDESC_DESC_IN_SKB))
|
||||
skb_put_data(skbcopy, skbdesc->desc, skbdesc->desc_len);
|
||||
|
|
|
@ -106,7 +106,7 @@ enum rt2x00_dump_type {
|
|||
*/
|
||||
struct rt2x00dump_hdr {
|
||||
__le32 version;
|
||||
#define DUMP_HEADER_VERSION 2
|
||||
#define DUMP_HEADER_VERSION 3
|
||||
|
||||
__le32 header_length;
|
||||
__le32 desc_length;
|
||||
|
|
|
@ -57,7 +57,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
|
|||
if (status >= 0)
|
||||
return 0;
|
||||
|
||||
if (status == -ENODEV) {
|
||||
if (status == -ENODEV || status == -ENOENT) {
|
||||
/* Device has disappeared. */
|
||||
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
break;
|
||||
|
@ -321,7 +321,7 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data)
|
|||
|
||||
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
|
||||
if (status) {
|
||||
if (status == -ENODEV)
|
||||
if (status == -ENODEV || status == -ENOENT)
|
||||
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
|
||||
rt2x00lib_dmadone(entry);
|
||||
|
@ -410,7 +410,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data)
|
|||
|
||||
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
|
||||
if (status) {
|
||||
if (status == -ENODEV)
|
||||
if (status == -ENODEV || status == -ENOENT)
|
||||
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
|
||||
rt2x00lib_dmadone(entry);
|
||||
|
|
|
@ -1630,7 +1630,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
struct ieee80211_sta *sta, u16 tid)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_tid_data *tid_data;
|
||||
struct rtl_sta_info *sta_entry = NULL;
|
||||
|
||||
if (sta == NULL)
|
||||
|
@ -1643,7 +1642,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
return -EINVAL;
|
||||
|
||||
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
|
||||
tid_data = &sta_entry->tids[tid];
|
||||
sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP;
|
||||
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
|
|
|
@ -550,15 +550,13 @@ static int rtl_op_suspend(struct ieee80211_hw *hw,
|
|||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
|
||||
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
||||
struct timeval ts;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n");
|
||||
if (WARN_ON(!wow))
|
||||
return -EINVAL;
|
||||
|
||||
/* to resolve s4 can not wake up*/
|
||||
do_gettimeofday(&ts);
|
||||
rtlhal->last_suspend_sec = ts.tv_sec;
|
||||
rtlhal->last_suspend_sec = ktime_get_real_seconds();
|
||||
|
||||
if ((ppsc->wo_wlan_mode & WAKE_ON_PATTERN_MATCH) && wow->n_patterns)
|
||||
_rtl_add_wowlan_patterns(hw, wow);
|
||||
|
@ -577,7 +575,7 @@ static int rtl_op_resume(struct ieee80211_hw *hw)
|
|||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
struct timeval ts;
|
||||
time64_t now;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n");
|
||||
rtlhal->driver_is_goingto_unload = false;
|
||||
|
@ -585,8 +583,8 @@ static int rtl_op_resume(struct ieee80211_hw *hw)
|
|||
rtlhal->wake_from_pnp_sleep = true;
|
||||
|
||||
/* to resovle s4 can not wake up*/
|
||||
do_gettimeofday(&ts);
|
||||
if (ts.tv_sec - rtlhal->last_suspend_sec < 5)
|
||||
now = ktime_get_real_seconds();
|
||||
if (now - rtlhal->last_suspend_sec < 5)
|
||||
return -1;
|
||||
|
||||
rtl_op_start(hw);
|
||||
|
@ -1748,7 +1746,7 @@ bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
|
|||
u8 faversion, u8 interface_type,
|
||||
struct wlan_pwr_cfg pwrcfgcmd[])
|
||||
{
|
||||
struct wlan_pwr_cfg cfg_cmd = {0};
|
||||
struct wlan_pwr_cfg cfg_cmd;
|
||||
bool polling_bit = false;
|
||||
u32 ary_idx = 0;
|
||||
u8 value = 0;
|
||||
|
|
|
@ -54,8 +54,7 @@ static const u8 ac_to_hwq[] = {
|
|||
BK_QUEUE
|
||||
};
|
||||
|
||||
static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb)
|
||||
static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
__le16 fc = rtl_get_fc(skb);
|
||||
|
@ -104,20 +103,18 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
|
|||
break;
|
||||
|
||||
case 3:
|
||||
/*
|
||||
* Always enable ASPM and Clock Req
|
||||
/* Always enable ASPM and Clock Req
|
||||
* from initialization to halt.
|
||||
* */
|
||||
*/
|
||||
ppsc->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM);
|
||||
ppsc->reg_rfps_level |= (RT_RF_PS_LEVEL_ALWAYS_ASPM |
|
||||
RT_RF_OFF_LEVL_CLK_REQ);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/*
|
||||
* Always enable ASPM without Clock Req
|
||||
/* Always enable ASPM without Clock Req
|
||||
* from initialization to halt.
|
||||
* */
|
||||
*/
|
||||
ppsc->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM |
|
||||
RT_RF_OFF_LEVL_CLK_REQ);
|
||||
ppsc->reg_rfps_level |= RT_RF_PS_LEVEL_ALWAYS_ASPM;
|
||||
|
@ -146,32 +143,19 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
|
|||
|
||||
/*Set HW definition to determine if it supports ASPM. */
|
||||
switch (rtlpci->const_support_pciaspm) {
|
||||
case 0:{
|
||||
/*Not support ASPM. */
|
||||
bool support_aspm = false;
|
||||
ppsc->support_aspm = support_aspm;
|
||||
break;
|
||||
}
|
||||
case 1:{
|
||||
/*Support ASPM. */
|
||||
bool support_aspm = true;
|
||||
bool support_backdoor = true;
|
||||
ppsc->support_aspm = support_aspm;
|
||||
|
||||
/*if (priv->oem_id == RT_CID_TOSHIBA &&
|
||||
!priv->ndis_adapter.amd_l1_patch)
|
||||
support_backdoor = false; */
|
||||
|
||||
ppsc->support_backdoor = support_backdoor;
|
||||
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
/*Not support ASPM. */
|
||||
ppsc->support_aspm = false;
|
||||
break;
|
||||
case 1:
|
||||
/*Support ASPM. */
|
||||
ppsc->support_aspm = true;
|
||||
ppsc->support_backdoor = true;
|
||||
break;
|
||||
case 2:
|
||||
/*ASPM value set by chipset. */
|
||||
if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) {
|
||||
bool support_aspm = true;
|
||||
ppsc->support_aspm = support_aspm;
|
||||
}
|
||||
if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL)
|
||||
ppsc->support_aspm = true;
|
||||
break;
|
||||
default:
|
||||
pr_err("switch case %#x not processed\n",
|
||||
|
@ -180,10 +164,11 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
/* toshiba aspm issue, toshiba will set aspm selfly
|
||||
* so we should not set aspm in driver */
|
||||
* so we should not set aspm in driver
|
||||
*/
|
||||
pci_read_config_byte(rtlpci->pdev, 0x80, &init_aspm);
|
||||
if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE &&
|
||||
init_aspm == 0x43)
|
||||
init_aspm == 0x43)
|
||||
ppsc->support_aspm = false;
|
||||
}
|
||||
|
||||
|
@ -263,8 +248,7 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
|
|||
udelay(50);
|
||||
}
|
||||
|
||||
/*
|
||||
*Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for
|
||||
/*Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for
|
||||
*power saving We should follow the sequence to enable
|
||||
*RTL8192SE first then enable Pci Bridge ASPM
|
||||
*or the system will show bluescreen.
|
||||
|
@ -334,7 +318,7 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
|
|||
|
||||
bool status = false;
|
||||
u8 offset_e0;
|
||||
unsigned offset_e4;
|
||||
unsigned int offset_e4;
|
||||
|
||||
pci_write_config_byte(rtlpci->pdev, 0xe0, 0xa0);
|
||||
|
||||
|
@ -369,12 +353,12 @@ static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw,
|
|||
"tpcipriv->ndis_adapter.funcnumber %x\n",
|
||||
tpcipriv->ndis_adapter.funcnumber);
|
||||
|
||||
if ((pcipriv->ndis_adapter.busnumber ==
|
||||
tpcipriv->ndis_adapter.busnumber) &&
|
||||
(pcipriv->ndis_adapter.devnumber ==
|
||||
tpcipriv->ndis_adapter.devnumber) &&
|
||||
(pcipriv->ndis_adapter.funcnumber !=
|
||||
tpcipriv->ndis_adapter.funcnumber)) {
|
||||
if (pcipriv->ndis_adapter.busnumber ==
|
||||
tpcipriv->ndis_adapter.busnumber &&
|
||||
pcipriv->ndis_adapter.devnumber ==
|
||||
tpcipriv->ndis_adapter.devnumber &&
|
||||
pcipriv->ndis_adapter.funcnumber !=
|
||||
tpcipriv->ndis_adapter.funcnumber) {
|
||||
find_buddy_priv = true;
|
||||
break;
|
||||
}
|
||||
|
@ -407,7 +391,7 @@ static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
static void rtl_pci_parse_configuration(struct pci_dev *pdev,
|
||||
struct ieee80211_hw *hw)
|
||||
struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
|
@ -441,7 +425,6 @@ static void rtl_pci_init_aspm(struct ieee80211_hw *hw)
|
|||
rtl_pci_enable_aspm(hw);
|
||||
RT_SET_PS_LEVEL(ppsc, RT_RF_PS_LEVEL_ALWAYS_ASPM);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void _rtl_pci_io_handler_init(struct device *dev,
|
||||
|
@ -458,11 +441,11 @@ static void _rtl_pci_io_handler_init(struct device *dev,
|
|||
rtlpriv->io.read8_sync = pci_read8_sync;
|
||||
rtlpriv->io.read16_sync = pci_read16_sync;
|
||||
rtlpriv->io.read32_sync = pci_read32_sync;
|
||||
|
||||
}
|
||||
|
||||
static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid)
|
||||
struct sk_buff *skb,
|
||||
struct rtl_tcb_desc *tcb_desc, u8 tid)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
@ -520,13 +503,15 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
|
|||
(rtlpriv->buddy_priv &&
|
||||
rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process)))
|
||||
return;
|
||||
/* we juse use em for BE/BK/VI/VO */
|
||||
/* we just use em for BE/BK/VI/VO */
|
||||
for (tid = 7; tid >= 0; tid--) {
|
||||
u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)];
|
||||
struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
|
||||
|
||||
while (!mac->act_scanning &&
|
||||
rtlpriv->psc.rfpwr_state == ERFON) {
|
||||
struct rtl_tcb_desc tcb_desc;
|
||||
|
||||
memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
|
||||
|
||||
spin_lock_bh(&rtlpriv->locks.waitq_lock);
|
||||
|
@ -541,7 +526,8 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
|
|||
spin_unlock_bh(&rtlpriv->locks.waitq_lock);
|
||||
|
||||
/* Some macaddr can't do early mode. like
|
||||
* multicast/broadcast/no_qos data */
|
||||
* multicast/broadcast/no_qos data
|
||||
*/
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
_rtl_update_earlymode_info(hw, skb,
|
||||
|
@ -552,7 +538,6 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
@ -603,7 +588,6 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
|
|||
if (prio == TXCMD_QUEUE) {
|
||||
dev_kfree_skb(skb);
|
||||
goto tx_status_ok;
|
||||
|
||||
}
|
||||
|
||||
/* for sw LPS, just after NULL skb send out, we can
|
||||
|
@ -643,15 +627,12 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
|
|||
ieee80211_tx_status_irqsafe(hw, skb);
|
||||
|
||||
if ((ring->entries - skb_queue_len(&ring->queue)) <= 4) {
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
|
||||
"more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n",
|
||||
prio, ring->idx,
|
||||
skb_queue_len(&ring->queue));
|
||||
|
||||
ieee80211_wake_queue(hw,
|
||||
skb_get_queue_mapping
|
||||
(skb));
|
||||
ieee80211_wake_queue(hw, skb_get_queue_mapping(skb));
|
||||
}
|
||||
tx_status_ok:
|
||||
skb = NULL;
|
||||
|
@ -659,7 +640,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
|
|||
|
||||
if (((rtlpriv->link_info.num_rx_inperiod +
|
||||
rtlpriv->link_info.num_tx_inperiod) > 8) ||
|
||||
(rtlpriv->link_info.num_rx_inperiod > 2))
|
||||
rtlpriv->link_info.num_rx_inperiod > 2)
|
||||
rtl_lps_leave(hw);
|
||||
}
|
||||
|
||||
|
@ -817,7 +798,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
|
|||
new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
|
||||
if (unlikely(!new_skb))
|
||||
goto no_new;
|
||||
memset(&rx_status , 0 , sizeof(rx_status));
|
||||
memset(&rx_status, 0, sizeof(rx_status));
|
||||
rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
|
||||
&rx_status, (u8 *)pdesc, skb);
|
||||
|
||||
|
@ -847,12 +828,11 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
|
|||
/* handle command packet here */
|
||||
if (rtlpriv->cfg->ops->rx_command_packet &&
|
||||
rtlpriv->cfg->ops->rx_command_packet(hw, &stats, skb)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
goto new_trx_end;
|
||||
dev_kfree_skb_any(skb);
|
||||
goto new_trx_end;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTICE This can not be use for mac80211,
|
||||
/* NOTICE This can not be use for mac80211,
|
||||
* this is done in mac80211 code,
|
||||
* if done here sec DHCP will fail
|
||||
* skb_trim(skb, skb->len - 4);
|
||||
|
@ -889,9 +869,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
|
|||
/* for sw lps */
|
||||
rtl_swlps_beacon(hw, (void *)skb->data, skb->len);
|
||||
rtl_recognize_peer(hw, (void *)skb->data, skb->len);
|
||||
if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) &&
|
||||
(rtlpriv->rtlhal.current_bandtype ==
|
||||
BAND_ON_2_4G) &&
|
||||
if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP &&
|
||||
rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G &&
|
||||
(ieee80211_is_beacon(fc) ||
|
||||
ieee80211_is_probe_resp(fc))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
|
@ -913,7 +892,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
|
|||
}
|
||||
if (((rtlpriv->link_info.num_rx_inperiod +
|
||||
rtlpriv->link_info.num_tx_inperiod) > 8) ||
|
||||
(rtlpriv->link_info.num_rx_inperiod > 2))
|
||||
rtlpriv->link_info.num_rx_inperiod > 2)
|
||||
rtl_lps_leave(hw);
|
||||
skb = new_skb;
|
||||
no_new:
|
||||
|
@ -947,35 +926,34 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
|
|||
unsigned long flags;
|
||||
u32 inta = 0;
|
||||
u32 intb = 0;
|
||||
u32 intc = 0;
|
||||
u32 intd = 0;
|
||||
irqreturn_t ret = IRQ_HANDLED;
|
||||
|
||||
if (rtlpci->irq_enabled == 0)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock , flags);
|
||||
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
|
||||
rtlpriv->cfg->ops->disable_interrupt(hw);
|
||||
|
||||
/*read ISR: 4/8bytes */
|
||||
rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb);
|
||||
rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb, &intc, &intd);
|
||||
|
||||
/*Shared IRQ or HW disappared */
|
||||
/*Shared IRQ or HW disappeared */
|
||||
if (!inta || inta == 0xffff)
|
||||
goto done;
|
||||
|
||||
/*<1> beacon related */
|
||||
if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK]) {
|
||||
if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK])
|
||||
RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
|
||||
"beacon ok interrupt!\n");
|
||||
}
|
||||
|
||||
if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_TBDER])) {
|
||||
if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_TBDER]))
|
||||
RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
|
||||
"beacon err interrupt!\n");
|
||||
}
|
||||
|
||||
if (inta & rtlpriv->cfg->maps[RTL_IMR_BDOK]) {
|
||||
if (inta & rtlpriv->cfg->maps[RTL_IMR_BDOK])
|
||||
RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n");
|
||||
}
|
||||
|
||||
if (inta & rtlpriv->cfg->maps[RTL_IMR_BCNINT]) {
|
||||
RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
|
||||
|
@ -1031,6 +1009,16 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
|
|||
_rtl_pci_tx_isr(hw, VO_QUEUE);
|
||||
}
|
||||
|
||||
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8822BE) {
|
||||
if (intd & rtlpriv->cfg->maps[RTL_IMR_H2CDOK]) {
|
||||
rtlpriv->link_info.num_tx_inperiod++;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
|
||||
"H2C TX OK interrupt!\n");
|
||||
_rtl_pci_tx_isr(hw, H2C_QUEUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) {
|
||||
if (inta & rtlpriv->cfg->maps[RTL_IMR_COMDOK]) {
|
||||
rtlpriv->link_info.num_tx_inperiod++;
|
||||
|
@ -1130,7 +1118,7 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
|
|||
|
||||
/*NB: the beacon data buffer must be 32-bit aligned. */
|
||||
pskb = ieee80211_beacon_get(hw, mac->vif);
|
||||
if (pskb == NULL)
|
||||
if (!pskb)
|
||||
return;
|
||||
hdr = rtl_get_hdr(pskb);
|
||||
info = IEEE80211_SKB_CB(pskb);
|
||||
|
@ -1152,7 +1140,6 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
|
|||
rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN,
|
||||
&temp_one);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
|
||||
|
@ -1165,14 +1152,15 @@ static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
|
|||
|
||||
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE)
|
||||
desc_num = TX_DESC_NUM_92E;
|
||||
else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8822BE)
|
||||
desc_num = TX_DESC_NUM_8822B;
|
||||
else
|
||||
desc_num = RT_TXDESC_NUM;
|
||||
|
||||
for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++)
|
||||
rtlpci->txringcount[i] = desc_num;
|
||||
|
||||
/*
|
||||
*we just alloc 2 desc for beacon queue,
|
||||
/*we just alloc 2 desc for beacon queue,
|
||||
*because we just need first desc in hw beacon.
|
||||
*/
|
||||
rtlpci->txringcount[BEACON_QUEUE] = 2;
|
||||
|
@ -1189,7 +1177,7 @@ static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
|
||||
struct pci_dev *pdev)
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
|
@ -1361,7 +1349,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx)
|
|||
}
|
||||
|
||||
static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
|
||||
unsigned int prio)
|
||||
unsigned int prio)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
@ -1378,8 +1366,7 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
|
|||
entry = (u8 *)(&ring->desc[ring->idx]);
|
||||
|
||||
pci_unmap_single(rtlpci->pdev,
|
||||
rtlpriv->cfg->
|
||||
ops->get_desc(hw, (u8 *)entry,
|
||||
rtlpriv->cfg->ops->get_desc(hw, (u8 *)entry,
|
||||
true,
|
||||
HW_DESC_TXBUFF_ADDR),
|
||||
skb->len, PCI_DMA_TODEVICE);
|
||||
|
@ -1451,8 +1438,7 @@ static int _rtl_pci_init_trx_ring(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) {
|
||||
ret = _rtl_pci_init_tx_ring(hw, i,
|
||||
rtlpci->txringcount[i]);
|
||||
ret = _rtl_pci_init_tx_ring(hw, i, rtlpci->txringcount[i]);
|
||||
if (ret)
|
||||
goto err_free_rings;
|
||||
}
|
||||
|
@ -1500,7 +1486,7 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
|
|||
/* force the rx_ring[RX_MPDU_QUEUE/
|
||||
* RX_CMD_QUEUE].idx to the first one
|
||||
*new trx flow, do nothing
|
||||
*/
|
||||
*/
|
||||
if (!rtlpriv->use_new_trx_flow &&
|
||||
rtlpci->rx_ring[rxring_idx].desc) {
|
||||
struct rtl_rx_desc *entry = NULL;
|
||||
|
@ -1510,8 +1496,8 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
|
|||
entry = &rtlpci->rx_ring[rxring_idx].desc[i];
|
||||
bufferaddress =
|
||||
rtlpriv->cfg->ops->get_desc(hw, (u8 *)entry,
|
||||
false , HW_DESC_RXBUFF_ADDR);
|
||||
memset((u8 *)entry , 0 ,
|
||||
false, HW_DESC_RXBUFF_ADDR);
|
||||
memset((u8 *)entry, 0,
|
||||
sizeof(*rtlpci->rx_ring
|
||||
[rxring_idx].desc));/*clear one entry*/
|
||||
if (rtlpriv->use_new_trx_flow) {
|
||||
|
@ -1540,8 +1526,7 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
|
|||
rtlpci->rx_ring[rxring_idx].idx = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*after reset, release previous pending packet,
|
||||
/*after reset, release previous pending packet,
|
||||
*and force the tx idx to the first one
|
||||
*/
|
||||
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
|
||||
|
@ -1642,7 +1627,7 @@ static int rtl_pci_tx(struct ieee80211_hw *hw,
|
|||
|
||||
if (rtlpriv->psc.sw_ps_enabled) {
|
||||
if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) &&
|
||||
!ieee80211_has_pm(fc))
|
||||
!ieee80211_has_pm(fc))
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
|
||||
}
|
||||
|
||||
|
@ -1674,7 +1659,7 @@ static int rtl_pci_tx(struct ieee80211_hw *hw,
|
|||
own = (u8)rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc,
|
||||
true, HW_DESC_OWN);
|
||||
|
||||
if ((own == 1) && (hw_queue != BEACON_QUEUE)) {
|
||||
if (own == 1 && hw_queue != BEACON_QUEUE) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
|
||||
"No more TX desc@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%x\n",
|
||||
hw_queue, ring->idx, idx,
|
||||
|
@ -1688,11 +1673,10 @@ static int rtl_pci_tx(struct ieee80211_hw *hw,
|
|||
|
||||
if (rtlpriv->cfg->ops->get_available_desc &&
|
||||
rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
|
||||
"get_available_desc fail\n");
|
||||
spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
|
||||
flags);
|
||||
return skb->len;
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
|
||||
"get_available_desc fail\n");
|
||||
spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
if (ieee80211_is_data(fc))
|
||||
|
@ -1751,7 +1735,7 @@ static void rtl_pci_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
|||
ring = &pcipriv->dev.tx_ring[queue_id];
|
||||
queue_len = skb_queue_len(&ring->queue);
|
||||
if (queue_len == 0 || queue_id == BEACON_QUEUE ||
|
||||
queue_id == TXCMD_QUEUE) {
|
||||
queue_id == TXCMD_QUEUE) {
|
||||
queue_id--;
|
||||
continue;
|
||||
} else {
|
||||
|
@ -1761,7 +1745,7 @@ static void rtl_pci_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
|
|||
|
||||
/* we just wait 1s for all queues */
|
||||
if (rtlpriv->psc.rfpwr_state == ERFOFF ||
|
||||
is_hal_stop(rtlhal) || i >= 200)
|
||||
is_hal_stop(rtlhal) || i >= 200)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1779,7 +1763,6 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)
|
|||
|
||||
flush_workqueue(rtlpriv->works.rtl_wq);
|
||||
destroy_workqueue(rtlpriv->works.rtl_wq);
|
||||
|
||||
}
|
||||
|
||||
static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev)
|
||||
|
@ -1837,7 +1820,7 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
|
|||
|
||||
rtlpci->up_first_time = false;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "rtl_pci_start OK\n");
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%s OK\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1848,13 +1831,12 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
|
|||
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
unsigned long flags;
|
||||
u8 RFInProgressTimeOut = 0;
|
||||
u8 rf_timeout = 0;
|
||||
|
||||
if (rtlpriv->cfg->ops->get_btc_status())
|
||||
rtlpriv->btcoexist.btc_ops->btc_halt_notify();
|
||||
|
||||
/*
|
||||
*should be before disable interrupt&adapter
|
||||
/*should be before disable interrupt&adapter
|
||||
*and will do it immediately.
|
||||
*/
|
||||
set_hal_stop(rtlhal);
|
||||
|
@ -1866,12 +1848,12 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
|
|||
spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
|
||||
while (ppsc->rfchange_inprogress) {
|
||||
spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);
|
||||
if (RFInProgressTimeOut > 100) {
|
||||
if (rf_timeout > 100) {
|
||||
spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
|
||||
break;
|
||||
}
|
||||
mdelay(1);
|
||||
RFInProgressTimeOut++;
|
||||
rf_timeout++;
|
||||
spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
|
||||
}
|
||||
ppsc->rfchange_inprogress = true;
|
||||
|
@ -1891,7 +1873,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
|
||||
struct ieee80211_hw *hw)
|
||||
struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
|
@ -1946,13 +1928,12 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
|
|||
venderid, deviceid);
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE;
|
||||
break;
|
||||
|
||||
}
|
||||
} else if (deviceid == RTL_PCI_8723AE_DID) {
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8723AE;
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
|
||||
"8723AE PCI-E is found - "
|
||||
"vid/did=%x/%x\n", venderid, deviceid);
|
||||
"8723AE PCI-E is found - vid/did=%x/%x\n",
|
||||
venderid, deviceid);
|
||||
} else if (deviceid == RTL_PCI_8192CET_DID ||
|
||||
deviceid == RTL_PCI_8192CE_DID ||
|
||||
deviceid == RTL_PCI_8191CE_DID ||
|
||||
|
@ -1972,21 +1953,26 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
|
|||
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8188EE\n");
|
||||
} else if (deviceid == RTL_PCI_8723BE_DID) {
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8723BE;
|
||||
RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8723BE\n");
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8723BE;
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8723BE\n");
|
||||
} else if (deviceid == RTL_PCI_8192EE_DID) {
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8192EE;
|
||||
RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8192EE\n");
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8192EE;
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8192EE\n");
|
||||
} else if (deviceid == RTL_PCI_8821AE_DID) {
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8821AE;
|
||||
RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8821AE\n");
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8821AE;
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8821AE\n");
|
||||
} else if (deviceid == RTL_PCI_8812AE_DID) {
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8812AE;
|
||||
RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8812AE\n");
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8812AE;
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8812AE\n");
|
||||
} else if (deviceid == RTL_PCI_8822BE_DID) {
|
||||
rtlhal->hw_type = HARDWARE_TYPE_RTL8822BE;
|
||||
rtlhal->bandset = BAND_ON_BOTH;
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
|
||||
"Find adapter, Hardware type is 8822BE\n");
|
||||
} else {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
|
||||
"Err: Unknown device - vid/did=%x/%x\n",
|
||||
|
@ -2014,11 +2000,17 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
|
|||
}
|
||||
}
|
||||
|
||||
/* 92ee use new trx flow */
|
||||
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE)
|
||||
switch (rtlhal->hw_type) {
|
||||
case HARDWARE_TYPE_RTL8192EE:
|
||||
case HARDWARE_TYPE_RTL8822BE:
|
||||
/* use new trx flow */
|
||||
rtlpriv->use_new_trx_flow = true;
|
||||
else
|
||||
break;
|
||||
|
||||
default:
|
||||
rtlpriv->use_new_trx_flow = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/*find bus info */
|
||||
pcipriv->ndis_adapter.busnumber = pdev->bus->number;
|
||||
|
@ -2109,7 +2101,7 @@ static int rtl_pci_intr_mode_msi(struct ieee80211_hw *hw)
|
|||
|
||||
rtlpci->using_msi = true;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG,
|
||||
RT_TRACE(rtlpriv, COMP_INIT | COMP_INTR, DBG_DMESG,
|
||||
"MSI Interrupt Mode!\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -2127,7 +2119,7 @@ static int rtl_pci_intr_mode_legacy(struct ieee80211_hw *hw)
|
|||
return ret;
|
||||
|
||||
rtlpci->using_msi = false;
|
||||
RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG,
|
||||
RT_TRACE(rtlpriv, COMP_INIT | COMP_INTR, DBG_DMESG,
|
||||
"Pin-based Interrupt Mode!\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -2164,7 +2156,7 @@ static void platform_enable_dma64(struct pci_dev *pdev, bool dma64)
|
|||
}
|
||||
|
||||
int rtl_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct ieee80211_hw *hw = NULL;
|
||||
|
||||
|
@ -2343,7 +2335,6 @@ int rtl_pci_probe(struct pci_dev *pdev,
|
|||
pci_disable_device(pdev);
|
||||
|
||||
return err;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(rtl_pci_probe);
|
||||
|
||||
|
@ -2402,20 +2393,20 @@ EXPORT_SYMBOL(rtl_pci_disconnect);
|
|||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/***************************************
|
||||
kernel pci power state define:
|
||||
PCI_D0 ((pci_power_t __force) 0)
|
||||
PCI_D1 ((pci_power_t __force) 1)
|
||||
PCI_D2 ((pci_power_t __force) 2)
|
||||
PCI_D3hot ((pci_power_t __force) 3)
|
||||
PCI_D3cold ((pci_power_t __force) 4)
|
||||
PCI_UNKNOWN ((pci_power_t __force) 5)
|
||||
* kernel pci power state define:
|
||||
* PCI_D0 ((pci_power_t __force) 0)
|
||||
* PCI_D1 ((pci_power_t __force) 1)
|
||||
* PCI_D2 ((pci_power_t __force) 2)
|
||||
* PCI_D3hot ((pci_power_t __force) 3)
|
||||
* PCI_D3cold ((pci_power_t __force) 4)
|
||||
* PCI_UNKNOWN ((pci_power_t __force) 5)
|
||||
|
||||
This function is called when system
|
||||
goes into suspend state mac80211 will
|
||||
call rtl_mac_stop() from the mac80211
|
||||
suspend function first, So there is
|
||||
no need to call hw_disable here.
|
||||
****************************************/
|
||||
* This function is called when system
|
||||
* goes into suspend state mac80211 will
|
||||
* call rtl_mac_stop() from the mac80211
|
||||
* suspend function first, So there is
|
||||
* no need to call hw_disable here.
|
||||
****************************************/
|
||||
int rtl_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
|
|
@ -27,10 +27,9 @@
|
|||
#define __RTL_PCI_H__
|
||||
|
||||
#include <linux/pci.h>
|
||||
/*
|
||||
1: MSDU packet queue,
|
||||
2: Rx Command Queue
|
||||
*/
|
||||
/* 1: MSDU packet queue,
|
||||
* 2: Rx Command Queue
|
||||
*/
|
||||
#define RTL_PCI_RX_MPDU_QUEUE 0
|
||||
#define RTL_PCI_RX_CMD_QUEUE 1
|
||||
#define RTL_PCI_MAX_RX_QUEUE 2
|
||||
|
@ -40,6 +39,7 @@
|
|||
|
||||
#define RT_TXDESC_NUM 128
|
||||
#define TX_DESC_NUM_92E 512
|
||||
#define TX_DESC_NUM_8822B 512
|
||||
#define RT_TXDESC_NUM_BE_QUEUE 256
|
||||
|
||||
#define BK_QUEUE 0
|
||||
|
@ -51,6 +51,7 @@
|
|||
#define MGNT_QUEUE 6
|
||||
#define HIGH_QUEUE 7
|
||||
#define HCCA_QUEUE 8
|
||||
#define H2C_QUEUE TXCMD_QUEUE /* In 8822B */
|
||||
|
||||
#define RTL_PCI_DEVICE(vend, dev, cfg) \
|
||||
.vendor = (vend), \
|
||||
|
@ -108,6 +109,7 @@
|
|||
#define RTL_PCI_8192EE_DID 0x818B /*8192ee*/
|
||||
#define RTL_PCI_8821AE_DID 0x8821 /*8821ae*/
|
||||
#define RTL_PCI_8812AE_DID 0x8812 /*8812ae*/
|
||||
#define RTL_PCI_8822BE_DID 0xB822 /*8822be*/
|
||||
|
||||
/*8192 support 16 pages of IO registers*/
|
||||
#define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000
|
||||
|
@ -209,7 +211,7 @@ struct rtl_pci {
|
|||
|
||||
/*irq */
|
||||
u8 irq_alloc;
|
||||
u32 irq_mask[2];
|
||||
u32 irq_mask[4]; /* 0-1: normal, 2: unused, 3: h2c */
|
||||
u32 sys_irq_mask;
|
||||
|
||||
/*Bcn control register setting */
|
||||
|
@ -223,8 +225,9 @@ struct rtl_pci {
|
|||
u8 const_hostpci_aspm_setting;
|
||||
/*pci-e device */
|
||||
u8 const_devicepci_aspm_setting;
|
||||
/*If it supports ASPM, Offset[560h] = 0x40,
|
||||
otherwise Offset[560h] = 0x00. */
|
||||
/* If it supports ASPM, Offset[560h] = 0x40,
|
||||
* otherwise Offset[560h] = 0x00.
|
||||
*/
|
||||
bool support_aspm;
|
||||
bool support_backdoor;
|
||||
|
||||
|
@ -279,7 +282,7 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw);
|
|||
extern const struct rtl_intf_ops rtl_pci_ops;
|
||||
|
||||
int rtl_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id);
|
||||
const struct pci_device_id *id);
|
||||
void rtl_pci_disconnect(struct pci_dev *pdev);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int rtl_pci_suspend(struct device *dev);
|
||||
|
@ -287,34 +290,34 @@ int rtl_pci_resume(struct device *dev);
|
|||
#endif /* CONFIG_PM_SLEEP */
|
||||
static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
|
||||
{
|
||||
return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
|
||||
return readb((u8 __iomem *)rtlpriv->io.pci_mem_start + addr);
|
||||
}
|
||||
|
||||
static inline u16 pci_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
|
||||
{
|
||||
return readw((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
|
||||
return readw((u8 __iomem *)rtlpriv->io.pci_mem_start + addr);
|
||||
}
|
||||
|
||||
static inline u32 pci_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
|
||||
{
|
||||
return readl((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
|
||||
return readl((u8 __iomem *)rtlpriv->io.pci_mem_start + addr);
|
||||
}
|
||||
|
||||
static inline void pci_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val)
|
||||
{
|
||||
writeb(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
|
||||
writeb(val, (u8 __iomem *)rtlpriv->io.pci_mem_start + addr);
|
||||
}
|
||||
|
||||
static inline void pci_write16_async(struct rtl_priv *rtlpriv,
|
||||
u32 addr, u16 val)
|
||||
{
|
||||
writew(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
|
||||
writew(val, (u8 __iomem *)rtlpriv->io.pci_mem_start + addr);
|
||||
}
|
||||
|
||||
static inline void pci_write32_async(struct rtl_priv *rtlpriv,
|
||||
u32 addr, u32 val)
|
||||
{
|
||||
writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
|
||||
writel(val, (u8 __iomem *)rtlpriv->io.pci_mem_start + addr);
|
||||
}
|
||||
|
||||
static inline u16 calc_fifo_space(u16 rp, u16 wp)
|
||||
|
|
|
@ -1472,7 +1472,8 @@ void rtl88ee_card_disable(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb)
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
|
||||
void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw);
|
||||
void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb);
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd);
|
||||
int rtl88ee_hw_init(struct ieee80211_hw *hw);
|
||||
void rtl88ee_card_disable(struct ieee80211_hw *hw);
|
||||
void rtl88ee_enable_interrupt(struct ieee80211_hw *hw);
|
||||
|
|
|
@ -1375,7 +1375,8 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb)
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
|
|
@ -42,7 +42,8 @@ static inline u8 rtl92c_get_chnl_group(u8 chnl)
|
|||
void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
|
||||
void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw);
|
||||
void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb);
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd);
|
||||
int rtl92ce_hw_init(struct ieee80211_hw *hw);
|
||||
void rtl92ce_card_disable(struct ieee80211_hw *hw);
|
||||
void rtl92ce_enable_interrupt(struct ieee80211_hw *hw);
|
||||
|
|
|
@ -1356,7 +1356,8 @@ void rtl92de_card_disable(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
void rtl92de_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb)
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
|
||||
void rtl92de_read_eeprom_info(struct ieee80211_hw *hw);
|
||||
void rtl92de_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb);
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd);
|
||||
int rtl92de_hw_init(struct ieee80211_hw *hw);
|
||||
void rtl92de_card_disable(struct ieee80211_hw *hw);
|
||||
void rtl92de_enable_interrupt(struct ieee80211_hw *hw);
|
||||
|
|
|
@ -1694,7 +1694,8 @@ void rtl92ee_card_disable(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
void rtl92ee_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb)
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
|
||||
void rtl92ee_read_eeprom_info(struct ieee80211_hw *hw);
|
||||
void rtl92ee_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb);
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd);
|
||||
int rtl92ee_hw_init(struct ieee80211_hw *hw);
|
||||
void rtl92ee_card_disable(struct ieee80211_hw *hw);
|
||||
void rtl92ee_enable_interrupt(struct ieee80211_hw *hw);
|
||||
|
|
|
@ -1559,7 +1559,7 @@ void rtl92se_card_disable(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, u32 *p_inta,
|
||||
u32 *p_intb)
|
||||
u32 *p_intb, u32 *p_intc, u32 *p_intd)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
|
|
@ -42,7 +42,8 @@ void rtl92se_get_hw_reg(struct ieee80211_hw *hw,
|
|||
u8 variable, u8 *val);
|
||||
void rtl92se_read_eeprom_info(struct ieee80211_hw *hw);
|
||||
void rtl92se_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *inta, u32 *intb);
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd);
|
||||
int rtl92se_hw_init(struct ieee80211_hw *hw);
|
||||
void rtl92se_card_disable(struct ieee80211_hw *hw);
|
||||
void rtl92se_enable_interrupt(struct ieee80211_hw *hw);
|
||||
|
|
|
@ -1340,7 +1340,8 @@ void rtl8723e_card_disable(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
void rtl8723e_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb)
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
|
|
@ -34,7 +34,8 @@ void rtl8723e_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
|
|||
void rtl8723e_read_eeprom_info(struct ieee80211_hw *hw);
|
||||
|
||||
void rtl8723e_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb);
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd);
|
||||
int rtl8723e_hw_init(struct ieee80211_hw *hw);
|
||||
void rtl8723e_card_disable(struct ieee80211_hw *hw);
|
||||
void rtl8723e_enable_interrupt(struct ieee80211_hw *hw);
|
||||
|
|
|
@ -1682,7 +1682,8 @@ void rtl8723be_card_disable(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
void rtl8723be_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb)
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
|
|
@ -30,7 +30,8 @@ void rtl8723be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
|
|||
void rtl8723be_read_eeprom_info(struct ieee80211_hw *hw);
|
||||
|
||||
void rtl8723be_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb);
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd);
|
||||
int rtl8723be_hw_init(struct ieee80211_hw *hw);
|
||||
void rtl8723be_card_disable(struct ieee80211_hw *hw);
|
||||
void rtl8723be_enable_interrupt(struct ieee80211_hw *hw);
|
||||
|
|
|
@ -1364,7 +1364,6 @@ static void _rtl8821ae_get_wakeup_reason(struct ieee80211_hw *hw)
|
|||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
|
||||
u8 fw_reason = 0;
|
||||
struct timeval ts;
|
||||
|
||||
fw_reason = rtl_read_byte(rtlpriv, REG_MCUTST_WOWLAN);
|
||||
|
||||
|
@ -1373,20 +1372,16 @@ static void _rtl8821ae_get_wakeup_reason(struct ieee80211_hw *hw)
|
|||
|
||||
ppsc->wakeup_reason = 0;
|
||||
|
||||
rtlhal->last_suspend_sec = ts.tv_sec;
|
||||
rtlhal->last_suspend_sec = ktime_get_real_seconds();
|
||||
|
||||
switch (fw_reason) {
|
||||
case FW_WOW_V2_PTK_UPDATE_EVENT:
|
||||
ppsc->wakeup_reason = WOL_REASON_PTK_UPDATE;
|
||||
do_gettimeofday(&ts);
|
||||
ppsc->last_wakeup_time = ts.tv_sec*1000 + ts.tv_usec/1000;
|
||||
RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
|
||||
"It's a WOL PTK Key update event!\n");
|
||||
break;
|
||||
case FW_WOW_V2_GTK_UPDATE_EVENT:
|
||||
ppsc->wakeup_reason = WOL_REASON_GTK_UPDATE;
|
||||
do_gettimeofday(&ts);
|
||||
ppsc->last_wakeup_time = ts.tv_sec*1000 + ts.tv_usec/1000;
|
||||
RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
|
||||
"It's a WOL GTK Key update event!\n");
|
||||
break;
|
||||
|
@ -2488,7 +2483,8 @@ void rtl8821ae_card_disable(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
void rtl8821ae_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb)
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
|
|
|
@ -30,7 +30,8 @@ void rtl8821ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
|
|||
void rtl8821ae_read_eeprom_info(struct ieee80211_hw *hw);
|
||||
|
||||
void rtl8821ae_interrupt_recognized(struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb);
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd);
|
||||
int rtl8821ae_hw_init(struct ieee80211_hw *hw);
|
||||
void rtl8821ae_card_disable(struct ieee80211_hw *hw);
|
||||
void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw);
|
||||
|
|
|
@ -709,6 +709,7 @@ enum rtl_var_map {
|
|||
RTL_IMR_RXFOVW, /*Receive FIFO Overflow */
|
||||
RTL_IMR_RDU, /*Receive Descriptor Unavailable */
|
||||
RTL_IMR_ATIMEND, /*For 92C,ATIM Window End Interrupt */
|
||||
RTL_IMR_H2CDOK, /*H2C Queue DMA OK Interrupt */
|
||||
RTL_IMR_BDOK, /*Beacon Queue DMA OK Interrup */
|
||||
RTL_IMR_HIGHDOK, /*High Queue DMA OK Interrupt */
|
||||
RTL_IMR_COMDOK, /*Command Queue DMA OK Interrupt*/
|
||||
|
@ -1599,7 +1600,7 @@ struct rtl_hal {
|
|||
bool enter_pnp_sleep;
|
||||
bool wake_from_pnp_sleep;
|
||||
bool wow_enabled;
|
||||
__kernel_time_t last_suspend_sec;
|
||||
time64_t last_suspend_sec;
|
||||
u32 wowlan_fwsize;
|
||||
u8 *wowlan_firmware;
|
||||
|
||||
|
@ -1953,8 +1954,6 @@ struct rtl_ps_ctl {
|
|||
u8 gtk_offload_enable;
|
||||
/* Used for WOL, indicates the reason for waking event.*/
|
||||
u32 wakeup_reason;
|
||||
/* Record the last waking time for comparison with setting key. */
|
||||
u64 last_wakeup_time;
|
||||
};
|
||||
|
||||
struct rtl_stats {
|
||||
|
@ -2100,7 +2099,8 @@ struct rtl_hal_ops {
|
|||
void (*read_chip_version)(struct ieee80211_hw *hw);
|
||||
void (*read_eeprom_info) (struct ieee80211_hw *hw);
|
||||
void (*interrupt_recognized) (struct ieee80211_hw *hw,
|
||||
u32 *p_inta, u32 *p_intb);
|
||||
u32 *p_inta, u32 *p_intb,
|
||||
u32 *p_intc, u32 *p_intd);
|
||||
int (*hw_init) (struct ieee80211_hw *hw);
|
||||
void (*hw_disable) (struct ieee80211_hw *hw);
|
||||
void (*hw_suspend) (struct ieee80211_hw *hw);
|
||||
|
@ -2144,6 +2144,9 @@ struct rtl_hal_ops {
|
|||
void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc,
|
||||
bool firstseg, bool lastseg,
|
||||
struct sk_buff *skb);
|
||||
void (*fill_tx_special_desc)(struct ieee80211_hw *hw,
|
||||
u8 *pdesc, u8 *pbd_desc,
|
||||
struct sk_buff *skb, u8 hw_queue);
|
||||
bool (*query_rx_desc) (struct ieee80211_hw *hw,
|
||||
struct rtl_stats *stats,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
|
|
|
@ -36,7 +36,6 @@ char *str_psstate(enum ps_state state)
|
|||
default:
|
||||
return "INVALID_STATE";
|
||||
}
|
||||
return "INVALID_STATE";
|
||||
}
|
||||
|
||||
static inline void rsi_modify_ps_state(struct rsi_hw *adapter,
|
||||
|
|
|
@ -230,8 +230,7 @@ static void zd1201_usbrx(struct urb *urb)
|
|||
/* Info frame */
|
||||
if (type == ZD1201_PACKET_INQUIRE) {
|
||||
int i = 0;
|
||||
unsigned short infotype, framelen, copylen;
|
||||
framelen = le16_to_cpu(*(__le16*)&data[4]);
|
||||
unsigned short infotype, copylen;
|
||||
infotype = le16_to_cpu(*(__le16*)&data[6]);
|
||||
|
||||
if (infotype == ZD1201_INF_LINKSTATUS) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user