summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/atmel/atmel.c3
-rw-r--r--drivers/net/wireless/broadcom/b43/main.c2
-rw-r--r--drivers/net/wireless/broadcom/b43legacy/main.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c22
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c58
-rw-r--r--drivers/net/wireless/cisco/airo.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c99
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.h22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/location.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h34
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h128
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c42
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c43
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h121
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c47
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c70
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c120
-rw-r--r--drivers/net/wireless/marvell/libertas/rx.c5
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c5
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cmdevt.c29
-rw-r--r--drivers/net/wireless/marvell/mwifiex/fw.h10
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/debugfs.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/dma.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h10
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/mac.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/init.c22
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mac.c17
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/main.c108
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mcu.c66
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mcu.h25
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h19
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/pci.c9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/usb.c3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02.h3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mac.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_util.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/init.c3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mac.c58
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/main.c9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.c41
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/util.c12
-rw-r--r--drivers/net/wireless/mediatek/mt76/util.h14
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2800lib.c4
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00mac.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/coex.c21
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac80211.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c17
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h4
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.c50
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.h1
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822b.c95
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822c.c24
-rw-r--r--drivers/net/wireless/st/cw1200/cw1200_sdio.c9
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c33
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c1
72 files changed, 1215 insertions, 478 deletions
diff --git a/drivers/net/wireless/atmel/atmel.c b/drivers/net/wireless/atmel/atmel.c
index 74538085cfb7..d5875836068c 100644
--- a/drivers/net/wireless/atmel/atmel.c
+++ b/drivers/net/wireless/atmel/atmel.c
@@ -798,7 +798,6 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast,
static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
{
- static const u8 SNAP_RFC1024[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
struct atmel_private *priv = netdev_priv(dev);
struct ieee80211_hdr header;
unsigned long flags;
@@ -853,7 +852,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
}
if (priv->use_wpa)
- memcpy(&header.addr4, SNAP_RFC1024, ETH_ALEN);
+ memcpy(&header.addr4, rfc1042_header, ETH_ALEN);
header.frame_control = cpu_to_le16(frame_ctl);
/* Copy the wireless header into the card */
diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 39da1a4c30ac..3ad94dad2d89 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -5569,7 +5569,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
/* fill hw info */
ieee80211_hw_set(hw, RX_INCLUDES_FCS);
ieee80211_hw_set(hw, SIGNAL_DBM);
-
+ ieee80211_hw_set(hw, MFP_CAPABLE);
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_MESH_POINT) |
diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c
index 8b6b657c4b85..5208a39fd6f7 100644
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
@@ -3801,6 +3801,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
/* fill hw info */
ieee80211_hw_set(hw, RX_INCLUDES_FCS);
ieee80211_hw_set(hw, SIGNAL_DBM);
+ ieee80211_hw_set(hw, MFP_CAPABLE); /* Allow WPA3 in software */
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_AP) |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 22a17ae09e94..b1a66320ba54 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -43,7 +43,8 @@
#define SDIO_FUNC1_BLOCKSIZE 64
#define SDIO_FUNC2_BLOCKSIZE 512
-#define SDIO_4359_FUNC2_BLOCKSIZE 256
+#define SDIO_4373_FUNC2_BLOCKSIZE 256
+#define SDIO_435X_FUNC2_BLOCKSIZE 256
/* Maximum milliseconds to wait for F2 to come up */
#define SDIO_WAIT_F2RDY 3000
@@ -910,13 +911,28 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
sdio_release_host(sdiodev->func1);
goto out;
}
- if (sdiodev->func2->device == SDIO_DEVICE_ID_BROADCOM_4359)
- f2_blksz = SDIO_4359_FUNC2_BLOCKSIZE;
+ switch (sdiodev->func2->device) {
+ case SDIO_DEVICE_ID_CYPRESS_4373:
+ f2_blksz = SDIO_4373_FUNC2_BLOCKSIZE;
+ break;
+ case SDIO_DEVICE_ID_BROADCOM_4359:
+ /* fallthrough */
+ case SDIO_DEVICE_ID_BROADCOM_4354:
+ /* fallthrough */
+ case SDIO_DEVICE_ID_BROADCOM_4356:
+ f2_blksz = SDIO_435X_FUNC2_BLOCKSIZE;
+ break;
+ default:
+ break;
+ }
+
ret = sdio_set_block_size(sdiodev->func2, f2_blksz);
if (ret) {
brcmf_err("Failed to set F2 blocksize\n");
sdio_release_host(sdiodev->func1);
goto out;
+ } else {
+ brcmf_dbg(SDIO, "set F2 blocksize to %d\n", f2_blksz);
}
/* increase F2 timeout */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index ce6f15284277..760b7737e745 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -41,9 +41,22 @@
/* watermark expressed in number of words */
#define DEFAULT_F2_WATERMARK 0x8
#define CY_4373_F2_WATERMARK 0x40
+#define CY_4373_F1_MESBUSYCTRL (CY_4373_F2_WATERMARK | SBSDIO_MESBUSYCTRL_ENAB)
#define CY_43012_F2_WATERMARK 0x60
-#define CY_4359_F2_WATERMARK 0x40
-#define CY_4359_F1_MESBUSYCTRL (CY_4359_F2_WATERMARK | SBSDIO_MESBUSYCTRL_ENAB)
+#define CY_43012_MES_WATERMARK 0x50
+#define CY_43012_MESBUSYCTRL (CY_43012_MES_WATERMARK | \
+ SBSDIO_MESBUSYCTRL_ENAB)
+#define CY_4339_F2_WATERMARK 48
+#define CY_4339_MES_WATERMARK 80
+#define CY_4339_MESBUSYCTRL (CY_4339_MES_WATERMARK | \
+ SBSDIO_MESBUSYCTRL_ENAB)
+#define CY_43455_F2_WATERMARK 0x60
+#define CY_43455_MES_WATERMARK 0x50
+#define CY_43455_MESBUSYCTRL (CY_43455_MES_WATERMARK | \
+ SBSDIO_MESBUSYCTRL_ENAB)
+#define CY_435X_F2_WATERMARK 0x40
+#define CY_435X_F1_MESBUSYCTRL (CY_435X_F2_WATERMARK | \
+ SBSDIO_MESBUSYCTRL_ENAB)
#ifdef DEBUG
@@ -4195,8 +4208,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
&err);
brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
- CY_4373_F2_WATERMARK |
- SBSDIO_MESBUSYCTRL_ENAB, &err);
+ CY_4373_F1_MESBUSYCTRL, &err);
break;
case SDIO_DEVICE_ID_CYPRESS_43012:
brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
@@ -4208,19 +4220,51 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
&err);
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
+ CY_43012_MESBUSYCTRL, &err);
+ break;
+ case SDIO_DEVICE_ID_BROADCOM_4339:
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes for 4339\n",
+ CY_4339_F2_WATERMARK);
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
+ CY_4339_F2_WATERMARK, &err);
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
+ &err);
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
+ &err);
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
+ CY_4339_MESBUSYCTRL, &err);
+ break;
+ case SDIO_DEVICE_ID_BROADCOM_43455:
+ brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes for 43455\n",
+ CY_43455_F2_WATERMARK);
+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
+ CY_43455_F2_WATERMARK, &err);
+ devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
+ &err);
+ devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
+ brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
+ &err);
+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
+ CY_43455_MESBUSYCTRL, &err);
break;
case SDIO_DEVICE_ID_BROADCOM_4359:
+ /* fallthrough */
+ case SDIO_DEVICE_ID_BROADCOM_4354:
+ /* fallthrough */
+ case SDIO_DEVICE_ID_BROADCOM_4356:
brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
- CY_4359_F2_WATERMARK);
+ CY_435X_F2_WATERMARK);
brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
- CY_4359_F2_WATERMARK, &err);
+ CY_435X_F2_WATERMARK, &err);
devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL,
&err);
devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl,
&err);
brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL,
- CY_4359_F1_MESBUSYCTRL, &err);
+ CY_435X_F1_MESBUSYCTRL, &err);
break;
default:
brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index 8363f91df7ea..827bb6d74815 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -1925,6 +1925,10 @@ static netdev_tx_t mpi_start_xmit(struct sk_buff *skb,
airo_print_err(dev->name, "%s: skb == NULL!",__func__);
return NETDEV_TX_OK;
}
+ if (skb_padto(skb, ETH_ZLEN)) {
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
npacks = skb_queue_len (&ai->txq);
if (npacks >= MAXTXQ - 1) {
@@ -2127,6 +2131,10 @@ static netdev_tx_t airo_start_xmit(struct sk_buff *skb,
airo_print_err(dev->name, "%s: skb == NULL!", __func__);
return NETDEV_TX_OK;
}
+ if (skb_padto(skb, ETH_ZLEN)) {
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
/* Find a vacant FID */
for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ );
@@ -2201,6 +2209,10 @@ static netdev_tx_t airo_start_xmit11(struct sk_buff *skb,
airo_print_err(dev->name, "%s: skb == NULL!", __func__);
return NETDEV_TX_OK;
}
+ if (skb_padto(skb, ETH_ZLEN)) {
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
/* Find a vacant FID */
for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ );
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index 1daa653bcb99..efe427049a6e 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -57,7 +57,7 @@
#include "iwl-prph.h"
/* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX 55
+#define IWL_22000_UCODE_API_MAX 56
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index e2184ba4d8b5..dc769b580431 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -58,44 +58,121 @@
*
*****************************************************************************/
+#include <linux/uuid.h>
#include "iwl-drv.h"
#include "iwl-debug.h"
#include "acpi.h"
#include "fw/runtime.h"
-void *iwl_acpi_get_object(struct device *dev, acpi_string method)
+static const guid_t intel_wifi_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6,
+ 0xA5, 0xB3, 0x1F, 0x73,
+ 0x8E, 0x28, 0x5A, 0xDE);
+
+static int iwl_acpi_get_handle(struct device *dev, acpi_string method,
+ acpi_handle *ret_handle)
{
acpi_handle root_handle;
- acpi_handle handle;
- struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
root_handle = ACPI_HANDLE(dev);
if (!root_handle) {
IWL_DEBUG_DEV_RADIO(dev,
- "Could not retrieve root port ACPI handle\n");
- return ERR_PTR(-ENOENT);
+ "ACPI: Could not retrieve root port handle\n");
+ return -ENOENT;
}
- /* Get the method's handle */
- status = acpi_get_handle(root_handle, method, &handle);
+ status = acpi_get_handle(root_handle, method, ret_handle);
if (ACPI_FAILURE(status)) {
- IWL_DEBUG_DEV_RADIO(dev, "%s method not found\n", method);
- return ERR_PTR(-ENOENT);
+ IWL_DEBUG_DEV_RADIO(dev,
+ "ACPI: %s method not found\n", method);
+ return -ENOENT;
}
+ return 0;
+}
+
+void *iwl_acpi_get_object(struct device *dev, acpi_string method)
+{
+ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+ acpi_handle handle;
+ acpi_status status;
+ int ret;
+
+ ret = iwl_acpi_get_handle(dev, method, &handle);
+ if (ret)
+ return ERR_PTR(-ENOENT);
/* Call the method with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &buf);
if (ACPI_FAILURE(status)) {
- IWL_DEBUG_DEV_RADIO(dev, "%s invocation failed (0x%x)\n",
+ IWL_DEBUG_DEV_RADIO(dev,
+ "ACPI: %s method invocation failed (status: 0x%x)\n",
method, status);
return ERR_PTR(-ENOENT);
}
-
return buf.pointer;
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_object);
+/**
+* Generic function for evaluating a method defined in the device specific
+* method (DSM) interface. The returned acpi object must be freed by calling
+* function.
+*/
+void *iwl_acpi_get_dsm_object(struct device *dev, int rev, int func,
+ union acpi_object *args)
+{
+ union acpi_object *obj;
+
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &intel_wifi_guid, rev, func,
+ args);
+ if (!obj) {
+ IWL_DEBUG_DEV_RADIO(dev,
+ "ACPI: DSM method invocation failed (rev: %d, func:%d)\n",
+ rev, func);
+ return ERR_PTR(-ENOENT);
+ }
+ return obj;
+}
+
+/**
+ * Evaluate a DSM with no arguments and a single u8 return value (inside a
+ * buffer object), verify and return that value.
+ */
+int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func)
+{
+ union acpi_object *obj;
+ int ret;
+
+ obj = iwl_acpi_get_dsm_object(dev, rev, func, NULL);
+ if (IS_ERR(obj))
+ return -ENOENT;
+
+ if (obj->type != ACPI_TYPE_BUFFER) {
+ IWL_DEBUG_DEV_RADIO(dev,
+ "ACPI: DSM method did not return a valid object, type=%d\n",
+ obj->type);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (obj->buffer.length != sizeof(u8)) {
+ IWL_DEBUG_DEV_RADIO(dev,
+ "ACPI: DSM method returned invalid buffer, length=%d\n",
+ obj->buffer.length);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = obj->buffer.pointer[0];
+ IWL_DEBUG_DEV_RADIO(dev,
+ "ACPI: DSM method evaluated: func=%d, ret=%d\n",
+ func, ret);
+out:
+ ACPI_FREE(obj);
+ return ret;
+}
+IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u8);
+
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
union acpi_object *data,
int data_size, int *tbl_rev)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
index 6a646dc524e1..0ada9eddb8b1 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
@@ -127,12 +127,23 @@ struct iwl_geo_profile {
u8 values[ACPI_GEO_TABLE_SIZE];
};
+enum iwl_dsm_funcs_rev_0 {
+ DSM_FUNC_QUERY = 0,
+ DSM_FUNC_DISABLE_SRD = 1,
+ DSM_FUNC_ENABLE_INDONESIA_5G2 = 2,
+};
+
#ifdef CONFIG_ACPI
struct iwl_fw_runtime;
void *iwl_acpi_get_object(struct device *dev, acpi_string method);
+void *iwl_acpi_get_dsm_object(struct device *dev, int rev, int func,
+ union acpi_object *args);
+
+int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func);
+
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
union acpi_object *data,
int data_size, int *tbl_rev);
@@ -192,6 +203,17 @@ static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
return ERR_PTR(-ENOENT);
}
+static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
+ int func, union acpi_object *args)
+{
+ return ERR_PTR(-ENOENT);
+}
+
+static inline int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func)
+{
+ return -ENOENT;
+}
+
static inline union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
union acpi_object *data,
int data_size,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
index 7ffad19d80fd..1df2e497fabf 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
@@ -550,13 +550,11 @@ struct iwl_tof_range_req_ap_entry_v4 {
/**
* enum iwl_location_cipher - location cipher selection
* @IWL_LOCATION_CIPHER_CCMP_128: CCMP 128
- * @IWL_LOCATION_CIPHER_CCMP_256: CCMP 256
* @IWL_LOCATION_CIPHER_GCMP_128: GCMP 128
* @IWL_LOCATION_CIPHER_GCMP_256: GCMP 256
*/
enum iwl_location_cipher {
IWL_LOCATION_CIPHER_CCMP_128,
- IWL_LOCATION_CIPHER_CCMP_256,
IWL_LOCATION_CIPHER_GCMP_128,
IWL_LOCATION_CIPHER_GCMP_256,
};
@@ -577,7 +575,8 @@ enum iwl_location_cipher {
* @samples_per_burst: the number of FTMs pairs in single Burst (1-31);
* @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of
* the number of measurement iterations (min 2^0 = 1, max 2^14)
- * @reserved: For alignment and future use
+ * @sta_id: the station id of the AP. Only relevant when associated to the AP,
+ * otherwise should be set to &IWL_MVM_INVALID_STA.
* @cipher: pairwise cipher suite for secured measurement.
* &enum iwl_location_cipher.
* @hltk: HLTK to be used for secured 11az measurement
@@ -586,7 +585,8 @@ enum iwl_location_cipher {
* If &IWL_INITIATOR_AP_FLAGS_USE_CALIB is set, the fw will use the
* calibration value that corresponds to the rx bandwidth of the FTM
* frame.
- * @reserved2: For alignment and future use.
+ * @beacon_interval: beacon interval of the AP in TUs. Only required if
+ * &IWL_INITIATOR_AP_FLAGS_TB is set.
*/
struct iwl_tof_range_req_ap_entry {
__le32 initiator_ap_flags;
@@ -598,13 +598,13 @@ struct iwl_tof_range_req_ap_entry {
__le16 burst_period;
u8 samples_per_burst;
u8 num_of_bursts;
- u8 reserved;
+ u8 sta_id;
u8 cipher;
u8 hltk[HLTK_11AZ_LEN];
u8 tk[TK_11AZ_LEN];
__le16 calib[IWL_TOF_BW_NUM];
- __le16 reserved2;
-} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_5 */
+ __le16 beacon_interval;
+} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_6 */
/**
* enum iwl_tof_response_mode
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
index 2d230a7893c2..fd719c37428c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(C) 2018 - 2019 Intel Corporation
+ * Copyright(C) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(C) 2018 - 2019 Intel Corporation
+ * Copyright(C) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -75,6 +75,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
NVM_ACCESS_COMPLETE = 0x0,
/**
+ * @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd
+ */
+ LARI_CONFIG_CHANGE = 0x1,
+
+ /**
* @NVM_GET_INFO:
* Command is &struct iwl_nvm_get_info,
* response is &struct iwl_nvm_get_info_rsp
@@ -446,4 +451,29 @@ struct iwl_tas_config_cmd {
__le32 black_list_size;
__le32 black_list_array[IWL_TAS_BLACK_LIST_MAX];
} __packed; /* TAS_CONFIG_CMD_API_S_VER_2 */
+
+/**
+ * enum iwl_lari_configs - bit masks for the various LARI config operations
+ * @LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK: disable 11ac in ukraine
+ * @LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK: ETSI 5.8GHz SRD passive scan
+ * @LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK: ETSI 5.8GHz SRD disabled
+ * @LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK: enable 5.15/5.35GHz bands in
+ * Indonesia
+ */
+enum iwl_lari_config_masks {
+ LARI_CONFIG_DISABLE_11AC_UKRAINE_MSK = BIT(0),
+ LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK = BIT(1),
+ LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK = BIT(2),
+ LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK = BIT(3),
+};
+
+/**
+ * struct iwl_lari_config_change_cmd - change LARI configuration
+ * @config_bitmap: bit map of the config commands. each bit will trigger a
+ * different predefined FW config operation
+ */
+struct iwl_lari_config_change_cmd {
+ __le32 config_bitmap;
+} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_1 */
+
#endif /* __iwl_fw_api_nvm_reg_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
index ebea99189ca9..9d7a04833cd0 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018, 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -18,7 +18,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018, 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -93,6 +93,11 @@ enum iwl_prph_scratch_mtr_format {
* @IWL_PRPH_SCRATCH_MTR_FORMAT: a mask for the size of the tfd.
* There are 4 optional values: 0: 16 bit, 1: 32 bit, 2: 64 bit,
* 3: 256 bit.
+ * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK: RB size full information, ignored
+ * by older firmware versions, so set IWL_PRPH_SCRATCH_RB_SIZE_4K
+ * appropriately; use the below values for this.
+ * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K: 8kB RB size
+ * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K: 12kB RB size
*/
enum iwl_prph_scratch_flags {
IWL_PRPH_SCRATCH_EARLY_DEBUG_EN = BIT(4),
@@ -103,6 +108,9 @@ enum iwl_prph_scratch_flags {
IWL_PRPH_SCRATCH_RB_SIZE_4K = BIT(16),
IWL_PRPH_SCRATCH_MTR_MODE = BIT(17),
IWL_PRPH_SCRATCH_MTR_FORMAT = BIT(18) | BIT(19),
+ IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK = 0xf << 20,
+ IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K = 8 << 20,
+ IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K = 9 << 20,
};
/*
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index d91a8e8349e6..ee410417761d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -240,6 +240,7 @@ enum iwl_nvm_channel_flags {
* @REG_CAPA_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden
* for this regulatory domain (valid only in 5Ghz).
* @REG_CAPA_DC_HIGH_ENABLED: DC HIGH allowed.
+ * @REG_CAPA_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
*/
enum iwl_reg_capa_flags {
REG_CAPA_BF_CCD_LOW_BAND = BIT(0),
@@ -250,6 +251,7 @@ enum iwl_reg_capa_flags {
REG_CAPA_MCS_9_ALLOWED = BIT(5),
REG_CAPA_40MHZ_FORBIDDEN = BIT(7),
REG_CAPA_DC_HIGH_ENABLED = BIT(9),
+ REG_CAPA_11AX_DISABLED = BIT(10),
};
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
@@ -1115,6 +1117,9 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
flags |= NL80211_RRF_NO_160MHZ;
}
+ if (cap_flags & REG_CAPA_11AX_DISABLED)
+ flags |= NL80211_RRF_NO_HE;
+
return flags;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index bba527b339b5..a301e2484cdb 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -795,6 +795,132 @@ struct iwl_trans_debug {
u32 domains_bitmap;
};
+struct iwl_dma_ptr {
+ dma_addr_t dma;
+ void *addr;
+ size_t size;
+};
+
+struct iwl_cmd_meta {
+ /* only for SYNC commands, iff the reply skb is wanted */
+ struct iwl_host_cmd *source;
+ u32 flags;
+ u32 tbs;
+};
+
+/*
+ * The FH will write back to the first TB only, so we need to copy some data
+ * into the buffer regardless of whether it should be mapped or not.
+ * This indicates how big the first TB must be to include the scratch buffer
+ * and the assigned PN.
+ * Since PN location is 8 bytes at offset 12, it's 20 now.
+ * If we make it bigger then allocations will be bigger and copy slower, so
+ * that's probably not useful.
+ */
+#define IWL_FIRST_TB_SIZE 20
+#define IWL_FIRST_TB_SIZE_ALIGN ALIGN(IWL_FIRST_TB_SIZE, 64)
+
+struct iwl_pcie_txq_entry {
+ void *cmd;
+ struct sk_buff *skb;
+ /* buffer to free after command completes */
+ const void *free_buf;
+ struct iwl_cmd_meta meta;
+};
+
+struct iwl_pcie_first_tb_buf {
+ u8 buf[IWL_FIRST_TB_SIZE_ALIGN];
+};
+
+/**
+ * struct iwl_txq - Tx Queue for DMA
+ * @q: generic Rx/Tx queue descriptor
+ * @tfds: transmit frame descriptors (DMA memory)
+ * @first_tb_bufs: start of command headers, including scratch buffers, for
+ * the writeback -- this is DMA memory and an array holding one buffer
+ * for each command on the queue
+ * @first_tb_dma: DMA address for the first_tb_bufs start
+ * @entries: transmit entries (driver state)
+ * @lock: queue lock
+ * @stuck_timer: timer that fires if queue gets stuck
+ * @trans: pointer back to transport (for timer)
+ * @need_update: indicates need to update read/write index
+ * @ampdu: true if this queue is an ampdu queue for an specific RA/TID
+ * @wd_timeout: queue watchdog timeout (jiffies) - per queue
+ * @frozen: tx stuck queue timer is frozen
+ * @frozen_expiry_remainder: remember how long until the timer fires
+ * @bc_tbl: byte count table of the queue (relevant only for gen2 transport)
+ * @write_ptr: 1-st empty entry (index) host_w
+ * @read_ptr: last used entry (index) host_r
+ * @dma_addr: physical addr for BD's
+ * @n_window: safe queue window
+ * @id: queue id
+ * @low_mark: low watermark, resume queue if free space more than this
+ * @high_mark: high watermark, stop queue if free space less than this
+ *
+ * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
+ * descriptors) and required locking structures.
+ *
+ * Note the difference between TFD_QUEUE_SIZE_MAX and n_window: the hardware
+ * always assumes 256 descriptors, so TFD_QUEUE_SIZE_MAX is always 256 (unless
+ * there might be HW changes in the future). For the normal TX
+ * queues, n_window, which is the size of the software queue data
+ * is also 256; however, for the command queue, n_window is only
+ * 32 since we don't need so many commands pending. Since the HW
+ * still uses 256 BDs for DMA though, TFD_QUEUE_SIZE_MAX stays 256.
+ * This means that we end up with the following:
+ * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
+ * SW entries: | 0 | ... | 31 |
+ * where N is a number between 0 and 7. This means that the SW
+ * data is a window overlayed over the HW queue.
+ */
+struct iwl_txq {
+ void *tfds;
+ struct iwl_pcie_first_tb_buf *first_tb_bufs;
+ dma_addr_t first_tb_dma;
+ struct iwl_pcie_txq_entry *entries;
+ /* lock for syncing changes on the queue */
+ spinlock_t lock;
+ unsigned long frozen_expiry_remainder;
+ struct timer_list stuck_timer;
+ struct iwl_trans *trans;
+ bool need_update;
+ bool frozen;
+ bool ampdu;
+ int block;
+ unsigned long wd_timeout;
+ struct sk_buff_head overflow_q;
+ struct iwl_dma_ptr bc_tbl;
+
+ int write_ptr;
+ int read_ptr;
+ dma_addr_t dma_addr;
+ int n_window;
+ u32 id;
+ int low_mark;
+ int high_mark;
+
+ bool overflow_tx;
+};
+
+/**
+ * struct iwl_trans_txqs - transport tx queues data
+ *
+ * @queue_used - bit mask of used queues
+ * @queue_stopped - bit mask of stopped queues
+ */
+struct iwl_trans_txqs {
+ unsigned long queue_used[BITS_TO_LONGS(IWL_MAX_TVQM_QUEUES)];
+ unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_TVQM_QUEUES)];
+ struct iwl_txq *txq[IWL_MAX_TVQM_QUEUES];
+ struct {
+ u8 fifo;
+ u8 q_id;
+ unsigned int wdg_timeout;
+ } cmd;
+
+};
+
/**
* struct iwl_trans - transport common data
*
@@ -828,6 +954,7 @@ struct iwl_trans_debug {
* @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.
+ * @iwl_trans_txqs: transport tx queues data.
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
@@ -875,6 +1002,7 @@ struct iwl_trans {
enum iwl_plat_pm_mode system_pm_mode;
const char *name;
+ struct iwl_trans_txqs txqs;
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index aaa7dd1788b1..5ca45915cf7c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -391,9 +391,27 @@ iwl_mvm_ftm_put_target_v3(struct iwl_mvm *mvm,
}
static int
-iwl_mvm_ftm_put_target(struct iwl_mvm *mvm,
+iwl_mvm_ftm_put_target_v4(struct iwl_mvm *mvm,
+ struct cfg80211_pmsr_request_peer *peer,
+ struct iwl_tof_range_req_ap_entry_v4 *target)
+{
+ int ret;
+
+ ret = iwl_mvm_ftm_target_chandef_v2(mvm, peer, &target->channel_num,
+ &target->format_bw,
+ &target->ctrl_ch_position);
+ if (ret)
+ return ret;
+
+ iwl_mvm_ftm_put_target_common(mvm, peer, (void *)target);
+
+ return 0;
+}
+
+static int
+iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct cfg80211_pmsr_request_peer *peer,
- struct iwl_tof_range_req_ap_entry_v4 *target)
+ struct iwl_tof_range_req_ap_entry *target)
{
int ret;
@@ -405,6 +423,20 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm,
iwl_mvm_ftm_put_target_common(mvm, peer, (void *)target);
+ if (vif->bss_conf.assoc &&
+ !memcmp(peer->addr, vif->bss_conf.bssid, ETH_ALEN)) {
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ target->sta_id = mvmvif->ap_sta_id;
+ } else {
+ target->sta_id = IWL_MVM_INVALID_STA;
+ }
+
+ /*
+ * TODO: Beacon interval is currently unknown, so use the common value
+ * of 100 TUs.
+ */
+ target->beacon_interval = cpu_to_le16(100);
return 0;
}
@@ -496,7 +528,7 @@ static int iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
for (i = 0; i < cmd.num_of_ap; i++) {
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
- err = iwl_mvm_ftm_put_target(mvm, peer, &cmd.ap[i]);
+ err = iwl_mvm_ftm_put_target_v4(mvm, peer, &cmd.ap[i]);
if (err)
return err;
}
@@ -521,8 +553,9 @@ static int iwl_mvm_ftm_start_v9(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
for (i = 0; i < cmd.num_of_ap; i++) {
struct cfg80211_pmsr_request_peer *peer = &req->peers[i];
+ struct iwl_tof_range_req_ap_entry *target = &cmd.ap[i];
- err = iwl_mvm_ftm_put_target(mvm, peer, (void *)&cmd.ap[i]);
+ err = iwl_mvm_ftm_put_target(mvm, vif, peer, target);
if (err)
return err;
}
@@ -548,6 +581,7 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
switch (cmd_ver) {
case 9:
+ case 10:
err = iwl_mvm_ftm_start_v9(mvm, vif, req);
break;
case 8:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 5e8d3f8c3d86..95a613537047 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -988,6 +988,44 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
if (ret < 0)
IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret);
}
+
+static bool iwl_mvm_eval_dsm_indonesia_5g2(struct iwl_mvm *mvm)
+{
+ int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0,
+ DSM_FUNC_ENABLE_INDONESIA_5G2);
+
+ IWL_DEBUG_RADIO(mvm,
+ "Evaluated DSM function ENABLE_INDONESIA_5G2, ret=%d\n",
+ ret);
+
+ return ret == 1;
+}
+
+static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
+{
+ int ret;
+ struct iwl_lari_config_change_cmd cmd = {};
+
+ if (iwl_mvm_eval_dsm_indonesia_5g2(mvm))
+ cmd.config_bitmap |=
+ cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
+
+ /* apply more config masks here */
+
+ if (cmd.config_bitmap) {
+ IWL_DEBUG_RADIO(mvm,
+ "sending LARI_CONFIG_CHANGE, config_bitmap=0x%x\n",
+ le32_to_cpu(cmd.config_bitmap));
+ ret = iwl_mvm_send_cmd_pdu(mvm,
+ WIDE_ID(REGULATORY_AND_NVM_GROUP,
+ LARI_CONFIG_CHANGE),
+ 0, sizeof(cmd), &cmd);
+ if (ret < 0)
+ IWL_DEBUG_RADIO(mvm,
+ "Failed to send LARI_CONFIG_CHANGE (%d)\n",
+ ret);
+ }
+}
#else /* CONFIG_ACPI */
inline int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm,
@@ -1019,6 +1057,10 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
{
}
+
+static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
+{
+}
#endif /* CONFIG_ACPI */
void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
@@ -1293,6 +1335,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
goto error;
+ iwl_mvm_lari_cfg(mvm);
/*
* RTNL is not taken during Ct-kill, but we don't need to scan/Tx
* anyway, so don't init MCC.
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 10df77ab1a77..77916231ff7d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1208,14 +1208,13 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
*/
flush_work(&mvm->roc_done_wk);
+ iwl_mvm_rm_aux_sta(mvm);
+
iwl_mvm_stop_device(mvm);
iwl_mvm_async_handlers_purge(mvm);
/* async_handlers_list is empty and will stay empty: HW is stopped */
- /* the fw is stopped, the aux sta is dead: clean up driver state */
- iwl_mvm_del_aux_sta(mvm);
-
/*
* Clear IN_HW_RESTART and HW_RESTART_REQUESTED flag when stopping the
* hw (as restart_complete() won't be called in this case) and mac80211
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 44d4720b7629..fee01cbbd3ac 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -2093,16 +2093,24 @@ int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return ret;
}
-void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm)
+int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm)
{
- iwl_mvm_dealloc_int_sta(mvm, &mvm->snif_sta);
-}
+ int ret;
-void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm)
-{
lockdep_assert_held(&mvm->mutex);
+ iwl_mvm_disable_txq(mvm, NULL, mvm->aux_queue, IWL_MAX_TID_COUNT, 0);
+ ret = iwl_mvm_rm_sta_common(mvm, mvm->aux_sta.sta_id);
+ if (ret)
+ IWL_WARN(mvm, "Failed sending remove station\n");
iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
+
+ return ret;
+}
+
+void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm)
+{
+ iwl_mvm_dealloc_int_sta(mvm, &mvm->snif_sta);
}
/*
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index 8d70093847cb..da2d1ac01229 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -541,7 +541,7 @@ int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int tid, u8 queue, bool start);
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm);
-void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm);
+int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm);
int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
index b6a5921a63c3..1ab136600415 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
@@ -138,9 +138,17 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
case IWL_AMSDU_2K:
break;
case IWL_AMSDU_4K:
+ control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_4K;
+ break;
case IWL_AMSDU_8K:
+ control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_4K;
+ /* if firmware supports the ext size, tell it */
+ control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K;
+ break;
case IWL_AMSDU_12K:
control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_4K;
+ /* if firmware supports the ext size, tell it */
+ control_flags |= IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K;
break;
}
@@ -213,7 +221,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
ctxt_info_gen3->tr_idx_arr_size =
cpu_to_le16(IWL_NUM_OF_TRANSFER_RINGS);
ctxt_info_gen3->mtr_base_addr =
- cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
+ cpu_to_le64(trans->txqs.txq[trans->txqs.cmd.q_id]->dma_addr);
ctxt_info_gen3->mcr_base_addr =
cpu_to_le64(trans_pcie->rxq->used_bd_dma);
ctxt_info_gen3->mtr_size =
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
index b65405009d02..23abfbd096b0 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -20,7 +20,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -263,7 +263,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
/* initialize TX command queue */
ctxt_info->hcmd_cfg.cmd_queue_addr =
- cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
+ cpu_to_le64(trans->txqs.txq[trans->txqs.cmd.q_id]->dma_addr);
ctxt_info->hcmd_cfg.cmd_queue_size =
TFD_QUEUE_CB_SIZE(IWL_CMD_QUEUE_SIZE);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index b76c0396335a..55808ba10d27 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -246,12 +246,6 @@ struct iwl_rb_allocator {
struct work_struct rx_alloc;
};
-struct iwl_dma_ptr {
- dma_addr_t dma;
- void *addr;
- size_t size;
-};
-
/**
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning
* @index -- current index
@@ -290,107 +284,6 @@ static inline int iwl_queue_dec_wrap(struct iwl_trans *trans, int index)
(trans->trans_cfg->base_params->max_tfd_queue_size - 1);
}
-struct iwl_cmd_meta {
- /* only for SYNC commands, iff the reply skb is wanted */
- struct iwl_host_cmd *source;
- u32 flags;
- u32 tbs;
-};
-
-/*
- * The FH will write back to the first TB only, so we need to copy some data
- * into the buffer regardless of whether it should be mapped or not.
- * This indicates how big the first TB must be to include the scratch buffer
- * and the assigned PN.
- * Since PN location is 8 bytes at offset 12, it's 20 now.
- * If we make it bigger then allocations will be bigger and copy slower, so
- * that's probably not useful.
- */
-#define IWL_FIRST_TB_SIZE 20
-#define IWL_FIRST_TB_SIZE_ALIGN ALIGN(IWL_FIRST_TB_SIZE, 64)
-
-struct iwl_pcie_txq_entry {
- void *cmd;
- struct sk_buff *skb;
- /* buffer to free after command completes */
- const void *free_buf;
- struct iwl_cmd_meta meta;
-};
-
-struct iwl_pcie_first_tb_buf {
- u8 buf[IWL_FIRST_TB_SIZE_ALIGN];
-};
-
-/**
- * struct iwl_txq - Tx Queue for DMA
- * @q: generic Rx/Tx queue descriptor
- * @tfds: transmit frame descriptors (DMA memory)
- * @first_tb_bufs: start of command headers, including scratch buffers, for
- * the writeback -- this is DMA memory and an array holding one buffer
- * for each command on the queue
- * @first_tb_dma: DMA address for the first_tb_bufs start
- * @entries: transmit entries (driver state)
- * @lock: queue lock
- * @stuck_timer: timer that fires if queue gets stuck
- * @trans_pcie: pointer back to transport (for timer)
- * @need_update: indicates need to update read/write index
- * @ampdu: true if this queue is an ampdu queue for an specific RA/TID
- * @wd_timeout: queue watchdog timeout (jiffies) - per queue
- * @frozen: tx stuck queue timer is frozen
- * @frozen_expiry_remainder: remember how long until the timer fires
- * @bc_tbl: byte count table of the queue (relevant only for gen2 transport)
- * @write_ptr: 1-st empty entry (index) host_w
- * @read_ptr: last used entry (index) host_r
- * @dma_addr: physical addr for BD's
- * @n_window: safe queue window
- * @id: queue id
- * @low_mark: low watermark, resume queue if free space more than this
- * @high_mark: high watermark, stop queue if free space less than this
- *
- * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
- * descriptors) and required locking structures.
- *
- * Note the difference between TFD_QUEUE_SIZE_MAX and n_window: the hardware
- * always assumes 256 descriptors, so TFD_QUEUE_SIZE_MAX is always 256 (unless
- * there might be HW changes in the future). For the normal TX
- * queues, n_window, which is the size of the software queue data
- * is also 256; however, for the command queue, n_window is only
- * 32 since we don't need so many commands pending. Since the HW
- * still uses 256 BDs for DMA though, TFD_QUEUE_SIZE_MAX stays 256.
- * This means that we end up with the following:
- * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
- * SW entries: | 0 | ... | 31 |
- * where N is a number between 0 and 7. This means that the SW
- * data is a window overlayed over the HW queue.
- */
-struct iwl_txq {
- void *tfds;
- struct iwl_pcie_first_tb_buf *first_tb_bufs;
- dma_addr_t first_tb_dma;
- struct iwl_pcie_txq_entry *entries;
- spinlock_t lock;
- unsigned long frozen_expiry_remainder;
- struct timer_list stuck_timer;
- struct iwl_trans_pcie *trans_pcie;
- bool need_update;
- bool frozen;
- bool ampdu;
- int block;
- unsigned long wd_timeout;
- struct sk_buff_head overflow_q;
- struct iwl_dma_ptr bc_tbl;
-
- int write_ptr;
- int read_ptr;
- dma_addr_t dma_addr;
- int n_window;
- u32 id;
- int low_mark;
- int high_mark;
-
- bool overflow_tx;
-};
-
static inline dma_addr_t
iwl_pcie_get_first_tb_dma(struct iwl_txq *txq, int idx)
{
@@ -561,9 +454,6 @@ struct iwl_trans_pcie {
struct dma_pool *bc_pool;
struct iwl_txq *txq_memory;
- struct iwl_txq *txq[IWL_MAX_TVQM_QUEUES];
- unsigned long queue_used[BITS_TO_LONGS(IWL_MAX_TVQM_QUEUES)];
- unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_TVQM_QUEUES)];
/* PCI bus related data */
struct pci_dev *pci_dev;
@@ -577,10 +467,7 @@ struct iwl_trans_pcie {
u8 page_offs, dev_cmd_offs;
- u8 cmd_queue;
u8 def_rx_queue;
- u8 cmd_fifo;
- unsigned int cmd_q_wdg_timeout;
u8 n_no_reclaim_cmds;
u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
u8 max_tbs;
@@ -983,9 +870,7 @@ void iwl_pcie_handle_rfkill_irq(struct iwl_trans *trans);
static inline void iwl_wake_queue(struct iwl_trans *trans,
struct iwl_txq *txq)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
- if (test_and_clear_bit(txq->id, trans_pcie->queue_stopped)) {
+ if (test_and_clear_bit(txq->id, trans->txqs.queue_stopped)) {
IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d\n", txq->id);
iwl_op_mode_queue_not_full(trans->op_mode, txq->id);
}
@@ -994,9 +879,7 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
static inline void iwl_stop_queue(struct iwl_trans *trans,
struct iwl_txq *txq)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
- if (!test_and_set_bit(txq->id, trans_pcie->queue_stopped)) {
+ if (!test_and_set_bit(txq->id, trans->txqs.queue_stopped)) {
iwl_op_mode_queue_full(trans->op_mode, txq->id);
IWL_DEBUG_TX_QUEUES(trans, "Stop hwq %d\n", txq->id);
} else
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index 72d1cf27e6a4..24cb1b1f21f0 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -1284,7 +1284,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
int i)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_txq *txq = trans->txqs.txq[trans->txqs.cmd.q_id];
bool page_stolen = false;
int max_len = trans_pcie->rx_buf_bytes;
u32 offset = 0;
@@ -1671,9 +1671,9 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
}
for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) {
- if (!trans_pcie->txq[i])
+ if (!trans->txqs.txq[i])
continue;
- del_timer(&trans_pcie->txq[i]->stuck_timer);
+ del_timer(&trans->txqs.txq[i]->stuck_timer);
}
/* The STATUS_FW_ERROR bit is set in this function. This must happen
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index 19a2c72081ab..97c9e9c87436 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -20,7 +20,7 @@
* BSD LICENSE
*
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -245,7 +245,7 @@ static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
return -ENOMEM;
/* Allocate or reset and init all Tx and Command queues */
- if (iwl_pcie_gen2_tx_init(trans, trans_pcie->cmd_queue, queue_size))
+ if (iwl_pcie_gen2_tx_init(trans, trans->txqs.cmd.q_id, queue_size))
return -ENOMEM;
/* enable shadow regs in HW */
@@ -262,8 +262,9 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr)
iwl_pcie_reset_ict(trans);
/* make sure all queue are not stopped/used */
- memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
- memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
+ memset(trans->txqs.queue_stopped, 0,
+ sizeof(trans->txqs.queue_stopped));
+ memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used));
/* now that we got alive we can free the fw image & the context info.
* paging memory cannot be freed included since FW will still use it
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 8ccfc7cc7348..e5160d620868 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -5,10 +5,9 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2007 - 2015, 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -28,10 +27,9 @@
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2007 - 2015, 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1495,14 +1493,10 @@ static int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test,
int ret;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- /*
- * Family IWL_DEVICE_FAMILY_AX210 and above persist mode is set by FW.
- */
- if (!reset && trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
+ if (!reset)
/* Enable persistence mode to avoid reset */
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_PERSIST_MODE);
- }
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
@@ -1910,9 +1904,9 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- trans_pcie->cmd_queue = trans_cfg->cmd_queue;
- trans_pcie->cmd_fifo = trans_cfg->cmd_fifo;
- trans_pcie->cmd_q_wdg_timeout = trans_cfg->cmd_q_wdg_timeout;
+ trans->txqs.cmd.q_id = trans_cfg->cmd_queue;
+ trans->txqs.cmd.fifo = trans_cfg->cmd_fifo;
+ trans->txqs.cmd.wdg_timeout = trans_cfg->cmd_q_wdg_timeout;
if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS))
trans_pcie->n_no_reclaim_cmds = 0;
else
@@ -2205,11 +2199,10 @@ static void iwl_trans_pcie_freeze_txq_timer(struct iwl_trans *trans,
unsigned long txqs,
bool freeze)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int queue;
for_each_set_bit(queue, &txqs, BITS_PER_LONG) {
- struct iwl_txq *txq = trans_pcie->txq[queue];
+ struct iwl_txq *txq = trans->txqs.txq[queue];
unsigned long now;
spin_lock_bh(&txq->lock);
@@ -2257,13 +2250,12 @@ next_queue:
static void iwl_trans_pcie_block_txq_ptrs(struct iwl_trans *trans, bool block)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int i;
for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) {
- struct iwl_txq *txq = trans_pcie->txq[i];
+ struct iwl_txq *txq = trans->txqs.txq[i];
- if (i == trans_pcie->cmd_queue)
+ if (i == trans->txqs.cmd.q_id)
continue;
spin_lock_bh(&txq->lock);
@@ -2332,7 +2324,6 @@ static int iwl_trans_pcie_rxq_dma_data(struct iwl_trans *trans, int queue,
static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq;
unsigned long now = jiffies;
bool overflow_tx;
@@ -2342,11 +2333,11 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
if (test_bit(STATUS_TRANS_DEAD, &trans->status))
return -ENODEV;
- if (!test_bit(txq_idx, trans_pcie->queue_used))
+ if (!test_bit(txq_idx, trans->txqs.queue_used))
return -EINVAL;
IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx);
- txq = trans_pcie->txq[txq_idx];
+ txq = trans->txqs.txq[txq_idx];
spin_lock_bh(&txq->lock);
overflow_tx = txq->overflow_tx ||
@@ -2394,7 +2385,6 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
static int iwl_trans_pcie_wait_txqs_empty(struct iwl_trans *trans, u32 txq_bm)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int cnt;
int ret = 0;
@@ -2403,9 +2393,9 @@ static int iwl_trans_pcie_wait_txqs_empty(struct iwl_trans *trans, u32 txq_bm)
cnt < trans->trans_cfg->base_params->num_of_queues;
cnt++) {
- if (cnt == trans_pcie->cmd_queue)
+ if (cnt == trans->txqs.cmd.q_id)
continue;
- if (!test_bit(cnt, trans_pcie->queue_used))
+ if (!test_bit(cnt, trans->txqs.queue_used))
continue;
if (!(BIT(cnt) & txq_bm))
continue;
@@ -2579,13 +2569,12 @@ static int iwl_dbgfs_tx_queue_seq_show(struct seq_file *seq, void *v)
struct iwl_dbgfs_tx_queue_priv *priv = seq->private;
struct iwl_dbgfs_tx_queue_state *state = v;
struct iwl_trans *trans = priv->trans;
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[state->pos];
+ struct iwl_txq *txq = trans->txqs.txq[state->pos];
seq_printf(seq, "hwq %.3u: used=%d stopped=%d ",
(unsigned int)state->pos,
- !!test_bit(state->pos, trans_pcie->queue_used),
- !!test_bit(state->pos, trans_pcie->queue_stopped));
+ !!test_bit(state->pos, trans->txqs.queue_used),
+ !!test_bit(state->pos, trans->txqs.queue_stopped));
if (txq)
seq_printf(seq,
"read=%u write=%u need_update=%d frozen=%d n_window=%d ampdu=%d",
@@ -2595,7 +2584,7 @@ static int iwl_dbgfs_tx_queue_seq_show(struct seq_file *seq, void *v)
else
seq_puts(seq, "(unallocated)");
- if (state->pos == trans_pcie->cmd_queue)
+ if (state->pos == trans->txqs.cmd.q_id)
seq_puts(seq, " (HCMD)");
seq_puts(seq, "\n");
@@ -3271,7 +3260,7 @@ static struct iwl_trans_dump_data
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_fw_error_dump_data *data;
- struct iwl_txq *cmdq = trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_txq *cmdq = trans->txqs.txq[trans->txqs.cmd.q_id];
struct iwl_fw_error_dump_txcmd *txcmd;
struct iwl_trans_dump_data *dump_data;
u32 len, num_rbs = 0, monitor_len = 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
index bb55563bba68..7fc7542535d8 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -64,7 +64,6 @@
*/
void iwl_pcie_gen2_tx_stop(struct iwl_trans *trans)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int txq_id;
/*
@@ -72,12 +71,13 @@ void iwl_pcie_gen2_tx_stop(struct iwl_trans *trans)
* queues. This happens when we have an rfkill interrupt.
* Since we stop Tx altogether - mark the queues as stopped.
*/
- memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
- memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
+ memset(trans->txqs.queue_stopped, 0,
+ sizeof(trans->txqs.queue_stopped));
+ memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used));
/* Unmap DMA from host system and free skb's */
- for (txq_id = 0; txq_id < ARRAY_SIZE(trans_pcie->txq); txq_id++) {
- if (!trans_pcie->txq[txq_id])
+ for (txq_id = 0; txq_id < ARRAY_SIZE(trans->txqs.txq); txq_id++) {
+ if (!trans->txqs.txq[txq_id])
continue;
iwl_pcie_gen2_txq_unmap(trans, txq_id);
}
@@ -716,7 +716,7 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_cmd_meta *out_meta;
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
u16 cmd_len;
int idx;
void *tfd;
@@ -725,7 +725,7 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
"queue %d out of range", txq_id))
return -EINVAL;
- if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used),
+ if (WARN_ONCE(!test_bit(txq_id, trans->txqs.queue_used),
"TX on unused queue %d\n", txq_id))
return -EINVAL;
@@ -819,7 +819,7 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_txq *txq = trans->txqs.txq[trans->txqs.cmd.q_id];
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
unsigned long flags;
@@ -931,7 +931,7 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
cpu_to_le16(cmd_size - sizeof(struct iwl_cmd_header_wide));
out_cmd->hdr_wide.reserved = 0;
out_cmd->hdr_wide.sequence =
- cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->cmd_queue) |
+ cpu_to_le16(QUEUE_TO_SEQ(trans->txqs.cmd.q_id) |
INDEX_TO_SEQ(txq->write_ptr));
cmd_pos = sizeof(struct iwl_cmd_header_wide);
@@ -979,7 +979,7 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
"Sending command %s (%.2x.%.2x), seq: 0x%04X, %d bytes at %d[%d]:%d\n",
iwl_get_cmd_string(trans, cmd->id), group_id,
out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
- cmd_size, txq->write_ptr, idx, trans_pcie->cmd_queue);
+ cmd_size, txq->write_ptr, idx, trans->txqs.cmd.q_id);
/* start the TFD with the minimum copy bytes */
tb0_size = min_t(int, copy_size, IWL_FIRST_TB_SIZE);
@@ -1056,7 +1056,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
const char *cmd_str = iwl_get_cmd_string(trans, cmd->id);
- struct iwl_txq *txq = trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_txq *txq = trans->txqs.txq[trans->txqs.cmd.q_id];
int cmd_idx;
int ret;
@@ -1175,14 +1175,14 @@ int iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans,
void iwl_pcie_gen2_txq_unmap(struct iwl_trans *trans, int txq_id)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
spin_lock_bh(&txq->lock);
while (txq->write_ptr != txq->read_ptr) {
IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n",
txq_id, txq->read_ptr);
- if (txq_id != trans_pcie->cmd_queue) {
+ if (txq_id != trans->txqs.cmd.q_id) {
int idx = iwl_pcie_get_cmd_index(txq, txq->read_ptr);
struct sk_buff *skb = txq->entries[idx].skb;
@@ -1240,7 +1240,6 @@ void iwl_pcie_gen2_txq_free_memory(struct iwl_trans *trans,
*/
static void iwl_pcie_gen2_txq_free(struct iwl_trans *trans, int txq_id)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq;
int i;
@@ -1248,7 +1247,7 @@ static void iwl_pcie_gen2_txq_free(struct iwl_trans *trans, int txq_id)
"queue %d out of range", txq_id))
return;
- txq = trans_pcie->txq[txq_id];
+ txq = trans->txqs.txq[txq_id];
if (WARN_ON(!txq))
return;
@@ -1256,7 +1255,7 @@ static void iwl_pcie_gen2_txq_free(struct iwl_trans *trans, int txq_id)
iwl_pcie_gen2_txq_unmap(trans, txq_id);
/* De-alloc array of command/tx buffers */
- if (txq_id == trans_pcie->cmd_queue)
+ if (txq_id == trans->txqs.cmd.q_id)
for (i = 0; i < txq->n_window; i++) {
kzfree(txq->entries[i].cmd);
kzfree(txq->entries[i].free_buf);
@@ -1265,9 +1264,9 @@ static void iwl_pcie_gen2_txq_free(struct iwl_trans *trans, int txq_id)
iwl_pcie_gen2_txq_free_memory(trans, txq);
- trans_pcie->txq[txq_id] = NULL;
+ trans->txqs.txq[txq_id] = NULL;
- clear_bit(txq_id, trans_pcie->queue_used);
+ clear_bit(txq_id, trans->txqs.queue_used);
}
int iwl_trans_pcie_dyn_txq_alloc_dma(struct iwl_trans *trans,
@@ -1327,7 +1326,6 @@ int iwl_trans_pcie_txq_alloc_response(struct iwl_trans *trans,
struct iwl_txq *txq,
struct iwl_host_cmd *hcmd)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tx_queue_cfg_rsp *rsp;
int ret, qid;
u32 wr_ptr;
@@ -1342,20 +1340,20 @@ int iwl_trans_pcie_txq_alloc_response(struct iwl_trans *trans,
qid = le16_to_cpu(rsp->queue_number);
wr_ptr = le16_to_cpu(rsp->write_pointer);
- if (qid >= ARRAY_SIZE(trans_pcie->txq)) {
+ if (qid >= ARRAY_SIZE(trans->txqs.txq)) {
WARN_ONCE(1, "queue index %d unsupported", qid);
ret = -EIO;
goto error_free_resp;
}
- if (test_and_set_bit(qid, trans_pcie->queue_used)) {
+ if (test_and_set_bit(qid, trans->txqs.queue_used)) {
WARN_ONCE(1, "queue %d already used", qid);
ret = -EIO;
goto error_free_resp;
}
txq->id = qid;
- trans_pcie->txq[qid] = txq;
+ trans->txqs.txq[qid] = txq;
wr_ptr &= (trans->trans_cfg->base_params->max_tfd_queue_size - 1);
/* Place first TFD at index corresponding to start sequence number */
@@ -1413,8 +1411,6 @@ error:
void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
if (WARN(queue >= IWL_MAX_TVQM_QUEUES,
"queue %d out of range", queue))
return;
@@ -1425,7 +1421,7 @@ void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue)
* allow the op_mode to call txq_disable after it already called
* stop_device.
*/
- if (!test_and_clear_bit(queue, trans_pcie->queue_used)) {
+ if (!test_and_clear_bit(queue, trans->txqs.queue_used)) {
WARN_ONCE(test_bit(STATUS_DEVICE_ENABLED, &trans->status),
"queue %d not used", queue);
return;
@@ -1433,22 +1429,21 @@ void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue)
iwl_pcie_gen2_txq_unmap(trans, queue);
- iwl_pcie_gen2_txq_free_memory(trans, trans_pcie->txq[queue]);
- trans_pcie->txq[queue] = NULL;
+ iwl_pcie_gen2_txq_free_memory(trans, trans->txqs.txq[queue]);
+ trans->txqs.txq[queue] = NULL;
IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", queue);
}
void iwl_pcie_gen2_tx_free(struct iwl_trans *trans)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int i;
- memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
+ memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used));
/* Free all TX queues */
- for (i = 0; i < ARRAY_SIZE(trans_pcie->txq); i++) {
- if (!trans_pcie->txq[i])
+ for (i = 0; i < ARRAY_SIZE(trans->txqs.txq); i++) {
+ if (!trans->txqs.txq[i])
continue;
iwl_pcie_gen2_txq_free(trans, i);
@@ -1457,35 +1452,34 @@ void iwl_pcie_gen2_tx_free(struct iwl_trans *trans)
int iwl_pcie_gen2_tx_init(struct iwl_trans *trans, int txq_id, int queue_size)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *queue;
int ret;
/* alloc and init the tx queue */
- if (!trans_pcie->txq[txq_id]) {
+ if (!trans->txqs.txq[txq_id]) {
queue = kzalloc(sizeof(*queue), GFP_KERNEL);
if (!queue) {
IWL_ERR(trans, "Not enough memory for tx queue\n");
return -ENOMEM;
}
- trans_pcie->txq[txq_id] = queue;
+ trans->txqs.txq[txq_id] = queue;
ret = iwl_pcie_txq_alloc(trans, queue, queue_size, true);
if (ret) {
IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
goto error;
}
} else {
- queue = trans_pcie->txq[txq_id];
+ queue = trans->txqs.txq[txq_id];
}
ret = iwl_pcie_txq_init(trans, queue, queue_size,
- (txq_id == trans_pcie->cmd_queue));
+ (txq_id == trans->txqs.cmd.q_id));
if (ret) {
IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
goto error;
}
- trans_pcie->txq[txq_id]->id = txq_id;
- set_bit(txq_id, trans_pcie->queue_used);
+ trans->txqs.txq[txq_id]->id = txq_id;
+ set_bit(txq_id, trans->txqs.queue_used);
return 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 9ff78bca460b..5c6c3fa0d29f 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -183,8 +183,7 @@ void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr)
static void iwl_pcie_txq_stuck_timer(struct timer_list *t)
{
struct iwl_txq *txq = from_timer(txq, t, stuck_timer);
- struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
- struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
+ struct iwl_trans *trans = txq->trans;
spin_lock(&txq->lock);
/* check if triggered erroneously */
@@ -262,7 +261,7 @@ static void iwl_pcie_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
- if (txq_id != trans_pcie->cmd_queue)
+ if (txq_id != trans->txqs.cmd.q_id)
sta_id = tx_cmd->sta_id;
bc_ent = cpu_to_le16(1 | (sta_id << 12));
@@ -280,7 +279,6 @@ static void iwl_pcie_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans,
struct iwl_txq *txq)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u32 reg = 0;
int txq_id = txq->id;
@@ -293,7 +291,7 @@ static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans,
* 3. there is a chance that the NIC is asleep
*/
if (!trans->trans_cfg->base_params->shadow_reg_enable &&
- txq_id != trans_pcie->cmd_queue &&
+ txq_id != trans->txqs.cmd.q_id &&
test_bit(STATUS_TPOWER_PMI, &trans->status)) {
/*
* wake up nic if it's powered down ...
@@ -324,13 +322,12 @@ static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans,
void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int i;
for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) {
- struct iwl_txq *txq = trans_pcie->txq[i];
+ struct iwl_txq *txq = trans->txqs.txq[i];
- if (!test_bit(i, trans_pcie->queue_used))
+ if (!test_bit(i, trans->txqs.queue_used))
continue;
spin_lock_bh(&txq->lock);
@@ -535,7 +532,7 @@ int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq,
tfd_sz = trans_pcie->tfd_size * slots_num;
timer_setup(&txq->stuck_timer, iwl_pcie_txq_stuck_timer, 0);
- txq->trans_pcie = trans_pcie;
+ txq->trans = trans;
txq->n_window = slots_num;
@@ -661,14 +658,14 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
spin_lock_bh(&txq->lock);
while (txq->write_ptr != txq->read_ptr) {
IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n",
txq_id, txq->read_ptr);
- if (txq_id != trans_pcie->cmd_queue) {
+ if (txq_id != trans->txqs.cmd.q_id) {
struct sk_buff *skb = txq->entries[txq->read_ptr].skb;
if (WARN_ON_ONCE(!skb))
@@ -683,7 +680,7 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
unsigned long flags;
spin_lock_irqsave(&trans_pcie->reg_lock, flags);
- if (txq_id == trans_pcie->cmd_queue)
+ if (txq_id == trans->txqs.cmd.q_id)
iwl_pcie_clear_cmd_in_flight(trans);
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
}
@@ -712,7 +709,7 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
struct device *dev = trans->dev;
int i;
@@ -722,7 +719,7 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
iwl_pcie_txq_unmap(trans, txq_id);
/* De-alloc array of command/tx buffers */
- if (txq_id == trans_pcie->cmd_queue)
+ if (txq_id == trans->txqs.cmd.q_id)
for (i = 0; i < txq->n_window; i++) {
kzfree(txq->entries[i].cmd);
kzfree(txq->entries[i].free_buf);
@@ -761,8 +758,9 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
SCD_CONTEXT_MEM_LOWER_BOUND) / sizeof(u32);
/* make sure all queue are not stopped/used */
- memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
- memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
+ memset(trans->txqs.queue_stopped, 0,
+ sizeof(trans->txqs.queue_stopped));
+ memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used));
trans_pcie->scd_base_addr =
iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
@@ -784,9 +782,9 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
if (trans->trans_cfg->base_params->scd_chain_ext_wa)
iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
- iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue,
- trans_pcie->cmd_fifo,
- trans_pcie->cmd_q_wdg_timeout);
+ iwl_trans_ac_txq_enable(trans, trans->txqs.cmd.q_id,
+ trans->txqs.cmd.fifo,
+ trans->txqs.cmd.wdg_timeout);
/* Activate all Tx DMA/FIFO channels */
iwl_scd_activate_fifos(trans);
@@ -822,7 +820,7 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) {
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
if (trans->trans_cfg->use_tfh)
iwl_write_direct64(trans,
FH_MEM_CBBC_QUEUE(trans, txq_id),
@@ -898,8 +896,9 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans)
* queues. This happens when we have an rfkill interrupt.
* Since we stop Tx altogether - mark the queues as stopped.
*/
- memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
- memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
+ memset(trans->txqs.queue_stopped, 0,
+ sizeof(trans->txqs.queue_stopped));
+ memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used));
/* This can happen: start_hw, stop_device */
if (!trans_pcie->txq_memory)
@@ -923,7 +922,7 @@ void iwl_pcie_tx_free(struct iwl_trans *trans)
int txq_id;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
+ memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used));
/* Tx queues */
if (trans_pcie->txq_memory) {
@@ -931,7 +930,7 @@ void iwl_pcie_tx_free(struct iwl_trans *trans)
txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) {
iwl_pcie_txq_free(trans, txq_id);
- trans_pcie->txq[txq_id] = NULL;
+ trans->txqs.txq[txq_id] = NULL;
}
}
@@ -992,7 +991,7 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) {
- bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
+ bool cmd_queue = (txq_id == trans->txqs.cmd.q_id);
if (cmd_queue)
slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE,
@@ -1000,14 +999,14 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
else
slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE,
trans->cfg->min_256_ba_txq_size);
- trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id];
- ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id],
+ trans->txqs.txq[txq_id] = &trans_pcie->txq_memory[txq_id];
+ ret = iwl_pcie_txq_alloc(trans, trans->txqs.txq[txq_id],
slots_num, cmd_queue);
if (ret) {
IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id);
goto error;
}
- trans_pcie->txq[txq_id]->id = txq_id;
+ trans->txqs.txq[txq_id]->id = txq_id;
}
return 0;
@@ -1046,7 +1045,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) {
- bool cmd_queue = (txq_id == trans_pcie->cmd_queue);
+ bool cmd_queue = (txq_id == trans->txqs.cmd.q_id);
if (cmd_queue)
slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE,
@@ -1054,7 +1053,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
else
slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE,
trans->cfg->min_256_ba_txq_size);
- ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id],
+ ret = iwl_pcie_txq_init(trans, trans->txqs.txq[txq_id],
slots_num, cmd_queue);
if (ret) {
IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
@@ -1068,7 +1067,7 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
* Circular buffer (TFD queue in DRAM) physical base address
*/
iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(trans, txq_id),
- trans_pcie->txq[txq_id]->dma_addr >> 8);
+ trans->txqs.txq[txq_id]->dma_addr >> 8);
}
iwl_set_bits_prph(trans, SCD_GP_CTRL, SCD_GP_CTRL_AUTO_ACTIVE_MODE);
@@ -1113,18 +1112,18 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
struct sk_buff_head *skbs)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
int tfd_num = iwl_pcie_get_cmd_index(txq, ssn);
int read_ptr = iwl_pcie_get_cmd_index(txq, txq->read_ptr);
int last_to_free;
/* This function is not meant to release cmd queue*/
- if (WARN_ON(txq_id == trans_pcie->cmd_queue))
+ if (WARN_ON(txq_id == trans->txqs.cmd.q_id))
return;
spin_lock_bh(&txq->lock);
- if (!test_bit(txq_id, trans_pcie->queue_used)) {
+ if (!test_bit(txq_id, trans->txqs.queue_used)) {
IWL_DEBUG_TX_QUEUES(trans, "Q %d inactive - ignoring idx %d\n",
txq_id, ssn);
goto out;
@@ -1176,7 +1175,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
iwl_pcie_txq_progress(txq);
if (iwl_queue_space(trans, txq) > txq->low_mark &&
- test_bit(txq_id, trans_pcie->queue_stopped)) {
+ test_bit(txq_id, trans->txqs.queue_stopped)) {
struct sk_buff_head overflow_skbs;
__skb_queue_head_init(&overflow_skbs);
@@ -1229,8 +1228,7 @@ out:
/* Set wr_ptr of specific device and txq */
void iwl_trans_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
spin_lock_bh(&txq->lock);
@@ -1290,7 +1288,7 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
unsigned long flags;
int nfreed = 0;
u16 r;
@@ -1302,7 +1300,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
if (idx >= trans->trans_cfg->base_params->max_tfd_queue_size ||
(!iwl_queue_used(txq, idx))) {
- WARN_ONCE(test_bit(txq_id, trans_pcie->queue_used),
+ WARN_ONCE(test_bit(txq_id, trans->txqs.queue_used),
"%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",
__func__, txq_id, idx,
trans->trans_cfg->base_params->max_tfd_queue_size,
@@ -1364,11 +1362,11 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
unsigned int wdg_timeout)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
int fifo = -1;
bool scd_bug = false;
- if (test_and_set_bit(txq_id, trans_pcie->queue_used))
+ if (test_and_set_bit(txq_id, trans->txqs.queue_used))
WARN_ONCE(1, "queue %d already used - expect issues", txq_id);
txq->wd_timeout = msecs_to_jiffies(wdg_timeout);
@@ -1377,7 +1375,7 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
fifo = cfg->fifo;
/* Disable the scheduler prior configuring the cmd queue */
- if (txq_id == trans_pcie->cmd_queue &&
+ if (txq_id == trans->txqs.cmd.q_id &&
trans_pcie->scd_set_active)
iwl_scd_enable_set_active(trans, 0);
@@ -1385,7 +1383,7 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
iwl_scd_txq_set_inactive(trans, txq_id);
/* Set this queue as a chain-building queue unless it is CMD */
- if (txq_id != trans_pcie->cmd_queue)
+ if (txq_id != trans->txqs.cmd.q_id)
iwl_scd_txq_set_chain(trans, txq_id);
if (cfg->aggregate) {
@@ -1455,7 +1453,7 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
SCD_QUEUE_STTS_REG_MSK);
/* enable the scheduler for this queue (only) */
- if (txq_id == trans_pcie->cmd_queue &&
+ if (txq_id == trans->txqs.cmd.q_id &&
trans_pcie->scd_set_active)
iwl_scd_enable_set_active(trans, BIT(txq_id));
@@ -1474,8 +1472,7 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
void iwl_trans_pcie_txq_set_shared_mode(struct iwl_trans *trans, u32 txq_id,
bool shared_mode)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[txq_id];
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
txq->ampdu = !shared_mode;
}
@@ -1488,8 +1485,8 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id,
SCD_TX_STTS_QUEUE_OFFSET(txq_id);
static const u32 zero_val[4] = {};
- trans_pcie->txq[txq_id]->frozen_expiry_remainder = 0;
- trans_pcie->txq[txq_id]->frozen = false;
+ trans->txqs.txq[txq_id]->frozen_expiry_remainder = 0;
+ trans->txqs.txq[txq_id]->frozen = false;
/*
* Upon HW Rfkill - we stop the device, and then stop the queues
@@ -1497,7 +1494,7 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id,
* allow the op_mode to call txq_disable after it already called
* stop_device.
*/
- if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
+ if (!test_and_clear_bit(txq_id, trans->txqs.queue_used)) {
WARN_ONCE(test_bit(STATUS_DEVICE_ENABLED, &trans->status),
"queue %d not used", txq_id);
return;
@@ -1511,7 +1508,7 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id,
}
iwl_pcie_txq_unmap(trans, txq_id);
- trans_pcie->txq[txq_id]->ampdu = false;
+ trans->txqs.txq[txq_id]->ampdu = false;
IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
}
@@ -1531,7 +1528,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_txq *txq = trans->txqs.txq[trans->txqs.cmd.q_id];
struct iwl_device_cmd *out_cmd;
struct iwl_cmd_meta *out_meta;
unsigned long flags;
@@ -1657,7 +1654,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
sizeof(struct iwl_cmd_header_wide));
out_cmd->hdr_wide.reserved = 0;
out_cmd->hdr_wide.sequence =
- cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->cmd_queue) |
+ cpu_to_le16(QUEUE_TO_SEQ(trans->txqs.cmd.q_id) |
INDEX_TO_SEQ(txq->write_ptr));
cmd_pos = sizeof(struct iwl_cmd_header_wide);
@@ -1665,7 +1662,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
} else {
out_cmd->hdr.cmd = iwl_cmd_opcode(cmd->id);
out_cmd->hdr.sequence =
- cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->cmd_queue) |
+ cpu_to_le16(QUEUE_TO_SEQ(trans->txqs.cmd.q_id) |
INDEX_TO_SEQ(txq->write_ptr));
out_cmd->hdr.group_id = 0;
@@ -1716,7 +1713,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
iwl_get_cmd_string(trans, cmd->id),
group_id, out_cmd->hdr.cmd,
le16_to_cpu(out_cmd->hdr.sequence),
- cmd_size, txq->write_ptr, idx, trans_pcie->cmd_queue);
+ cmd_size, txq->write_ptr, idx, trans->txqs.cmd.q_id);
/* start the TFD with the minimum copy bytes */
tb0_size = min_t(int, copy_size, IWL_FIRST_TB_SIZE);
@@ -1816,14 +1813,14 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
struct iwl_device_cmd *cmd;
struct iwl_cmd_meta *meta;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_txq *txq = trans->txqs.txq[trans->txqs.cmd.q_id];
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
* in the queue management code. */
- if (WARN(txq_id != trans_pcie->cmd_queue,
+ if (WARN(txq_id != trans->txqs.cmd.q_id,
"wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
- txq_id, trans_pcie->cmd_queue, sequence, txq->read_ptr,
+ txq_id, trans->txqs.cmd.q_id, sequence, txq->read_ptr,
txq->write_ptr)) {
iwl_print_hex_error(trans, pkt, 32);
return;
@@ -1895,7 +1892,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_txq *txq = trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_txq *txq = trans->txqs.txq[trans->txqs.cmd.q_id];
int cmd_idx;
int ret;
@@ -2129,7 +2126,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
u16 tb1_len)
{
struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
- struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
+ struct iwl_trans_pcie *trans_pcie =
+ IWL_TRANS_GET_PCIE_TRANS(txq->trans);
struct ieee80211_hdr *hdr = (void *)skb->data;
unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
unsigned int mss = skb_shinfo(skb)->gso_size;
@@ -2332,9 +2330,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
u16 wifi_seq;
bool amsdu;
- txq = trans_pcie->txq[txq_id];
+ txq = trans->txqs.txq[txq_id];
- if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used),
+ if (WARN_ONCE(!test_bit(txq_id, trans->txqs.queue_used),
"TX on unused queue %d\n", txq_id))
return -EINVAL;
diff --git a/drivers/net/wireless/marvell/libertas/rx.c b/drivers/net/wireless/marvell/libertas/rx.c
index 58a1fc433b73..f28aa09d1f9e 100644
--- a/drivers/net/wireless/marvell/libertas/rx.c
+++ b/drivers/net/wireless/marvell/libertas/rx.c
@@ -62,9 +62,6 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
struct rxpd *p_rx_pd;
int hdrchop;
struct ethhdr *p_ethhdr;
- static const u8 rfc1042_eth_hdr[] = {
- 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
- };
BUG_ON(!skb);
@@ -102,7 +99,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
sizeof(p_rx_pkt->eth803_hdr.src_addr));
if (memcmp(&p_rx_pkt->rfc1042_hdr,
- rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
+ rfc1042_header, sizeof(rfc1042_header)) == 0) {
/*
* Replace the 803 header and rfc1042 header (llc/snap) with an
* EthernetII header, keep the src/dst and snap_type (ethertype)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 97813ac291ae..4e4f59c17ded 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -4335,6 +4335,11 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
wiphy->n_iface_combinations = 1;
+ if (adapter->max_sta_conn > adapter->max_p2p_conn)
+ wiphy->max_ap_assoc_sta = adapter->max_sta_conn;
+ else
+ wiphy->max_ap_assoc_sta = adapter->max_p2p_conn;
+
/* Initialize cipher suits */
wiphy->cipher_suites = mwifiex_cipher_suites;
wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 7e4b8cd52605..d068b9075c32 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -1495,6 +1495,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_ie_types_header *tlv;
struct hw_spec_api_rev *api_rev;
+ struct hw_spec_max_conn *max_conn;
u16 resp_size, api_id;
int i, left_len, parsed_len = 0;
@@ -1581,8 +1582,21 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
adapter->fw_api_ver =
api_rev->major_ver;
mwifiex_dbg(adapter, INFO,
- "Firmware api version %d\n",
- adapter->fw_api_ver);
+ "Firmware api version %d.%d\n",
+ adapter->fw_api_ver,
+ api_rev->minor_ver);
+ break;
+ case UAP_FW_API_VER_ID:
+ mwifiex_dbg(adapter, INFO,
+ "uAP api version %d.%d\n",
+ api_rev->major_ver,
+ api_rev->minor_ver);
+ break;
+ case CHANRPT_API_VER_ID:
+ mwifiex_dbg(adapter, INFO,
+ "channel report api version %d.%d\n",
+ api_rev->major_ver,
+ api_rev->minor_ver);
break;
default:
mwifiex_dbg(adapter, FATAL,
@@ -1591,6 +1605,17 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
break;
}
break;
+ case TLV_TYPE_MAX_CONN:
+ max_conn = (struct hw_spec_max_conn *)tlv;
+ adapter->max_p2p_conn = max_conn->max_p2p_conn;
+ adapter->max_sta_conn = max_conn->max_sta_conn;
+ mwifiex_dbg(adapter, INFO,
+ "max p2p connections: %u\n",
+ adapter->max_p2p_conn);
+ mwifiex_dbg(adapter, INFO,
+ "max sta connections: %u\n",
+ adapter->max_sta_conn);
+ break;
default:
mwifiex_dbg(adapter, FATAL,
"Unknown GET_HW_SPEC TLV type: %#x\n",
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index a415d73a73e6..8047e307892e 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -220,6 +220,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_BSS_MODE (PROPRIETARY_TLV_BASE_ID + 206)
#define TLV_TYPE_RANDOM_MAC (PROPRIETARY_TLV_BASE_ID + 236)
#define TLV_TYPE_CHAN_ATTR_CFG (PROPRIETARY_TLV_BASE_ID + 237)
+#define TLV_TYPE_MAX_CONN (PROPRIETARY_TLV_BASE_ID + 279)
#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048
@@ -1052,6 +1053,8 @@ struct host_cmd_ds_802_11_ps_mode_enh {
enum API_VER_ID {
KEY_API_VER_ID = 1,
FW_API_VER_ID = 2,
+ UAP_FW_API_VER_ID = 3,
+ CHANRPT_API_VER_ID = 4,
};
struct hw_spec_api_rev {
@@ -2386,4 +2389,11 @@ struct mwifiex_opt_sleep_confirm {
__le16 action;
__le16 resp_ctrl;
} __packed;
+
+struct hw_spec_max_conn {
+ struct mwifiex_ie_types_header header;
+ u8 max_p2p_conn;
+ u8 max_sta_conn;
+} __packed;
+
#endif /* !_MWIFIEX_FW_H_ */
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index afaffc325452..5923c5c14c8d 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1022,6 +1022,7 @@ struct mwifiex_adapter {
bool ext_scan;
u8 fw_api_ver;
u8 key_api_major_ver, key_api_minor_ver;
+ u8 max_p2p_conn, max_sta_conn;
struct memory_type_mapping *mem_type_mapping_tbl;
u8 num_mem_types;
bool scan_chan_gap_enabled;
diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c
index 0278e1b44576..3a5de1d1b121 100644
--- a/drivers/net/wireless/mediatek/mt76/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/debugfs.c
@@ -51,7 +51,7 @@ static int mt76_rx_queues_read(struct seq_file *s, void *data)
struct mt76_dev *dev = dev_get_drvdata(s->private);
int i, queued;
- for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) {
+ mt76_for_each_q_rx(dev, i) {
struct mt76_queue *q = &dev->q_rx[i];
if (!q->ndesc)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index 75e659774e07..f4d6074fe32a 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -576,7 +576,7 @@ mt76_dma_init(struct mt76_dev *dev)
init_dummy_netdev(&dev->napi_dev);
- for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) {
+ mt76_for_each_q_rx(dev, i) {
netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll,
64);
mt76_dma_rx_fill(dev, &dev->q_rx[i]);
@@ -610,7 +610,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++)
mt76_dma_tx_cleanup(dev, i, true);
- for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) {
+ mt76_for_each_q_rx(dev, i) {
netif_napi_del(&dev->napi[i]);
mt76_dma_rx_cleanup(dev, &dev->q_rx[i]);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index e6de4a1b8f26..dfe625a53c63 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -288,8 +288,8 @@ enum {
MT76_REMOVED,
MT76_READING_STATS,
MT76_STATE_POWER_OFF,
- MT76_STATE_PS,
MT76_STATE_SUSPEND,
+ MT76_STATE_ROC,
};
struct mt76_hw_cap {
@@ -537,8 +537,8 @@ struct mt76_dev {
wait_queue_head_t tx_wait;
struct sk_buff_head status_list;
- unsigned long wcid_mask[MT76_N_WCIDS / BITS_PER_LONG];
- unsigned long wcid_phy_mask[MT76_N_WCIDS / BITS_PER_LONG];
+ u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
+ u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
struct mt76_wcid global_wcid;
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
@@ -671,6 +671,10 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
+#define mt76_for_each_q_rx(dev, i) \
+ for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \
+ (dev)->q_rx[i].ndesc; i++)
+
struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size,
const struct ieee80211_ops *ops,
const struct mt76_driver_ops *drv_ops);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index f8c0c957ca01..8060c1514396 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -473,7 +473,7 @@ mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast)
struct mt7603_sta *sta;
struct mt76_wcid *wcid;
- if (idx >= ARRAY_SIZE(dev->mt76.wcid))
+ if (idx >= MT7603_WTBL_SIZE)
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
@@ -1238,7 +1238,7 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
if (pid == MT_PACKET_ID_NO_ACK)
return;
- if (wcidx >= ARRAY_SIZE(dev->mt76.wcid))
+ if (wcidx >= MT7603_WTBL_SIZE)
return;
rcu_read_lock();
@@ -1438,8 +1438,9 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, i, true);
- for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++)
+ mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i);
+ }
mt7603_dma_sched_reset(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
index 6a5ae047c63b..edac37e7847b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
@@ -111,6 +111,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
return;
}
+ if (is_mt7611(&dev->mt76)) {
+ /* 5GHz only */
+ dev->mt76.cap.has_5ghz = true;
+ return;
+ }
+
val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
eeprom[MT_EE_WIFI_CONF]);
switch (val) {
@@ -310,6 +316,7 @@ static void mt7615_cal_free_data(struct mt7615_dev *dev)
mt7622_apply_cal_free_data(dev);
break;
case 0x7615:
+ case 0x7611:
mt7615_apply_cal_free_data(dev);
break;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 1d8fdc7e062b..e2d80518e5af 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -139,8 +139,10 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev)
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
+ wiphy->max_remain_on_channel_duration = 5000;
wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
+ WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
NL80211_FEATURE_P2P_GO_CTWIN |
NL80211_FEATURE_P2P_GO_OPPPS;
} else {
@@ -149,6 +151,8 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev)
dev->ops->sched_scan_start = NULL;
dev->ops->sched_scan_stop = NULL;
dev->ops->set_rekey_data = NULL;
+ dev->ops->remain_on_channel = NULL;
+ dev->ops->cancel_remain_on_channel = NULL;
wiphy->max_sched_scan_plan_interval = 0;
wiphy->max_sched_scan_ie_len = 0;
@@ -368,12 +372,6 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
if (phy)
return 0;
- INIT_DELAYED_WORK(&phy->mac_work, mt7615_mac_work);
- INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work);
- skb_queue_head_init(&phy->scan_event_list);
-
- INIT_WORK(&phy->ps_work, mt7615_ps_work);
-
mt7615_cap_dbdc_enable(dev);
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops);
if (!mphy)
@@ -386,6 +384,14 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1;
mt7615_init_wiphy(mphy->hw);
+ INIT_DELAYED_WORK(&phy->mac_work, mt7615_mac_work);
+ INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work);
+ skb_queue_head_init(&phy->scan_event_list);
+
+ INIT_WORK(&phy->roc_work, mt7615_roc_work);
+ timer_setup(&phy->roc_timer, mt7615_roc_timer, 0);
+ init_waitqueue_head(&phy->roc_wait);
+
mt7615_mac_set_scs(phy, true);
/*
@@ -437,9 +443,11 @@ void mt7615_init_device(struct mt7615_dev *dev)
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
+ init_waitqueue_head(&dev->phy.roc_wait);
INIT_WORK(&dev->reset_work, mt7615_mac_reset_work);
- INIT_WORK(&dev->phy.ps_work, mt7615_ps_work);
+ INIT_WORK(&dev->phy.roc_work, mt7615_roc_work);
+ timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0);
mt7615_init_wiphy(hw);
dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index 7d65a3fb0c23..9f1c6ca7a665 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -61,7 +61,7 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev,
struct mt7615_sta *sta;
struct mt76_wcid *wcid;
- if (idx >= ARRAY_SIZE(dev->mt76.wcid))
+ if (idx >= MT7615_WTBL_SIZE)
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
@@ -175,7 +175,8 @@ mt7615_get_status_freq_info(struct mt7615_dev *dev, struct mt76_phy *mphy,
struct mt76_rx_status *status, u8 chfreq)
{
if (!test_bit(MT76_HW_SCANNING, &mphy->state) &&
- !test_bit(MT76_HW_SCHED_SCANNING, &mphy->state)) {
+ !test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) &&
+ !test_bit(MT76_STATE_ROC, &mphy->state)) {
status->freq = mphy->chandef.chan->center_freq;
status->band = mphy->chandef.chan->band;
return;
@@ -1302,7 +1303,7 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
if (pid == MT_PACKET_ID_NO_ACK)
return;
- if (wcidx >= ARRAY_SIZE(dev->mt76.wcid))
+ if (wcidx >= MT7615_WTBL_SIZE)
return;
rcu_read_lock();
@@ -1819,8 +1820,9 @@ void mt7615_dma_reset(struct mt7615_dev *dev)
for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, i, true);
- for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++)
+ mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i);
+ }
mt76_set(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN |
@@ -1849,8 +1851,13 @@ void mt7615_mac_reset_work(struct work_struct *work)
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
cancel_delayed_work_sync(&dev->phy.mac_work);
- if (phy2)
+ del_timer_sync(&dev->phy.roc_timer);
+ cancel_work_sync(&dev->phy.roc_work);
+ if (phy2) {
cancel_delayed_work_sync(&phy2->mac_work);
+ del_timer_sync(&phy2->roc_timer);
+ cancel_work_sync(&phy2->roc_work);
+ }
/* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index 2e9e9d3519d7..c26f99b368d9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -71,7 +71,8 @@ static void mt7615_stop(struct ieee80211_hw *hw)
struct mt7615_phy *phy = mt7615_hw_phy(hw);
cancel_delayed_work_sync(&phy->mac_work);
- cancel_work_sync(&phy->ps_work);
+ del_timer_sync(&phy->roc_timer);
+ cancel_work_sync(&phy->roc_work);
mutex_lock(&dev->mt76.mutex);
@@ -289,12 +290,11 @@ mt7615_queue_key_update(struct mt7615_dev *dev, enum set_key_cmd cmd,
wd->type = MT7615_WTBL_KEY_DESC;
wd->sta = msta;
- wd->key.key = kzalloc(key->keylen, GFP_KERNEL);
+ wd->key.key = kmemdup(key->key, key->keylen, GFP_KERNEL);
if (!wd->key.key) {
kfree(wd);
return -ENOMEM;
}
- memcpy(wd->key.key, key->key, key->keylen);
wd->key.cipher = key->cipher;
wd->key.keyidx = key->keyidx;
wd->key.keylen = key->keylen;
@@ -360,20 +360,6 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
}
-void mt7615_ps_work(struct work_struct *work)
-{
- struct mt7615_phy *phy;
-
- phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy,
- ps_work);
-
- mutex_lock(&phy->dev->mt76.mutex);
- ieee80211_iterate_active_interfaces(phy->mt76->hw,
- IEEE80211_IFACE_ITER_RESUME_ALL,
- m7615_mcu_set_ps_iter, phy);
- mutex_unlock(&phy->dev->mt76.mutex);
-}
-
static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
@@ -399,14 +385,6 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
}
- if (changed & IEEE80211_CONF_CHANGE_PS) {
- if (hw->conf.flags & IEEE80211_CONF_PS)
- set_bit(MT76_STATE_PS, &phy->mt76->state);
- else
- clear_bit(MT76_STATE_PS, &phy->mt76->state);
- ieee80211_queue_work(hw, &phy->ps_work);
- }
-
mutex_unlock(&dev->mt76.mutex);
return ret;
@@ -509,6 +487,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
BSS_CHANGED_BEACON_ENABLED))
mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon);
+ if (changed & BSS_CHANGED_PS)
+ mt7615_mcu_set_vif_ps(dev, vif);
+
mutex_unlock(&dev->mt76.mutex);
}
@@ -791,6 +772,37 @@ mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
return 0;
}
+static void mt7615_roc_iter(void *priv, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct mt7615_phy *phy = priv;
+
+ mt7615_mcu_set_roc(phy, vif, NULL, 0);
+}
+
+void mt7615_roc_work(struct work_struct *work)
+{
+ struct mt7615_phy *phy;
+
+ phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy,
+ roc_work);
+
+ if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
+ return;
+
+ ieee80211_iterate_active_interfaces(phy->mt76->hw,
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt7615_roc_iter, phy);
+ ieee80211_remain_on_channel_expired(phy->mt76->hw);
+}
+
+void mt7615_roc_timer(struct timer_list *timer)
+{
+ struct mt7615_phy *phy = from_timer(phy, timer, roc_timer);
+
+ ieee80211_queue_work(phy->mt76->hw, &phy->roc_work);
+}
+
void mt7615_scan_work(struct work_struct *work)
{
struct mt7615_phy *phy;
@@ -864,6 +876,50 @@ mt7615_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
return mt7615_mcu_sched_scan_enable(mphy->priv, vif, false);
}
+static int mt7615_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan,
+ int duration,
+ enum ieee80211_roc_type type)
+{
+ struct mt7615_phy *phy = mt7615_hw_phy(hw);
+ int err;
+
+ if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state))
+ return 0;
+
+ err = mt7615_mcu_set_roc(phy, vif, chan, duration);
+ if (err < 0) {
+ clear_bit(MT76_STATE_ROC, &phy->mt76->state);
+ return err;
+ }
+
+ if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, HZ)) {
+ mt7615_mcu_set_roc(phy, vif, NULL, 0);
+ clear_bit(MT76_STATE_ROC, &phy->mt76->state);
+
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct mt7615_phy *phy = mt7615_hw_phy(hw);
+
+ if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
+ return 0;
+
+ del_timer_sync(&phy->roc_timer);
+ cancel_work_sync(&phy->roc_work);
+
+ mt7615_mcu_set_roc(phy, vif, NULL, 0);
+
+ return 0;
+}
+
#ifdef CONFIG_PM
static int mt7615_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
@@ -978,6 +1034,8 @@ const struct ieee80211_ops mt7615_ops = {
.cancel_hw_scan = mt7615_cancel_hw_scan,
.sched_scan_start = mt7615_start_sched_scan,
.sched_scan_stop = mt7615_stop_sched_scan,
+ .remain_on_channel = mt7615_remain_on_channel,
+ .cancel_remain_on_channel = mt7615_cancel_remain_on_channel,
#ifdef CONFIG_PM
.suspend = mt7615_suspend,
.resume = mt7615_resume,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index b944f372738a..6e869b8c5e26 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -360,6 +360,33 @@ mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb)
}
static void
+mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb)
+{
+ struct mt7615_roc_tlv *event;
+ struct mt7615_phy *phy;
+ struct mt76_phy *mphy;
+ int duration;
+
+ skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
+ event = (struct mt7615_roc_tlv *)skb->data;
+
+ if (event->dbdc_band && dev->mt76.phy2)
+ mphy = dev->mt76.phy2;
+ else
+ mphy = &dev->mt76.phy;
+
+ ieee80211_ready_on_channel(mphy->hw);
+
+ phy = (struct mt7615_phy *)mphy->priv;
+ phy->roc_grant = true;
+ wake_up(&phy->roc_wait);
+
+ duration = le32_to_cpu(event->max_interval);
+ mod_timer(&phy->roc_timer,
+ round_jiffies_up(jiffies + msecs_to_jiffies(duration)));
+}
+
+static void
mt7615_mcu_beacon_loss_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
@@ -426,6 +453,9 @@ mt7615_mcu_rx_unsolicited_event(struct mt7615_dev *dev, struct sk_buff *skb)
case MCU_EVENT_BSS_BEACON_LOSS:
mt7615_mcu_beacon_loss_event(dev, skb);
break;
+ case MCU_EVENT_ROC:
+ mt7615_mcu_roc_event(dev, skb);
+ break;
case MCU_EVENT_SCHED_SCAN_DONE:
case MCU_EVENT_SCAN_DONE:
mt7615_mcu_scan_event(dev, skb);
@@ -451,6 +481,7 @@ void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb)
rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||
rxd->eid == MCU_EVENT_BSS_ABSENCE ||
rxd->eid == MCU_EVENT_SCAN_DONE ||
+ rxd->eid == MCU_EVENT_ROC ||
!rxd->seq)
mt7615_mcu_rx_unsolicited_event(dev, skb);
else
@@ -2741,11 +2772,9 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable)
sizeof(req), true);
}
-void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
- struct mt7615_phy *phy = priv;
- struct mt76_phy *mphy = phy->mt76;
struct {
u8 bss_idx;
u8 ps_state; /* 0: device awake
@@ -2754,12 +2783,14 @@ void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
*/
} req = {
.bss_idx = mvif->idx,
- .ps_state = test_bit(MT76_STATE_PS, &mphy->state) ? 2 : 0,
+ .ps_state = vif->bss_conf.ps ? 2 : 0,
};
- if (vif->type == NL80211_IFTYPE_STATION)
- __mt76_mcu_send_msg(&phy->dev->mt76, MCU_CMD_SET_PS_PROFILE,
- &req, sizeof(req), false);
+ if (vif->type != NL80211_IFTYPE_STATION)
+ return -ENOTSUPP;
+
+ return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_PS_PROFILE,
+ &req, sizeof(req), false);
}
int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy)
@@ -2867,6 +2898,7 @@ int mt7615_mcu_hw_scan(struct mt7615_phy *phy, struct ieee80211_vif *vif,
n_ssids++;
}
req->ssid_type = n_ssids ? BIT(2) : BIT(0);
+ req->ssid_type_ext = n_ssids ? BIT(0) : 0;
req->ssids_num = n_ssids;
/* increase channel time for passive scan */
@@ -3601,6 +3633,26 @@ int mt7615_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
}
#endif /* CONFIG_PM */
+int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan, int duration)
+{
+ struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
+ struct mt7615_dev *dev = phy->dev;
+ struct mt7615_roc_tlv req = {
+ .bss_idx = mvif->idx,
+ .active = !chan,
+ .max_interval = cpu_to_le32(duration),
+ .primary_chan = chan ? chan->hw_value : 0,
+ .band = chan ? chan->band : 0,
+ .req_type = 2,
+ };
+
+ phy->roc_grant = false;
+
+ return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req,
+ sizeof(req), false);
+}
+
int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
index 348521b0d44c..2314d0b23af1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h
@@ -82,6 +82,7 @@ enum {
MCU_EVENT_ACCESS_REG = 0x02,
MCU_EVENT_MT_PATCH_SEM = 0x04,
MCU_EVENT_SCAN_DONE = 0x0d,
+ MCU_EVENT_ROC = 0x10,
MCU_EVENT_BSS_ABSENCE = 0x11,
MCU_EVENT_BSS_BEACON_LOSS = 0x13,
MCU_EVENT_CH_PRIVILEGE = 0x18,
@@ -326,7 +327,8 @@ struct mt7615_hw_scan_req {
*/
u8 ssid_type; /* BIT(0) wildcard SSID
* BIT(1) P2P wildcard SSID
- * BIT(2) specified SSID
+ * BIT(2) specified SSID + wildcard SSID
+ * BIT(2) + ssid_type_ext BIT(0) specified SSID only
*/
u8 ssids_num;
u8 probe_req_num; /* Number of probe request for each SSID */
@@ -361,7 +363,8 @@ struct mt7615_hw_scan_req {
struct mt7615_mcu_scan_ssid ext_ssids[6];
u8 bssid[ETH_ALEN];
u8 random_mac[ETH_ALEN]; /* valid when BIT(1) in scan_func is set. */
- u8 pad[64];
+ u8 pad[63];
+ u8 ssid_type_ext;
} __packed;
#define SCAN_DONE_EVENT_MAX_CHANNEL_NUM 64
@@ -525,6 +528,23 @@ struct mt7615_gtk_rekey_tlv {
u8 reserverd[3];
} __packed;
+struct mt7615_roc_tlv {
+ u8 bss_idx;
+ u8 token;
+ u8 active;
+ u8 primary_chan;
+ u8 sco;
+ u8 band;
+ u8 width; /* To support 80/160MHz bandwidth */
+ u8 freq_seg1; /* To support 80/160MHz bandwidth */
+ u8 freq_seg2; /* To support 80/160MHz bandwidth */
+ u8 req_type;
+ u8 dbdc_band;
+ u8 rsv0;
+ __le32 max_interval; /* ms */
+ u8 rsv1[8];
+} __packed;
+
/* offload mcu commands */
enum {
MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03,
@@ -533,6 +553,7 @@ enum {
MCU_CMD_SET_BSS_CONNECTED = MCU_CE_PREFIX | 0x16,
MCU_CMD_SET_BSS_ABORT = MCU_CE_PREFIX | 0x17,
MCU_CMD_CANCEL_HW_SCAN = MCU_CE_PREFIX | 0x1b,
+ MCU_CMD_SET_ROC = MCU_CE_PREFIX | 0x1c,
MCU_CMD_SET_P2P_OPPPS = MCU_CE_PREFIX | 0x33,
MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61,
MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
index ebdfca64b079..d6176d316bee 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
@@ -201,7 +201,10 @@ struct mt7615_phy {
struct sk_buff_head scan_event_list;
struct delayed_work scan_work;
- struct work_struct ps_work;
+ struct work_struct roc_work;
+ struct timer_list roc_timer;
+ wait_queue_head_t roc_wait;
+ bool roc_grant;
};
#define mt7615_mcu_add_tx_ba(dev, ...) (dev)->mcu_ops->add_tx_ba((dev), __VA_ARGS__)
@@ -411,7 +414,7 @@ static inline bool is_mt7622(struct mt76_dev *dev)
static inline bool is_mt7615(struct mt76_dev *dev)
{
- return mt76_chip(dev) == 0x7615;
+ return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611;
}
static inline bool is_mt7663(struct mt76_dev *dev)
@@ -419,6 +422,11 @@ static inline bool is_mt7663(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7663;
}
+static inline bool is_mt7611(struct mt76_dev *dev)
+{
+ return mt76_chip(dev) == 0x7611;
+}
+
static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask)
{
mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
@@ -441,7 +449,8 @@ static inline u16 mt7615_wtbl_size(struct mt7615_dev *dev)
void mt7615_dma_reset(struct mt7615_dev *dev);
void mt7615_scan_work(struct work_struct *work);
-void mt7615_ps_work(struct work_struct *work);
+void mt7615_roc_work(struct work_struct *work);
+void mt7615_roc_timer(struct timer_list *timer);
void mt7615_init_txpower(struct mt7615_dev *dev,
struct ieee80211_supported_band *sband);
void mt7615_phy_init(struct mt7615_dev *dev);
@@ -527,11 +536,13 @@ int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index,
int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable);
int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy);
int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy);
-void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif);
+int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif);
int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy);
int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
+int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan, int duration);
int mt7615_firmware_own(struct mt7615_dev *dev);
int mt7615_driver_own(struct mt7615_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c
index 88ff14564521..ba12f199bce0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c
@@ -14,6 +14,7 @@
static const struct pci_device_id mt7615_pci_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7615) },
{ PCI_DEVICE(0x14c3, 0x7663) },
+ { PCI_DEVICE(0x14c3, 0x7611) },
{ },
};
@@ -85,8 +86,9 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
napi_disable(&mdev->tx_napi);
tasklet_kill(&mdev->tx_tasklet);
- for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++)
+ mt76_for_each_q_rx(mdev, i) {
napi_disable(&mdev->napi[i]);
+ }
tasklet_kill(&dev->irq_tasklet);
mt7615_dma_reset(dev);
@@ -119,8 +121,9 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
restore:
- for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++)
+ mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
+ }
napi_enable(&mdev->tx_napi);
if (hif_suspend)
mt7615_mcu_set_hif_suspend(dev, false);
@@ -155,7 +158,7 @@ static int mt7615_pci_resume(struct pci_dev *pdev)
if (pdma_reset)
dev_err(mdev->dev, "PDMA engine must be reinitialized\n");
- for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) {
+ mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c
index d74253319622..a50077eb24d7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c
@@ -51,7 +51,8 @@ static void mt7663u_stop(struct ieee80211_hw *hw)
struct mt7615_dev *dev = hw->priv;
clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
- cancel_work_sync(&phy->ps_work);
+ del_timer_sync(&phy->roc_timer);
+ cancel_work_sync(&phy->roc_work);
cancel_delayed_work_sync(&phy->scan_work);
cancel_delayed_work_sync(&phy->mac_work);
mt76u_stop_tx(&dev->mt76);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index 6ea210bd3f07..4c9bbc7ce023 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -15,6 +15,7 @@
#include "mt76x02_dfs.h"
#include "mt76x02_dma.h"
+#define MT76x02_N_WCIDS 128
#define MT_CALIBRATE_INTERVAL HZ
#define MT_MAC_WORK_INTERVAL (HZ / 10)
@@ -246,7 +247,7 @@ mt76x02_rx_get_sta(struct mt76_dev *dev, u8 idx)
{
struct mt76_wcid *wcid;
- if (idx >= ARRAY_SIZE(dev->wcid))
+ if (idx >= MT76x02_N_WCIDS)
return NULL;
wcid = rcu_dereference(dev->wcid[idx]);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index a5a3bcd30d6f..e4e03beabe43 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -561,7 +561,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
rcu_read_lock();
- if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid))
+ if (stat->wcid < MT76x02_N_WCIDS)
wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]);
if (wcid && wcid->sta) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
index 89a8992d84fa..267058086a90 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c
@@ -20,7 +20,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
int ret;
u8 seq;
- if (mt76_is_mmio(&dev->mt76) && dev->mcu_timeout)
+ if (dev->mcu_timeout)
return -EIO;
skb = mt76_mcu_msg_alloc(mdev, data, len);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index 7e389dbccfeb..cbbe986655fe 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -415,7 +415,7 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev)
ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL);
rcu_read_unlock();
- for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid); i++) {
+ for (i = 0; i < MT76x02_N_WCIDS; i++) {
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
struct mt76x02_sta *msta;
@@ -489,8 +489,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, i, true);
- for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++)
+ mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i);
+ }
mt76x02_mac_start(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 9a2c9afa2fb5..44822a849eb1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -249,7 +249,7 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
memset(msta, 0, sizeof(*msta));
- idx = mt76_wcid_alloc(dev->mt76.wcid_mask, ARRAY_SIZE(dev->mt76.wcid));
+ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT76x02_N_WCIDS);
if (idx < 0)
return -ENOSPC;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
index ee0066fedd04..5278bee812f1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
@@ -173,14 +173,14 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
/* Tx Beamformee Rx NDPA & Tx feedback report */
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));
- seq_printf(s, "Tx Beamformee sucessful feedback frames: %ld\n",
+ seq_printf(s, "Tx Beamformee successful feedback frames: %ld\n",
FIELD_GET(MT_ETBF_TX_FB_CPL, cnt));
- seq_printf(s, "Tx Beamformee feedback triggerd counts: %ld\n",
+ seq_printf(s, "Tx Beamformee feedback triggered counts: %ld\n",
FIELD_GET(MT_ETBF_TX_FB_TRI, cnt));
/* Tx SU counters */
cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy));
- seq_printf(s, "Tx single-user sucessful MPDU counts: %d\n", cnt);
+ seq_printf(s, "Tx single-user successful MPDU counts: %d\n", cnt);
seq_puts(s, "\n");
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 6f200ab3ac28..aadf56e80bae 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -592,7 +592,6 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev)
if (phy)
return 0;
- INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work);
mt7915_cap_dbdc_enable(dev);
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops);
if (!mphy)
@@ -605,6 +604,8 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev)
mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1;
mt7915_init_wiphy(mphy->hw);
+ INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work);
+
/*
* Make the secondary PHY MAC address local without overlapping with
* the usual MAC address allocation scheme on multiple virtual interfaces
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index 7ad7c2b7afdc..a264e304a3df 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -235,9 +235,14 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
.data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
HE_BITS(DATA1_DATA_DCM_KNOWN) |
HE_BITS(DATA1_STBC_KNOWN) |
- HE_BITS(DATA1_CODING_KNOWN),
+ HE_BITS(DATA1_CODING_KNOWN) |
+ HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
+ HE_BITS(DATA1_DOPPLER_KNOWN) |
+ HE_BITS(DATA1_BSS_COLOR_KNOWN),
.data2 = HE_BITS(DATA2_GI_KNOWN) |
- HE_BITS(DATA2_TXBF_KNOWN),
+ HE_BITS(DATA2_TXBF_KNOWN) |
+ HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
+ HE_BITS(DATA2_TXOP_KNOWN),
};
struct ieee80211_radiotap_he *he = NULL;
__le32 v2 = rxv->v[2];
@@ -248,12 +253,6 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
he = skb_push(skb, sizeof(known));
memcpy(he, &known, sizeof(known));
- he->data1 = HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
- HE_BITS(DATA1_DOPPLER_KNOWN) |
- HE_BITS(DATA1_BSS_COLOR_KNOWN);
- he->data2 = HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
- HE_BITS(DATA2_TXOP_KNOWN);
-
he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, v14) |
HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, v2);
he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, v2) |
@@ -296,10 +295,10 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
- he->data4 = HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, v11) |
- HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, v11) |
- HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, v11) |
- HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, v11);
+ he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, v11) |
+ HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, v11) |
+ HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, v11) |
+ HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, v11);
mt7915_mac_decode_he_radiotap_ru(status, rxv, he);
break;
@@ -426,20 +425,26 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
/* RXD Group 3 - P-RXV */
if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
+ u32 v0, v1, v2;
+
memcpy(rxv.v, rxd, sizeof(rxv.v));
rxd += 2;
if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL;
- if (rxv.v[0] & MT_PRXV_HT_AD_CODE)
+ v0 = le32_to_cpu(rxv.v[0]);
+ v1 = le32_to_cpu(rxv.v[1]);
+ v2 = le32_to_cpu(rxv.v[2]);
+
+ if (v0 & MT_PRXV_HT_AD_CODE)
status->enc_flags |= RX_ENC_FLAG_LDPC;
status->chains = mphy->antenna_mask;
- status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, rxv.v[1]);
- status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, rxv.v[1]);
- status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, rxv.v[1]);
- status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, rxv.v[1]);
+ status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v1);
+ status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1);
+ status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1);
+ status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1);
status->signal = status->chain_signal[0];
for (i = 1; i < hweight8(mphy->antenna_mask); i++) {
@@ -452,16 +457,16 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
/* RXD Group 5 - C-RXV */
if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
- u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, rxv.v[2]);
- u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, rxv.v[2]);
+ u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, v2);
+ u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2);
bool cck = false;
rxd += 18;
if ((u8 *)rxd - skb->data >= skb->len)
return -EINVAL;
- idx = i = FIELD_GET(MT_PRXV_TX_RATE, rxv.v[0]);
- rxv.phy = FIELD_GET(MT_CRXV_TX_MODE, rxv.v[2]);
+ idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
+ rxv.phy = FIELD_GET(MT_CRXV_TX_MODE, v2);
switch (rxv.phy) {
case MT_PHY_TYPE_CCK:
@@ -478,7 +483,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
break;
case MT_PHY_TYPE_VHT:
status->nss =
- FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1;
+ FIELD_GET(MT_PRXV_NSTS, v0) + 1;
status->encoding = RX_ENC_VHT;
if (i > 9)
return -EINVAL;
@@ -490,7 +495,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
case MT_PHY_TYPE_HE_EXT_SU:
case MT_PHY_TYPE_HE_TB:
status->nss =
- FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1;
+ FIELD_GET(MT_PRXV_NSTS, v0) + 1;
status->encoding = RX_ENC_HE;
status->flag |= RX_FLAG_RADIOTAP_HE;
i &= GENMASK(3, 0);
@@ -506,7 +511,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
}
status->rate_idx = i;
- switch (FIELD_GET(MT_CRXV_FRAME_MODE, rxv.v[2])) {
+ switch (FIELD_GET(MT_CRXV_FRAME_MODE, v2)) {
case IEEE80211_STA_RX_BW_20:
break;
case IEEE80211_STA_RX_BW_40:
@@ -612,7 +617,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
skb->priority & IEEE80211_QOS_CTL_TID_MASK) |
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
- val |= cpu_to_le32(MT_TXD1_TGID);
+ val |= MT_TXD1_TGID;
txwi[1] = cpu_to_le32(val);
@@ -1141,8 +1146,9 @@ mt7915_dma_reset(struct mt7915_dev *dev)
for (i = 0; i < __MT_TXQ_MAX; i++)
mt76_queue_tx_cleanup(dev, i, true);
- for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++)
+ mt76_for_each_q_rx(&dev->mt76, i) {
mt76_queue_rx_reset(dev, i);
+ }
/* re-init prefetch settings after reset */
mt7915_dma_prefetch(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 98567374c2c9..0575c259f245 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -437,8 +437,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
mt7915_mcu_add_sta(dev, vif, NULL, join);
}
- if (changed & BSS_CHANGED_ASSOC)
+ if (changed & BSS_CHANGED_ASSOC) {
mt7915_mcu_add_bss_info(phy, vif, info->assoc);
+ mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
+ }
if (changed & BSS_CHANGED_ERP_SLOT) {
int slottime = info->use_short_slot ? 9 : 20;
@@ -458,6 +460,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
mt7915_mcu_set_tx(dev, vif);
+ if (changed & BSS_CHANGED_HE_OBSS_PD)
+ mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
+
if (changed & (BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED))
mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
@@ -790,7 +795,7 @@ mt7915_sta_rc_update(struct ieee80211_hw *hw,
rcu_read_unlock();
return;
}
- rcu_read_lock();
+ rcu_read_unlock();
set_bit(changed, &msta->stats.changed);
ieee80211_queue_work(hw, &msta->stats_work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 99eeea42478f..c8c12c740c1a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -220,7 +220,7 @@ static int __mt7915_mcu_msg_send(struct mt7915_dev *dev, struct sk_buff *skb,
{
struct mt7915_mcu_txd *mcu_txd;
u8 seq, pkt_fmt, qidx;
- enum mt7915_txq_id txq;
+ enum mt76_txq_id txq;
__le32 *txd;
u32 val;
@@ -815,8 +815,7 @@ static void mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
struct mt7915_he_obss_narrow_bw_ru_data *data = _data;
const struct element *elem;
- elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, bss->ies->data,
- bss->ies->len);
+ elem = ieee80211_bss_get_elem(bss, WLAN_EID_EXT_CAPABILITY);
if (!elem || elem->datalen < 10 ||
!(elem->data[10] &
@@ -1802,15 +1801,12 @@ static u8
mt7915_mcu_sta_txbf_type(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct mt7915_sta *msta;
u8 type = 0;
if (vif->type != NL80211_IFTYPE_STATION &&
vif->type != NL80211_IFTYPE_AP)
return 0;
- msta = (struct mt7915_sta *)sta->drv_priv;
-
if (sta->he_cap.has_he) {
struct ieee80211_he_cap_elem *pe;
const struct ieee80211_he_cap_elem *ve;
@@ -1954,7 +1950,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
ra->supp_mode |= MODE_HT;
- mcs = hweight32(ra->supp_ht_mcs) - 1;
+ mcs = hweight32(le32_to_cpu(ra->supp_ht_mcs)) - 1;
ra->af = sta->ht_cap.ampdu_factor;
ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
@@ -1972,7 +1968,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
}
if (sta->vht_cap.vht_supported) {
- __le16 mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map;
+ u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map);
u16 vht_mcs;
u8 af, mcs_prev;
@@ -2399,7 +2395,7 @@ static int mt7915_mcu_init_download(struct mt7915_dev *dev, u32 addr,
};
int attr;
- if (req.addr == MCU_PATCH_ADDRESS)
+ if (req.addr == cpu_to_le32(MCU_PATCH_ADDRESS))
attr = -MCU_CMD_PATCH_START_REQ;
else
attr = -MCU_CMD_TARGET_ADDRESS_LEN_REQ;
@@ -2672,7 +2668,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level)
u16 len;
u8 level;
u8 rsv[3];
- u32 module_idx;
+ __le32 module_idx;
} data = {
.module_idx = cpu_to_le32(module),
.level = level,
@@ -3159,3 +3155,28 @@ int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev)
return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION,
&req, sizeof(req), true);
}
+
+int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+ bool enable)
+{
+#define MT_SPR_ENABLE 1
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+ struct {
+ u8 action;
+ u8 arg_num;
+ u8 band_idx;
+ u8 status;
+ u8 drop_tx_idx;
+ u8 sta_idx; /* 256 sta */
+ u8 rsv[2];
+ u32 val;
+ } __packed req = {
+ .action = MT_SPR_ENABLE,
+ .arg_num = 1,
+ .band_idx = mvif->band_idx,
+ .val = enable,
+ };
+
+ return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR,
+ &req, sizeof(req), true);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 34ace6e672d0..c241dd7c4c36 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -212,6 +212,7 @@ enum {
MCU_EXT_CMD_RATE_CTRL = 0x87,
MCU_EXT_CMD_FW_DBG_CTRL = 0x95,
MCU_EXT_CMD_SET_RDD_TH = 0x9d,
+ MCU_EXT_CMD_SET_SPR = 0xa8,
};
enum {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index 5392292a838e..85d74ecd0351 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -301,6 +301,8 @@ int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif,
enum set_key_cmd cmd);
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int enable);
+int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
+ bool enable);
int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c
index 07cf71242d9e..ecde87465bf6 100644
--- a/drivers/net/wireless/mediatek/mt76/util.c
+++ b/drivers/net/wireless/mediatek/mt76/util.c
@@ -42,17 +42,17 @@ bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
}
EXPORT_SYMBOL_GPL(__mt76_poll_msec);
-int mt76_wcid_alloc(unsigned long *mask, int size)
+int mt76_wcid_alloc(u32 *mask, int size)
{
int i, idx = 0, cur;
- for (i = 0; i < DIV_ROUND_UP(size, BITS_PER_LONG); i++) {
+ for (i = 0; i < DIV_ROUND_UP(size, 32); i++) {
idx = ffs(~mask[i]);
if (!idx)
continue;
idx--;
- cur = i * BITS_PER_LONG + idx;
+ cur = i * 32 + idx;
if (cur >= size)
break;
@@ -74,13 +74,13 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy)
rcu_read_lock();
for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
- unsigned long mask = dev->wcid_mask[i];
- unsigned long phy_mask = dev->wcid_phy_mask[i];
+ u32 mask = dev->wcid_mask[i];
+ u32 phy_mask = dev->wcid_phy_mask[i];
if (!mask)
continue;
- for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1, phy_mask >>= 1) {
+ for (j = i * 32; mask; j++, mask >>= 1, phy_mask >>= 1) {
if (!(mask & 1))
continue;
diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h
index 48a71e7479e5..fd1a68820e0a 100644
--- a/drivers/net/wireless/mediatek/mt76/util.h
+++ b/drivers/net/wireless/mediatek/mt76/util.h
@@ -14,24 +14,24 @@
#define MT76_INCR(_var, _size) \
(_var = (((_var) + 1) % (_size)))
-int mt76_wcid_alloc(unsigned long *mask, int size);
+int mt76_wcid_alloc(u32 *mask, int size);
static inline bool
-mt76_wcid_mask_test(unsigned long *mask, int idx)
+mt76_wcid_mask_test(u32 *mask, int idx)
{
- return mask[idx / BITS_PER_LONG] & BIT(idx % BITS_PER_LONG);
+ return mask[idx / 32] & BIT(idx % 32);
}
static inline void
-mt76_wcid_mask_set(unsigned long *mask, int idx)
+mt76_wcid_mask_set(u32 *mask, int idx)
{
- mask[idx / BITS_PER_LONG] |= BIT(idx % BITS_PER_LONG);
+ mask[idx / 32] |= BIT(idx % 32);
}
static inline void
-mt76_wcid_mask_clear(unsigned long *mask, int idx)
+mt76_wcid_mask_clear(u32 *mask, int idx)
{
- mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG);
+ mask[idx / 32] &= ~BIT(idx % 32);
}
static inline void
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 6beac1f74e7c..a779fe771a55 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -9971,9 +9971,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
if (!rt2x00_is_usb(rt2x00dev))
ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
- /* Set MFP if HW crypto is disabled. */
- if (rt2800_hwcrypt_disabled(rt2x00dev))
- ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE);
+ ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE);
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
index 32efbc8e9f92..2f68a31072ae 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
@@ -468,7 +468,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
- if (!rt2x00_has_cap_hw_crypto(rt2x00dev))
+ /* The hardware can't do MFP */
+ if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || (sta && sta->mfp))
return -EOPNOTSUPP;
/*
diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c
index 924dccd5d146..cbf3d503df1c 100644
--- a/drivers/net/wireless/realtek/rtw88/coex.c
+++ b/drivers/net/wireless/realtek/rtw88/coex.c
@@ -751,10 +751,18 @@ EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
{
- if (wifi_control)
+ struct rtw_chip_info *chip = rtwdev->chip;
+ const struct rtw_hw_reg *btg_reg = chip->btg_reg;
+
+ if (wifi_control) {
rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
- else
+ if (btg_reg)
+ rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
+ } else {
rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
+ if (btg_reg)
+ rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
+ }
}
static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
@@ -1346,12 +1354,15 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
tdma_case = 108;
else
tdma_case = 109;
+ } else if (coex_stat->wl_gl_busy) {
+ table_case = 114;
+ tdma_case = 121;
} else if (coex_stat->wl_connected) {
- table_case = 101;
- tdma_case = 110;
- } else {
table_case = 100;
tdma_case = 100;
+ } else {
+ table_case = 101;
+ tdma_case = 100;
}
}
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 98d2ac22f6f6..c412bc54efde 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -341,13 +341,11 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw_leave_lps_deep(rtwdev);
if (changed & BSS_CHANGED_ASSOC) {
- struct rtw_chip_info *chip = rtwdev->chip;
enum rtw_net_type net_type;
if (conf->assoc) {
rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH);
net_type = RTW_NET_MGD_LINKED;
- chip->ops->phy_calibration(rtwdev);
rtwvif->aid = conf->aid;
rtw_fw_download_rsvd_page(rtwdev);
@@ -663,6 +661,7 @@ static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw,
mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev);
rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START);
+ rtw_chip_prepare_tx(rtwdev);
mutex_unlock(&rtwdev->mutex);
}
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index f88a7d2370aa..0eefafc51c62 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -408,6 +408,23 @@ void rtw_set_channel(struct rtw_dev *rtwdev)
}
rtw_phy_set_tx_power_level(rtwdev, center_chan);
+
+ /* if the channel isn't set for scanning, we will do RF calibration
+ * in ieee80211_ops::mgd_prepare_tx(). Performing the calibration
+ * during scanning on each channel takes too long.
+ */
+ if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
+ rtwdev->need_rfk = true;
+}
+
+void rtw_chip_prepare_tx(struct rtw_dev *rtwdev)
+{
+ struct rtw_chip_info *chip = rtwdev->chip;
+
+ if (rtwdev->need_rfk) {
+ rtwdev->need_rfk = false;
+ chip->ops->phy_calibration(rtwdev);
+ }
}
static void rtw_vif_write_addr(struct rtw_dev *rtwdev, u32 start, u8 *addr)
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 7ee09c008cd4..0841f5fa4bf2 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -1174,6 +1174,7 @@ struct rtw_chip_info {
const struct coex_rf_para *wl_rf_para_tx;
const struct coex_rf_para *wl_rf_para_rx;
const struct coex_5g_afh_map *afh_5g;
+ const struct rtw_hw_reg *btg_reg;
const struct rtw_reg_domain *coex_info_hw_regs;
};
@@ -1719,6 +1720,8 @@ struct rtw_dev {
struct rtw_fw_state wow_fw;
struct rtw_wow_param wow;
+ bool need_rfk;
+
/* hci related data, must be last */
u8 priv[] __aligned(sizeof(void *));
};
@@ -1792,6 +1795,7 @@ void rtw_restore_reg(struct rtw_dev *rtwdev,
struct rtw_backup_info *bckp, u32 num);
void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss);
void rtw_set_channel(struct rtw_dev *rtwdev);
+void rtw_chip_prepare_tx(struct rtw_dev *rtwdev);
void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
u32 config);
void rtw_tx_report_purge_timer(struct timer_list *t);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 8641ea645c4b..4700195c8eef 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -2040,7 +2040,7 @@ static const struct coex_tdma_para tdma_sant_8723d[] = {
/* Non-Shared-Antenna TDMA */
static const struct coex_tdma_para tdma_nsant_8723d[] = {
- { {0x00, 0x00, 0x00, 0x40, 0x00} }, /* case-100 */
+ { {0x00, 0x00, 0x00, 0x40, 0x01} }, /* case-100 */
{ {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-101 */
{ {0x61, 0x3a, 0x03, 0x11, 0x11} },
{ {0x61, 0x30, 0x03, 0x11, 0x11} },
@@ -2060,7 +2060,8 @@ static const struct coex_tdma_para tdma_nsant_8723d[] = {
{ {0x51, 0x3a, 0x03, 0x10, 0x50} },
{ {0x51, 0x30, 0x03, 0x10, 0x50} },
{ {0x51, 0x20, 0x03, 0x10, 0x50} },
- { {0x51, 0x10, 0x03, 0x10, 0x50} }
+ { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-120 */
+ { {0x51, 0x08, 0x03, 0x10, 0x50} },
};
/* rssi in percentage % (dbm = % - 100) */
@@ -2068,6 +2069,10 @@ static const u8 wl_rssi_step_8723d[] = {60, 50, 44, 30};
static const u8 bt_rssi_step_8723d[] = {30, 30, 30, 30};
static const struct coex_5g_afh_map afh_5g_8723d[] = { {0, 0, 0} };
+static const struct rtw_hw_reg btg_reg_8723d = {
+ .addr = REG_BTG_SEL, .mask = BIT_MASK_BTG_WL,
+};
+
/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */
static const struct coex_rf_para rf_para_tx_8723d[] = {
{0, 0, false, 7}, /* for normal */
@@ -2093,6 +2098,16 @@ static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8723d[] = {
RTW_PWR_INTF_ALL_MSK,
RTW_PWR_ADDR_MAC,
RTW_PWR_CMD_WRITE, BIT(3) | BIT(7), 0},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
{0x004A,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_USB_MSK,
@@ -2103,6 +2118,11 @@ static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8723d[] = {
RTW_PWR_INTF_ALL_MSK,
RTW_PWR_ADDR_MAC,
RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), 0},
+ {0x0023,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4), 0},
{0x0301,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_PCI_MSK,
@@ -2310,6 +2330,11 @@ static const struct rtw_pwr_seq_cmd trans_act_to_lps_8723d[] = {
RTW_PWR_INTF_ALL_MSK,
RTW_PWR_ADDR_MAC,
RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0093,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x00},
{0x0553,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
@@ -2389,6 +2414,11 @@ static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8723d[] = {
};
static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8723d[] = {
+ {0x0007,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x20},
{0x0005,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
@@ -2409,6 +2439,21 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8723d[] = {
RTW_PWR_INTF_USB_MSK,
RTW_PWR_ADDR_MAC,
RTW_PWR_CMD_WRITE, BIT(0), 1},
+ {0x0023,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4), BIT(4)},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_POLLING, BIT(1), 0},
{0xFFFF,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
@@ -2694,6 +2739,7 @@ struct rtw_chip_info rtw8723d_hw_spec = {
.bt_afh_span_bw40 = 0x30,
.afh_5g_num = ARRAY_SIZE(afh_5g_8723d),
.afh_5g = afh_5g_8723d,
+ .btg_reg = &btg_reg_8723d,
.coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8723d),
.coex_info_hw_regs = coex_info_hw_regs_8723d,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index 31b8ed9ee652..7894d321cd7e 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -145,6 +145,7 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
#define REG_GPIO_INTM 0x0048
#define REG_BTG_SEL 0x0067
+#define BIT_MASK_BTG_WL BIT(7)
#define REG_LTECOEX_PATH_CONTROL 0x0070
#define REG_LTECOEX_CTRL 0x07c0
#define REG_LTECOEX_WRITE_DATA 0x07c4
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
index 6abcdf4070a2..e49bdd76ab9a 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -1551,6 +1551,16 @@ static void rtw8822b_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif,
}
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = {
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
{0x004A,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_USB_MSK,
@@ -1679,6 +1689,11 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = {
RTW_PWR_INTF_ALL_MSK,
RTW_PWR_ADDR_MAC,
RTW_PWR_CMD_WRITE, 0xFF, 0x0c},
+ {0x0068,
+ RTW_PWR_CUT_C_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4), BIT(4)},
{0x0029,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
@@ -1707,6 +1722,11 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = {
};
static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = {
+ {0x0003,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(2), 0},
{0x0093,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
@@ -1775,6 +1795,11 @@ static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = {
};
static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = {
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(7), BIT(7)},
{0x0007,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
@@ -1795,6 +1820,46 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = {
RTW_PWR_INTF_USB_MSK,
RTW_PWR_ADDR_MAC,
RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0067,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(5), 0},
+ {0x0067,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4), 0},
+ {0x004F,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0067,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0046,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(6), BIT(6)},
+ {0x0067,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(2), 0},
+ {0x0046,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(7), BIT(7)},
+ {0x0062,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4), BIT(4)},
{0x0081,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
@@ -1805,11 +1870,41 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = {
RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
RTW_PWR_ADDR_MAC,
RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_POLLING, BIT(1), 0},
{0x0090,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_PCI_MSK,
RTW_PWR_ADDR_MAC,
RTW_PWR_CMD_WRITE, BIT(1), 0},
+ {0x0044,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, 0xFF, 0},
+ {0x0040,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x90},
+ {0x0041,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x00},
+ {0x0042,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, 0xFF, 0x04},
{0xFFFF,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
index fe995bb4e43e..c3d72ef611c6 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -1037,7 +1037,7 @@ static void rtw8822c_set_power_trim(struct rtw_dev *rtwdev, s8 bb_gain[2][8])
static void rtw8822c_power_trim(struct rtw_dev *rtwdev)
{
u8 pg_pwr = 0xff, i, path, idx;
- s8 bb_gain[2][8] = {0};
+ s8 bb_gain[2][8] = {};
u16 rf_efuse_2g[3] = {PPG_2GL_TXAB, PPG_2GM_TXAB, PPG_2GH_TXAB};
u16 rf_efuse_5g[2][5] = {{PPG_5GL1_TXA, PPG_5GL2_TXA, PPG_5GM1_TXA,
PPG_5GM2_TXA, PPG_5GH1_TXA},
@@ -1496,7 +1496,6 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
{
if (IS_CH_2G_BAND(channel)) {
rtw_write32_clr(rtwdev, REG_BGCTRL, BITS_RX_IQ_WEIGHT);
- rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x8);
rtw_write32_set(rtwdev, REG_TXF4, BIT(20));
rtw_write32_clr(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN);
rtw_write32_clr(rtwdev, REG_CCKTXONLY, BIT_BB_CCK_CHECK_EN);
@@ -1564,7 +1563,6 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw_write32_set(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN);
rtw_write32_set(rtwdev, REG_BGCTRL, BITS_RX_IQ_WEIGHT);
rtw_write32_clr(rtwdev, REG_TXF4, BIT(20));
- rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x0);
rtw_write32_mask(rtwdev, REG_CCAMSK, 0x3F000000, 0x22);
rtw_write32_mask(rtwdev, REG_TXDFIR0, 0x70, 0x3);
if (IS_CH_5G_BAND_1(channel) || IS_CH_5G_BAND_2(channel)) {
@@ -3563,6 +3561,16 @@ static void rtw8822c_pwr_track(struct rtw_dev *rtwdev)
}
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = {
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
{0x002E,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
@@ -3773,6 +3781,11 @@ static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822c[] = {
};
static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = {
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(7), BIT(7)},
{0x0007,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
@@ -3818,6 +3831,11 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = {
RTW_PWR_INTF_PCI_MSK,
RTW_PWR_ADDR_MAC,
RTW_PWR_CMD_WRITE, BIT(2), BIT(2)},
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
{0xFFFF,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
diff --git a/drivers/net/wireless/st/cw1200/cw1200_sdio.c b/drivers/net/wireless/st/cw1200/cw1200_sdio.c
index 43e012073dbf..b65ec14136c7 100644
--- a/drivers/net/wireless/st/cw1200/cw1200_sdio.c
+++ b/drivers/net/wireless/st/cw1200/cw1200_sdio.c
@@ -14,6 +14,7 @@
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/card.h>
#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_ids.h>
#include <net/mac80211.h>
#include "cw1200.h"
@@ -48,14 +49,6 @@ struct hwbus_priv {
const struct cw1200_platform_data_sdio *pdata;
};
-#ifndef SDIO_VENDOR_ID_STE
-#define SDIO_VENDOR_ID_STE 0x0020
-#endif
-
-#ifndef SDIO_DEVICE_ID_STE_CW1200
-#define SDIO_DEVICE_ID_STE_CW1200 0x2280
-#endif
-
static const struct sdio_device_id cw1200_sdio_ids[] = {
{ SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) },
{ /* end: all zeroes */ },
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 4421fc656b1c..de6c8a7589ca 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -548,7 +548,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
ret = wlcore_fw_status(wl, wl->fw_status);
if (ret < 0)
- goto out;
+ goto err_ret;
wlcore_hw_tx_immediate_compl(wl);
@@ -565,7 +565,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
ret = -EIO;
/* restarting the chip. ignore any other interrupt. */
- goto out;
+ goto err_ret;
}
if (unlikely(intr & WL1271_ACX_SW_INTR_WATCHDOG)) {
@@ -575,7 +575,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
ret = -EIO;
/* restarting the chip. ignore any other interrupt. */
- goto out;
+ goto err_ret;
}
if (likely(intr & WL1271_ACX_INTR_DATA)) {
@@ -583,7 +583,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
ret = wlcore_rx(wl, wl->fw_status);
if (ret < 0)
- goto out;
+ goto err_ret;
/* Check if any tx blocks were freed */
spin_lock_irqsave(&wl->wl_lock, flags);
@@ -596,7 +596,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
*/
ret = wlcore_tx_work_locked(wl);
if (ret < 0)
- goto out;
+ goto err_ret;
} else {
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
@@ -604,7 +604,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
/* check for tx results */
ret = wlcore_hw_tx_delayed_compl(wl);
if (ret < 0)
- goto out;
+ goto err_ret;
/* Make sure the deferred queues don't get too long */
defer_count = skb_queue_len(&wl->deferred_tx_queue) +
@@ -617,14 +617,14 @@ static int wlcore_irq_locked(struct wl1271 *wl)
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
ret = wl1271_event_handle(wl, 0);
if (ret < 0)
- goto out;
+ goto err_ret;
}
if (intr & WL1271_ACX_INTR_EVENT_B) {
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
ret = wl1271_event_handle(wl, 1);
if (ret < 0)
- goto out;
+ goto err_ret;
}
if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
@@ -635,6 +635,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
}
+err_ret:
pm_runtime_mark_last_busy(wl->dev);
pm_runtime_put_autosuspend(wl->dev);
@@ -1746,9 +1747,7 @@ static int __maybe_unused wl1271_op_suspend(struct ieee80211_hw *hw,
ret = wl1271_configure_suspend(wl, wlvif, wow);
if (ret < 0) {
- mutex_unlock(&wl->mutex);
- wl1271_warning("couldn't prepare device to suspend");
- return ret;
+ goto out_sleep;
}
}
@@ -2698,12 +2697,16 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
if (!wlcore_is_p2p_mgmt(wlvif)) {
ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id);
- if (ret < 0)
+ if (ret < 0) {
+ pm_runtime_put_noidle(wl->dev);
goto deinit;
+ }
} else {
ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
- if (ret < 0)
+ if (ret < 0) {
+ pm_runtime_put_noidle(wl->dev);
goto deinit;
+ }
}
pm_runtime_mark_last_busy(wl->dev);
@@ -3665,8 +3668,10 @@ void wlcore_regdomain_config(struct wl1271 *wl)
goto out;
ret = pm_runtime_get_sync(wl->dev);
- if (ret < 0)
+ if (ret < 0) {
+ pm_runtime_put_autosuspend(wl->dev);
goto out;
+ }
ret = wlcore_cmd_regdomain_config_locked(wl);
if (ret < 0) {
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 90e56d4c3df3..e20e18cd04ae 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -863,6 +863,7 @@ void wl1271_tx_work(struct work_struct *work)
ret = wlcore_tx_work_locked(wl);
if (ret < 0) {
+ pm_runtime_put_noidle(wl->dev);
wl12xx_queue_recovery_work(wl);
goto out;
}