Skip to contentSkip to conversation

wil6210 patches

PATCH In review Maya Erez 2 participants 14 messages May 13, 2018 – May 28, 2018 Wilocity WIL6210 wireless driver

lore
Share & tools
lore

Maya Erez

author
#0 lore raw

cover wil6210 patches

The following set of patches add support for new wil6210 device (Talyn ver 2.0):
- Definition of the new device ID and memory areas
- New boot flow procedure and reset sequence
- Support new DMA interface - enhanced DMA
- Support new HW offloads, such as TSO, RX reorder and AMSDU

Gidon Studinski (3):
wil6210: add support for enhanced DMA structures
wil6210: initialize TX and RX enhanced DMA rings
wil6210: add support for enhanced DMA RX data flows

Maya Erez (4):
wil6210: add support for Talyn-MB (Talyn ver 2.0) device
wil6210: add support for enhanced DMA TX data flows
wil6210: add support for enhanced DMA debugfs
wil6210: add support for Talyn-MB boot flow

 drivers/net/wireless/ath/wil6210/Makefile     |    1 +
 drivers/net/wireless/ath/wil6210/cfg80211.c   |   12 +-
 drivers/net/wireless/ath/wil6210/debugfs.c    |  431 +++++--
 drivers/net/wireless/ath/wil6210/ethtool.c    |    2 +-
 drivers/net/wireless/ath/wil6210/interrupt.c  |  225 +++-
 drivers/net/wireless/ath/wil6210/main.c       |  350 ++++--
 drivers/net/wireless/ath/wil6210/netdev.c     |   73 +-
 drivers/net/wireless/ath/wil6210/pcie_bus.c   |   62 +-
 drivers/net/wireless/ath/wil6210/pm.c         |    6 +-
 drivers/net/wireless/ath/wil6210/rx_reorder.c |   20 +-
 drivers/net/wireless/ath/wil6210/trace.h      |   57 +
 drivers/net/wireless/ath/wil6210/txrx.c       |  648 +++++-----
 drivers/net/wireless/ath/wil6210/txrx.h       |  105 +-
 drivers/net/wireless/ath/wil6210/txrx_edma.c  | 1637 +++++++++++++++++++++++++
 drivers/net/wireless/ath/wil6210/txrx_edma.h  |  553 +++++++++
 drivers/net/wireless/ath/wil6210/wil6210.h    |  220 +++-
 drivers/net/wireless/ath/wil6210/wmi.c        |  458 ++++++-
 drivers/net/wireless/ath/wil6210/wmi.h        |  166 ++-
 18 files changed, 4389 insertions(+), 637 deletions(-)
 create mode 100644 drivers/net/wireless/ath/wil6210/txrx_edma.c
 create mode 100644 drivers/net/wireless/ath/wil6210/txrx_edma.h
Signature · 1 line
1.9.1
author
#1 lore raw

PATCH 1/7 wil6210: add support for Talyn-MB (Talyn ver 2.0) device

Add changes to support initialization of Talyn-MB wil6210 device:
- Add definition for Talyn-MB new JTAG id
- Define talyn_mb_fw_mapping array
- Add Talyn-MB reset sequence

---
 drivers/net/wireless/ath/wil6210/main.c     | 48 +++++++++++++++++++------
 drivers/net/wireless/ath/wil6210/pcie_bus.c | 11 +++++-
 drivers/net/wireless/ath/wil6210/wil6210.h  | 11 +++++-
 drivers/net/wireless/ath/wil6210/wmi.c      | 55 +++++++++++++++++++++++++++++
 4 files changed, 113 insertions(+), 12 deletions(-)
drivers/net/wireless/ath/wil6210/main.c +38 -10
index e7006c2..1282e1a 100644
@@ -736,14 +736,24 @@ static void wil_bl_prepare_halt(struct wil6210_priv *wil)
 
 static inline void wil_halt_cpu(struct wil6210_priv *wil)
 {
-	wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST);
-	wil_w(wil, RGF_USER_MAC_CPU_0,  BIT_USER_MAC_CPU_MAN_RST);
+	if (wil->hw_version >= HW_VER_TALYN_MB) {
+		wil_w(wil, RGF_USER_USER_CPU_0_TALYN_MB,
+		      BIT_USER_USER_CPU_MAN_RST);
+		wil_w(wil, RGF_USER_MAC_CPU_0_TALYN_MB,
+		      BIT_USER_MAC_CPU_MAN_RST);
+	} else {
+		wil_w(wil, RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST);
+		wil_w(wil, RGF_USER_MAC_CPU_0,  BIT_USER_MAC_CPU_MAN_RST);
+	}
 }
 
 static inline void wil_release_cpu(struct wil6210_priv *wil)
 {
 	/* Start CPU */
-	wil_w(wil, RGF_USER_USER_CPU_0, 1);
+	if (wil->hw_version >= HW_VER_TALYN_MB)
+		wil_w(wil, RGF_USER_USER_CPU_0_TALYN_MB, 1);
+	else
+		wil_w(wil, RGF_USER_USER_CPU_0, 1);
 }
 
 static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode)
@@ -811,10 +821,17 @@ static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
 	wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
 	wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
 
-	wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
-	wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
-	wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x000000f0);
-	wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00);
+	if (wil->hw_version >= HW_VER_TALYN_MB) {
+		wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x7e000000);
+		wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003f);
+		wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0xc00000f0);
+		wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xffe7fe00);
+	} else {
+		wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xfe000000);
+		wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003f);
+		wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x000000f0);
+		wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xffe7fe00);
+	}
 
 	wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
 	wil_w(wil, RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0);
@@ -1042,8 +1059,14 @@ static int wil_get_otp_info(struct wil6210_priv *wil)
 	struct net_device *ndev = wil->main_ndev;
 	struct wiphy *wiphy = wil_to_wiphy(wil);
 	u8 mac[8];
+	int mac_addr;
+
+	if (wil->hw_version >= HW_VER_TALYN_MB)
+		mac_addr = RGF_OTP_MAC_TALYN_MB;
+	else
+		mac_addr = RGF_OTP_MAC;
 
-	wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(RGF_OTP_MAC),
+	wil_memcpy_fromio_32(mac, wil->csr + HOSTADDR(mac_addr),
 			     sizeof(mac));
 	if (!is_valid_ether_addr(mac)) {
 		wil_err(wil, "Invalid MAC %pM\n", mac);
@@ -1147,8 +1170,13 @@ static void wil_pre_fw_config(struct wil6210_priv *wil)
 	/* it is W1C, clear by writing back same value */
 	wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0);
 	wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
-	/* clear PAL_UNIT_ICR (potential D0->D3 leftover) */
-	wil_s(wil, RGF_PAL_UNIT_ICR + offsetof(struct RGF_ICR, ICR), 0);
+	/* clear PAL_UNIT_ICR (potential D0->D3 leftover)
+	 * In Talyn-MB host cannot access this register due to
+	 * access control, hence PAL_UNIT_ICR is cleared by the FW
+	 */
+	if (wil->hw_version < HW_VER_TALYN_MB)
+		wil_s(wil, RGF_PAL_UNIT_ICR + offsetof(struct RGF_ICR, ICR),
+		      0);
 
 	if (wil->fw_calib_result > 0) {
 		__le32 val = cpu_to_le32(wil->fw_calib_result |
drivers/net/wireless/ath/wil6210/pcie_bus.c +10 -1
index 19cbc6a..3a7e406 100644
@@ -85,7 +85,7 @@ int wil_set_capabilities(struct wil6210_priv *wil)
 		wil->rgf_ucode_assert_code_addr = SPARROW_RGF_UCODE_ASSERT_CODE;
 		break;
 	case JTAG_DEV_ID_TALYN:
-		wil->hw_name = "Talyn";
+		wil->hw_name = "Talyn-MA";
 		wil->hw_version = HW_VER_TALYN;
 		memcpy(fw_mapping, talyn_fw_mapping, sizeof(talyn_fw_mapping));
 		wil->rgf_fw_assert_code_addr = TALYN_RGF_FW_ASSERT_CODE;
@@ -94,6 +94,15 @@ int wil_set_capabilities(struct wil6210_priv *wil)
 		    BIT_NO_FLASH_INDICATION)
 			set_bit(hw_capa_no_flash, wil->hw_capa);
 		break;
+	case JTAG_DEV_ID_TALYN_MB:
+		wil->hw_name = "Talyn-MB";
+		wil->hw_version = HW_VER_TALYN_MB;
+		memcpy(fw_mapping, talyn_mb_fw_mapping,
+		       sizeof(talyn_mb_fw_mapping));
+		wil->rgf_fw_assert_code_addr = TALYN_RGF_FW_ASSERT_CODE;
+		wil->rgf_ucode_assert_code_addr = TALYN_RGF_UCODE_ASSERT_CODE;
+		set_bit(hw_capa_no_flash, wil->hw_capa);
+		break;
 	default:
 		wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n",
 			jtag_id, chip_revision);
drivers/net/wireless/ath/wil6210/wil6210.h +10 -1
index b623510c..4cd8e40 100644
@@ -311,14 +311,20 @@ struct RGF_ICR {
 #define RGF_USER_JTAG_DEV_ID	(0x880b34) /* device ID */
 	#define JTAG_DEV_ID_SPARROW	(0x2632072f)
 	#define JTAG_DEV_ID_TALYN	(0x7e0e1)
+	#define JTAG_DEV_ID_TALYN_MB	(0x1007e0e1)
 
 #define RGF_USER_REVISION_ID		(0x88afe4)
 #define RGF_USER_REVISION_ID_MASK	(3)
 	#define REVISION_ID_SPARROW_B0	(0x0)
 	#define REVISION_ID_SPARROW_D0	(0x3)
 
+#define RGF_OTP_MAC_TALYN_MB		(0x8a0304)
 #define RGF_OTP_MAC			(0x8a0620)
 
+/* Talyn-MB */
+#define RGF_USER_USER_CPU_0_TALYN_MB	(0x8c0138)
+#define RGF_USER_MAC_CPU_0_TALYN_MB	(0x8c0154)
+
 /* crash codes for FW/Ucode stored here */
 
 /* ASSERT RGFs */
@@ -332,6 +338,7 @@ enum {
 	HW_VER_SPARROW_B0, /* REVISION_ID_SPARROW_B0 */
 	HW_VER_SPARROW_D0, /* REVISION_ID_SPARROW_D0 */
 	HW_VER_TALYN,	/* JTAG_DEV_ID_TALYN */
+	HW_VER_TALYN_MB	/* JTAG_DEV_ID_TALYN_MB */
 };
 
 /* popular locations */
@@ -349,7 +356,8 @@ enum {
 /* Hardware definitions end */
 #define SPARROW_FW_MAPPING_TABLE_SIZE 10
 #define TALYN_FW_MAPPING_TABLE_SIZE 13
-#define MAX_FW_MAPPING_TABLE_SIZE 13
+#define TALYN_MB_FW_MAPPING_TABLE_SIZE 19
+#define MAX_FW_MAPPING_TABLE_SIZE 19
 
 struct fw_map {
 	u32 from; /* linker address - from, inclusive */
@@ -363,6 +371,7 @@ struct fw_map {
 extern const struct fw_map sparrow_fw_mapping[SPARROW_FW_MAPPING_TABLE_SIZE];
 extern const struct fw_map sparrow_d0_mac_rgf_ext;
 extern const struct fw_map talyn_fw_mapping[TALYN_FW_MAPPING_TABLE_SIZE];
+extern const struct fw_map talyn_mb_fw_mapping[TALYN_MB_FW_MAPPING_TABLE_SIZE];
 extern struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
 
 /**
drivers/net/wireless/ath/wil6210/wmi.c +55 -0

61 lines not on this page · raw message

Signature · 1 line
1.9.1
author
#2 lore raw

PATCH 2/7 wil6210: add support for enhanced DMA structures

In reply to Maya Erez

From: Gidon Studinski <[email protected]>

In enhanced DMA the vrings are handled internally by the FW and are not exposed to the driver.
Instead, the driver handles descriptor rings, which are mapped by the FW to vrings.
The completions of the TX and RX descriptors are notified to the driver using status rings. Each status ring descriptor includes information of the completed descriptors and the ring id of their descriptor ring.

This patch changes struct vring to generic wil_ring to allow its reuse for enhanced DMA descriptor rings and adds the descriptor and status rings specific descriptors.

---
 drivers/net/wireless/ath/wil6210/cfg80211.c   |  12 +-
 drivers/net/wireless/ath/wil6210/debugfs.c    | 111 ++++----
 drivers/net/wireless/ath/wil6210/main.c       |  34 +--
 drivers/net/wireless/ath/wil6210/netdev.c     |   8 +-
 drivers/net/wireless/ath/wil6210/rx_reorder.c |   2 +-
 drivers/net/wireless/ath/wil6210/txrx.c       | 356 ++++++++++++--------------
 drivers/net/wireless/ath/wil6210/txrx.h       |  68 ++++-
 drivers/net/wireless/ath/wil6210/txrx_edma.h  | 290 +++++++++++++++++++++
 drivers/net/wireless/ath/wil6210/wil6210.h    | 110 ++++++--
 drivers/net/wireless/ath/wil6210/wmi.c        |  24 +-
 10 files changed, 696 insertions(+), 319 deletions(-)
 create mode 100644 drivers/net/wireless/ath/wil6210/txrx_edma.h
drivers/net/wireless/ath/wil6210/cfg80211.c +6 -6
index 78946f2..dfe64b0 100644
@@ -1726,7 +1726,7 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy,
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 	int authorize;
 	int cid, i;
-	struct vring_tx_data *txdata = NULL;
+	struct wil_ring_tx_data *txdata = NULL;
 
 	wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x mid %d\n",
 		     mac, params->sta_flags_mask, params->sta_flags_set,
@@ -1746,20 +1746,20 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy,
 		return -ENOLINK;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++)
-		if (wil->vring2cid_tid[i][0] == cid) {
-			txdata = &wil->vring_tx_data[i];
+	for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++)
+		if (wil->ring2cid_tid[i][0] == cid) {
+			txdata = &wil->ring_tx_data[i];
 			break;
 		}
 
 	if (!txdata) {
-		wil_err(wil, "vring data not found\n");
+		wil_err(wil, "ring data not found\n");
 		return -ENOLINK;
 	}
 
 	authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED);
 	txdata->dot1x_open = authorize ? 1 : 0;
-	wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i,
+	wil_dbg_misc(wil, "cid %d ring %d authorize %d\n", cid, i,
 		     txdata->dot1x_open);
 
 	return 0;
drivers/net/wireless/ath/wil6210/debugfs.c +56 -55

236 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/main.c +17 -17
index 1282e1a..bfe6284 100644
@@ -219,9 +219,9 @@ static void wil_disconnect_cid(struct wil6210_vif *vif, int cid,
 	memset(sta->tid_crypto_rx, 0, sizeof(sta->tid_crypto_rx));
 	memset(&sta->group_crypto_rx, 0, sizeof(sta->group_crypto_rx));
 	/* release vrings */
-	for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
-		if (wil->vring2cid_tid[i][0] == cid)
-			wil_vring_fini_tx(wil, i);
+	for (i = 0; i < ARRAY_SIZE(wil->ring_tx); i++) {
+		if (wil->ring2cid_tid[i][0] == cid)
+			wil_ring_fini_tx(wil, i);
 	}
 	/* statistics */
 	memset(&sta->stats, 0, sizeof(sta->stats));
@@ -453,12 +453,12 @@ static void wil_fw_error_worker(struct work_struct *work)
 	mutex_unlock(&wil->mutex);
 }
 
-static int wil_find_free_vring(struct wil6210_priv *wil)
+static int wil_find_free_ring(struct wil6210_priv *wil)
 {
 	int i;
 
 	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
-		if (!wil->vring_tx[i].va)
+		if (!wil->ring_tx[i].va)
 			return i;
 	}
 	return -EINVAL;
@@ -473,13 +473,13 @@ int wil_tx_init(struct wil6210_vif *vif, int cid)
 		wil_err(wil, "No connection pending\n");
 		goto out;
 	}
-	ringid = wil_find_free_vring(wil);
+	ringid = wil_find_free_ring(wil);
 	if (ringid < 0) {
 		wil_err(wil, "No free vring found\n");
 		goto out;
 	}
 
-	wil_dbg_wmi(wil, "Configure for connection CID %d MID %d vring %d\n",
+	wil_dbg_wmi(wil, "Configure for connection CID %d MID %d ring %d\n",
 		    cid, vif->mid, ringid);
 
 	rc = wil_vring_init_tx(vif, ringid, 1 << tx_ring_order, cid, 0);
@@ -494,19 +494,19 @@ int wil_tx_init(struct wil6210_vif *vif, int cid)
 int wil_bcast_init(struct wil6210_vif *vif)
 {
 	struct wil6210_priv *wil = vif_to_wil(vif);
-	int ri = vif->bcast_vring, rc;
+	int ri = vif->bcast_ring, rc;
 
-	if ((ri >= 0) && wil->vring_tx[ri].va)
+	if (ri >= 0 && wil->ring_tx[ri].va)
 		return 0;
 
-	ri = wil_find_free_vring(wil);
+	ri = wil_find_free_ring(wil);
 	if (ri < 0)
 		return ri;
 
-	vif->bcast_vring = ri;
+	vif->bcast_ring = ri;
 	rc = wil_vring_init_bcast(vif, ri, 1 << bcast_ring_order);
 	if (rc)
-		vif->bcast_vring = -1;
+		vif->bcast_ring = -1;
 
 	return rc;
 }
@@ -514,13 +514,13 @@ int wil_bcast_init(struct wil6210_vif *vif)
 void wil_bcast_fini(struct wil6210_vif *vif)
 {
 	struct wil6210_priv *wil = vif_to_wil(vif);
-	int ri = vif->bcast_vring;
+	int ri = vif->bcast_ring;
 
 	if (ri < 0)
 		return;
 
-	vif->bcast_vring = -1;
-	wil_vring_fini_tx(wil, ri);
+	vif->bcast_ring = -1;
+	wil_ring_fini_tx(wil, ri);
 }
 
 void wil_bcast_fini_all(struct wil6210_priv *wil)
@@ -548,7 +548,7 @@ int wil_priv_init(struct wil6210_priv *wil)
 	}
 
 	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++)
-		spin_lock_init(&wil->vring_tx_data[i].lock);
+		spin_lock_init(&wil->ring_tx_data[i].lock);
 
 	mutex_init(&wil->mutex);
 	mutex_init(&wil->vif_mutex);
@@ -589,7 +589,7 @@ int wil_priv_init(struct wil6210_priv *wil)
 	wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST |
 			      WMI_WAKEUP_TRIGGER_BCAST;
 	memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
-	wil->vring_idle_trsh = 16;
+	wil->ring_idle_trsh = 16;
 
 	wil->reply_mid = U8_MAX;
 	wil->max_vifs = 1;
drivers/net/wireless/ath/wil6210/netdev.c +4 -4
index eb6c14ed..3c6a59f 100644
@@ -129,11 +129,11 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
 
 	/* always process ALL Tx complete, regardless budget - it is fast */
 	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
-		struct vring *vring = &wil->vring_tx[i];
-		struct vring_tx_data *txdata = &wil->vring_tx_data[i];
+		struct wil_ring *ring = &wil->ring_tx[i];
+		struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i];
 		struct wil6210_vif *vif;
 
-		if (!vring->va || !txdata->enabled ||
+		if (!ring->va || !txdata->enabled ||
 		    txdata->mid >= wil->max_vifs)
 			continue;
 
@@ -228,7 +228,7 @@ static void wil_p2p_discovery_timer_fn(struct timer_list *t)
 
 static void wil_vif_init(struct wil6210_vif *vif)
 {
-	vif->bcast_vring = -1;
+	vif->bcast_ring = -1;
 
 	mutex_init(&vif->probe_client_mutex);
 
drivers/net/wireless/ath/wil6210/rx_reorder.c +1 -1
index 76f8084..a586929 100644
@@ -384,7 +384,7 @@ int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize)
 {
 	u8 agg_wsize = wil_agg_size(wil, wsize);
 	u16 agg_timeout = 0;
-	struct vring_tx_data *txdata = &wil->vring_tx_data[ringid];
+	struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ringid];
 	int rc = 0;
 
 	if (txdata->addba_in_progress) {
drivers/net/wireless/ath/wil6210/txrx.c +162 -194

851 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/txrx.h +55 -13

114 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/txrx_edma.h new file +290 -0

290 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/wil6210.h +93 -17

196 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/wmi.c +12 -12
index ef991d7..4c8e0bf 100644
@@ -1120,7 +1120,7 @@ static void wmi_evt_vring_en(struct wil6210_vif *vif, int id, void *d, int len)
 
 	wil_dbg_wmi(wil, "Enable vring %d MID %d\n", vri, vif->mid);
 
-	if (vri >= ARRAY_SIZE(wil->vring_tx)) {
+	if (vri >= ARRAY_SIZE(wil->ring_tx)) {
 		wil_err(wil, "Enable for invalid vring %d\n", vri);
 		return;
 	}
@@ -1129,8 +1129,8 @@ static void wmi_evt_vring_en(struct wil6210_vif *vif, int id, void *d, int len)
 		/* in AP mode with disable_ap_sme, this is done by
 		 * wil_cfg80211_change_station()
 		 */
-		wil->vring_tx_data[vri].dot1x_open = true;
-	if (vri == vif->bcast_vring) /* no BA for bcast */
+		wil->ring_tx_data[vri].dot1x_open = true;
+	if (vri == vif->bcast_ring) /* no BA for bcast */
 		return;
 	if (agg_wsize >= 0)
 		wil_addba_tx_request(wil, vri, agg_wsize);
@@ -1141,7 +1141,7 @@ static void wmi_evt_ba_status(struct wil6210_vif *vif, int id,
 {
 	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_ba_status_event *evt = d;
-	struct vring_tx_data *txdata;
+	struct wil_ring_tx_data *txdata;
 
 	wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
 		    evt->ringid,
@@ -1160,7 +1160,7 @@ static void wmi_evt_ba_status(struct wil6210_vif *vif, int id,
 		evt->amsdu = 0;
 	}
 
-	txdata = &wil->vring_tx_data[evt->ringid];
+	txdata = &wil->ring_tx_data[evt->ringid];
 
 	txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
 	txdata->agg_wsize = evt->agg_wsize;
@@ -1198,11 +1198,11 @@ static void wmi_evt_delba(struct wil6210_vif *vif, int id, void *d, int len)
 	if (!evt->from_initiator) {
 		int i;
 		/* find Tx vring it belongs to */
-		for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
-			if ((wil->vring2cid_tid[i][0] == cid) &&
-			    (wil->vring2cid_tid[i][1] == tid)) {
-				struct vring_tx_data *txdata =
-					&wil->vring_tx_data[i];
+		for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++) {
+			if (wil->ring2cid_tid[i][0] == cid &&
+			    wil->ring2cid_tid[i][1] == tid) {
+				struct wil_ring_tx_data *txdata =
+					&wil->ring_tx_data[i];
 
 				wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
 				txdata->agg_timeout = 0;
@@ -1212,7 +1212,7 @@ static void wmi_evt_delba(struct wil6210_vif *vif, int id, void *d, int len)
 				break; /* max. 1 matching ring */
 			}
 		}
-		if (i >= ARRAY_SIZE(wil->vring2cid_tid))
+		if (i >= ARRAY_SIZE(wil->ring2cid_tid))
 			wil_err(wil, "DELBA: unable to find Tx vring\n");
 		return;
 	}
@@ -1957,7 +1957,7 @@ int wmi_rxon(struct wil6210_priv *wil, bool on)
 	return rc;
 }
 
-int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
+int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring)
 {
 	struct net_device *ndev = wil->main_ndev;
 	struct wireless_dev *wdev = ndev->ieee80211_ptr;
Signature · 1 line
1.9.1
#3 lore raw

Re: [PATCH 2/7] wil6210: add support for enhanced DMA structures

Quoted 17 lines · Maya Erez

From: Gidon Studinski <[email protected]>

In enhanced DMA the vrings are handled internally by the FW and are not exposed to the driver.
Instead, the driver handles descriptor rings, which are mapped by the FW to vrings.
The completions of the TX and RX descriptors are notified to the driver using status rings. Each status ring descriptor includes information of the completed descriptors and the ring id of their descriptor ring.

This patch changes struct vring to generic wil_ring to allow its reuse for enhanced DMA descriptor rings and adds the descriptor and status rings specific descriptors.

[...]

drivers/net/wireless/ath/wil6210/debugfs.c static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, · line 1788

Quoted 6 lines
drivers/net/wireless/ath/wil6210/debugfs.c +1 -1
@@ -1784,7 +1785,7 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
 	const struct file_operations *fops;
 } dbg_files[] = {
 	{"mbox",	0444,		&fops_mbox},
-	{"vrings",	0444,		&fops_vring},
+	{"rings",	0444,		&fops_ring},

When making changes to the debugfs interface please document that in the in commit log and how the changes look from user space point of view. Doesn't need to be long but just some sort of overview so that the reader understands the changes without looking at the code.

Signature · 1 line
Kalle Valo
author
#4 lore raw

PATCH 3/7 wil6210: initialize TX and RX enhanced DMA rings

In reply to Maya Erez

From: Gidon Studinski <[email protected]>

Enhanced DMA design includes the following rings:
- Single RX descriptor ring is used for all VIFs
- Multiple RX status rings are supported, to allow RSS
- TX descriptor ring is allocated per connection
- A single TX status ring is used for all TX descriptor rings

This patch initializes and frees the above descriptor and status rings.

The RX SKBs are handled by a new entity of RX buffers manager, which handles RX buffers, each one points to an allocated SKB. During Rx completion processing, the driver extracts a buffer ID which is used as an index to the buffers array. After the SKB is freed the buffer is moved from the 'active' list to the 'free' list, indicating it can be used for another descriptor. During Rx refill, SKBs are allocated and attached to 'free' buffers. Those buffers are attached to new descriptors and moved to the 'active' list.

---
 drivers/net/wireless/ath/wil6210/Makefile    |   1 +
 drivers/net/wireless/ath/wil6210/debugfs.c   |   1 +
 drivers/net/wireless/ath/wil6210/ethtool.c   |   2 +-
 drivers/net/wireless/ath/wil6210/interrupt.c |  21 +
 drivers/net/wireless/ath/wil6210/main.c      |  74 ++-
 drivers/net/wireless/ath/wil6210/pcie_bus.c  |  51 +-
 drivers/net/wireless/ath/wil6210/txrx.c      |  90 ++--
 drivers/net/wireless/ath/wil6210/txrx.h      |   8 +
 drivers/net/wireless/ath/wil6210/txrx_edma.c | 761 +++++++++++++++++++++++++++
 drivers/net/wireless/ath/wil6210/txrx_edma.h |  46 +-
 drivers/net/wireless/ath/wil6210/wil6210.h   |  81 ++-
 drivers/net/wireless/ath/wil6210/wmi.c       | 316 ++++++++++-
 drivers/net/wireless/ath/wil6210/wmi.h       | 166 +++++-
 13 files changed, 1490 insertions(+), 128 deletions(-)
 create mode 100644 drivers/net/wireless/ath/wil6210/txrx_edma.c
drivers/net/wireless/ath/wil6210/Makefile +1 -0
index 398edd2..d3d61ae 100644
@@ -9,6 +9,7 @@ wil6210-$(CONFIG_WIL6210_DEBUGFS) += debugfs.o
 wil6210-y += wmi.o
 wil6210-y += interrupt.o
 wil6210-y += txrx.o
+wil6210-y += txrx_edma.o
 wil6210-y += debug.o
 wil6210-y += rx_reorder.o
 wil6210-y += fw.o
drivers/net/wireless/ath/wil6210/debugfs.c +1 -0
index af7c59c..1165bc7 100644
@@ -1854,6 +1854,7 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil,
 	WIL_FIELD(abft_len, 0644,		doff_u8),
 	WIL_FIELD(wakeup_trigger, 0644,		doff_u8),
 	WIL_FIELD(ring_idle_trsh, 0644,	doff_u32),
+	WIL_FIELD(num_rx_status_rings, 0644,	doff_u8),
 	{},
 };
 
drivers/net/wireless/ath/wil6210/ethtool.c +1 -1
index e7ff41e..a04c87f 100644
@@ -101,7 +101,7 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev,
 	if (ret < 0)
 		return ret;
 
-	wil_configure_interrupt_moderation(wil);
+	wil->txrx_ops.configure_interrupt_moderation(wil);
 
 	wil_pm_runtime_put(wil);
 
drivers/net/wireless/ath/wil6210/interrupt.c +21 -0
index 84e9840..311d482 100644
@@ -186,6 +186,27 @@ void wil_unmask_irq(struct wil6210_priv *wil)
 	wil6210_unmask_irq_misc(wil, true);
 }
 
+void wil_configure_interrupt_moderation_edma(struct wil6210_priv *wil)
+{
+	u32 moderation;
+
+	wil_s(wil, RGF_INT_GEN_IDLE_TIME_LIMIT, WIL_EDMA_IDLE_TIME_LIMIT_USEC);
+
+	wil_s(wil, RGF_INT_GEN_TIME_UNIT_LIMIT, WIL_EDMA_TIME_UNIT_CLK_CYCLES);
+
+	/* Update RX and TX moderation */
+	moderation = wil->rx_max_burst_duration |
+		(WIL_EDMA_AGG_WATERMARK << WIL_EDMA_AGG_WATERMARK_POS);
+	wil_w(wil, RGF_INT_CTRL_INT_GEN_CFG_0, moderation);
+	wil_w(wil, RGF_INT_CTRL_INT_GEN_CFG_1, moderation);
+
+	/* Treat special events as regular
+	 * (set bit 0 to 0x1 and clear bits 1-8)
+	 */
+	wil_c(wil, RGF_INT_COUNT_ON_SPECIAL_EVT, 0x1FE);
+	wil_s(wil, RGF_INT_COUNT_ON_SPECIAL_EVT, 0x1);
+}
+
 void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
 {
 	struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
drivers/net/wireless/ath/wil6210/main.c +63 -11

155 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/pcie_bus.c +31 -20

87 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/txrx.c +43 -47

205 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/txrx.h +8 -0
index 66217f8..4e3781d 100644
@@ -570,6 +570,12 @@ static inline int wil_ring_avail_tx(struct wil_ring *ring)
 	return ring->size - wil_ring_used_tx(ring) - 1;
 }
 
+static inline int wil_get_min_tx_ring_id(struct wil6210_priv *wil)
+{
+	/* In Enhanced DMA ring 0 is reserved for RX */
+	return wil->use_enhanced_dma_hw ? 1 : 0;
+}
+
 void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev);
 void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb);
 void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif,
@@ -578,5 +584,7 @@ struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil,
 						int size, u16 ssn);
 void wil_tid_ampdu_rx_free(struct wil6210_priv *wil,
 			   struct wil_tid_ampdu_rx *r);
+void wil_tx_data_init(struct wil_ring_tx_data *txdata);
+void wil_init_txrx_ops_legacy_dma(struct wil6210_priv *wil);
 
 #endif /* WIL6210_TXRX_H */
drivers/net/wireless/ath/wil6210/txrx_edma.c new file +761 -0

761 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/txrx_edma.h +45 -1

63 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/wil6210.h +62 -19

134 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/wmi.c +299 -17

384 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/wmi.h +154 -12

226 lines not on this page · raw message

Signature · 1 line
1.9.1
#5 lore raw

Re: [PATCH 3/7] wil6210: initialize TX and RX enhanced DMA rings

Quoted 23 lines · Maya Erez

From: Gidon Studinski <[email protected]>

Enhanced DMA design includes the following rings:
- Single RX descriptor ring is used for all VIFs
- Multiple RX status rings are supported, to allow RSS
- TX descriptor ring is allocated per connection
- A single TX status ring is used for all TX descriptor rings

This patch initializes and frees the above descriptor and status rings.

The RX SKBs are handled by a new entity of RX buffers manager, which handles RX buffers, each one points to an allocated SKB. During Rx completion processing, the driver extracts a buffer ID which is used as an index to the buffers array. After the SKB is freed the buffer is moved from the 'active' list to the 'free' list, indicating it can be used for another descriptor. During Rx refill, SKBs are allocated and attached to 'free' buffers. Those buffers are attached to new descriptors and moved to the 'active' list.

[...]

drivers/net/wireless/ath/wil6210/pcie_bus.c line 37

Quoted 9 lines
drivers/net/wireless/ath/wil6210/pcie_bus.c +3 -0
@@ -32,6 +32,10 @@
 module_param(ftm_mode, bool, 0444);
 MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - false");
 
+static bool use_enhanced_dma_hw = true;
+module_param(use_enhanced_dma_hw, bool, 0444);
+MODULE_PARM_DESC(use_enhanced_dma_hw, " Use enhanced or legacy DMA HW. Default: true when available");

Similarly as with debugfs, please document in the commit log any changes in module parameters.

Signature · 1 line
Kalle Valo
#6 lore raw

Re: [PATCH 3/7] wil6210: initialize TX and RX enhanced DMA rings

Quoted 34 lines · Kalle Valo
Quoted 23 lines · Maya Erez

From: Gidon Studinski <[email protected]>

Enhanced DMA design includes the following rings:
- Single RX descriptor ring is used for all VIFs
- Multiple RX status rings are supported, to allow RSS
- TX descriptor ring is allocated per connection
- A single TX status ring is used for all TX descriptor rings

This patch initializes and frees the above descriptor and status rings.

The RX SKBs are handled by a new entity of RX buffers manager, which handles RX buffers, each one points to an allocated SKB. During Rx completion processing, the driver extracts a buffer ID which is used as an index to the buffers array. After the SKB is freed the buffer is moved from the 'active' list to the 'free' list, indicating it can be used for another descriptor. During Rx refill, SKBs are allocated and attached to 'free' buffers. Those buffers are attached to new descriptors and moved to the 'active' list.

[...]

Quoted 6 lines
drivers/net/wireless/ath/wil6210/pcie_bus.c +0 -0
@@ -32,6 +32,10 @@
 module_param(ftm_mode, bool, 0444);
 MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - false");
 
Quoted 6 lines

drivers/net/wireless/ath/wil6210/pcie_bus.c line 37

Quoted 3 lines
drivers/net/wireless/ath/wil6210/pcie_bus.c +3 -0
+static bool use_enhanced_dma_hw = true;
+module_param(use_enhanced_dma_hw, bool, 0444);
+MODULE_PARM_DESC(use_enhanced_dma_hw, " Use enhanced or legacy DMA HW. Default: true when available");

Similarly as with debugfs, please document in the commit log any changes in module parameters.

Oh, and in this patch there are even more new module parameters and no mention them in the commit log.

But a bigger problem is that wil6210 has now 24 module parameters (with this patchset included). That is quite a lot, are those all really needed? Module parameters are bad user experience and there should be good reasons before adding them.

Signature · 1 line
Kalle Valo
#7 lore raw

Re: [PATCH 3/7] wil6210: initialize TX and RX enhanced DMA rings

Quoted 45 lines · Kalle Valo
Quoted 35 lines · Kalle Valo
Quoted 23 lines · Maya Erez

From: Gidon Studinski <[email protected]>

Enhanced DMA design includes the following rings:
- Single RX descriptor ring is used for all VIFs
- Multiple RX status rings are supported, to allow RSS
- TX descriptor ring is allocated per connection
- A single TX status ring is used for all TX descriptor rings

This patch initializes and frees the above descriptor and status rings.

The RX SKBs are handled by a new entity of RX buffers manager, which handles RX buffers, each one points to an allocated SKB. During Rx completion processing, the driver extracts a buffer ID which is used as an index to the buffers array. After the SKB is freed the buffer is moved from the 'active' list to the 'free' list, indicating it can be used for another descriptor. During Rx refill, SKBs are allocated and attached to 'free' buffers. Those buffers are attached to new descriptors and moved to the 'active' list.

[...]

Quoted 7 lines
drivers/net/wireless/ath/wil6210/pcie_bus.c +0 -0
@@ -32,6 +32,10 @@
 module_param(ftm_mode, bool, 0444);
 MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - 
 false");
 
Quoted 7 lines

drivers/net/wireless/ath/wil6210/pcie_bus.c

Quoted 4 lines
drivers/net/wireless/ath/wil6210/pcie_bus.c +3 -0
+static bool use_enhanced_dma_hw = true;
+module_param(use_enhanced_dma_hw, bool, 0444);
+MODULE_PARM_DESC(use_enhanced_dma_hw, " Use enhanced or legacy DMA 
 HW. Default: true when available");

Similarly as with debugfs, please document in the commit log any changes in module parameters.

Quoted 7 lines

Oh, and in this patch there are even more new module parameters and no mention them in the commit log.

But a bigger problem is that wil6210 has now 24 module parameters (with this patchset included). That is quite a lot, are those all really needed? Module parameters are bad user experience and there should be good reasons before adding them.

24 module parameters is indeed a lot.
We will review the new module parameters added for enhanced DMA to check what can be configured via debugfs. Regardless, we will review the existing module parameters and see what can be removed or moved to debugfs.

Signature · 3 lines
Maya Erez
Qualcomm Israel, Inc. on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
author
#8 lore raw

PATCH 4/7 wil6210: add support for enhanced DMA TX data flows

In reply to Maya Erez

The enhanced DMA TX data path is handled using a descriptor ring per connection and a single status ring.

The driver gets TX completions via the TX status ring. Each status message points to the completed descriptor ring and includes the number of completed descriptors in this ring.

Non TSO enhanced DMA TX descriptors are similar to legacy DMA TX descriptors, hence the same transmit function can be used.

However, enhanced DMA TSO frames division is performed by the HW, hence a new function is added to handle enhanced DMA TSO.

---
 drivers/net/wireless/ath/wil6210/interrupt.c | 126 ++++++--
 drivers/net/wireless/ath/wil6210/netdev.c    |  36 ++-
 drivers/net/wireless/ath/wil6210/trace.h     |  25 ++
 drivers/net/wireless/ath/wil6210/txrx.c      | 194 ++++++------
 drivers/net/wireless/ath/wil6210/txrx.h      |  22 ++
 drivers/net/wireless/ath/wil6210/txrx_edma.c | 425 ++++++++++++++++++++++++++-
 drivers/net/wireless/ath/wil6210/txrx_edma.h |  33 ++-
 drivers/net/wireless/ath/wil6210/wil6210.h   |  15 +
 8 files changed, 748 insertions(+), 128 deletions(-)
drivers/net/wireless/ath/wil6210/interrupt.c +105 -21
index 311d482..1603b9f 100644
@@ -44,6 +44,7 @@
 				    (~(BIT_DMA_EP_RX_ICR_RX_HTRSH)))
 #define WIL6210_IMC_TX		(BIT_DMA_EP_TX_ICR_TX_DONE | \
 				BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
+#define WIL6210_IMC_TX_EDMA		BIT_TX_STATUS_IRQ
 #define WIL6210_IMC_MISC_NO_HALP	(ISR_MISC_FW_READY | \
 					 ISR_MISC_MBOX_EVT | \
 					 ISR_MISC_FW_ERROR)
@@ -87,6 +88,12 @@ static void wil6210_mask_irq_tx(struct wil6210_priv *wil)
 	      WIL6210_IRQ_DISABLE);
 }
 
+static void wil6210_mask_irq_tx_edma(struct wil6210_priv *wil)
+{
+	wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, IMS),
+	      WIL6210_IRQ_DISABLE);
+}
+
 static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
 {
 	wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMS),
@@ -125,6 +132,12 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
 	      WIL6210_IMC_TX);
 }
 
+void wil6210_unmask_irq_tx_edma(struct wil6210_priv *wil)
+{
+	wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, IMC),
+	      WIL6210_IMC_TX_EDMA);
+}
+
 void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
 {
 	bool unmask_rx_htrsh = atomic_read(&wil->connected_vifs) > 0;
@@ -164,6 +177,7 @@ void wil_mask_irq(struct wil6210_priv *wil)
 	wil_dbg_irq(wil, "mask_irq\n");
 
 	wil6210_mask_irq_tx(wil);
+	wil6210_mask_irq_tx_edma(wil);
 	wil6210_mask_irq_rx(wil);
 	wil6210_mask_irq_misc(wil, true);
 	wil6210_mask_irq_pseudo(wil);
@@ -179,10 +193,16 @@ void wil_unmask_irq(struct wil6210_priv *wil)
 	      WIL_ICR_ICC_VALUE);
 	wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC),
 	      WIL_ICR_ICC_MISC_VALUE);
+	wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC),
+	      WIL_ICR_ICC_VALUE);
 
 	wil6210_unmask_irq_pseudo(wil);
-	wil6210_unmask_irq_tx(wil);
-	wil6210_unmask_irq_rx(wil);
+	if (wil->use_enhanced_dma_hw) {
+		wil6210_unmask_irq_tx_edma(wil);
+	} else {
+		wil6210_unmask_irq_tx(wil);
+		wil6210_unmask_irq_rx(wil);
+	}
 	wil6210_unmask_irq_misc(wil, true);
 }
 
@@ -315,6 +335,49 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t wil6210_irq_tx_edma(int irq, void *cookie)
+{
+	struct wil6210_priv *wil = cookie;
+	u32 isr = wil_ioread32_and_clear(wil->csr +
+					 HOSTADDR(RGF_INT_GEN_TX_ICR) +
+					 offsetof(struct RGF_ICR, ICR));
+	bool need_unmask = true;
+
+	trace_wil6210_irq_tx(isr);
+	wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
+
+	if (unlikely(!isr)) {
+		wil_err(wil, "spurious IRQ: TX\n");
+		return IRQ_NONE;
+	}
+
+	wil6210_mask_irq_tx_edma(wil);
+
+	if (likely(isr & BIT_TX_STATUS_IRQ)) {
+		wil_dbg_irq(wil, "TX status ring\n");
+		isr &= ~BIT_TX_STATUS_IRQ;
+		if (likely(test_bit(wil_status_fwready, wil->status))) {
+			wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
+			need_unmask = false;
+			napi_schedule(&wil->napi_tx);
+		} else {
+			wil_err(wil, "Got Tx status ring IRQ while in reset\n");
+		}
+	}
+
+	if (unlikely(isr))
+		wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
+
+	/* Tx IRQ will be enabled when NAPI processing finished */
+
+	atomic_inc(&wil->isr_count_tx);
+
+	if (unlikely(need_unmask))
+		wil6210_unmask_irq_tx_edma(wil);
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
 {
 	struct wil6210_priv *wil = cookie;
@@ -531,30 +594,45 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
  */
 static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
 {
+	u32 icm_rx = 0, icr_rx = 0, imv_rx = 0;
+	u32 icm_tx, icr_tx, imv_tx;
+	u32 icm_misc, icr_misc, imv_misc;
+
 	if (!test_bit(wil_status_irqen, wil->status)) {
-		u32 icm_rx = wil_ioread32_and_clear(wil->csr +
-				HOSTADDR(RGF_DMA_EP_RX_ICR) +
-				offsetof(struct RGF_ICR, ICM));
-		u32 icr_rx = wil_ioread32_and_clear(wil->csr +
-				HOSTADDR(RGF_DMA_EP_RX_ICR) +
-				offsetof(struct RGF_ICR, ICR));
-		u32 imv_rx = wil_r(wil, RGF_DMA_EP_RX_ICR +
-				   offsetof(struct RGF_ICR, IMV));
-		u32 icm_tx = wil_ioread32_and_clear(wil->csr +
-				HOSTADDR(RGF_DMA_EP_TX_ICR) +
-				offsetof(struct RGF_ICR, ICM));
-		u32 icr_tx = wil_ioread32_and_clear(wil->csr +
-				HOSTADDR(RGF_DMA_EP_TX_ICR) +
-				offsetof(struct RGF_ICR, ICR));
-		u32 imv_tx = wil_r(wil, RGF_DMA_EP_TX_ICR +
+		if (wil->use_enhanced_dma_hw) {
+			icm_tx = wil_ioread32_and_clear(wil->csr +
+					HOSTADDR(RGF_INT_GEN_TX_ICR) +
+					offsetof(struct RGF_ICR, ICM));
+			icr_tx = wil_ioread32_and_clear(wil->csr +
+					HOSTADDR(RGF_INT_GEN_TX_ICR) +
+					offsetof(struct RGF_ICR, ICR));
+			imv_tx = wil_r(wil, RGF_INT_GEN_TX_ICR +
+					   offsetof(struct RGF_ICR, IMV));
+		} else {
+			icm_rx = wil_ioread32_and_clear(wil->csr +
+					HOSTADDR(RGF_DMA_EP_RX_ICR) +
+					offsetof(struct RGF_ICR, ICM));
+			icr_rx = wil_ioread32_and_clear(wil->csr +
+					HOSTADDR(RGF_DMA_EP_RX_ICR) +
+					offsetof(struct RGF_ICR, ICR));
+			imv_rx = wil_r(wil, RGF_DMA_EP_RX_ICR +
 				   offsetof(struct RGF_ICR, IMV));
-		u32 icm_misc = wil_ioread32_and_clear(wil->csr +
+			icm_tx = wil_ioread32_and_clear(wil->csr +
+					HOSTADDR(RGF_DMA_EP_TX_ICR) +
+					offsetof(struct RGF_ICR, ICM));
+			icr_tx = wil_ioread32_and_clear(wil->csr +
+					HOSTADDR(RGF_DMA_EP_TX_ICR) +
+					offsetof(struct RGF_ICR, ICR));
+			imv_tx = wil_r(wil, RGF_DMA_EP_TX_ICR +
+					   offsetof(struct RGF_ICR, IMV));
+		}
+		icm_misc = wil_ioread32_and_clear(wil->csr +
 				HOSTADDR(RGF_DMA_EP_MISC_ICR) +
 				offsetof(struct RGF_ICR, ICM));
-		u32 icr_misc = wil_ioread32_and_clear(wil->csr +
+		icr_misc = wil_ioread32_and_clear(wil->csr +
 				HOSTADDR(RGF_DMA_EP_MISC_ICR) +
 				offsetof(struct RGF_ICR, ICR));
-		u32 imv_misc = wil_r(wil, RGF_DMA_EP_MISC_ICR +
+		imv_misc = wil_r(wil, RGF_DMA_EP_MISC_ICR +
 				     offsetof(struct RGF_ICR, IMV));
 
 		/* HALP interrupt can be unmasked when misc interrupts are
@@ -617,7 +695,7 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
 		rc = IRQ_WAKE_THREAD;
 
 	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) &&
-	    (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD))
+	    (wil->txrx_ops.irq_tx(irq, cookie) == IRQ_WAKE_THREAD))
 		rc = IRQ_WAKE_THREAD;
 
 	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) &&
@@ -645,6 +723,8 @@ void wil6210_clear_irq(struct wil6210_priv *wil)
 		    offsetof(struct RGF_ICR, ICR));
 	wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
 		    offsetof(struct RGF_ICR, ICR));
+	wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) +
+		    offsetof(struct RGF_ICR, ICR));
 	wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
 		    offsetof(struct RGF_ICR, ICR));
 	wmb(); /* make sure write completed */
@@ -673,6 +753,10 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi)
 
 	wil_dbg_misc(wil, "init_irq: %s\n", use_msi ? "MSI" : "INTx");
 
+	if (wil->use_enhanced_dma_hw)
+		wil->txrx_ops.irq_tx = wil6210_irq_tx_edma;
+	else
+		wil->txrx_ops.irq_tx = wil6210_irq_tx;
 	rc = request_threaded_irq(irq, wil6210_hardirq,
 				  wil6210_thread_irq,
 				  use_msi ? 0 : IRQF_SHARED,
drivers/net/wireless/ath/wil6210/netdev.c +33 -3
index 3c6a59f..eeda2b6 100644
@@ -157,6 +157,30 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
 	return min(tx_done, budget);
 }
 
+static int wil6210_netdev_poll_tx_edma(struct napi_struct *napi, int budget)
+{
+	struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
+						napi_tx);
+	int tx_done;
+	/* There is only one status TX ring */
+	struct wil_status_ring *sring = &wil->srings[wil->tx_sring_idx];
+
+	if (!sring->va)
+		return 0;
+
+	tx_done = wil_tx_sring_handler(wil, sring);
+
+	if (tx_done < budget) {
+		napi_complete(napi);
+		wil6210_unmask_irq_tx_edma(wil);
+		wil_dbg_txrx(wil, "NAPI TX complete\n");
+	}
+
+	wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done);
+
+	return min(tx_done, budget);
+}
+
 static void wil_dev_setup(struct net_device *dev)
 {
 	ether_setup(dev);
@@ -420,9 +444,15 @@ int wil_if_add(struct wil6210_priv *wil)
 	init_dummy_netdev(&wil->napi_ndev);
 	netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx,
 		       WIL6210_NAPI_BUDGET);
-	netif_tx_napi_add(&wil->napi_ndev,
-			  &wil->napi_tx, wil6210_netdev_poll_tx,
-			  WIL6210_NAPI_BUDGET);
+	if (wil->use_enhanced_dma_hw)
+		netif_tx_napi_add(&wil->napi_ndev,
+				  &wil->napi_tx, wil6210_netdev_poll_tx_edma,
+				  WIL6210_NAPI_BUDGET);
+	else
+		netif_tx_napi_add(&wil->napi_ndev,
+				  &wil->napi_tx, wil6210_netdev_poll_tx,
+				  WIL6210_NAPI_BUDGET);
+
 
 	wil_update_net_queues_bh(wil, vif, NULL, true);
 
drivers/net/wireless/ath/wil6210/trace.h +25 -0
index c4db2a9..6aed246 100644
@@ -226,6 +226,31 @@
 		  __entry->err)
 );
 
+TRACE_EVENT(wil6210_tx_status,
+	    TP_PROTO(struct wil_ring_tx_status *msg, u16 index,
+		     unsigned int len),
+	    TP_ARGS(msg, index, len),
+	    TP_STRUCT__entry(__field(u16, index)
+			     __field(unsigned int, len)
+			     __field(u8, num_descs)
+			     __field(u8, ring_id)
+			     __field(u8, status)
+			     __field(u8, mcs)
+
+	    ),
+	    TP_fast_assign(__entry->index = index;
+			   __entry->len = len;
+			   __entry->num_descs = msg->num_descriptors;
+			   __entry->ring_id = msg->ring_id;
+			   __entry->status = msg->status;
+			   __entry->mcs = wil_tx_status_get_mcs(msg);
+	    ),
+	    TP_printk(
+		      "ring_id %d swtail 0x%x len %d num_descs %d status 0x%x mcs %d",
+		      __entry->ring_id, __entry->index, __entry->len,
+		      __entry->num_descs, __entry->status, __entry->mcs)
+);
+
 #endif /* WIL6210_TRACE_H || TRACE_HEADER_MULTI_READ*/
 
 #if defined(CONFIG_WIL6210_TRACING) && !defined(__CHECKER__)
drivers/net/wireless/ath/wil6210/txrx.c +93 -101

418 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/txrx.h +22 -0
index 4e3781d..62806c5 100644
@@ -555,6 +555,22 @@ static inline int wil_ring_is_full(struct wil_ring *ring)
 	return wil_ring_next_tail(ring) == ring->swhead;
 }
 
+static inline bool wil_need_txstat(struct sk_buff *skb)
+{
+	struct ethhdr *eth = (void *)skb->data;
+
+	return is_unicast_ether_addr(eth->h_dest) && skb->sk &&
+	       (skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS);
+}
+
+static inline void wil_consume_skb(struct sk_buff *skb, bool acked)
+{
+	if (unlikely(wil_need_txstat(skb)))
+		skb_complete_wifi_ack(skb, acked);
+	else
+		acked ? dev_consume_skb_any(skb) : dev_kfree_skb_any(skb);
+}
+
 /* Used space in Tx ring */
 static inline int wil_ring_used_tx(struct wil_ring *ring)
 {
@@ -576,6 +592,12 @@ static inline int wil_get_min_tx_ring_id(struct wil6210_priv *wil)
 	return wil->use_enhanced_dma_hw ? 1 : 0;
 }
 
+/* wil_val_in_range - check if value in [min,max) */
+static inline bool wil_val_in_range(int val, int min, int max)
+{
+	return val >= min && val < max;
+}
+
 void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev);
 void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb);
 void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif,
drivers/net/wireless/ath/wil6210/txrx_edma.c +423 -2

463 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/txrx_edma.h +32 -1
index 645ba17..7cdb3e4 100644
@@ -30,6 +30,30 @@
 #define WIL_EDMA_IDLE_TIME_LIMIT_USEC (50)
 #define WIL_EDMA_TIME_UNIT_CLK_CYCLES (330) /* fits 1 usec */
 
+#define WIL_EDMA_DESC_TX_MAC_CFG_0_QID_POS 16
+#define WIL_EDMA_DESC_TX_MAC_CFG_0_QID_LEN 6
+
+#define WIL_EDMA_DESC_TX_CFG_EOP_POS 0
+#define WIL_EDMA_DESC_TX_CFG_EOP_LEN 1
+
+#define WIL_EDMA_DESC_TX_CFG_TSO_DESC_TYPE_POS 3
+#define WIL_EDMA_DESC_TX_CFG_TSO_DESC_TYPE_LEN 2
+
+#define WIL_EDMA_DESC_TX_CFG_SEG_EN_POS 5
+#define WIL_EDMA_DESC_TX_CFG_SEG_EN_LEN 1
+
+#define WIL_EDMA_DESC_TX_CFG_INSERT_IP_CHKSUM_POS 6
+#define WIL_EDMA_DESC_TX_CFG_INSERT_IP_CHKSUM_LEN 1
+
+#define WIL_EDMA_DESC_TX_CFG_INSERT_TCP_CHKSUM_POS 7
+#define WIL_EDMA_DESC_TX_CFG_INSERT_TCP_CHKSUM_LEN 1
+
+#define WIL_EDMA_DESC_TX_CFG_L4_TYPE_POS 15
+#define WIL_EDMA_DESC_TX_CFG_L4_TYPE_LEN 1
+
+#define WIL_EDMA_DESC_TX_CFG_PSEUDO_HEADER_CALC_EN_POS 5
+#define WIL_EDMA_DESC_TX_CFG_PSEUDO_HEADER_CALC_EN_LEN 1
+
 /* Enhanced Rx descriptor - MAC part
  * [dword 0] : Reserved
  * [dword 1] : Reserved
@@ -295,7 +319,12 @@ struct wil_rx_status_extension {
 struct wil_rx_status_extended {
 	struct wil_rx_status_compressed comp;
 	struct wil_rx_status_extension ext;
-};
+} __packed;
+
+static inline u8 wil_tx_status_get_mcs(struct wil_ring_tx_status *msg)
+{
+	return WIL_GET_BITS(msg->d2, 0, 4);
+}
 
 static inline u32 wil_ring_next_head(struct wil_ring *ring)
 {
@@ -328,6 +357,8 @@ dma_addr_t wil_rx_desc_get_addr_edma(struct wil_ring_rx_enhanced_dma *dma)
 }
 
 void wil_configure_interrupt_moderation_edma(struct wil6210_priv *wil);
+int wil_tx_sring_handler(struct wil6210_priv *wil,
+			 struct wil_status_ring *sring);
 void wil_init_txrx_ops_edma(struct wil6210_priv *wil);
 
 #endif /* WIL6210_TXRX_EDMA_H */
drivers/net/wireless/ath/wil6210/wil6210.h +15 -0
index 5930907..5822d2b 100644
@@ -24,6 +24,7 @@
 #include <net/cfg80211.h>
 #include <linux/timex.h>
 #include <linux/types.h>
+#include <linux/irqreturn.h>
 #include "wmi.h"
 #include "wil_platform.h"
 #include "fw.h"
@@ -40,6 +41,7 @@
 
 struct wil6210_priv;
 struct wil6210_vif;
+union wil_tx_desc;
 
 #define WIL_NAME "wil6210"
 
@@ -321,6 +323,10 @@ struct RGF_ICR {
 #define RGF_INT_GEN_CTRL		(0x8bc0ec)
 	#define BIT_CONTROL_0			BIT(0)
 
+/* eDMA status interrupts */
+#define RGF_INT_GEN_TX_ICR		(0x8bc110)
+	#define BIT_TX_STATUS_IRQ BIT(WIL_TX_STATUS_IRQ_IDX)
+#define RGF_INT_CTRL_TX_INT_MASK	(0x8bc130)
 #define RGF_INT_GEN_IDLE_TIME_LIMIT	(0x8bc134)
 
 #define USER_EXT_USER_PMU_3		(0x88d00c)
@@ -540,6 +546,14 @@ struct wil_txrx_ops {
 	int (*ring_init_bcast)(struct wil6210_vif *vif, int id, int size);
 	int (*tx_init)(struct wil6210_priv *wil);
 	void (*tx_fini)(struct wil6210_priv *wil);
+	int (*tx_desc_map)(union wil_tx_desc *desc, dma_addr_t pa,
+			   u32 len, int ring_index);
+	void (*tx_desc_unmap)(struct device *dev,
+			      union wil_tx_desc *desc,
+			      struct wil_ctx *ctx);
+	int (*tx_ring_tso)(struct wil6210_priv *wil, struct wil6210_vif *vif,
+			   struct wil_ring *ring, struct sk_buff *skb);
+	irqreturn_t (*irq_tx)(int irq, void *cookie);
 	/* RX ops */
 	int (*rx_init)(struct wil6210_priv *wil, u16 ring_size);
 	void (*rx_fini)(struct wil6210_priv *wil);
@@ -1221,6 +1235,7 @@ void wil_update_net_queues_bh(struct wil6210_priv *wil, struct wil6210_vif *vif,
 netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev);
 int wil_tx_complete(struct wil6210_vif *vif, int ringid);
 void wil6210_unmask_irq_tx(struct wil6210_priv *wil);
+void wil6210_unmask_irq_tx_edma(struct wil6210_priv *wil);
 
 /* RX API */
 void wil_rx_handle(struct wil6210_priv *wil, int *quota);
Signature · 1 line
1.9.1
author
#9 lore raw

PATCH 5/7 wil6210: add support for enhanced DMA RX data flows

In reply to Maya Erez

From: Gidon Studinski <[email protected]>

Enhanced DMA RX data path is handled using a single RX descriptor ring for all VIFs.
Multiple RX status rings are supported, to allow RSS and multi MSI support.
The driver gets the RX completions via the RX status rings. The RX status message includes the completed RX buffer ID, which points to the allocated SKB.

The enhanced DMA RX data flow supports RX chaining, where multiple SKBs are merged into a single packet.

Enhanced DMA HW supports RX HW reorder offload, enabled by default and can be disabled via module parameter.

---
 drivers/net/wireless/ath/wil6210/interrupt.c  |  86 ++++-
 drivers/net/wireless/ath/wil6210/netdev.c     |  35 +-
 drivers/net/wireless/ath/wil6210/pm.c         |   6 +-
 drivers/net/wireless/ath/wil6210/rx_reorder.c |  18 +-
 drivers/net/wireless/ath/wil6210/trace.h      |  32 ++
 drivers/net/wireless/ath/wil6210/txrx.c       |  52 ++-
 drivers/net/wireless/ath/wil6210/txrx.h       |   7 +
 drivers/net/wireless/ath/wil6210/txrx_edma.c  | 455 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/wil6210/txrx_edma.h  | 188 +++++++++++
 drivers/net/wireless/ath/wil6210/wil6210.h    |  23 +-
 drivers/net/wireless/ath/wil6210/wmi.c        |  63 +++-
 11 files changed, 925 insertions(+), 40 deletions(-)
drivers/net/wireless/ath/wil6210/interrupt.c +82 -4
index 1603b9f..d7e112d 100644
@@ -45,6 +45,7 @@
 #define WIL6210_IMC_TX		(BIT_DMA_EP_TX_ICR_TX_DONE | \
 				BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
 #define WIL6210_IMC_TX_EDMA		BIT_TX_STATUS_IRQ
+#define WIL6210_IMC_RX_EDMA		BIT_RX_STATUS_IRQ
 #define WIL6210_IMC_MISC_NO_HALP	(ISR_MISC_FW_READY | \
 					 ISR_MISC_MBOX_EVT | \
 					 ISR_MISC_FW_ERROR)
@@ -100,6 +101,12 @@ static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
 	      WIL6210_IRQ_DISABLE);
 }
 
+static void wil6210_mask_irq_rx_edma(struct wil6210_priv *wil)
+{
+	wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMS),
+	      WIL6210_IRQ_DISABLE);
+}
+
 static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp)
 {
 	wil_dbg_irq(wil, "mask_irq_misc: mask_halp(%s)\n",
@@ -146,6 +153,12 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
 	      unmask_rx_htrsh ? WIL6210_IMC_RX : WIL6210_IMC_RX_NO_RX_HTRSH);
 }
 
+void wil6210_unmask_irq_rx_edma(struct wil6210_priv *wil)
+{
+	wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, IMC),
+	      WIL6210_IMC_RX_EDMA);
+}
+
 static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp)
 {
 	wil_dbg_irq(wil, "unmask_irq_misc: unmask_halp(%s)\n",
@@ -179,6 +192,7 @@ void wil_mask_irq(struct wil6210_priv *wil)
 	wil6210_mask_irq_tx(wil);
 	wil6210_mask_irq_tx_edma(wil);
 	wil6210_mask_irq_rx(wil);
+	wil6210_mask_irq_rx_edma(wil);
 	wil6210_mask_irq_misc(wil, true);
 	wil6210_mask_irq_pseudo(wil);
 }
@@ -195,10 +209,13 @@ void wil_unmask_irq(struct wil6210_priv *wil)
 	      WIL_ICR_ICC_MISC_VALUE);
 	wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC),
 	      WIL_ICR_ICC_VALUE);
+	wil_w(wil, RGF_INT_GEN_RX_ICR + offsetof(struct RGF_ICR, ICC),
+	      WIL_ICR_ICC_VALUE);
 
 	wil6210_unmask_irq_pseudo(wil);
 	if (wil->use_enhanced_dma_hw) {
 		wil6210_unmask_irq_tx_edma(wil);
+		wil6210_unmask_irq_rx_edma(wil);
 	} else {
 		wil6210_unmask_irq_tx(wil);
 		wil6210_unmask_irq_rx(wil);
@@ -335,6 +352,54 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t wil6210_irq_rx_edma(int irq, void *cookie)
+{
+	struct wil6210_priv *wil = cookie;
+	u32 isr = wil_ioread32_and_clear(wil->csr +
+					 HOSTADDR(RGF_INT_GEN_RX_ICR) +
+					 offsetof(struct RGF_ICR, ICR));
+	bool need_unmask = true;
+
+	trace_wil6210_irq_rx(isr);
+	wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
+
+	if (unlikely(!isr)) {
+		wil_err(wil, "spurious IRQ: RX\n");
+		return IRQ_NONE;
+	}
+
+	wil6210_mask_irq_rx_edma(wil);
+
+	if (likely(isr & BIT_RX_STATUS_IRQ)) {
+		wil_dbg_irq(wil, "RX status ring\n");
+		isr &= ~BIT_RX_STATUS_IRQ;
+		if (likely(test_bit(wil_status_fwready, wil->status))) {
+			if (likely(test_bit(wil_status_napi_en, wil->status))) {
+				wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
+				need_unmask = false;
+				napi_schedule(&wil->napi_rx);
+			} else {
+				wil_err(wil,
+					"Got Rx interrupt while stopping interface\n");
+			}
+		} else {
+			wil_err(wil, "Got Rx interrupt while in reset\n");
+		}
+	}
+
+	if (unlikely(isr))
+		wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr);
+
+	/* Rx IRQ will be enabled when NAPI processing finished */
+
+	atomic_inc(&wil->isr_count_rx);
+
+	if (unlikely(need_unmask))
+		wil6210_unmask_irq_rx_edma(wil);
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t wil6210_irq_tx_edma(int irq, void *cookie)
 {
 	struct wil6210_priv *wil = cookie;
@@ -594,12 +659,20 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
  */
 static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
 {
-	u32 icm_rx = 0, icr_rx = 0, imv_rx = 0;
+	u32 icm_rx, icr_rx, imv_rx;
 	u32 icm_tx, icr_tx, imv_tx;
 	u32 icm_misc, icr_misc, imv_misc;
 
 	if (!test_bit(wil_status_irqen, wil->status)) {
 		if (wil->use_enhanced_dma_hw) {
+			icm_rx = wil_ioread32_and_clear(wil->csr +
+					HOSTADDR(RGF_INT_GEN_RX_ICR) +
+					offsetof(struct RGF_ICR, ICM));
+			icr_rx = wil_ioread32_and_clear(wil->csr +
+					HOSTADDR(RGF_INT_GEN_RX_ICR) +
+					offsetof(struct RGF_ICR, ICR));
+			imv_rx = wil_r(wil, RGF_INT_GEN_RX_ICR +
+				   offsetof(struct RGF_ICR, IMV));
 			icm_tx = wil_ioread32_and_clear(wil->csr +
 					HOSTADDR(RGF_INT_GEN_TX_ICR) +
 					offsetof(struct RGF_ICR, ICM));
@@ -691,7 +764,7 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
 	 * voting for wake thread - need at least 1 vote
 	 */
 	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) &&
-	    (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
+	    (wil->txrx_ops.irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
 		rc = IRQ_WAKE_THREAD;
 
 	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) &&
@@ -723,6 +796,8 @@ void wil6210_clear_irq(struct wil6210_priv *wil)
 		    offsetof(struct RGF_ICR, ICR));
 	wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
 		    offsetof(struct RGF_ICR, ICR));
+	wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) +
+		    offsetof(struct RGF_ICR, ICR));
 	wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) +
 		    offsetof(struct RGF_ICR, ICR));
 	wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
@@ -753,10 +828,13 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi)
 
 	wil_dbg_misc(wil, "init_irq: %s\n", use_msi ? "MSI" : "INTx");
 
-	if (wil->use_enhanced_dma_hw)
+	if (wil->use_enhanced_dma_hw) {
 		wil->txrx_ops.irq_tx = wil6210_irq_tx_edma;
-	else
+		wil->txrx_ops.irq_rx = wil6210_irq_rx_edma;
+	} else {
 		wil->txrx_ops.irq_tx = wil6210_irq_tx;
+		wil->txrx_ops.irq_rx = wil6210_irq_rx;
+	}
 	rc = request_threaded_irq(irq, wil6210_hardirq,
 				  wil6210_thread_irq,
 				  use_msi ? 0 : IRQF_SHARED,
drivers/net/wireless/ath/wil6210/netdev.c +30 -5
index eeda2b6..7a78a06 100644
@@ -120,6 +120,27 @@ static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
 	return done;
 }
 
+static int wil6210_netdev_poll_rx_edma(struct napi_struct *napi, int budget)
+{
+	struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
+						napi_rx);
+	int quota = budget;
+	int done;
+
+	wil_rx_handle_edma(wil, &quota);
+	done = budget - quota;
+
+	if (done < budget) {
+		napi_complete_done(napi, done);
+		wil6210_unmask_irq_rx_edma(wil);
+		wil_dbg_txrx(wil, "NAPI RX complete\n");
+	}
+
+	wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done);
+
+	return done;
+}
+
 static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
 {
 	struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
@@ -442,17 +463,21 @@ int wil_if_add(struct wil6210_priv *wil)
 	}
 
 	init_dummy_netdev(&wil->napi_ndev);
-	netif_napi_add(&wil->napi_ndev, &wil->napi_rx, wil6210_netdev_poll_rx,
-		       WIL6210_NAPI_BUDGET);
-	if (wil->use_enhanced_dma_hw)
+	if (wil->use_enhanced_dma_hw) {
+		netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
+			       wil6210_netdev_poll_rx_edma,
+			       WIL6210_NAPI_BUDGET);
 		netif_tx_napi_add(&wil->napi_ndev,
 				  &wil->napi_tx, wil6210_netdev_poll_tx_edma,
 				  WIL6210_NAPI_BUDGET);
-	else
+	} else {
+		netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
+			       wil6210_netdev_poll_rx,
+			       WIL6210_NAPI_BUDGET);
 		netif_tx_napi_add(&wil->napi_ndev,
 				  &wil->napi_tx, wil6210_netdev_poll_tx,
 				  WIL6210_NAPI_BUDGET);
-
+	}
 
 	wil_update_net_queues_bh(wil, vif, NULL, true);
 
drivers/net/wireless/ath/wil6210/pm.c +3 -3
index ba81fb3..3a41947 100644
@@ -211,7 +211,7 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
 		goto reject_suspend;
 	}
 
-	if (!wil_is_rx_idle(wil)) {
+	if (!wil->txrx_ops.is_rx_idle(wil)) {
 		wil_dbg_pm(wil, "Pending RX data, reject suspend\n");
 		wil->suspend_stats.rejected_by_host++;
 		goto reject_suspend;
@@ -235,9 +235,9 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
 	start = jiffies;
 	data_comp_to = jiffies + msecs_to_jiffies(WIL_DATA_COMPLETION_TO_MS);
 	if (test_bit(wil_status_napi_en, wil->status)) {
-		while (!wil_is_rx_idle(wil)) {
+		while (!wil->txrx_ops.is_rx_idle(wil)) {
 			if (time_after(jiffies, data_comp_to)) {
-				if (wil_is_rx_idle(wil))
+				if (wil->txrx_ops.is_rx_idle(wil))
 					break;
 				wil_err(wil,
 					"TO waiting for idle RX, suspend failed\n");
drivers/net/wireless/ath/wil6210/rx_reorder.c +9 -9
index a586929..ce017e4 100644
@@ -95,17 +95,16 @@ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb)
 {
 	struct wil6210_vif *vif;
 	struct net_device *ndev;
-	struct vring_rx_desc *d = wil_skb_rxdesc(skb);
-	int tid = wil_rxdesc_tid(d);
-	int cid = wil_rxdesc_cid(d);
-	int mid = wil_rxdesc_mid(d);
-	u16 seq = wil_rxdesc_seq(d);
-	int mcast = wil_rxdesc_mcast(d);
-	struct wil_sta_info *sta = &wil->sta[cid];
+	int tid, cid, mid, mcast;
+	u16 seq;
+	struct wil_sta_info *sta;
 	struct wil_tid_ampdu_rx *r;
 	u16 hseq;
 	int index;
 
+	wil->txrx_ops.get_reorder_params(skb, &tid, &cid, &mid, &seq, &mcast);
+	sta = &wil->sta[cid];
+
 	wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x mcast %01x\n",
 		     mid, cid, tid, seq, mcast);
 
@@ -360,8 +359,9 @@ int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
 		}
 	}
 
-	rc = wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token, status,
-			       agg_amsdu, agg_wsize, agg_timeout);
+	rc = wil->txrx_ops.wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token,
+					     status, agg_amsdu, agg_wsize,
+					     agg_timeout);
 	if (rc || (status != WLAN_STATUS_SUCCESS)) {
 		wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc,
 			status);
drivers/net/wireless/ath/wil6210/trace.h +32 -0
index 6aed246..efd4c72 100644
@@ -187,6 +187,38 @@
 		  __entry->seq, __entry->type, __entry->subtype)
 );
 
+TRACE_EVENT(wil6210_rx_status,
+	    TP_PROTO(u8 use_compressed, u16 buff_id, void *msg),
+	    TP_ARGS(use_compressed, buff_id, msg),
+	    TP_STRUCT__entry(__field(u8, use_compressed)
+			     __field(u16, buff_id)
+			     __field(unsigned int, len)
+			     __field(u8, mid)
+			     __field(u8, cid)
+			     __field(u8, tid)
+			     __field(u8, type)
+			     __field(u8, subtype)
+			     __field(u16, seq)
+			     __field(u8, mcs)
+	    ),
+	    TP_fast_assign(__entry->use_compressed = use_compressed;
+			   __entry->buff_id = buff_id;
+			   __entry->len = wil_rx_status_get_length(msg);
+			   __entry->mid = wil_rx_status_get_mid(msg);
+			   __entry->cid = wil_rx_status_get_cid(msg);
+			   __entry->tid = wil_rx_status_get_tid(msg);
+			   __entry->type = wil_rx_status_get_frame_type(msg);
+			   __entry->subtype = wil_rx_status_get_fc1(msg);
+			   __entry->seq = wil_rx_status_get_seq(msg);
+			   __entry->mcs = wil_rx_status_get_mcs(msg);
+	    ),
+	    TP_printk(
+		      "compressed %d buff_id %d len %d mid %d cid %d tid %d mcs %d seq 0x%03x type 0x%1x subtype 0x%1x",
+		      __entry->use_compressed, __entry->buff_id, __entry->len,
+		      __entry->mid, __entry->cid, __entry->tid, __entry->mcs,
+		      __entry->seq, __entry->type, __entry->subtype)
+);
+
 TRACE_EVENT(wil6210_tx,
 	TP_PROTO(u8 vring, u16 index, unsigned int len, u8 frags),
 	TP_ARGS(vring, index, len, frags),
drivers/net/wireless/ath/wil6210/txrx.c +38 -14

110 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/txrx.h +7 -0
index 62806c5..f361423 100644
@@ -592,6 +592,13 @@ static inline int wil_get_min_tx_ring_id(struct wil6210_priv *wil)
 	return wil->use_enhanced_dma_hw ? 1 : 0;
 }
 
+/* similar to ieee80211_ version, but FC contain only 1-st byte */
+static inline int wil_is_back_req(u8 fc)
+{
+	return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
+	       (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ);
+}
+
 /* wil_val_in_range - check if value in [min,max) */
 static inline bool wil_val_in_range(int val, int min, int max)
 {
drivers/net/wireless/ath/wil6210/txrx_edma.c +455 -0

491 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/txrx_edma.h +188 -0

206 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/wil6210.h +21 -2
index 5822d2b..b645fcf 100644
@@ -37,6 +37,7 @@
 extern bool rx_large_buf;
 extern bool debug_fw;
 extern bool disable_ap_sme;
+extern bool use_rx_hw_reordering;
 extern bool use_compressed_rx_status;
 
 struct wil6210_priv;
@@ -324,9 +325,13 @@ struct RGF_ICR {
 	#define BIT_CONTROL_0			BIT(0)
 
 /* eDMA status interrupts */
+#define RGF_INT_GEN_RX_ICR		(0x8bc0f4)
+	#define BIT_RX_STATUS_IRQ BIT(WIL_RX_STATUS_IRQ_IDX)
 #define RGF_INT_GEN_TX_ICR		(0x8bc110)
 	#define BIT_TX_STATUS_IRQ BIT(WIL_TX_STATUS_IRQ_IDX)
+#define RGF_INT_CTRL_RX_INT_MASK	(0x8bc12c)
 #define RGF_INT_CTRL_TX_INT_MASK	(0x8bc130)
+
 #define RGF_INT_GEN_IDLE_TIME_LIMIT	(0x8bc134)
 
 #define USER_EXT_USER_PMU_3		(0x88d00c)
@@ -557,6 +562,16 @@ struct wil_txrx_ops {
 	/* RX ops */
 	int (*rx_init)(struct wil6210_priv *wil, u16 ring_size);
 	void (*rx_fini)(struct wil6210_priv *wil);
+	int (*wmi_addba_rx_resp)(struct wil6210_priv *wil, u8 mid, u8 cid,
+				 u8 tid, u8 token, u16 status, bool amsdu,
+				 u16 agg_wsize, u16 timeout);
+	void (*get_reorder_params)(struct sk_buff *skb, int *tid, int *cid,
+				   int *mid, u16 *seq, int *mcast);
+	void (*get_netif_rx_params)(struct sk_buff *skb,
+				    int *cid, int *security);
+	int (*rx_crypto_check)(struct wil6210_priv *wil, struct sk_buff *skb);
+	bool (*is_rx_idle)(struct wil6210_priv *wil);
+	irqreturn_t (*irq_rx)(int irq, void *cookie);
 };
 
 /**
@@ -891,7 +906,6 @@ struct wil6210_priv {
 
 	/* DMA related */
 	struct wil_ring ring_rx;
-	struct wil_ring_rx_data ring_rx_data;
 	unsigned int rx_buf_len;
 	struct wil_ring ring_tx[WIL6210_MAX_TX_RINGS];
 	struct wil_ring_tx_data ring_tx_data[WIL6210_MAX_TX_RINGS];
@@ -1240,6 +1254,7 @@ void wil_update_net_queues_bh(struct wil6210_priv *wil, struct wil6210_vif *vif,
 /* RX API */
 void wil_rx_handle(struct wil6210_priv *wil, int *quota);
 void wil6210_unmask_irq_rx(struct wil6210_priv *wil);
+void wil6210_unmask_irq_rx_edma(struct wil6210_priv *wil);
 
 int wil_iftype_nl2wmi(enum nl80211_iftype type);
 
@@ -1260,7 +1275,6 @@ int wil_request_firmware(struct wil6210_priv *wil, const char *name,
 int wmi_resume(struct wil6210_priv *wil);
 int wmi_suspend(struct wil6210_priv *wil);
 bool wil_is_tx_idle(struct wil6210_priv *wil);
-bool wil_is_rx_idle(struct wil6210_priv *wil);
 
 int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size);
 void wil_fw_core_dump(struct wil6210_priv *wil);
@@ -1275,6 +1289,8 @@ int wmi_start_sched_scan(struct wil6210_priv *wil,
 int wmi_stop_sched_scan(struct wil6210_priv *wil);
 int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len);
 
+int reverse_memcmp(const void *cs, const void *ct, size_t count);
+
 /* WMI for enhanced DMA */
 int wil_wmi_tx_sring_cfg(struct wil6210_priv *wil, int ring_id);
 int wil_wmi_cfg_def_rx_offload(struct wil6210_priv *wil,
@@ -1284,5 +1300,8 @@ int wil_wmi_cfg_def_rx_offload(struct wil6210_priv *wil,
 int wil_wmi_tx_desc_ring_add(struct wil6210_vif *vif, int ring_id, int cid,
 			     int tid);
 int wil_wmi_bcast_desc_ring_add(struct wil6210_vif *vif, int ring_id);
+int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid,
+			   u8 tid, u8 token, u16 status, bool amsdu,
+			   u16 agg_wsize, u16 timeout);
 
 #endif /* __WIL6210_H__ */
drivers/net/wireless/ath/wil6210/wmi.c +60 -3

93 lines not on this page · raw message

Signature · 1 line
1.9.1
#10 lore raw

Re: [PATCH 5/7] wil6210: add support for enhanced DMA RX data flows

Quoted 10 lines · Maya Erez

From: Gidon Studinski <[email protected]>

Enhanced DMA RX data path is handled using a single RX descriptor ring for all VIFs.
Multiple RX status rings are supported, to allow RSS and multi MSI support.
The driver gets the RX completions via the RX status rings. The RX status message includes the completed RX buffer ID, which points to the allocated SKB.

Quoted 8 lines

The enhanced DMA RX data flow supports RX chaining, where multiple SKBs are merged into a single packet.

Enhanced DMA HW supports RX HW reorder offload, enabled by default and can be disabled via module parameter.

kbuild bot reported a warning but not sure if it's valid, please take a look:

drivers/net/wireless/ath/wil6210/txrx_edma.c: In function 'wil_rx_handle_edma':

Quoted 1 line
Quoted 1 line

drivers/net/wireless/ath/wil6210/txrx_edma.c:815:7: warning: 'stats'

may be used uninitialized in this function [-Wmaybe-uninitialized]

     stats->rx_non_data_frame++;
     ~~~~~^~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/ath/wil6210/txrx_edma.c:908:24: note: 'stats'
   was declared here
     struct wil_net_stats *stats;
                           ^~~~~
Signature · 1 line
Kalle Valo
#11 lore raw

Re: [PATCH 5/7] wil6210: add support for enhanced DMA RX data flows

Quoted 26 lines · Kalle Valo
Quoted 10 lines · Maya Erez

From: Gidon Studinski <[email protected]>

Enhanced DMA RX data path is handled using a single RX descriptor ring for all VIFs.
Multiple RX status rings are supported, to allow RSS and multi MSI support.
The driver gets the RX completions via the RX status rings. The RX status message includes the completed RX buffer ID, which points to the allocated SKB.

Quoted 8 lines

The enhanced DMA RX data flow supports RX chaining, where multiple SKBs are merged into a single packet.

Enhanced DMA HW supports RX HW reorder offload, enabled by default and can be disabled via module parameter.

kbuild bot reported a warning but not sure if it's valid, please take a look:

drivers/net/wireless/ath/wil6210/txrx_edma.c: In function 'wil_rx_handle_edma':

Quoted 8 lines
Quoted 1 line
Quoted 1 line

drivers/net/wireless/ath/wil6210/txrx_edma.c:815:7: warning: 'stats'

may be used uninitialized in this function [-Wmaybe-uninitialized]

     stats->rx_non_data_frame++;
     ~~~~~^~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/ath/wil6210/txrx_edma.c:908:24: note: 'stats'
   was declared here
     struct wil_net_stats *stats;
                           ^~~~~

This is false alarm but looking again on the code I think it is better to initialize stats. I'll upload a fix.

Signature · 3 lines
Maya Erez
Qualcomm Israel, Inc. on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
author
#12 lore raw

PATCH 6/7 wil6210: add support for enhanced DMA debugfs

In reply to Maya Erez

Add debugfs support for enhanced DMA TX and RX descriptor rings, TX and RX status rings and RX buffer management.

Run the following command to print the TX and RX status rings:
cat srings

Run the following command in order to select the status ring:
echo STATUS_RING_IDX > dbg_sring_index

Run the following command in order to select the status message:
echo STATUS_MSG_IDX > dbg_status_msg_index

Run the following command in order to print the selected status message from the selected status ring:
cat status_msg

Run the following command in order to print the RX buffer management debug information:
cat rx_buff_mgmt

---
 drivers/net/wireless/ath/wil6210/debugfs.c | 347 +++++++++++++++++++++++++----
 1 file changed, 307 insertions(+), 40 deletions(-)
drivers/net/wireless/ath/wil6210/debugfs.c +307 -40
index 1165bc7..bdd6978 100644
@@ -30,6 +30,9 @@
 static u32 mem_addr;
 static u32 dbg_txdesc_index;
 static u32 dbg_ring_index; /* 24+ for Rx, 0..23 for Tx */
+static u32 dbg_status_msg_index;
+/* 0..wil->num_rx_status_rings-1 for Rx, wil->tx_sring_idx for Tx */
+static u32 dbg_sring_index;
 
 enum dbg_off_type {
 	doff_u32 = 0,
@@ -47,6 +50,36 @@ struct dbg_off {
 	enum dbg_off_type type;
 };
 
+static void wil_print_desc_edma(struct seq_file *s, struct wil6210_priv *wil,
+				struct wil_ring *ring,
+				char _s, char _h, int idx)
+{
+	u8 num_of_descs;
+	bool has_skb = false;
+
+	if (ring->is_rx) {
+		struct wil_rx_enhanced_desc *rx_d =
+			(struct wil_rx_enhanced_desc *)
+			&ring->va[idx].rx.enhanced;
+		u16 buff_id = le16_to_cpu(rx_d->mac.buff_id);
+
+		has_skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;
+		seq_printf(s, "%c", (has_skb) ? _h : _s);
+	} else {
+		struct wil_tx_enhanced_desc *d =
+			(struct wil_tx_enhanced_desc *)
+			&ring->va[idx].tx.enhanced;
+
+		num_of_descs = (u8)d->mac.d[2];
+		has_skb = ring->ctx[idx].skb;
+		if (num_of_descs >= 1)
+			seq_printf(s, "%c", ring->ctx[idx].skb ? _h : _s);
+		else
+			/* num_of_descs == 0, it's a frag in a list of descs */
+			seq_printf(s, "%c", has_skb ? 'h' : _s);
+	}
+}
+
 static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil,
 			   const char *name, struct wil_ring *ring,
 			   char _s, char _h)
@@ -58,7 +91,10 @@ static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil,
 	seq_printf(s, "  pa     = %pad\n", &ring->pa);
 	seq_printf(s, "  va     = 0x%p\n", ring->va);
 	seq_printf(s, "  size   = %d\n", ring->size);
-	seq_printf(s, "  swtail = %d\n", ring->swtail);
+	if (wil->use_enhanced_dma_hw && ring->is_rx)
+		seq_printf(s, "  swtail = %u\n", *ring->edma_rx_swtail.va);
+	else
+		seq_printf(s, "  swtail = %d\n", ring->swtail);
 	seq_printf(s, "  swhead = %d\n", ring->swhead);
 	seq_printf(s, "  hwtail = [0x%08x] -> ", ring->hwtail);
 	if (x) {
@@ -72,13 +108,16 @@ static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil,
 		uint i;
 
 		for (i = 0; i < ring->size; i++) {
-			volatile struct vring_tx_desc *d =
-				&ring->va[i].tx.legacy;
-
-			if ((i % 128) == 0 && (i != 0))
+			if ((i % 128) == 0 && i != 0)
 				seq_puts(s, "\n");
-			seq_printf(s, "%c", (d->dma.status & BIT(0)) ?
-					_s : (ring->ctx[i].skb ? _h : 'h'));
+			if (wil->use_enhanced_dma_hw) {
+				wil_print_desc_edma(s, wil, ring, _s, _h, i);
+			} else {
+				volatile struct vring_tx_desc *d =
+					&ring->va[i].tx.legacy;
+				seq_printf(s, "%c", (d->dma.status & BIT(0)) ?
+					   _s : (ring->ctx[i].skb ? _h : 'h'));
+			}
 		}
 		seq_puts(s, "\n");
 	}
@@ -157,6 +196,74 @@ static int wil_ring_seq_open(struct inode *inode, struct file *file)
 	.llseek		= seq_lseek,
 };
 
+static void wil_print_sring(struct seq_file *s, struct wil6210_priv *wil,
+			    struct wil_status_ring *sring)
+{
+	void __iomem *x = wmi_addr(wil, sring->hwtail);
+	int sring_idx = sring - wil->srings;
+	u32 v;
+
+	seq_printf(s, "Status Ring %s [ %d ] = {\n",
+		   sring->is_rx ? "RX" : "TX", sring_idx);
+	seq_printf(s, "  pa     = %pad\n", &sring->pa);
+	seq_printf(s, "  va     = 0x%pK\n", sring->va);
+	seq_printf(s, "  size   = %d\n", sring->size);
+	seq_printf(s, "  elem_size   = %zu\n", sring->elem_size);
+	seq_printf(s, "  swhead = %d\n", sring->swhead);
+	seq_printf(s, "  hwtail = [0x%08x] -> ", sring->hwtail);
+	if (x) {
+		v = readl_relaxed(x);
+		seq_printf(s, "0x%08x = %d\n", v, v);
+	} else {
+		seq_puts(s, "???\n");
+	}
+	seq_printf(s, "  desc_rdy_pol   = %d\n", sring->desc_rdy_pol);
+
+	if (sring->va && (sring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) {
+		uint i;
+
+		for (i = 0; i < sring->size; i++) {
+			u32 *sdword_0 =
+				(u32 *)(sring->va + (sring->elem_size * i));
+
+			if ((i % 128) == 0 && i != 0)
+				seq_puts(s, "\n");
+			if (i == sring->swhead)
+				seq_printf(s, "%c", (*sdword_0 & BIT(31)) ?
+					   'X' : 'x');
+			else
+				seq_printf(s, "%c", (*sdword_0 & BIT(31)) ?
+					   '1' : '0');
+		}
+		seq_puts(s, "\n");
+	}
+	seq_puts(s, "}\n");
+}
+
+static int wil_srings_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	int i = 0;
+
+	for (i = 0; i < WIL6210_MAX_STATUS_RINGS; i++)
+		if (wil->srings[i].va)
+			wil_print_sring(s, wil, &wil->srings[i]);
+
+	return 0;
+}
+
+static int wil_srings_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_srings_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_srings = {
+	.open		= wil_srings_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
 static void wil_seq_hexdump(struct seq_file *s, void *p, int len,
 			    const char *prefix)
 {
@@ -974,53 +1081,92 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
 {
 	struct wil6210_priv *wil = s->private;
 	struct wil_ring *ring;
-	bool tx = (dbg_ring_index < WIL6210_MAX_TX_RINGS);
+	bool tx;
+	int ring_idx = dbg_ring_index;
+	int txdesc_idx = dbg_txdesc_index;
+	volatile struct vring_tx_desc *d;
+	volatile u32 *u;
+	struct sk_buff *skb;
+
+	if (wil->use_enhanced_dma_hw) {
+		/* RX ring index == 0 */
+		if (ring_idx >= WIL6210_MAX_TX_RINGS) {
+			seq_printf(s, "invalid ring index %d\n", ring_idx);
+			return 0;
+		}
+		tx = ring_idx > 0; /* desc ring 0 is reserved for RX */
+	} else {
+		/* RX ring index == WIL6210_MAX_TX_RINGS */
+		if (ring_idx > WIL6210_MAX_TX_RINGS) {
+			seq_printf(s, "invalid ring index %d\n", ring_idx);
+			return 0;
+		}
+		tx = (ring_idx < WIL6210_MAX_TX_RINGS);
+	}
 
-	ring = tx ? &wil->ring_tx[dbg_ring_index] : &wil->ring_rx;
+	ring = tx ? &wil->ring_tx[ring_idx] : &wil->ring_rx;
 
 	if (!ring->va) {
 		if (tx)
-			seq_printf(s, "No Tx[%2d] VRING\n", dbg_ring_index);
+			seq_printf(s, "No Tx[%2d] RING\n", ring_idx);
 		else
-			seq_puts(s, "No Rx VRING\n");
+			seq_puts(s, "No Rx RING\n");
 		return 0;
 	}
 
-	if (dbg_txdesc_index < ring->size) {
-		/* use struct vring_tx_desc for Rx as well,
-		 * only field used, .dma.length, is the same
-		 */
-		volatile struct vring_tx_desc *d =
-				&ring->va[dbg_txdesc_index].tx.legacy;
-		volatile u32 *u = (volatile u32 *)d;
-		struct sk_buff *skb = ring->ctx[dbg_txdesc_index].skb;
-
+	if (txdesc_idx >= ring->size) {
 		if (tx)
-			seq_printf(s, "Tx[%2d][%3d] = {\n", dbg_ring_index,
-				   dbg_txdesc_index);
+			seq_printf(s, "[%2d] TxDesc index (%d) >= size (%d)\n",
+				   ring_idx, txdesc_idx, ring->size);
 		else
-			seq_printf(s, "Rx[%3d] = {\n", dbg_txdesc_index);
-		seq_printf(s, "  MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
-			   u[0], u[1], u[2], u[3]);
-		seq_printf(s, "  DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
-			   u[4], u[5], u[6], u[7]);
-		seq_printf(s, "  SKB = 0x%p\n", skb);
+			seq_printf(s, "RxDesc index (%d) >= size (%d)\n",
+				   txdesc_idx, ring->size);
+		return 0;
+	}
+
+	/* use struct vring_tx_desc for Rx as well,
+	 * only field used, .dma.length, is the same
+	 */
+	d = &ring->va[txdesc_idx].tx.legacy;
+	u = (volatile u32 *)d;
+	skb = NULL;
 
-		if (skb) {
-			skb_get(skb);
-			wil_seq_print_skb(s, skb);
-			kfree_skb(skb);
+	if (wil->use_enhanced_dma_hw) {
+		if (tx) {
+			skb = ring->ctx[txdesc_idx].skb;
+		} else {
+			struct wil_rx_enhanced_desc *rx_d =
+				(struct wil_rx_enhanced_desc *)
+				&ring->va[txdesc_idx].rx.enhanced;
+			u16 buff_id = le16_to_cpu(rx_d->mac.buff_id);
+
+			if (!wil_val_in_range(buff_id, 0,
+					      wil->rx_buff_mgmt.size)) {
+				seq_printf(s, "invalid buff_id %d\n", buff_id);
+				return 0;
+			}
+			skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;
 		}
-		seq_puts(s, "}\n");
 	} else {
-		if (tx)
-			seq_printf(s, "[%2d] TxDesc index (%d) >= size (%d)\n",
-				   dbg_ring_index, dbg_txdesc_index,
-				   ring->size);
-		else
-			seq_printf(s, "RxDesc index (%d) >= size (%d)\n",
-				   dbg_txdesc_index, ring->size);
+		skb = ring->ctx[txdesc_idx].skb;
+	}
+	if (tx)
+		seq_printf(s, "Tx[%2d][%3d] = {\n", ring_idx,
+			   txdesc_idx);
+	else
+		seq_printf(s, "Rx[%3d] = {\n", txdesc_idx);
+	seq_printf(s, "  MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
+		   u[0], u[1], u[2], u[3]);
+	seq_printf(s, "  DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
+		   u[4], u[5], u[6], u[7]);
+	seq_printf(s, "  SKB = 0x%p\n", skb);
+
+	if (skb) {
+		skb_get(skb);
+		wil_seq_print_skb(s, skb);
+		kfree_skb(skb);
 	}
+	seq_puts(s, "}\n");
 
 	return 0;
 }
@@ -1037,6 +1183,115 @@ static int wil_txdesc_seq_open(struct inode *inode, struct file *file)
 	.llseek		= seq_lseek,
 };
 
+/*---------Tx/Rx status message------------*/
+static int wil_status_msg_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	int sring_idx = dbg_sring_index;
+	struct wil_status_ring *sring;
+	bool tx = sring_idx == wil->tx_sring_idx ? 1 : 0;
+	u32 status_msg_idx = dbg_status_msg_index;
+	u32 *u;
+
+	if (sring_idx >= WIL6210_MAX_STATUS_RINGS) {
+		seq_printf(s, "invalid status ring index %d\n", sring_idx);
+		return 0;
+	}
+
+	sring = &wil->srings[sring_idx];
+
+	if (!sring->va) {
+		seq_printf(s, "No %cX status ring\n", tx ? 'T' : 'R');
+		return 0;
+	}
+
+	if (status_msg_idx >= sring->size) {
+		seq_printf(s, "%cxDesc index (%d) >= size (%d)\n",
+			   tx ? 'T' : 'R', status_msg_idx, sring->size);
+		return 0;
+	}
+
+	u = sring->va + (sring->elem_size * status_msg_idx);
+
+	seq_printf(s, "%cx[%d][%3d] = {\n",
+		   tx ? 'T' : 'R', sring_idx, status_msg_idx);
+
+	seq_printf(s, "  0x%08x 0x%08x 0x%08x 0x%08x\n",
+		   u[0], u[1], u[2], u[3]);
+	if (!tx && !use_compressed_rx_status)
+		seq_printf(s, "  0x%08x 0x%08x 0x%08x 0x%08x\n",
+			   u[4], u[5], u[6], u[7]);
+
+	seq_puts(s, "}\n");
+
+	return 0;
+}
+
+static int wil_status_msg_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_status_msg_debugfs_show,
+			   inode->i_private);
+}
+
+static const struct file_operations fops_status_msg = {
+	.open		= wil_status_msg_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
+static int wil_print_rx_buff(struct seq_file *s, struct list_head *lh)
+{
+	struct wil_rx_buff *it;
+	int i = 0;
+
+	list_for_each_entry(it, lh, list) {
+		if ((i % 16) == 0 && i != 0)
+			seq_puts(s, "\n    ");
+		seq_printf(s, "[%4d] ", it->id);
+		i++;
+	}
+	seq_printf(s, "\nNumber of buffers: %u\n", i);
+
+	return i;
+}
+
+static int wil_rx_buff_mgmt_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	struct wil_rx_buff_mgmt *rbm = &wil->rx_buff_mgmt;
+	int num_active;
+	int num_free;
+
+	seq_printf(s, "  size = %zu\n", rbm->size);
+	seq_printf(s, "  free_list_empty_cnt = %lu\n",
+		   rbm->free_list_empty_cnt);
+
+	/* Print active list */
+	seq_puts(s, "  Active list:\n");
+	num_active = wil_print_rx_buff(s, &rbm->active);
+	seq_puts(s, "\n  Free list:\n");
+	num_free = wil_print_rx_buff(s, &rbm->free);
+
+	seq_printf(s, "  Total number of buffers: %u\n",
+		   num_active + num_free);
+
+	return 0;
+}
+
+static int wil_rx_buff_mgmt_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_rx_buff_mgmt_debugfs_show,
+			   inode->i_private);
+}
+
+static const struct file_operations fops_rx_buff_mgmt = {
+	.open		= wil_rx_buff_mgmt_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
 /*---------beamforming------------*/
 static char *wil_bfstatus_str(u32 status)
 {
@@ -1473,6 +1728,13 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data)
 				   p->stats.rx_large_frame,
 				   p->stats.rx_replay);
 
+			if (wil->use_enhanced_dma_hw)
+				seq_printf(s,
+					   "mic error  %lu, key error %lu, amsdu error %lu\n",
+					   p->stats.rx_mic_error,
+					   p->stats.rx_key_error,
+					   p->stats.rx_amsdu_error);
+
 			seq_puts(s, "Rx/MCS:");
 			for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs);
 			     mcs++)
@@ -1808,6 +2070,9 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
 	{"fw_capabilities",	0444,	&fops_fw_capabilities},
 	{"fw_version",	0444,		&fops_fw_version},
 	{"suspend_stats",	0644,	&fops_suspend_stats},
+	{"srings",	0444,		&fops_srings},
+	{"status_msg",	0444,		&fops_status_msg},
+	{"rx_buff_mgmt",	0444,	&fops_rx_buff_mgmt},
 };
 
 static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
@@ -1871,6 +2136,8 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil,
 	{"ring_index",	0644, (ulong)&dbg_ring_index, doff_u32},
 	{"mem_addr",	0644, (ulong)&mem_addr, doff_u32},
 	{"led_polarity", 0644, (ulong)&led_polarity, doff_u8},
+	{"status_index", 0644, (ulong)&dbg_status_msg_index, doff_u32},
+	{"sring_index",	0644, (ulong)&dbg_sring_index, doff_u32},
 	{},
 };
 
Signature · 1 line
1.9.1
author
#13 lore raw

PATCH 7/7 wil6210: add support for Talyn-MB boot flow

In reply to Maya Erez

Talyn-MB introduces various of FW download options:
FW download via PCIe, SPI or PBL for secured access. The boot and FW download path is determined based on the OTP HW register. Driver reads this register as part of the SW reset flow and performs the appropriate initialization sequence.

---
 drivers/net/wireless/ath/wil6210/main.c    | 194 ++++++++++++++++++++++++-----
 drivers/net/wireless/ath/wil6210/wil6210.h |  10 +-
 2 files changed, 172 insertions(+), 32 deletions(-)
drivers/net/wireless/ath/wil6210/main.c +163 -31
index 995b332..ba5ebcb 100644
@@ -112,9 +112,29 @@ static int ring_order_set(const char *val, const struct kernel_param *kp)
 module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, 0444);
 MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order");
 
-#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
+enum {
+	WIL_BOOT_ERR,
+	WIL_BOOT_VANILLA,
+	WIL_BOOT_PRODUCTION,
+	WIL_BOOT_DEVELOPMENT,
+};
+
+enum {
+	WIL_SIG_STATUS_VANILLA = 0x0,
+	WIL_SIG_STATUS_DEVELOPMENT = 0x1,
+	WIL_SIG_STATUS_PRODUCTION = 0x2,
+	WIL_SIG_STATUS_CORRUPTED_PRODUCTION = 0x3,
+};
+
+#define RST_DELAY (20) /* msec, for loop in @wil_wait_device_ready */
 #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
 
+#define PMU_READY_DELAY_MS (4) /* ms, for sleep in @wil_wait_device_ready */
+
+#define OTP_HW_DELAY (200) /* usec, loop in @wil_wait_device_ready_talyn_mb */
+/* round up to be above 2 ms total */
+#define OTP_HW_COUNT (1 + 2000 / OTP_HW_DELAY)
+
 /*
  * Due to a hardware issue,
  * one has to read/write to/from NIC in 32-bit chunks;
@@ -815,11 +835,146 @@ static void wil_set_oob_mode(struct wil6210_priv *wil, u8 mode)
 	}
 }
 
-static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
+static int wil_wait_device_ready(struct wil6210_priv *wil, int no_flash)
 {
 	int delay = 0;
 	u32 x, x1 = 0;
 
+	/* wait until device ready. */
+	if (no_flash) {
+		msleep(PMU_READY_DELAY_MS);
+
+		wil_dbg_misc(wil, "Reset completed\n");
+	} else {
+		do {
+			msleep(RST_DELAY);
+			x = wil_r(wil, RGF_USER_BL +
+				  offsetof(struct bl_dedicated_registers_v0,
+					   boot_loader_ready));
+			if (x1 != x) {
+				wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n",
+					     x1, x);
+				x1 = x;
+			}
+			if (delay++ > RST_COUNT) {
+				wil_err(wil, "Reset not completed, bl.ready 0x%08x\n",
+					x);
+				return -ETIME;
+			}
+		} while (x != BL_READY);
+
+		wil_dbg_misc(wil, "Reset completed in %d ms\n",
+			     delay * RST_DELAY);
+	}
+
+	return 0;
+}
+
+static int wil_wait_device_ready_talyn_mb(struct wil6210_priv *wil)
+{
+	u32 otp_hw;
+	u8 signature_status;
+	bool otp_signature_err;
+	bool hw_section_done;
+	u32 otp_qc_secured;
+	int delay = 0;
+
+	/* Wait for OTP signature test to complete */
+	usleep_range(2000, 2200);
+
+	wil->boot_config = WIL_BOOT_ERR;
+
+	/* Poll until OTP signature status is valid.
+	 * In vanilla and development modes, when signature test is complete
+	 * HW sets BIT_OTP_SIGNATURE_ERR_TALYN_MB.
+	 * In production mode BIT_OTP_SIGNATURE_ERR_TALYN_MB remains 0, poll
+	 * for signature status change to 2 or 3.
+	 */
+	do {
+		otp_hw = wil_r(wil, RGF_USER_OTP_HW_RD_MACHINE_1);
+		signature_status = WIL_GET_BITS(otp_hw, 8, 9);
+		otp_signature_err = otp_hw & BIT_OTP_SIGNATURE_ERR_TALYN_MB;
+
+		if (otp_signature_err &&
+		    signature_status == WIL_SIG_STATUS_VANILLA) {
+			wil->boot_config = WIL_BOOT_VANILLA;
+			break;
+		}
+		if (otp_signature_err &&
+		    signature_status == WIL_SIG_STATUS_DEVELOPMENT) {
+			wil->boot_config = WIL_BOOT_DEVELOPMENT;
+			break;
+		}
+		if (!otp_signature_err &&
+		    signature_status == WIL_SIG_STATUS_PRODUCTION) {
+			wil->boot_config = WIL_BOOT_PRODUCTION;
+			break;
+		}
+		if  (!otp_signature_err &&
+		     signature_status ==
+		     WIL_SIG_STATUS_CORRUPTED_PRODUCTION) {
+			/* Unrecognized OTP signature found. Possibly a
+			 * corrupted production signature, access control
+			 * is applied as in production mode, therefore
+			 * do not fail
+			 */
+			wil->boot_config = WIL_BOOT_PRODUCTION;
+			break;
+		}
+		if (delay++ > OTP_HW_COUNT)
+			break;
+
+		usleep_range(OTP_HW_DELAY, OTP_HW_DELAY + 10);
+	} while (!otp_signature_err && signature_status == 0);
+
+	if (wil->boot_config == WIL_BOOT_ERR) {
+		wil_err(wil,
+			"invalid boot config, signature_status %d otp_signature_err %d\n",
+			signature_status, otp_signature_err);
+		return -ETIME;
+	}
+
+	wil_dbg_misc(wil,
+		     "signature test done in %d usec, otp_hw 0x%x, boot_config %d\n",
+		     delay * OTP_HW_DELAY, otp_hw, wil->boot_config);
+
+	if (wil->boot_config == WIL_BOOT_VANILLA)
+		/* Assuming not SPI boot (currently not supported) */
+		goto out;
+
+	hw_section_done = otp_hw & BIT_OTP_HW_SECTION_DONE_TALYN_MB;
+	delay = 0;
+
+	while (!hw_section_done) {
+		msleep(RST_DELAY);
+
+		otp_hw = wil_r(wil, RGF_USER_OTP_HW_RD_MACHINE_1);
+		hw_section_done = otp_hw & BIT_OTP_HW_SECTION_DONE_TALYN_MB;
+
+		if (delay++ > RST_COUNT) {
+			wil_err(wil, "TO waiting for hw_section_done\n");
+			return -ETIME;
+		}
+	}
+
+	wil_dbg_misc(wil, "HW section done in %d ms\n", delay * RST_DELAY);
+
+	otp_qc_secured = wil_r(wil, RGF_OTP_QC_SECURED);
+	wil->secured_boot = otp_qc_secured & BIT_BOOT_FROM_ROM ? 1 : 0;
+	wil_dbg_misc(wil, "secured boot is %sabled\n",
+		     wil->secured_boot ? "en" : "dis");
+
+out:
+	wil_dbg_misc(wil, "Reset completed\n");
+
+	return 0;
+}
+
+static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
+{
+	u32 x;
+	int rc;
+
 	wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->hw_name);
 
 	/* Clear MAC link up */
@@ -885,34 +1040,12 @@ static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
 
 	wil_w(wil, RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
 
-	/* wait until device ready. typical time is 20..80 msec */
-	if (no_flash)
-		do {
-			msleep(RST_DELAY);
-			x = wil_r(wil, USER_EXT_USER_PMU_3);
-			if (delay++ > RST_COUNT) {
-				wil_err(wil, "Reset not completed, PMU_3 0x%08x\n",
-					x);
-				return -ETIME;
-			}
-		} while ((x & BIT_PMU_DEVICE_RDY) == 0);
+	if (wil->hw_version == HW_VER_TALYN_MB)
+		rc = wil_wait_device_ready_talyn_mb(wil);
 	else
-		do {
-			msleep(RST_DELAY);
-			x = wil_r(wil, RGF_USER_BL +
-				  offsetof(struct bl_dedicated_registers_v0,
-					   boot_loader_ready));
-			if (x1 != x) {
-				wil_dbg_misc(wil, "BL.ready 0x%08x => 0x%08x\n",
-					     x1, x);
-				x1 = x;
-			}
-			if (delay++ > RST_COUNT) {
-				wil_err(wil, "Reset not completed, bl.ready 0x%08x\n",
-					x);
-				return -ETIME;
-			}
-		} while (x != BL_READY);
+		rc = wil_wait_device_ready(wil, no_flash);
+	if (rc)
+		return rc;
 
 	wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
 
@@ -920,7 +1053,7 @@ static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
 	wil_s(wil, RGF_DMA_OFUL_NID_0, BIT_DMA_OFUL_NID_0_RX_EXT_TR_EN |
 	      BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC);
 
-	if (no_flash) {
+	if (wil->hw_version < HW_VER_TALYN_MB && no_flash) {
 		/* Reset OTP HW vectors to fit 40MHz */
 		wil_w(wil, RGF_USER_XPM_IFC_RD_TIME1, 0x60001);
 		wil_w(wil, RGF_USER_XPM_IFC_RD_TIME2, 0x20027);
@@ -935,7 +1068,6 @@ static int wil_target_reset(struct wil6210_priv *wil, int no_flash)
 		wil_w(wil, RGF_USER_XPM_RD_DOUT_SAMPLE_TIME, 0x57);
 	}
 
-	wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY);
 	return 0;
 }
 
drivers/net/wireless/ath/wil6210/wil6210.h +9 -1
index b645fcf..81d982f 100644
@@ -212,7 +212,9 @@ struct RGF_ICR {
 #define RGF_USER_SPARROW_M_4			(0x880c50) /* Sparrow */
 	#define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF	BIT(2)
 #define RGF_USER_OTP_HW_RD_MACHINE_1	(0x880ce0)
-	#define BIT_NO_FLASH_INDICATION		BIT(8)
+	#define BIT_OTP_SIGNATURE_ERR_TALYN_MB		BIT(0)
+	#define BIT_OTP_HW_SECTION_DONE_TALYN_MB	BIT(2)
+	#define BIT_NO_FLASH_INDICATION			BIT(8)
 #define RGF_USER_XPM_IFC_RD_TIME1	(0x880cec)
 #define RGF_USER_XPM_IFC_RD_TIME2	(0x880cf0)
 #define RGF_USER_XPM_IFC_RD_TIME3	(0x880cf4)
@@ -314,6 +316,9 @@ struct RGF_ICR {
 #define RGF_CAF_PLL_LOCK_STATUS		(0x88afec)
 	#define BIT_CAF_OSC_DIG_XTAL_STABLE	BIT(0)
 
+#define RGF_OTP_QC_SECURED		(0x8a0038)
+	#define BIT_BOOT_FROM_ROM		BIT(31)
+
 /* eDMA */
 #define RGF_INT_COUNT_ON_SPECIAL_EVT	(0x8b62d8)
 
@@ -961,6 +966,9 @@ struct wil6210_priv {
 	u32 rgf_fw_assert_code_addr;
 	u32 rgf_ucode_assert_code_addr;
 	u32 iccm_base;
+
+	bool secured_boot;
+	u8 boot_config;
 };
 
 #define wil_to_wiphy(i) (i->wiphy)
Signature · 1 line
1.9.1