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
next prev 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.