Skip to contentSkip to conversation

mt76: connac: move shared connac2 fw loading in connac module

PATCH In review Lorenzo Bianconi 2 participants 7 messages Jun 3, 2022 – Jun 7, 2022

Subsystems (2)
lore
Share & tools
lore

Lorenzo Bianconi

author maintainer
#0 lore raw

cover mt76: connac: move shared connac2 fw loading in connac module

Lorenzo Bianconi (5):
mt76: connac: move shared fw structures in connac module
mt76: mt7921: move fw toggle in mt7921_load_firmware
mt76: connac: move mt76_connac2_load_ram in connac module
mt76: connac: move mt76_connac2_load_patch in connac module
mt76: mt7663: rely on mt76_connac2_fw_trailer

 .../net/wireless/mediatek/mt76/mt7615/mcu.c   |  18 +-
 .../wireless/mediatek/mt76/mt76_connac_mcu.c  | 224 ++++++++++++++
 .../wireless/mediatek/mt76/mt76_connac_mcu.h  |  66 ++++
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 259 +---------------
 .../net/wireless/mediatek/mt76/mt7921/mcu.c   | 288 +-----------------
 5 files changed, 304 insertions(+), 551 deletions(-)
Signature · 1 line
2.35.3
author maintainer
#1 lore raw

PATCH 1/5 mt76: connac: move shared fw structures in connac module

Move mt76_connac2 fw structures in connac module since they are shared between mt7921 and mt7915 drivers. This is a preliminary patch to add mt7902e support.

---
 .../wireless/mediatek/mt76/mt76_connac_mcu.h  | 56 ++++++++++++
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 85 +++----------------
 .../net/wireless/mediatek/mt76/mt7921/mcu.c   | 81 +++---------------
 3 files changed, 79 insertions(+), 143 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +56 -0
index 561fb0368708..ccc17cf2fb0a 100644
@@ -26,6 +26,62 @@
 #define PATCH_SEC_TYPE_MASK		GENMASK(15, 0)
 #define PATCH_SEC_TYPE_INFO		0x2
 
+struct mt76_connac2_patch_hdr {
+	char build_date[16];
+	char platform[4];
+	__be32 hw_sw_ver;
+	__be32 patch_ver;
+	__be16 checksum;
+	u16 rsv;
+	struct {
+		__be32 patch_ver;
+		__be32 subsys;
+		__be32 feature;
+		__be32 n_region;
+		__be32 crc;
+		u32 rsv[11];
+	} desc;
+} __packed;
+
+struct mt76_connac2_patch_sec {
+	__be32 type;
+	__be32 offs;
+	__be32 size;
+	union {
+		__be32 spec[13];
+		struct {
+			__be32 addr;
+			__be32 len;
+			__be32 sec_key_idx;
+			__be32 align_len;
+			u32 rsv[9];
+		} info;
+	};
+} __packed;
+
+struct mt76_connac2_fw_trailer {
+	u8 chip_id;
+	u8 eco_code;
+	u8 n_region;
+	u8 format_ver;
+	u8 format_flag;
+	u8 rsv[2];
+	char fw_ver[10];
+	char build_date[15];
+	__le32 crc;
+} __packed;
+
+struct mt76_connac2_fw_region {
+	__le32 decomp_crc;
+	__le32 decomp_len;
+	__le32 decomp_blk_sz;
+	u8 rsv[4];
+	__le32 addr;
+	__le32 len;
+	u8 feature_set;
+	u8 rsv1[15];
+} __packed;
+
 struct tlv {
 	__le16 tag;
 	__le16 len;
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +12 -73

143 lines not on this page · raw message

drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +11 -70

134 lines not on this page · raw message

Signature · 1 line
2.35.3
author maintainer
#2 lore raw

PATCH 2/5 mt76: mt7921: move fw toggle in mt7921_load_firmware

In reply to Lorenzo Bianconi

Move drv_own/fw_own toggle in mt7921_load_firmware. This change allow to reuse connac code to load patch for mt7921 driver.

---
 drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +7 -7
index 1f1c270a4d81..bf1648b02ab5 100644
@@ -537,13 +537,6 @@ static int mt7921_load_patch(struct mt7921_dev *dev)
 		break;
 	}
 
-	if (!ret && mt76_is_sdio(&dev->mt76)) {
-		/* activate again */
-		ret = __mt7921_mcu_fw_pmctrl(dev);
-		if (!ret)
-			ret = __mt7921_mcu_drv_pmctrl(dev);
-	}
-
 	release_firmware(fw);
 
 	return ret;
@@ -662,6 +655,13 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
 	if (ret)
 		return ret;
 
+	if (mt76_is_sdio(&dev->mt76)) {
+		/* activate again */
+		ret = __mt7921_mcu_fw_pmctrl(dev);
+		if (!ret)
+			ret = __mt7921_mcu_drv_pmctrl(dev);
+	}
+
 	ret = mt7921_load_ram(dev);
 	if (ret)
 		return ret;
Signature · 1 line
2.35.3
author maintainer
#4 lore raw

PATCH 3/5 mt76: connac: move mt76_connac2_load_ram in connac module

In reply to Lorenzo Bianconi

Move mt76_connac2_load_ram utility routine in mt76_connac module since it is shared between mt7921 and mt7915. This is a preliminary patch to support mt7902e driver.

---
 .../wireless/mediatek/mt76/mt76_connac_mcu.c  | 111 +++++++++++++++++
 .../wireless/mediatek/mt76/mt76_connac_mcu.h  |   2 +
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   | 112 +-----------------
 .../net/wireless/mediatek/mt76/mt7921/mcu.c   |  89 +-------------
 4 files changed, 116 insertions(+), 198 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +111 -0
index faa279bbbcb2..1a2094778f0b 100644
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: ISC
 /* Copyright (C) 2020 MediaTek Inc. */
 
+#include <linux/firmware.h>
 #include "mt76_connac_mcu.h"
 
 int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
@@ -2806,5 +2807,115 @@ int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_rdd_cmd);
 
+static int
+mt76_connac_mcu_send_ram_firmware(struct mt76_dev *dev,
+				  const struct mt76_connac2_fw_trailer *hdr,
+				  const u8 *data, bool is_wa)
+{
+	int i, offset = 0, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
+	u32 override = 0, option = 0;
+
+	for (i = 0; i < hdr->n_region; i++) {
+		const struct mt76_connac2_fw_region *region;
+		u32 len, addr, mode;
+		int err;
+
+		region = (const void *)((const u8 *)hdr -
+					(hdr->n_region - i) * sizeof(*region));
+		mode = mt76_connac_mcu_gen_dl_mode(dev, region->feature_set,
+						   is_wa);
+		len = le32_to_cpu(region->len);
+		addr = le32_to_cpu(region->addr);
+
+		if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR)
+			override = addr;
+
+		err = mt76_connac_mcu_init_download(dev, addr, len, mode);
+		if (err) {
+			dev_err(dev->dev, "Download request failed\n");
+			return err;
+		}
+
+		err = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
+					       data + offset, len, max_len);
+		if (err) {
+			dev_err(dev->dev, "Failed to send firmware.\n");
+			return err;
+		}
+
+		offset += len;
+	}
+
+	if (override)
+		option |= FW_START_OVERRIDE;
+	if (is_wa)
+		option |= FW_START_WORKING_PDA_CR4;
+
+	return mt76_connac_mcu_start_firmware(dev, override, option);
+}
+
+int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
+			  const char *fw_wa)
+{
+	const struct mt76_connac2_fw_trailer *hdr;
+	const struct firmware *fw;
+	int ret;
+
+	ret = request_firmware(&fw, fw_wm, dev->dev);
+	if (ret)
+		return ret;
+
+	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+		dev_err(dev->dev, "Invalid firmware\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
+	dev_info(dev->dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
+		 hdr->fw_ver, hdr->build_date);
+
+	ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, false);
+	if (ret) {
+		dev_err(dev->dev, "Failed to start WM firmware\n");
+		goto out;
+	}
+
+	release_firmware(fw);
+
+	if (!fw_wa)
+		return 0;
+
+	ret = request_firmware(&fw, fw_wa, dev->dev);
+	if (ret)
+		return ret;
+
+	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+		dev_err(dev->dev, "Invalid firmware\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
+	dev_info(dev->dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
+		 hdr->fw_ver, hdr->build_date);
+
+	ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, true);
+	if (ret) {
+		dev_err(dev->dev, "Failed to start WA firmware\n");
+		goto out;
+	}
+
+	snprintf(dev->hw->wiphy->fw_version,
+		 sizeof(dev->hw->wiphy->fw_version),
+		 "%.10s-%.15s", hdr->fw_ver, hdr->build_date);
+
+out:
+	release_firmware(fw);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mt76_connac2_load_ram);
+
 MODULE_AUTHOR("Lorenzo Bianconi <[email protected]>");
 MODULE_LICENSE("Dual BSD/GPL");
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +2 -0
index ccc17cf2fb0a..355ed5e5d0ec 100644
@@ -1709,4 +1709,6 @@ int mt76_connac_mcu_set_pm(struct mt76_dev *dev, int band, int enter);
 int mt76_connac_mcu_restart(struct mt76_dev *dev);
 int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
 			    u8 rx_sel, u8 val);
+int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
+			  const char *fw_wa);
 #endif /* __MT76_CONNAC_MCU_H */
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +2 -110

124 lines not on this page · raw message

drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +1 -88

107 lines not on this page · raw message

Signature · 1 line
2.35.3
author maintainer
#5 lore raw

PATCH 4/5 mt76: connac: move mt76_connac2_load_patch in connac module

In reply to Lorenzo Bianconi

Move mt76_connac2_load_patch utility routine in mt76_connac module since it is shared between mt7921 and mt7915. This is a preliminary patch to support mt7902e driver.

---
 .../wireless/mediatek/mt76/mt76_connac_mcu.c  | 113 ++++++++++++++++
 .../wireless/mediatek/mt76/mt76_connac_mcu.h  |   8 ++
 .../net/wireless/mediatek/mt76/mt7915/mcu.c   |  86 +-----------
 .../net/wireless/mediatek/mt76/mt7921/mcu.c   | 126 +-----------------
 4 files changed, 123 insertions(+), 210 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +113 -0
index 1a2094778f0b..0dbcfbe00e4b 100644
@@ -2917,5 +2917,118 @@ int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
 }
 EXPORT_SYMBOL_GPL(mt76_connac2_load_ram);
 
+static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)
+{
+	u32 mode = DL_MODE_NEED_RSP;
+
+	if (!is_mt7921(dev) || info == PATCH_SEC_NOT_SUPPORT)
+		return mode;
+
+	switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
+	case PATCH_SEC_ENC_TYPE_PLAIN:
+		break;
+	case PATCH_SEC_ENC_TYPE_AES:
+		mode |= DL_MODE_ENCRYPT;
+		mode |= FIELD_PREP(DL_MODE_KEY_IDX,
+				(info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX;
+		mode |= DL_MODE_RESET_SEC_IV;
+		break;
+	case PATCH_SEC_ENC_TYPE_SCRAMBLE:
+		mode |= DL_MODE_ENCRYPT;
+		mode |= DL_CONFIG_ENCRY_MODE_SEL;
+		mode |= DL_MODE_RESET_SEC_IV;
+		break;
+	default:
+		dev_err(dev->dev, "Encryption type not support!\n");
+	}
+
+	return mode;
+}
+
+int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)
+{
+	int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
+	const struct mt76_connac2_patch_hdr *hdr;
+	const struct firmware *fw = NULL;
+
+	sem = mt76_connac_mcu_patch_sem_ctrl(dev, true);
+	switch (sem) {
+	case PATCH_IS_DL:
+		return 0;
+	case PATCH_NOT_DL_SEM_SUCCESS:
+		break;
+	default:
+		dev_err(dev->dev, "Failed to get patch semaphore\n");
+		return -EAGAIN;
+	}
+
+	ret = request_firmware(&fw, fw_name, dev->dev);
+	if (ret)
+		goto out;
+
+	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+		dev_err(dev->dev, "Invalid firmware\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	hdr = (const void *)fw->data;
+	dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
+		 be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
+
+	for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
+		struct mt76_connac2_patch_sec *sec;
+		u32 len, addr, mode;
+		const u8 *dl;
+		u32 sec_info;
+
+		sec = (void *)(fw->data + sizeof(*hdr) + i * sizeof(*sec));
+		if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
+		    PATCH_SEC_TYPE_INFO) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		addr = be32_to_cpu(sec->info.addr);
+		len = be32_to_cpu(sec->info.len);
+		dl = fw->data + be32_to_cpu(sec->offs);
+		sec_info = be32_to_cpu(sec->info.sec_key_idx);
+		mode = mt76_connac2_get_data_mode(dev, sec_info);
+
+		ret = mt76_connac_mcu_init_download(dev, addr, len, mode);
+		if (ret) {
+			dev_err(dev->dev, "Download request failed\n");
+			goto out;
+		}
+
+		ret = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
+					       dl, len, max_len);
+		if (ret) {
+			dev_err(dev->dev, "Failed to send patch\n");
+			goto out;
+		}
+	}
+
+	ret = mt76_connac_mcu_start_patch(dev);
+	if (ret)
+		dev_err(dev->dev, "Failed to start patch\n");
+
+out:
+	sem = mt76_connac_mcu_patch_sem_ctrl(dev, false);
+	switch (sem) {
+	case PATCH_REL_SEM_SUCCESS:
+		break;
+	default:
+		ret = -EAGAIN;
+		dev_err(dev->dev, "Failed to release patch semaphore\n");
+		break;
+	}
+
+	release_firmware(fw);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mt76_connac2_load_patch);
+
 MODULE_AUTHOR("Lorenzo Bianconi <[email protected]>");
 MODULE_LICENSE("Dual BSD/GPL");
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +8 -0
index 355ed5e5d0ec..d65b3cba1ace 100644
@@ -26,6 +26,13 @@
 #define PATCH_SEC_TYPE_MASK		GENMASK(15, 0)
 #define PATCH_SEC_TYPE_INFO		0x2
 
+#define PATCH_SEC_ENC_TYPE_MASK			GENMASK(31, 24)
+#define PATCH_SEC_ENC_TYPE_PLAIN		0x00
+#define PATCH_SEC_ENC_TYPE_AES			0x01
+#define PATCH_SEC_ENC_TYPE_SCRAMBLE		0x02
+#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK	GENMASK(15, 0)
+#define PATCH_SEC_ENC_AES_KEY_MASK		GENMASK(7, 0)
+
 struct mt76_connac2_patch_hdr {
 	char build_date[16];
 	char platform[4];
@@ -1711,4 +1718,5 @@ int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
 			    u8 rx_sel, u8 val);
 int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
 			  const char *fw_wa);
+int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name);
 #endif /* __MT76_CONNAC_MCU_H */
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +1 -85

104 lines not on this page · raw message

drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +1 -125

156 lines not on this page · raw message

Signature · 1 line
2.35.3
author maintainer
#6 lore raw

PATCH 5/5 mt76: mt7663: rely on mt76_connac2_fw_trailer

In reply to Lorenzo Bianconi

Remove duplicated code

---
 .../net/wireless/mediatek/mt76/mt7615/mcu.c    | 18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +2 -16
index 97e2a85cb728..52635fa430af 100644
@@ -40,18 +40,6 @@ struct mt7615_fw_trailer {
 #define FW_START_DLYCAL                 BIT(1)
 #define FW_START_WORKING_PDA_CR4	BIT(2)
 
-struct mt7663_fw_trailer {
-	u8 chip_id;
-	u8 eco_code;
-	u8 n_region;
-	u8 format_ver;
-	u8 format_flag;
-	u8 reserv[2];
-	char fw_ver[10];
-	char build_date[15];
-	__le32 crc;
-} __packed;
-
 struct mt7663_fw_buf {
 	__le32 crc;
 	__le32 d_img_size;
@@ -1518,7 +1506,7 @@ static int mt7615_mcu_cal_cache_apply(struct mt7615_dev *dev)
 static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)
 {
 	u32 offset = 0, override_addr = 0, flag = FW_START_DLYCAL;
-	const struct mt7663_fw_trailer *hdr;
+	const struct mt76_connac2_fw_trailer *hdr;
 	const struct mt7663_fw_buf *buf;
 	const struct firmware *fw;
 	const u8 *base_addr;
@@ -1534,9 +1522,7 @@ static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)
 		goto out;
 	}
 
-	hdr = (const struct mt7663_fw_trailer *)(fw->data + fw->size -
-						 FW_V3_COMMON_TAILER_SIZE);
-
+	hdr = (const void *)(fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE);
 	dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n",
 		 hdr->fw_ver, hdr->build_date);
 	dev_info(dev->mt76.dev, "Region number: 0x%x\n", hdr->n_region);
Signature · 1 line
2.35.3