All of lore.kernel.org
 help / color / mirror / Atom feed
From: <yhchuang@realtek.com>
To: <kvalo@codeaurora.org>
Cc: <Larry.Finger@lwfinger.net>, <pkshih@realtek.com>,
	<tehuang@realtek.com>, <sgruszka@redhat.com>,
	<linux-wireless@vger.kernel.org>
Subject: [RFC v3 06/12] rtw88: fw and efuse files
Date: Wed, 3 Oct 2018 19:20:53 +0800	[thread overview]
Message-ID: <1538565659-29530-7-git-send-email-yhchuang@realtek.com> (raw)
In-Reply-To: <1538565659-29530-1-git-send-email-yhchuang@realtek.com>

From: Yan-Hsuan Chuang <yhchuang@realtek.com>

fw and efuse files for Realtek 802.11ac wireless network chips

Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---
 drivers/net/wireless/realtek/rtw88/efuse.c | 150 +++++++
 drivers/net/wireless/realtek/rtw88/efuse.h |  53 +++
 drivers/net/wireless/realtek/rtw88/fw.c    | 638 +++++++++++++++++++++++++++++
 drivers/net/wireless/realtek/rtw88/fw.h    | 182 ++++++++
 4 files changed, 1023 insertions(+)
 create mode 100644 drivers/net/wireless/realtek/rtw88/efuse.c
 create mode 100644 drivers/net/wireless/realtek/rtw88/efuse.h
 create mode 100644 drivers/net/wireless/realtek/rtw88/fw.c
 create mode 100644 drivers/net/wireless/realtek/rtw88/fw.h

diff --git a/drivers/net/wireless/realtek/rtw88/efuse.c b/drivers/net/wireless/realtek/rtw88/efuse.c
new file mode 100644
index 0000000..7c1b782
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/efuse.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2018  Realtek Corporation.
+ */
+
+#include "main.h"
+#include "efuse.h"
+#include "reg.h"
+#include "debug.h"
+
+#define RTW_EFUSE_BANK_WIFI		0x0
+
+static void switch_efuse_bank(struct rtw_dev *rtwdev)
+{
+	rtw_write32_mask(rtwdev, REG_LDO_EFUSE_CTRL, BIT_MASK_EFUSE_BANK_SEL,
+			 RTW_EFUSE_BANK_WIFI);
+}
+
+static int rtw_dump_logical_efuse_map(struct rtw_dev *rtwdev, u8 *phy_map,
+				      u8 *log_map)
+{
+	u32 physical_size = rtwdev->efuse.physical_size;
+	u32 protect_size = rtwdev->efuse.protect_size;
+	u32 logical_size = rtwdev->efuse.logical_size;
+	u32 phy_idx, log_idx;
+	u8 hdr1, hdr2;
+	u8 blk_idx;
+	u8 valid;
+	u8 word_en;
+	int i;
+
+	phy_idx = 0;
+
+	do {
+		hdr1 = *(phy_map + phy_idx);
+		if ((hdr1 & 0x1f) == 0xf) {
+			phy_idx++;
+			hdr2 = *(phy_map + phy_idx);
+			if (hdr2 == 0xff)
+				break;
+			blk_idx = ((hdr2 & 0xf0) >> 1) | ((hdr1 >> 5) & 0x07);
+			word_en = hdr2 & 0x0f;
+		} else {
+			blk_idx = (hdr1 & 0xf0) >> 4;
+			word_en = hdr1 & 0x0f;
+		}
+
+		if (hdr1 == 0xff)
+			break;
+
+		phy_idx++;
+		for (i = 0; i < 4; i++) {
+			valid = (~(word_en >> i)) & 0x1;
+			if (valid != 0x1)
+				continue;
+			log_idx = (blk_idx << 3) + (i << 1);
+			*(log_map + log_idx) = *(phy_map + phy_idx);
+			log_idx++;
+			phy_idx++;
+			*(log_map + log_idx) = *(phy_map + phy_idx);
+			phy_idx++;
+			if (phy_idx > physical_size - protect_size ||
+			    log_idx > logical_size)
+				return -EINVAL;
+		}
+	} while (1);
+
+	return 0;
+}
+
+static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	u32 size = rtwdev->efuse.physical_size;
+	u32 efuse_ctl;
+	u32 addr;
+	u32 cnt;
+
+	switch_efuse_bank(rtwdev);
+
+	/* disable 2.5V LDO */
+	chip->ops->cfg_ldo25(rtwdev, false);
+
+	efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
+
+	for (addr = 0; addr < size; addr++) {
+		efuse_ctl &= ~(BIT_MASK_EF_DATA | BITS_EF_ADDR);
+		efuse_ctl |= (addr & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR;
+		rtw_write32(rtwdev, REG_EFUSE_CTRL, efuse_ctl & (~BIT_EF_FLAG));
+
+		cnt = 1000000;
+		do {
+			udelay(1);
+			efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL);
+			if (--cnt == 0)
+				return -EBUSY;
+		} while (!(efuse_ctl & BIT_EF_FLAG));
+
+		*(map + addr) = (u8)(efuse_ctl & BIT_MASK_EF_DATA);
+	}
+
+	return 0;
+}
+
+int rtw_parse_efuse_map(struct rtw_dev *rtwdev)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_efuse *efuse = &rtwdev->efuse;
+	u32 phy_size = efuse->physical_size;
+	u32 log_size = efuse->logical_size;
+	u8 *phy_map = NULL;
+	u8 *log_map = NULL;
+	int ret = 0;
+
+	phy_map = kmalloc(phy_size, GFP_KERNEL);
+	log_map = kmalloc(log_size, GFP_KERNEL);
+	if (!phy_map || !log_map) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	ret = rtw_dump_physical_efuse_map(rtwdev, phy_map);
+	if (ret) {
+		rtw_err(rtwdev, "failed to dump efuse physical map\n");
+		goto out_free;
+	}
+
+	memset(log_map, 0xff, log_size);
+	ret = rtw_dump_logical_efuse_map(rtwdev, phy_map, log_map);
+	if (ret) {
+		rtw_err(rtwdev, "failed to dump efuse logical map\n");
+		goto out_free;
+	}
+
+	print_hex_dump_bytes("efuse: ", DUMP_PREFIX_OFFSET, log_map, log_size);
+
+	efuse->x3d7 = phy_map[0x3d7];
+	efuse->x3d8 = phy_map[0x3d8];
+
+	ret = chip->ops->read_efuse(rtwdev, log_map);
+	if (ret) {
+		rtw_err(rtwdev, "failed to read efuse map\n");
+		goto out_free;
+	}
+
+out_free:
+	kfree(log_map);
+	kfree(phy_map);
+
+	return ret;
+}
diff --git a/drivers/net/wireless/realtek/rtw88/efuse.h b/drivers/net/wireless/realtek/rtw88/efuse.h
new file mode 100644
index 0000000..3635d08
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/efuse.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2018  Realtek Corporation.
+ */
+
+#ifndef __RTW_EFUSE_H__
+#define __RTW_EFUSE_H__
+
+#define EFUSE_HW_CAP_IGNORE		0
+#define EFUSE_HW_CAP_PTCL_VHT		3
+#define EFUSE_HW_CAP_SUPP_BW80		7
+#define EFUSE_HW_CAP_SUPP_BW40		6
+
+struct efuse_hw_cap {
+	u8 rsvd_0;
+	u8 rsvd_1;
+	u8 rsvd_2;
+	u8 rsvd_3;
+#ifdef __LITTLE_ENDIAN
+	u8 hci:4;
+	u8 rsvd_4:4;
+#else
+	u8 rsvd_4:4;
+	u8 hci:4;
+#endif
+	u8 rsvd_5;
+#ifdef __LITTLE_ENDIAN
+	u8 bw:3;
+	u8 nss:2;
+	u8 ant_num:3;
+#else
+	u8 ant_num:3;
+	u8 nss:2;
+	u8 bw:3;
+#endif
+#ifdef __LITTLE_ENDIAN
+	u8 rsvd_7_1:2;
+	u8 ptcl:2;
+	u8 rsvd_7_2:4;
+#else
+	u8 rsvd_7_2:4;
+	u8 ptcl:2;
+	u8 rsvd_7_1:2;
+#endif
+	u8 rsvd_8;
+	u8 rsvd_9;
+	u8 rsvd_10;
+	u8 rsvd_11;
+	u8 rsvd_12;
+};
+
+int rtw_parse_efuse_map(struct rtw_dev *rtwdev);
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
new file mode 100644
index 0000000..d22ca08
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -0,0 +1,638 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2018  Realtek Corporation.
+ */
+
+#include "main.h"
+#include "fw.h"
+#include "tx.h"
+#include "reg.h"
+#include "debug.h"
+
+void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
+{
+	struct rtw_c2h_cmd *c2h;
+	u32 pkt_offset;
+	u8 len;
+
+	pkt_offset = *((u32 *)skb->cb);
+	c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
+	len = skb->len - pkt_offset - 2;
+
+	rtw_dbg(rtwdev, "recv C2H, id=0x%02x, seq=0x%02x, len=%d\n",
+		c2h->id, c2h->seq, len);
+
+	switch (c2h->id) {
+	case C2H_HALMAC:
+		/* halmac needs rx_desc + c2h payload */
+		break;
+	default:
+		break;
+	}
+}
+
+void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, u8 cmd, u8 *h2c)
+{
+	u8 box;
+	u8 box_state;
+	u32 box_reg, box_ex_reg;
+	u32 h2c_wait;
+	int idx;
+
+	rtw_dbg(rtwdev,
+		"send H2C 0x%02x, content %02x%02x%02x%02x %02x%02x%02x%02x\n",
+		cmd, h2c[3], h2c[2], h2c[1], h2c[0],
+		h2c[7], h2c[6], h2c[5], h2c[4]);
+
+	spin_lock(&rtwdev->h2c.lock);
+
+	box = rtwdev->h2c.last_box_num;
+	switch (box) {
+	case 0:
+		box_reg = REG_HMEBOX0;
+		box_ex_reg = REG_HMEBOX0_EX;
+		break;
+	case 1:
+		box_reg = REG_HMEBOX1;
+		box_ex_reg = REG_HMEBOX1_EX;
+		break;
+	case 2:
+		box_reg = REG_HMEBOX2;
+		box_ex_reg = REG_HMEBOX2_EX;
+		break;
+	case 3:
+		box_reg = REG_HMEBOX3;
+		box_ex_reg = REG_HMEBOX3_EX;
+		break;
+	default:
+		WARN(1, "invalid h2c mail box number\n");
+		goto out;
+	}
+
+	h2c_wait = 20;
+	do {
+		box_state = rtw_read8(rtwdev, REG_HMETFR);
+	} while ((box_state >> box) & 0x1 && --h2c_wait > 0);
+
+	if (!h2c_wait) {
+		rtw_err(rtwdev, "fail sending h2c");
+		goto out;
+	}
+
+	for (idx = 0; idx < 4; idx++)
+		rtw_write8(rtwdev, box_reg + idx, h2c[idx]);
+	for (idx = 0; idx < 4; idx++)
+		rtw_write8(rtwdev, box_ex_reg + idx, h2c[idx + 4]);
+
+	if (++rtwdev->h2c.last_box_num >= 4)
+		rtwdev->h2c.last_box_num = 0;
+
+out:
+	spin_unlock(&rtwdev->h2c.lock);
+}
+
+static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c)
+{
+	int ret;
+
+	spin_lock(&rtwdev->h2c.lock);
+
+	FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c, rtwdev->h2c.seq);
+	ret = rtw_hci_write_data_h2c(rtwdev, h2c, H2C_PKT_SIZE);
+	if (ret)
+		rtw_err(rtwdev, "failed to send h2c packet\n");
+	rtwdev->h2c.seq++;
+
+	spin_unlock(&rtwdev->h2c.lock);
+}
+
+void
+rtw_fw_send_general_info(struct rtw_dev *rtwdev, struct rtw_general_info *info)
+{
+	struct rtw_fifo_conf *fifo = &rtwdev->fifo;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	u16 total_size = H2C_PKT_HDR_SIZE + 4;
+	u16 sub_cmd_id = SUB_CMD_ID_GENERAL_INFO;
+
+	GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_pkt,
+					fifo->rsvd_fw_txbuf_addr -
+					fifo->rsvd_boundary);
+	FW_OFFLOAD_H2C_SET_TOTAL_LEN(h2c_pkt, total_size);
+	FW_OFFLOAD_H2C_SET_SUB_CMD_ID(h2c_pkt, sub_cmd_id);
+
+	FW_OFFLOAD_H2C_SET_CATEGORY(h2c_pkt, 0x01);
+	FW_OFFLOAD_H2C_SET_CMD_ID(h2c_pkt, 0xFF);
+
+	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
+}
+
+void
+rtw_fw_send_phydm_info(struct rtw_dev *rtwdev, struct rtw_general_info *info)
+{
+	struct rtw_hal *hal = &rtwdev->hal;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	u16 total_size = H2C_PKT_HDR_SIZE + 8;
+	u16 sub_cmd_id = SUB_CMD_ID_PHYDM_INFO;
+
+	PHYDM_INFO_SET_REF_TYPE(h2c_pkt, info->rfe_type);
+	PHYDM_INFO_SET_RF_TYPE(h2c_pkt, info->rf_type);
+	PHYDM_INFO_SET_CUT_VER(h2c_pkt, hal->chip_version);
+	PHYDM_INFO_SET_RX_ANT_STATUS(h2c_pkt, info->rx_ant_status);
+	PHYDM_INFO_SET_TX_ANT_STATUS(h2c_pkt, info->tx_ant_status);
+
+	FW_OFFLOAD_H2C_SET_TOTAL_LEN(h2c_pkt, total_size);
+	FW_OFFLOAD_H2C_SET_SUB_CMD_ID(h2c_pkt, sub_cmd_id);
+
+	FW_OFFLOAD_H2C_SET_CATEGORY(h2c_pkt, 0x01);
+	FW_OFFLOAD_H2C_SET_CMD_ID(h2c_pkt, 0xFF);
+
+	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para)
+{
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	u16 total_size = H2C_PKT_HDR_SIZE + 1;
+	u16 sub_cmd_id = SUB_CMD_ID_IQK;
+
+	IQK_SET_CLEAR(h2c_pkt, para->clear);
+	IQK_SET_SEGMENT_IQK(h2c_pkt, para->segment_iqk);
+
+	FW_OFFLOAD_H2C_SET_TOTAL_LEN(h2c_pkt, total_size);
+	FW_OFFLOAD_H2C_SET_SUB_CMD_ID(h2c_pkt, sub_cmd_id);
+
+	FW_OFFLOAD_H2C_SET_CATEGORY(h2c_pkt, 0x01);
+	FW_OFFLOAD_H2C_SET_CMD_ID(h2c_pkt, 0xFF);
+
+	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_fill_h2c_cmd(struct rtw_dev *rtwdev, u8 cmd, u8 len, u8 *buf)
+{
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+	if (WARN(len > H2C_PKT_SIZE, "invalid h2c command length"))
+		return;
+
+	/* The buffer does not contain ID of the H2C, appends it */
+	memcpy(h2c_pkt, &cmd, 1);
+	memcpy(h2c_pkt + 1, buf, len);
+
+	rtw_fw_send_h2c_command(rtwdev, cmd, h2c_pkt);
+}
+
+void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
+{
+	u8 cmd_id = CMD_ID_RSSI_MONITOR;
+	u8 cmd_class = CLASS_RSSI_MONITOR;
+	u8 cmd = (cmd_class << RTW_H2C_CLASS_OFFSET) | cmd_id;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	u8 rssi = ewma_rssi_read(&si->avg_rssi);
+	bool stbc_en = si->stbc_en ? true : false;
+
+	h2c_pkt[0] = cmd;
+	h2c_pkt[1] = si->mac_id;
+	h2c_pkt[3] = rssi;
+	h2c_pkt[4] = stbc_en << 1;
+
+	rtw_fw_send_h2c_command(rtwdev, cmd, h2c_pkt);
+}
+
+void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
+{
+	u8 cmd_id = CMD_ID_RA_INFO;
+	u8 cmd_class = CLASS_RA_INFO;
+	u8 cmd = (cmd_class << RTW_H2C_CLASS_OFFSET) | cmd_id;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	bool no_update = si->updated;
+	bool disable_pt = true;
+
+	h2c_pkt[0] = cmd;
+	h2c_pkt[1] = si->mac_id;
+	h2c_pkt[2] = (si->rate_id & 0x1f) | ((si->init_ra_lv & 0x3) << 5) |
+		     (si->sgi_enable << 7);
+	h2c_pkt[3] = (si->bw_mode & 0x03) | ((si->ldpc_en ? 1 : 2) << 2) |
+		     (no_update << 3) | (si->vht_enable << 4) |
+		     (disable_pt << 6);
+	h2c_pkt[4] = (si->ra_mask & 0xff);
+	h2c_pkt[5] = (si->ra_mask & 0xff00) >> 8;
+	h2c_pkt[6] = (si->ra_mask & 0xff0000) >> 16;
+	h2c_pkt[7] = (si->ra_mask & 0xff000000) >> 24;
+
+	si->init_ra_lv = 0;
+	si->updated = true;
+
+	rtw_fw_send_h2c_command(rtwdev, cmd, h2c_pkt);
+}
+
+void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool connect)
+{
+	u8 cmd_id = CMD_ID_MEDIA_STATUS_RPT;
+	u8 cmd_class = CLASS_MEDIA_STATUS_RPT;
+	u8 cmd = (cmd_class << RTW_H2C_CLASS_OFFSET) | cmd_id;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+	MEDIA_STATUS_RPT_SET_CMD_ID(h2c_pkt, cmd_id);
+	MEDIA_STATUS_RPT_SET_CLASS(h2c_pkt, cmd_class);
+	MEDIA_STATUS_RPT_SET_OP_MODE(h2c_pkt, connect);
+	MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, mac_id);
+
+	rtw_fw_send_h2c_command(rtwdev, cmd, h2c_pkt);
+}
+
+void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev)
+{
+	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
+	u8 cmd_id = CMD_ID_SET_PWR_MODE;
+	u8 cmd_class = CLASS_SET_PWR_MODE;
+	u8 cmd = (cmd_class << RTW_H2C_CLASS_OFFSET) | cmd_id;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+	SET_PWR_MODE_SET_CMD_ID(h2c_pkt, cmd_id);
+	SET_PWR_MODE_SET_CLASS(h2c_pkt, cmd_class);
+	SET_PWR_MODE_SET_MODE(h2c_pkt, conf->mode);
+	SET_PWR_MODE_SET_RLBM(h2c_pkt, conf->rlbm);
+	SET_PWR_MODE_SET_SMART_PS(h2c_pkt, conf->smart_ps);
+	SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_pkt, conf->awake_interval);
+	SET_PWR_MODE_SET_PORT_ID(h2c_pkt, conf->port_id);
+	SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, conf->state);
+
+	rtw_fw_send_h2c_command(rtwdev, cmd, h2c_pkt);
+}
+
+static void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev)
+{
+	struct rtw_rsvd_page *rsvd_pkt;
+	enum rtw_rsvd_packet_type type;
+	u8 cmd_id = CMD_ID_RSVD_PAGE;
+	u8 cmd_class = CLASS_RSVD_PAGE;
+	u8 cmd = (cmd_class << RTW_H2C_CLASS_OFFSET) | cmd_id;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
+		type = rsvd_pkt->type;
+		switch (type) {
+		case RSVD_PROBE_RESP:
+			*(h2c_pkt + 1) = rsvd_pkt->page;
+			rtw_dbg(rtwdev, "RSVD_PROBE_RESP Loc: %d",
+				rsvd_pkt->page);
+			break;
+		case RSVD_PS_POLL:
+			*(h2c_pkt + 2) = rsvd_pkt->page;
+			rtw_dbg(rtwdev, "RSVD_PS_POLL Loc: %d", rsvd_pkt->page);
+			break;
+		case RSVD_NULL:
+			*(h2c_pkt + 3) = rsvd_pkt->page;
+			rtw_dbg(rtwdev, "RSVD_NULL Loc: %d", rsvd_pkt->page);
+			break;
+		case RSVD_QOS_NULL:
+			*(h2c_pkt + 4) = rsvd_pkt->page;
+			rtw_dbg(rtwdev, "RSVD_QOS_NULL Loc: %d\n",
+				rsvd_pkt->page);
+			break;
+		default:
+			break;
+		}
+	}
+	RSVD_PAGE_SET_CMD_ID(h2c_pkt, cmd_id);
+	RSVD_PAGE_SET_CLASS(h2c_pkt, cmd_class);
+
+	rtw_fw_send_h2c_command(rtwdev, cmd, h2c_pkt);
+}
+
+static struct sk_buff *
+rtw_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct sk_buff *skb_new;
+
+	if (vif->type != NL80211_IFTYPE_AP &&
+	    vif->type != NL80211_IFTYPE_ADHOC &&
+	    !ieee80211_vif_is_mesh(vif)) {
+		skb_new = alloc_skb(1, GFP_KERNEL);
+		skb_put(skb_new, 1);
+	} else {
+		skb_new = ieee80211_beacon_get(hw, vif);
+	}
+
+	return skb_new;
+}
+
+static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
+					     struct ieee80211_vif *vif,
+					     enum rtw_rsvd_packet_type type)
+{
+	struct sk_buff *skb_new;
+
+	switch (type) {
+	case RSVD_BEACON:
+		skb_new = rtw_beacon_get(hw, vif);
+		break;
+	case RSVD_PS_POLL:
+		skb_new = ieee80211_pspoll_get(hw, vif);
+		break;
+	case RSVD_PROBE_RESP:
+		skb_new = ieee80211_proberesp_get(hw, vif);
+		break;
+	case RSVD_NULL:
+		skb_new = ieee80211_nullfunc_get(hw, vif, false);
+		break;
+	case RSVD_QOS_NULL:
+		skb_new = ieee80211_nullfunc_get(hw, vif, true);
+		break;
+	default:
+		return NULL;
+	}
+
+	if (!skb_new)
+		return NULL;
+
+	return skb_new;
+}
+
+static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb)
+{
+	struct rtw_tx_pkt_info pkt_info;
+	struct rtw_chip_info *chip = rtwdev->chip;
+	u8 *pkt_desc;
+
+	memset(&pkt_info, 0, sizeof(pkt_info));
+	rtw_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb);
+	pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
+	memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
+	rtw_tx_fill_tx_desc(&pkt_info, skb);
+}
+
+static inline u8 rtw_len_to_page(unsigned int len, u8 page_size)
+{
+	return DIV_ROUND_UP(len, page_size);
+}
+
+static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u8 page_size,
+				      u8 page_margin, u32 page, u8 *buf,
+				      struct rtw_rsvd_page *rsvd_pkt)
+{
+	struct sk_buff *skb = rsvd_pkt->skb;
+
+	if (rsvd_pkt->add_txdesc)
+		rtw_fill_rsvd_page_desc(rtwdev, skb);
+
+	if (page >= 1)
+		memcpy(buf + page_margin + page_size * (page - 1),
+		       skb->data, skb->len);
+	else
+		memcpy(buf, skb->data, skb->len);
+}
+
+void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type,
+		       bool txdesc)
+{
+	struct rtw_rsvd_page *rsvd_pkt;
+
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
+		if (rsvd_pkt->type == type)
+			return;
+	}
+
+	rsvd_pkt = kmalloc(sizeof(*rsvd_pkt),
+			   in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+	rsvd_pkt->type = type;
+	rsvd_pkt->add_txdesc = txdesc;
+	list_add_tail(&rsvd_pkt->list, &rtwdev->rsvd_page_list);
+}
+
+void rtw_reset_rsvd_page(struct rtw_dev *rtwdev)
+{
+	struct rtw_rsvd_page *rsvd_pkt, *tmp;
+
+	list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) {
+		if (rsvd_pkt->type == RSVD_BEACON)
+			continue;
+		list_del(&rsvd_pkt->list);
+		kfree(rsvd_pkt);
+	}
+}
+
+int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
+				u8 *buf, u32 size)
+{
+	u8 bckp[2];
+	u8 val;
+	u16 rsvd_pg_head;
+	u32 cnt;
+	int ret;
+
+	if (!size)
+		return -EINVAL;
+
+	pg_addr &= BIT_MASK_BCN_HEAD_1_V1;
+	rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, pg_addr | BIT(15));
+
+	val = rtw_read8(rtwdev, REG_CR + 1);
+	bckp[0] = val;
+	val |= BIT(0);
+	rtw_write8(rtwdev, REG_CR + 1, val);
+
+	val = rtw_read8(rtwdev, REG_FWHW_TXQ_CTRL + 2);
+	bckp[1] = val;
+	val &= ~BIT(6);
+	rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, val);
+
+	ret = rtw_hci_write_data_rsvd_page(rtwdev, buf, size);
+	if (ret) {
+		rtw_err(rtwdev, "failed to write data to rsvd page\n");
+		goto restore;
+	}
+
+	cnt = 1000;
+	while (!(rtw_read8(rtwdev, REG_FIFOPAGE_CTRL_2 + 1) & BIT(7))) {
+		udelay(10);
+		cnt--;
+		if (cnt == 0) {
+			rtw_err(rtwdev, "error beacon valid\n");
+			ret = -EBUSY;
+			break;
+		}
+	}
+
+restore:
+	rsvd_pg_head = rtwdev->fifo.rsvd_boundary;
+	rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, rsvd_pg_head | BIT(15));
+	rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, bckp[1]);
+	rtw_write8(rtwdev, REG_CR + 1, bckp[0]);
+
+	return ret;
+}
+
+static int rtw_download_drv_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
+{
+	u32 pg_size;
+	u32 pg_num = 0;
+	u16 pg_addr = 0;
+
+	pg_size = rtwdev->chip->page_size;
+	pg_num = size / pg_size + ((size & (pg_size - 1)) ? 1 : 0);
+	if (pg_num > rtwdev->fifo.rsvd_drv_pg_num)
+		return -ENOMEM;
+
+	pg_addr = rtwdev->fifo.rsvd_drv_addr;
+
+	return rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, size);
+}
+
+static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev,
+			       struct ieee80211_vif *vif, u32 *size)
+{
+	struct ieee80211_hw *hw = rtwdev->hw;
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct sk_buff *iter;
+	struct rtw_rsvd_page *rsvd_pkt;
+	u32 page = 0;
+	u8 total_page = 0;
+	u8 page_size, page_margin, tx_desc_sz;
+	u8 *buf;
+
+	page_size = chip->page_size;
+	tx_desc_sz = chip->tx_pkt_desc_sz;
+	page_margin = page_size - tx_desc_sz;
+
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
+		iter = rtw_get_rsvd_page_skb(hw, vif, rsvd_pkt->type);
+		if (!iter) {
+			rtw_err(rtwdev, "fail to build rsvd packet\n");
+			goto release_skb;
+		}
+		rsvd_pkt->skb = iter;
+		rsvd_pkt->page = total_page;
+		if (rsvd_pkt->add_txdesc)
+			total_page += rtw_len_to_page(iter->len + tx_desc_sz,
+						      page_size);
+		else
+			total_page += rtw_len_to_page(iter->len, page_size);
+	}
+
+	if (total_page > rtwdev->fifo.rsvd_drv_pg_num) {
+		rtw_err(rtwdev, "rsvd page over size: %d\n", total_page);
+		goto release_skb;
+	}
+
+	*size = (total_page - 1) * page_size + page_margin;
+	buf = kzalloc(*size, GFP_KERNEL | GFP_ATOMIC);
+
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
+		rtw_rsvd_page_list_to_buf(rtwdev, page_size, page_margin,
+					  page, buf, rsvd_pkt);
+		page += rtw_len_to_page(rsvd_pkt->skb->len, page_size);
+	}
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list)
+		kfree_skb(rsvd_pkt->skb);
+
+	return buf;
+
+release_skb:
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list)
+		kfree_skb(rsvd_pkt->skb);
+
+	return NULL;
+}
+
+static int
+rtw_download_beacon(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
+{
+	struct ieee80211_hw *hw = rtwdev->hw;
+	struct sk_buff *skb;
+	int ret = 0;
+
+	skb = rtw_beacon_get(hw, vif);
+	if (!skb) {
+		rtw_err(rtwdev, "failed to get beacon skb\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = rtw_download_drv_rsvd_page(rtwdev, skb->data, skb->len);
+	if (ret)
+		rtw_err(rtwdev, "failed to download drv rsvd page\n");
+
+	dev_kfree_skb(skb);
+
+out:
+	return ret;
+}
+
+int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
+{
+	u8 *buf;
+	u32 size;
+	int ret;
+
+	buf = rtw_build_rsvd_page(rtwdev, vif, &size);
+	if (!buf) {
+		rtw_err(rtwdev, "failed to build rsvd page pkt\n");
+		return -ENOMEM;
+	}
+
+	ret = rtw_download_drv_rsvd_page(rtwdev, buf, size);
+	if (ret) {
+		rtw_err(rtwdev, "failed to download drv rsvd page\n");
+		goto free;
+	}
+
+	ret = rtw_download_beacon(rtwdev, vif);
+	if (ret) {
+		rtw_err(rtwdev, "failed to download beacon\n");
+		goto free;
+	}
+
+	rtw_send_rsvd_page_h2c(rtwdev);
+
+free:
+	kfree(buf);
+
+	return ret;
+}
+
+int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
+			   u32 offset, u32 size, u32 *buf)
+{
+	struct rtw_fifo_conf *fifo = &rtwdev->fifo;
+	u32 residue, i;
+	u16 start_pg;
+	u16 idx = 0;
+	u16 ctl;
+	u8 rcr;
+
+	if (size & 0x3) {
+		rtw_warn(rtwdev, "should be 4-byte aligned\n");
+		return -EINVAL;
+	}
+
+	offset += fifo->rsvd_boundary << TX_PAGE_SIZE_SHIFT;
+	residue = offset & (FIFO_PAGE_SIZE - 1);
+	start_pg = offset >> FIFO_PAGE_SIZE_SHIFT;
+	start_pg += RSVD_PAGE_START_ADDR;
+
+	rcr = rtw_read8(rtwdev, REG_RCR + 2);
+	ctl = rtw_read16(rtwdev, REG_PKTBUF_DBG_CTRL) & 0xf000;
+
+	/* disable rx clock gate */
+	rtw_write8(rtwdev, REG_RCR, rcr | BIT(3));
+
+	do {
+		rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, start_pg | ctl);
+
+		for (i = FIFO_DUMP_ADDR + residue;
+		     i < FIFO_DUMP_ADDR + FIFO_PAGE_SIZE; i += 4) {
+			buf[idx++] = rtw_read32(rtwdev, i);
+			size -= 4;
+			if (size == 0)
+				goto out;
+		}
+
+		residue = 0;
+		start_pg++;
+	} while (size);
+
+out:
+	rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, ctl);
+	rtw_write8(rtwdev, REG_RCR + 2, rcr);
+	return 0;
+}
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
new file mode 100644
index 0000000..c063ffd
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2018  Realtek Corporation.
+ */
+
+#ifndef __RTW_FW_H_
+#define __RTW_FW_H_
+
+#define RTW_H2C_CLASS_OFFSET	5
+
+#define H2C_PKT_SIZE		32
+#define H2C_PKT_HDR_SIZE	8
+
+/* FW bin information */
+#define FW_HDR_SIZE			64
+#define FW_HDR_CHKSUM_SIZE		8
+#define FW_HDR_VERSION			4
+#define FW_HDR_SUBVERSION		6
+#define FW_HDR_SUBINDEX			7
+#define FW_HDR_MONTH			16
+#define FW_HDR_DATE			17
+#define FW_HDR_HOUR			18
+#define FW_HDR_MIN			19
+#define FW_HDR_YEAR			20
+#define FW_HDR_MEM_USAGE		24
+#define FW_HDR_H2C_FMT_VER		28
+#define FW_HDR_DMEM_ADDR		32
+#define FW_HDR_DMEM_SIZE		36
+#define FW_HDR_IMEM_SIZE		48
+#define FW_HDR_EMEM_SIZE		52
+#define FW_HDR_EMEM_ADDR		56
+#define FW_HDR_IMEM_ADDR		60
+
+#define FIFO_PAGE_SIZE_SHIFT		12
+#define FIFO_PAGE_SIZE			4096
+#define RSVD_PAGE_START_ADDR		0x780
+#define FIFO_DUMP_ADDR			0x8000
+
+enum rtw_c2h_cmd_id {
+	C2H_BT_INFO = 0x09,
+	C2H_HW_FEATURE_REPORT = 0x19,
+	C2H_HW_FEATURE_DUMP = 0xfd,
+	C2H_HALMAC = 0xff,
+};
+
+struct rtw_c2h_cmd {
+	u8 id;
+	u8 seq;
+	u8 payload[0];
+} __packed;
+
+enum rtw_rsvd_packet_type {
+	RSVD_BEACON,
+	RSVD_PS_POLL,
+	RSVD_PROBE_RESP,
+	RSVD_NULL,
+	RSVD_QOS_NULL,
+};
+
+enum rtw_fw_rf_type {
+	FW_RF_1T2R = 0,
+	FW_RF_2T4R = 1,
+	FW_RF_2T2R = 2,
+	FW_RF_2T3R = 3,
+	FW_RF_1T1R = 4,
+	FW_RF_2T2R_GREEN = 5,
+	FW_RF_3T3R = 6,
+	FW_RF_3T4R = 7,
+	FW_RF_4T4R = 8,
+	FW_RF_MAX_TYPE = 0xF,
+};
+
+struct rtw_general_info {
+	u8 rfe_type;
+	u8 rf_type;
+	u8 tx_ant_status;
+	u8 rx_ant_status;
+};
+
+struct rtw_iqk_para {
+	u8 clear;
+	u8 segment_iqk;
+};
+
+struct rtw_rsvd_page {
+	struct list_head list;
+	struct sk_buff *skb;
+	enum rtw_rsvd_packet_type type;
+	u8 page;
+	bool add_txdesc;
+};
+
+#define SUB_CMD_ID_GENERAL_INFO 0X0D
+#define SUB_CMD_ID_PHYDM_INFO 0X11
+#define SUB_CMD_ID_IQK 0X0E
+
+#define CMD_ID_RSSI_MONITOR	0x02
+#define CLASS_RSSI_MONITOR	0x02
+#define CMD_ID_RA_INFO		0x00
+#define CLASS_RA_INFO		0x02
+#define CMD_ID_MEDIA_STATUS_RPT	0X01
+#define CLASS_MEDIA_STATUS_RPT	0X0
+#define CMD_ID_SET_PWR_MODE	0X00
+#define CLASS_SET_PWR_MODE	0X01
+#define CMD_ID_RSVD_PAGE	0X0
+#define CLASS_RSVD_PAGE		0X0
+
+#define FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, value)                             \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X04, 16, 16, value)
+#define GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_pkt, value)                        \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X08, 16, 8, value)
+#define FW_OFFLOAD_H2C_SET_TOTAL_LEN(h2c_pkt, value)                           \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X04, 0, 16, value)
+#define FW_OFFLOAD_H2C_SET_SUB_CMD_ID(h2c_pkt, value)                          \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 16, 16, value)
+#define FW_OFFLOAD_H2C_SET_CATEGORY(h2c_pkt, value)                            \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 0, 7, value)
+#define FW_OFFLOAD_H2C_SET_CMD_ID(h2c_pkt, value)                              \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 8, 8, value)
+#define PHYDM_INFO_SET_REF_TYPE(h2c_pkt, value)                                \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X08, 0, 8, value)
+#define PHYDM_INFO_SET_RF_TYPE(h2c_pkt, value)                                 \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X08, 8, 8, value)
+#define PHYDM_INFO_SET_CUT_VER(h2c_pkt, value)                                 \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X08, 16, 8, value)
+#define PHYDM_INFO_SET_RX_ANT_STATUS(h2c_pkt, value)                           \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X08, 24, 4, value)
+#define PHYDM_INFO_SET_TX_ANT_STATUS(h2c_pkt, value)                           \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X08, 28, 4, value)
+#define IQK_SET_CLEAR(h2c_pkt, value)                                          \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X08, 0, 1, value)
+#define IQK_SET_SEGMENT_IQK(h2c_pkt, value)                                    \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X08, 1, 1, value)
+#define MEDIA_STATUS_RPT_SET_CMD_ID(h2c_pkt, value)                            \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 0, 5, value)
+#define MEDIA_STATUS_RPT_SET_CLASS(h2c_pkt, value)                             \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 5, 3, value)
+#define MEDIA_STATUS_RPT_SET_OP_MODE(h2c_pkt, value)                           \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 8, 1, value)
+#define MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, value)                             \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 16, 8, value)
+#define SET_PWR_MODE_SET_CMD_ID(h2c_pkt, value)                                \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 0, 5, value)
+#define SET_PWR_MODE_SET_CLASS(h2c_pkt, value)                                 \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 5, 3, value)
+#define SET_PWR_MODE_SET_MODE(h2c_pkt, value)                                  \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 8, 7, value)
+#define SET_PWR_MODE_SET_RLBM(h2c_pkt, value)                                  \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 16, 4, value)
+#define SET_PWR_MODE_SET_SMART_PS(h2c_pkt, value)                              \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 20, 4, value)
+#define SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_pkt, value)                        \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 24, 8, value)
+#define SET_PWR_MODE_SET_PORT_ID(h2c_pkt, value)                               \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X04, 5, 3, value)
+#define SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, value)                             \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X04, 8, 8, value)
+#define RSVD_PAGE_SET_CMD_ID(h2c_pkt, value)                                   \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 0, 5, value)
+#define RSVD_PAGE_SET_CLASS(h2c_pkt, value)                                    \
+	SET_BITS_TO_LE_4BYTE((h2c_pkt) + 0X00, 5, 3, value)
+
+void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
+void rtw_fw_send_general_info(struct rtw_dev *rtwdev,
+			      struct rtw_general_info *info);
+void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev,
+			    struct rtw_general_info *info);
+void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para);
+void rtw_fw_fill_h2c_cmd(struct rtw_dev *rtwdev, u8 cmd, u8 len, u8 *buf);
+void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev);
+void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
+void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
+void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn);
+void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type,
+		       bool txdesc);
+int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
+				u8 *buf, u32 size);
+void rtw_reset_rsvd_page(struct rtw_dev *rtwdev);
+int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev,
+			      struct ieee80211_vif *vif);
+int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
+			   u32 offset, u32 size, u32 *buf);
+#endif
-- 
2.7.4


  parent reply	other threads:[~2018-10-03 11:21 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-03 11:20 [RFC v3 00/12] rtw88: mac80211 driver for Realtek 802.11ac wireless network chips yhchuang
2018-10-03 11:20 ` [RFC v3 01/12] rtw88: main files yhchuang
2018-10-08 14:10   ` Johannes Berg
     [not found]   ` <201810081447.w98ElQfu018110@rtits1.realtek.com.tw>
2018-10-11  7:23     ` Tony Chuang
2018-10-11  7:30       ` Johannes Berg
2018-10-13 17:47       ` Kalle Valo
2018-10-22  3:40         ` Tony Chuang
2018-11-15 14:18           ` Kalle Valo
2018-10-03 11:20 ` [RFC v3 02/12] rtw88: core files yhchuang
2018-10-08 14:12   ` Johannes Berg
2018-10-03 11:20 ` [RFC v3 03/12] rtw88: hci files yhchuang
2018-10-03 11:20 ` [RFC v3 04/12] rtw88: trx files yhchuang
2018-10-03 11:20 ` [RFC v3 05/12] rtw88: mac files yhchuang
2018-10-08 13:38   ` Johannes Berg
2018-10-03 11:20 ` yhchuang [this message]
2018-10-03 11:20 ` [RFC v3 07/12] rtw88: phy files yhchuang
2018-10-04 14:10   ` Stanislaw Gruszka
2018-10-08  2:28     ` Tony Chuang
2018-10-03 11:20 ` [RFC v3 08/12] rtw88: debug files yhchuang
2018-10-04 14:23   ` Stanislaw Gruszka
2018-10-08  7:57     ` Tony Chuang
2018-10-08 13:29   ` Johannes Berg
     [not found]   ` <201810081446.w98EkN0r017815@rtits1.realtek.com.tw>
2018-10-09  2:42     ` Tony Chuang
2018-10-03 11:20 ` [RFC v3 09/12] rtw88: chip files yhchuang
2018-10-04 14:36   ` Stanislaw Gruszka
2018-10-08  9:38     ` Tony Chuang
2018-10-03 11:20 ` [RFC v3 10/12] rtw88: 8822B init table yhchuang
2018-10-03 11:20 ` [RFC v3 11/12] rtw88: 8822C " yhchuang
2018-10-03 11:20 ` [RFC v3 12/12] rtw88: Kconfig & Makefile yhchuang
2018-10-08 14:00   ` Johannes Berg
     [not found]   ` <201810081447.w98ElIFH018051@rtits1.realtek.com.tw>
2018-10-09  5:10     ` Tony Chuang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1538565659-29530-7-git-send-email-yhchuang@realtek.com \
    --to=yhchuang@realtek.com \
    --cc=Larry.Finger@lwfinger.net \
    --cc=kvalo@codeaurora.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=pkshih@realtek.com \
    --cc=sgruszka@redhat.com \
    --cc=tehuang@realtek.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.