Commit ee1bfbcc authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'bnxt_en-updates'

Michael Chan says:

====================
bnxt_en: Updates

This small patchset adds an improvement to the configuration of ethtool
RSS tuple hash and a PTP improvement when running in a multi-host
environment.
====================

Link: https://lore.kernel.org/r/1667780192-3700-1-git-send-email-michael.chan@broadcom.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents b2140e97 85036aee
...@@ -5250,7 +5250,7 @@ int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings) ...@@ -5250,7 +5250,7 @@ int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings)
return 1; return 1;
} }
static void __bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic) static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic)
{ {
bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG); bool no_rss = !(vnic->flags & BNXT_VNIC_RSS_FLAG);
u16 i, j; u16 i, j;
...@@ -5263,8 +5263,8 @@ static void __bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic) ...@@ -5263,8 +5263,8 @@ static void __bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic)
} }
} }
static void __bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp, static void bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
struct bnxt_vnic_info *vnic) struct bnxt_vnic_info *vnic)
{ {
__le16 *ring_tbl = vnic->rss_table; __le16 *ring_tbl = vnic->rss_table;
struct bnxt_rx_ring_info *rxr; struct bnxt_rx_ring_info *rxr;
...@@ -5285,12 +5285,27 @@ static void __bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp, ...@@ -5285,12 +5285,27 @@ static void __bnxt_fill_hw_rss_tbl_p5(struct bnxt *bp,
} }
} }
static void bnxt_fill_hw_rss_tbl(struct bnxt *bp, struct bnxt_vnic_info *vnic) static void
__bnxt_hwrm_vnic_set_rss(struct bnxt *bp, struct hwrm_vnic_rss_cfg_input *req,
struct bnxt_vnic_info *vnic)
{ {
if (bp->flags & BNXT_FLAG_CHIP_P5) if (bp->flags & BNXT_FLAG_CHIP_P5)
__bnxt_fill_hw_rss_tbl_p5(bp, vnic); bnxt_fill_hw_rss_tbl_p5(bp, vnic);
else else
__bnxt_fill_hw_rss_tbl(bp, vnic); bnxt_fill_hw_rss_tbl(bp, vnic);
if (bp->rss_hash_delta) {
req->hash_type = cpu_to_le32(bp->rss_hash_delta);
if (bp->rss_hash_cfg & bp->rss_hash_delta)
req->flags |= VNIC_RSS_CFG_REQ_FLAGS_HASH_TYPE_INCLUDE;
else
req->flags |= VNIC_RSS_CFG_REQ_FLAGS_HASH_TYPE_EXCLUDE;
} else {
req->hash_type = cpu_to_le32(bp->rss_hash_cfg);
}
req->hash_mode_flags = VNIC_RSS_CFG_REQ_HASH_MODE_FLAGS_DEFAULT;
req->ring_grp_tbl_addr = cpu_to_le64(vnic->rss_table_dma_addr);
req->hash_key_tbl_addr = cpu_to_le64(vnic->rss_hash_key_dma_addr);
} }
static int bnxt_hwrm_vnic_set_rss(struct bnxt *bp, u16 vnic_id, bool set_rss) static int bnxt_hwrm_vnic_set_rss(struct bnxt *bp, u16 vnic_id, bool set_rss)
...@@ -5307,14 +5322,8 @@ static int bnxt_hwrm_vnic_set_rss(struct bnxt *bp, u16 vnic_id, bool set_rss) ...@@ -5307,14 +5322,8 @@ static int bnxt_hwrm_vnic_set_rss(struct bnxt *bp, u16 vnic_id, bool set_rss)
if (rc) if (rc)
return rc; return rc;
if (set_rss) { if (set_rss)
bnxt_fill_hw_rss_tbl(bp, vnic); __bnxt_hwrm_vnic_set_rss(bp, req, vnic);
req->hash_type = cpu_to_le32(bp->rss_hash_cfg);
req->hash_mode_flags = VNIC_RSS_CFG_REQ_HASH_MODE_FLAGS_DEFAULT;
req->ring_grp_tbl_addr = cpu_to_le64(vnic->rss_table_dma_addr);
req->hash_key_tbl_addr =
cpu_to_le64(vnic->rss_hash_key_dma_addr);
}
req->rss_ctx_idx = cpu_to_le16(vnic->fw_rss_cos_lb_ctx[0]); req->rss_ctx_idx = cpu_to_le16(vnic->fw_rss_cos_lb_ctx[0]);
return hwrm_req_send(bp, req); return hwrm_req_send(bp, req);
} }
...@@ -5335,10 +5344,7 @@ static int bnxt_hwrm_vnic_set_rss_p5(struct bnxt *bp, u16 vnic_id, bool set_rss) ...@@ -5335,10 +5344,7 @@ static int bnxt_hwrm_vnic_set_rss_p5(struct bnxt *bp, u16 vnic_id, bool set_rss)
if (!set_rss) if (!set_rss)
return hwrm_req_send(bp, req); return hwrm_req_send(bp, req);
bnxt_fill_hw_rss_tbl(bp, vnic); __bnxt_hwrm_vnic_set_rss(bp, req, vnic);
req->hash_type = cpu_to_le32(bp->rss_hash_cfg);
req->hash_mode_flags = VNIC_RSS_CFG_REQ_HASH_MODE_FLAGS_DEFAULT;
req->hash_key_tbl_addr = cpu_to_le64(vnic->rss_hash_key_dma_addr);
ring_tbl_map = vnic->rss_table_dma_addr; ring_tbl_map = vnic->rss_table_dma_addr;
nr_ctxs = bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings); nr_ctxs = bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings);
...@@ -5357,6 +5363,25 @@ static int bnxt_hwrm_vnic_set_rss_p5(struct bnxt *bp, u16 vnic_id, bool set_rss) ...@@ -5357,6 +5363,25 @@ static int bnxt_hwrm_vnic_set_rss_p5(struct bnxt *bp, u16 vnic_id, bool set_rss)
return rc; return rc;
} }
static void bnxt_hwrm_update_rss_hash_cfg(struct bnxt *bp)
{
struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
struct hwrm_vnic_rss_qcfg_output *resp;
struct hwrm_vnic_rss_qcfg_input *req;
if (hwrm_req_init(bp, req, HWRM_VNIC_RSS_QCFG))
return;
/* all contexts configured to same hash_type, zero always exists */
req->rss_ctx_idx = cpu_to_le16(vnic->fw_rss_cos_lb_ctx[0]);
resp = hwrm_req_hold(bp, req);
if (!hwrm_req_send(bp, req)) {
bp->rss_hash_cfg = le32_to_cpu(resp->hash_type) ?: bp->rss_hash_cfg;
bp->rss_hash_delta = 0;
}
hwrm_req_drop(bp, req);
}
static int bnxt_hwrm_vnic_set_hds(struct bnxt *bp, u16 vnic_id) static int bnxt_hwrm_vnic_set_hds(struct bnxt *bp, u16 vnic_id)
{ {
struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id]; struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
...@@ -5614,6 +5639,8 @@ static int bnxt_hwrm_vnic_qcaps(struct bnxt *bp) ...@@ -5614,6 +5639,8 @@ static int bnxt_hwrm_vnic_qcaps(struct bnxt *bp)
(BNXT_CHIP_P5_THOR(bp) && (BNXT_CHIP_P5_THOR(bp) &&
!(bp->fw_cap & BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED))) !(bp->fw_cap & BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED)))
bp->fw_cap |= BNXT_FW_CAP_VLAN_RX_STRIP; bp->fw_cap |= BNXT_FW_CAP_VLAN_RX_STRIP;
if (flags & VNIC_QCAPS_RESP_FLAGS_RSS_HASH_TYPE_DELTA_CAP)
bp->fw_cap |= BNXT_FW_CAP_RSS_HASH_TYPE_DELTA;
bp->max_tpa_v2 = le16_to_cpu(resp->max_aggs_supported); bp->max_tpa_v2 = le16_to_cpu(resp->max_aggs_supported);
if (bp->max_tpa_v2) { if (bp->max_tpa_v2) {
if (BNXT_CHIP_P5_THOR(bp)) if (BNXT_CHIP_P5_THOR(bp))
...@@ -6958,8 +6985,11 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp) ...@@ -6958,8 +6985,11 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp)
if (flags & FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED) if (flags & FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED)
bp->fw_cap |= BNXT_FW_CAP_DCBX_AGENT; bp->fw_cap |= BNXT_FW_CAP_DCBX_AGENT;
} }
if (BNXT_PF(bp) && (flags & FUNC_QCFG_RESP_FLAGS_MULTI_HOST)) if (BNXT_PF(bp) && (flags & FUNC_QCFG_RESP_FLAGS_MULTI_HOST)) {
bp->flags |= BNXT_FLAG_MULTI_HOST; bp->flags |= BNXT_FLAG_MULTI_HOST;
if (bp->fw_cap & BNXT_FW_CAP_PTP_RTC)
bp->fw_cap &= ~BNXT_FW_CAP_PTP_RTC;
}
if (flags & FUNC_QCFG_RESP_FLAGS_RING_MONITOR_ENABLED) if (flags & FUNC_QCFG_RESP_FLAGS_RING_MONITOR_ENABLED)
bp->fw_cap |= BNXT_FW_CAP_RING_MONITOR; bp->fw_cap |= BNXT_FW_CAP_RING_MONITOR;
...@@ -8808,6 +8838,8 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) ...@@ -8808,6 +8838,8 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
rc = bnxt_setup_vnic(bp, 0); rc = bnxt_setup_vnic(bp, 0);
if (rc) if (rc)
goto err_out; goto err_out;
if (bp->fw_cap & BNXT_FW_CAP_RSS_HASH_TYPE_DELTA)
bnxt_hwrm_update_rss_hash_cfg(bp);
if (bp->flags & BNXT_FLAG_RFS) { if (bp->flags & BNXT_FLAG_RFS) {
rc = bnxt_alloc_rfs_vnics(bp); rc = bnxt_alloc_rfs_vnics(bp);
...@@ -12243,6 +12275,8 @@ static void bnxt_set_dflt_rss_hash_type(struct bnxt *bp) ...@@ -12243,6 +12275,8 @@ static void bnxt_set_dflt_rss_hash_type(struct bnxt *bp)
VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 | VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 |
VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 | VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 |
VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6; VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
if (bp->fw_cap & BNXT_FW_CAP_RSS_HASH_TYPE_DELTA)
bp->rss_hash_delta = bp->rss_hash_cfg;
if (BNXT_CHIP_P4_PLUS(bp) && bp->hwrm_spec_code >= 0x10501) { if (BNXT_CHIP_P4_PLUS(bp) && bp->hwrm_spec_code >= 0x10501) {
bp->flags |= BNXT_FLAG_UDP_RSS_CAP; bp->flags |= BNXT_FLAG_UDP_RSS_CAP;
bp->rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 | bp->rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 |
......
...@@ -1900,6 +1900,7 @@ struct bnxt { ...@@ -1900,6 +1900,7 @@ struct bnxt {
u16 *rss_indir_tbl; u16 *rss_indir_tbl;
u16 rss_indir_tbl_entries; u16 rss_indir_tbl_entries;
u32 rss_hash_cfg; u32 rss_hash_cfg;
u32 rss_hash_delta;
u16 max_mtu; u16 max_mtu;
u8 max_tc; u8 max_tc;
...@@ -1965,6 +1966,7 @@ struct bnxt { ...@@ -1965,6 +1966,7 @@ struct bnxt {
#define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2 0x00010000 #define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2 0x00010000
#define BNXT_FW_CAP_PCIE_STATS_SUPPORTED 0x00020000 #define BNXT_FW_CAP_PCIE_STATS_SUPPORTED 0x00020000
#define BNXT_FW_CAP_EXT_STATS_SUPPORTED 0x00040000 #define BNXT_FW_CAP_EXT_STATS_SUPPORTED 0x00040000
#define BNXT_FW_CAP_RSS_HASH_TYPE_DELTA 0x00080000
#define BNXT_FW_CAP_ERR_RECOVER_RELOAD 0x00100000 #define BNXT_FW_CAP_ERR_RECOVER_RELOAD 0x00100000
#define BNXT_FW_CAP_HOT_RESET 0x00200000 #define BNXT_FW_CAP_HOT_RESET 0x00200000
#define BNXT_FW_CAP_PTP_RTC 0x00400000 #define BNXT_FW_CAP_PTP_RTC 0x00400000
......
...@@ -1234,6 +1234,8 @@ static int bnxt_srxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd) ...@@ -1234,6 +1234,8 @@ static int bnxt_srxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd)
if (bp->rss_hash_cfg == rss_hash_cfg) if (bp->rss_hash_cfg == rss_hash_cfg)
return 0; return 0;
if (bp->fw_cap & BNXT_FW_CAP_RSS_HASH_TYPE_DELTA)
bp->rss_hash_delta = bp->rss_hash_cfg ^ rss_hash_cfg;
bp->rss_hash_cfg = rss_hash_cfg; bp->rss_hash_cfg = rss_hash_cfg;
if (netif_running(bp->dev)) { if (netif_running(bp->dev)) {
bnxt_close_nic(bp, false, false); bnxt_close_nic(bp, false, false);
......
...@@ -6768,6 +6768,53 @@ struct hwrm_vnic_rss_cfg_cmd_err { ...@@ -6768,6 +6768,53 @@ struct hwrm_vnic_rss_cfg_cmd_err {
u8 unused_0[7]; u8 unused_0[7];
}; };
/* hwrm_vnic_rss_qcfg_input (size:192b/24B) */
struct hwrm_vnic_rss_qcfg_input {
__le16 req_type;
__le16 cmpl_ring;
__le16 seq_id;
__le16 target_id;
__le64 resp_addr;
__le16 rss_ctx_idx;
__le16 vnic_id;
u8 unused_0[4];
};
/* hwrm_vnic_rss_qcfg_output (size:512b/64B) */
struct hwrm_vnic_rss_qcfg_output {
__le16 error_code;
__le16 req_type;
__le16 seq_id;
__le16 resp_len;
__le32 hash_type;
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_IPV4 0x1UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_TCP_IPV4 0x2UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_UDP_IPV4 0x4UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_IPV6 0x8UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_TCP_IPV6 0x10UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_UDP_IPV6 0x20UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_IPV6_FLOW_LABEL 0x40UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_AH_SPI_IPV4 0x80UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_ESP_SPI_IPV4 0x100UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_AH_SPI_IPV6 0x200UL
#define VNIC_RSS_QCFG_RESP_HASH_TYPE_ESP_SPI_IPV6 0x400UL
u8 unused_0[4];
__le32 hash_key[10];
u8 hash_mode_flags;
#define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_DEFAULT 0x1UL
#define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_INNERMOST_4 0x2UL
#define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_INNERMOST_2 0x4UL
#define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_OUTERMOST_4 0x8UL
#define VNIC_RSS_QCFG_RESP_HASH_MODE_FLAGS_OUTERMOST_2 0x10UL
u8 ring_select_mode;
#define VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_TOEPLITZ 0x0UL
#define VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_XOR 0x1UL
#define VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_TOEPLITZ_CHECKSUM 0x2UL
#define VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_LAST VNIC_RSS_QCFG_RESP_RING_SELECT_MODE_TOEPLITZ_CHECKSUM
u8 unused_1[5];
u8 valid;
};
/* hwrm_vnic_plcmodes_cfg_input (size:320b/40B) */ /* hwrm_vnic_plcmodes_cfg_input (size:320b/40B) */
struct hwrm_vnic_plcmodes_cfg_input { struct hwrm_vnic_plcmodes_cfg_input {
__le16 req_type; __le16 req_type;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/net_tstamp.h> #include <linux/net_tstamp.h>
#include <linux/timekeeping.h> #include <linux/timekeeping.h>
#include <linux/ptp_classify.h> #include <linux/ptp_classify.h>
#include <linux/clocksource.h>
#include "bnxt_hsi.h" #include "bnxt_hsi.h"
#include "bnxt.h" #include "bnxt.h"
#include "bnxt_hwrm.h" #include "bnxt_hwrm.h"
...@@ -210,18 +211,37 @@ static int bnxt_ptp_adjfreq(struct ptp_clock_info *ptp_info, s32 ppb) ...@@ -210,18 +211,37 @@ static int bnxt_ptp_adjfreq(struct ptp_clock_info *ptp_info, s32 ppb)
ptp_info); ptp_info);
struct hwrm_port_mac_cfg_input *req; struct hwrm_port_mac_cfg_input *req;
struct bnxt *bp = ptp->bp; struct bnxt *bp = ptp->bp;
int rc; int rc = 0;
rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG); if (!(ptp->bp->fw_cap & BNXT_FW_CAP_PTP_RTC)) {
if (rc) int neg_adj = 0;
return rc; u32 diff;
u64 adj;
req->ptp_freq_adj_ppb = cpu_to_le32(ppb); if (ppb < 0) {
req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_FREQ_ADJ_PPB); neg_adj = 1;
rc = hwrm_req_send(ptp->bp, req); ppb = -ppb;
if (rc) }
netdev_err(ptp->bp->dev, adj = ptp->cmult;
"ptp adjfreq failed. rc = %d\n", rc); adj *= ppb;
diff = div_u64(adj, 1000000000ULL);
spin_lock_bh(&ptp->ptp_lock);
timecounter_read(&ptp->tc);
ptp->cc.mult = neg_adj ? ptp->cmult - diff : ptp->cmult + diff;
spin_unlock_bh(&ptp->ptp_lock);
} else {
rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG);
if (rc)
return rc;
req->ptp_freq_adj_ppb = cpu_to_le32(ppb);
req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_FREQ_ADJ_PPB);
rc = hwrm_req_send(ptp->bp, req);
if (rc)
netdev_err(ptp->bp->dev,
"ptp adjfreq failed. rc = %d\n", rc);
}
return rc; return rc;
} }
...@@ -846,8 +866,9 @@ static void bnxt_ptp_timecounter_init(struct bnxt *bp, bool init_tc) ...@@ -846,8 +866,9 @@ static void bnxt_ptp_timecounter_init(struct bnxt *bp, bool init_tc)
memset(&ptp->cc, 0, sizeof(ptp->cc)); memset(&ptp->cc, 0, sizeof(ptp->cc));
ptp->cc.read = bnxt_cc_read; ptp->cc.read = bnxt_cc_read;
ptp->cc.mask = CYCLECOUNTER_MASK(48); ptp->cc.mask = CYCLECOUNTER_MASK(48);
ptp->cc.shift = 0; ptp->cc.shift = BNXT_CYCLES_SHIFT;
ptp->cc.mult = 1; ptp->cc.mult = clocksource_khz2mult(BNXT_DEVCLK_FREQ, ptp->cc.shift);
ptp->cmult = ptp->cc.mult;
ptp->next_overflow_check = jiffies + BNXT_PHC_OVERFLOW_PERIOD; ptp->next_overflow_check = jiffies + BNXT_PHC_OVERFLOW_PERIOD;
} }
if (init_tc) if (init_tc)
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#define BNXT_PTP_GRC_WIN_BASE 0x6000 #define BNXT_PTP_GRC_WIN_BASE 0x6000
#define BNXT_MAX_PHC_DRIFT 31000000 #define BNXT_MAX_PHC_DRIFT 31000000
#define BNXT_CYCLES_SHIFT 23
#define BNXT_DEVCLK_FREQ 1000000
#define BNXT_LO_TIMER_MASK 0x0000ffffffffUL #define BNXT_LO_TIMER_MASK 0x0000ffffffffUL
#define BNXT_HI_TIMER_MASK 0xffff00000000UL #define BNXT_HI_TIMER_MASK 0xffff00000000UL
...@@ -88,8 +90,9 @@ struct bnxt_ptp_cfg { ...@@ -88,8 +90,9 @@ struct bnxt_ptp_cfg {
u64 old_time; u64 old_time;
unsigned long next_period; unsigned long next_period;
unsigned long next_overflow_check; unsigned long next_overflow_check;
/* 48-bit PHC overflows in 78 hours. Check overflow every 19 hours. */ u32 cmult;
#define BNXT_PHC_OVERFLOW_PERIOD (19 * 3600 * HZ) /* a 23b shift cyclecounter will overflow in ~36 mins. Check overflow every 18 mins. */
#define BNXT_PHC_OVERFLOW_PERIOD (18 * 60 * HZ)
u16 tx_seqid; u16 tx_seqid;
u16 tx_hdr_off; u16 tx_hdr_off;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment