Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
igb: Implement Rx PTP2 timestamp
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
  • Loading branch information
akihikodaki authored and jasowang committed May 23, 2023
1 parent bb97003 commit 3a9926d
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 41 deletions.
16 changes: 9 additions & 7 deletions hw/net/igb_common.h
Expand Up @@ -51,7 +51,7 @@
defreg_indexeda(x, 0), defreg_indexeda(x, 1), \
defreg_indexeda(x, 2), defreg_indexeda(x, 3)

#define defregv(x) defreg_indexed(x, 0), defreg_indexed(x, 1), \
#define defreg8(x) defreg_indexed(x, 0), defreg_indexed(x, 1), \
defreg_indexed(x, 2), defreg_indexed(x, 3), \
defreg_indexed(x, 4), defreg_indexed(x, 5), \
defreg_indexed(x, 6), defreg_indexed(x, 7)
Expand Down Expand Up @@ -122,6 +122,8 @@ enum {
defreg(EICS), defreg(EIMS), defreg(EIMC), defreg(EIAM),
defreg(EICR), defreg(IVAR_MISC), defreg(GPIE),

defreg(TSYNCRXCFG), defreg8(ETQF),

defreg(RXPBS), defregd(RDBAL), defregd(RDBAH), defregd(RDLEN),
defregd(SRRCTL), defregd(RDH), defregd(RDT),
defregd(RXDCTL), defregd(RXCTL), defregd(RQDPC), defreg(RA2),
Expand All @@ -133,15 +135,15 @@ enum {

defreg(VT_CTL),

defregv(P2VMAILBOX), defregv(V2PMAILBOX), defreg(MBVFICR), defreg(MBVFIMR),
defreg8(P2VMAILBOX), defreg8(V2PMAILBOX), defreg(MBVFICR), defreg(MBVFIMR),
defreg(VFLRE), defreg(VFRE), defreg(VFTE), defreg(WVBR),
defreg(QDE), defreg(DTXSWC), defreg_indexed(VLVF, 0),
defregv(VMOLR), defreg(RPLOLR), defregv(VMBMEM), defregv(VMVIR),
defreg8(VMOLR), defreg(RPLOLR), defreg8(VMBMEM), defreg8(VMVIR),

defregv(PVTCTRL), defregv(PVTEICS), defregv(PVTEIMS), defregv(PVTEIMC),
defregv(PVTEIAC), defregv(PVTEIAM), defregv(PVTEICR), defregv(PVFGPRC),
defregv(PVFGPTC), defregv(PVFGORC), defregv(PVFGOTC), defregv(PVFMPRC),
defregv(PVFGPRLBC), defregv(PVFGPTLBC), defregv(PVFGORLBC), defregv(PVFGOTLBC),
defreg8(PVTCTRL), defreg8(PVTEICS), defreg8(PVTEIMS), defreg8(PVTEIMC),
defreg8(PVTEIAC), defreg8(PVTEIAM), defreg8(PVTEICR), defreg8(PVFGPRC),
defreg8(PVFGPTC), defreg8(PVFGORC), defreg8(PVFGOTC), defreg8(PVFMPRC),
defreg8(PVFGPRLBC), defreg8(PVFGPTLBC), defreg8(PVFGORLBC), defreg8(PVFGOTLBC),

defreg(MTA_A),

Expand Down
129 changes: 95 additions & 34 deletions hw/net/igb_core.c
Expand Up @@ -72,6 +72,24 @@ typedef struct L2Header {
struct vlan_header vlan[2];
} L2Header;

typedef struct PTP2 {
uint8_t message_id_transport_specific;
uint8_t version_ptp;
uint16_t message_length;
uint8_t subdomain_number;
uint8_t reserved0;
uint16_t flags;
uint64_t correction;
uint8_t reserved1[5];
uint8_t source_communication_technology;
uint32_t source_uuid_lo;
uint16_t source_uuid_hi;
uint16_t source_port_id;
uint16_t sequence_id;
uint8_t control;
uint8_t log_message_period;
} PTP2;

static ssize_t
igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
bool has_vnet, bool *external_tx);
Expand Down Expand Up @@ -989,21 +1007,25 @@ static bool igb_rx_is_oversized(IGBCore *core, const struct eth_header *ehdr,
return lpe ? size + ETH_FCS_LEN > rlpml : size > header_size + ETH_MTU;
}

static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header,
size_t size, E1000E_RSSInfo *rss_info,
bool *external_tx)
static uint16_t igb_receive_assign(IGBCore *core, const struct iovec *iov,
size_t iovcnt, size_t iov_ofs,
const L2Header *l2_header, size_t size,
E1000E_RSSInfo *rss_info,
uint16_t *etqf, bool *ts, bool *external_tx)
{
static const int ta_shift[] = { 4, 3, 2, 0 };
const struct eth_header *ehdr = &l2_header->eth;
uint32_t f, ra[2], *macp, rctl = core->mac[RCTL];
uint16_t queues = 0;
uint16_t oversized = 0;
size_t vlan_num = 0;
PTP2 ptp2;
bool lpe;
uint16_t rlpml;
int i;

memset(rss_info, 0, sizeof(E1000E_RSSInfo));
*ts = false;

if (external_tx) {
*external_tx = true;
Expand All @@ -1028,6 +1050,26 @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header,
return queues;
}

for (*etqf = 0; *etqf < 8; (*etqf)++) {
if ((core->mac[ETQF0 + *etqf] & E1000_ETQF_FILTER_ENABLE) &&
be16_to_cpu(ehdr->h_proto) == (core->mac[ETQF0 + *etqf] & E1000_ETQF_ETYPE_MASK)) {
if ((core->mac[ETQF0 + *etqf] & E1000_ETQF_1588) &&
(core->mac[TSYNCRXCTL] & E1000_TSYNCRXCTL_ENABLED) &&
!(core->mac[TSYNCRXCTL] & E1000_TSYNCRXCTL_VALID) &&
iov_to_buf(iov, iovcnt, iov_ofs + ETH_HLEN, &ptp2, sizeof(ptp2)) >= sizeof(ptp2) &&
(ptp2.version_ptp & 15) == 2 &&
ptp2.message_id_transport_specific == ((core->mac[TSYNCRXCFG] >> 8) & 255)) {
e1000x_timestamp(core->mac, core->timadj, RXSTMPL, RXSTMPH);
*ts = true;
core->mac[TSYNCRXCTL] |= E1000_TSYNCRXCTL_VALID;
core->mac[RXSATRL] = le32_to_cpu(ptp2.source_uuid_lo);
core->mac[RXSATRH] = le16_to_cpu(ptp2.source_uuid_hi) |
(le16_to_cpu(ptp2.sequence_id) << 16);
}
break;
}
}

if (vlan_num &&
!e1000x_rx_vlan_filter(core->mac, l2_header->vlan + vlan_num - 1)) {
return queues;
Expand Down Expand Up @@ -1238,7 +1280,7 @@ static void
igb_build_rx_metadata(IGBCore *core,
struct NetRxPkt *pkt,
bool is_eop,
const E1000E_RSSInfo *rss_info,
const E1000E_RSSInfo *rss_info, uint16_t etqf, bool ts,
uint16_t *pkt_info, uint16_t *hdr_info,
uint32_t *rss,
uint32_t *status_flags,
Expand Down Expand Up @@ -1289,36 +1331,44 @@ igb_build_rx_metadata(IGBCore *core,
if (pkt_info) {
*pkt_info = rss_info->enabled ? rss_info->type : 0;

if (hasip4) {
*pkt_info |= E1000_ADVRXD_PKT_IP4;
}
if (etqf < 8) {
*pkt_info |= (BIT(11) | etqf) << 4;
} else {
if (hasip4) {
*pkt_info |= E1000_ADVRXD_PKT_IP4;
}

if (hasip6) {
*pkt_info |= E1000_ADVRXD_PKT_IP6;
}
if (hasip6) {
*pkt_info |= E1000_ADVRXD_PKT_IP6;
}

switch (l4hdr_proto) {
case ETH_L4_HDR_PROTO_TCP:
*pkt_info |= E1000_ADVRXD_PKT_TCP;
break;
switch (l4hdr_proto) {
case ETH_L4_HDR_PROTO_TCP:
*pkt_info |= E1000_ADVRXD_PKT_TCP;
break;

case ETH_L4_HDR_PROTO_UDP:
*pkt_info |= E1000_ADVRXD_PKT_UDP;
break;
case ETH_L4_HDR_PROTO_UDP:
*pkt_info |= E1000_ADVRXD_PKT_UDP;
break;

case ETH_L4_HDR_PROTO_SCTP:
*pkt_info |= E1000_ADVRXD_PKT_SCTP;
break;
case ETH_L4_HDR_PROTO_SCTP:
*pkt_info |= E1000_ADVRXD_PKT_SCTP;
break;

default:
break;
default:
break;
}
}
}

if (hdr_info) {
*hdr_info = 0;
}

if (ts) {
*status_flags |= BIT(16);
}

/* RX CSO information */
if (hasip6 && (core->mac[RFCTL] & E1000_RFCTL_IPV6_XSUM_DIS)) {
trace_e1000e_rx_metadata_ipv6_sum_disabled();
Expand Down Expand Up @@ -1374,7 +1424,7 @@ igb_build_rx_metadata(IGBCore *core,
static inline void
igb_write_lgcy_rx_descr(IGBCore *core, struct e1000_rx_desc *desc,
struct NetRxPkt *pkt,
const E1000E_RSSInfo *rss_info,
const E1000E_RSSInfo *rss_info, uint16_t etqf, bool ts,
uint16_t length)
{
uint32_t status_flags, rss;
Expand All @@ -1385,7 +1435,7 @@ igb_write_lgcy_rx_descr(IGBCore *core, struct e1000_rx_desc *desc,
desc->csum = 0;

igb_build_rx_metadata(core, pkt, pkt != NULL,
rss_info,
rss_info, etqf, ts,
NULL, NULL, &rss,
&status_flags, &ip_id,
&desc->special);
Expand All @@ -1396,15 +1446,15 @@ igb_write_lgcy_rx_descr(IGBCore *core, struct e1000_rx_desc *desc,
static inline void
igb_write_adv_rx_descr(IGBCore *core, union e1000_adv_rx_desc *desc,
struct NetRxPkt *pkt,
const E1000E_RSSInfo *rss_info,
const E1000E_RSSInfo *rss_info, uint16_t etqf, bool ts,
uint16_t length)
{
memset(&desc->wb, 0, sizeof(desc->wb));

desc->wb.upper.length = cpu_to_le16(length);

igb_build_rx_metadata(core, pkt, pkt != NULL,
rss_info,
rss_info, etqf, ts,
&desc->wb.lower.lo_dword.pkt_info,
&desc->wb.lower.lo_dword.hdr_info,
&desc->wb.lower.hi_dword.rss,
Expand All @@ -1415,12 +1465,15 @@ igb_write_adv_rx_descr(IGBCore *core, union e1000_adv_rx_desc *desc,

static inline void
igb_write_rx_descr(IGBCore *core, union e1000_rx_desc_union *desc,
struct NetRxPkt *pkt, const E1000E_RSSInfo *rss_info, uint16_t length)
struct NetRxPkt *pkt, const E1000E_RSSInfo *rss_info,
uint16_t etqf, bool ts, uint16_t length)
{
if (igb_rx_use_legacy_descriptor(core)) {
igb_write_lgcy_rx_descr(core, &desc->legacy, pkt, rss_info, length);
igb_write_lgcy_rx_descr(core, &desc->legacy, pkt, rss_info,
etqf, ts, length);
} else {
igb_write_adv_rx_descr(core, &desc->adv, pkt, rss_info, length);
igb_write_adv_rx_descr(core, &desc->adv, pkt, rss_info,
etqf, ts, length);
}
}

Expand Down Expand Up @@ -1497,7 +1550,8 @@ igb_rx_descr_threshold_hit(IGBCore *core, const E1000E_RingInfo *rxi)
static void
igb_write_packet_to_guest(IGBCore *core, struct NetRxPkt *pkt,
const E1000E_RxRing *rxr,
const E1000E_RSSInfo *rss_info)
const E1000E_RSSInfo *rss_info,
uint16_t etqf, bool ts)
{
PCIDevice *d;
dma_addr_t base;
Expand Down Expand Up @@ -1579,7 +1633,7 @@ igb_write_packet_to_guest(IGBCore *core, struct NetRxPkt *pkt,
}

igb_write_rx_descr(core, &desc, is_last ? core->rx_pkt : NULL,
rss_info, written);
rss_info, etqf, ts, written);
igb_pci_dma_write_rx_desc(core, d, base, &desc, core->rx_desc_len);

igb_ring_advance(core, rxi, core->rx_desc_len / E1000_MIN_RX_DESC_LEN);
Expand Down Expand Up @@ -1634,6 +1688,8 @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
size_t iov_ofs = 0;
E1000E_RxRing rxr;
E1000E_RSSInfo rss_info;
uint16_t etqf;
bool ts;
size_t total_size;
int strip_vlan_index;
int i;
Expand Down Expand Up @@ -1677,8 +1733,9 @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
get_eth_packet_type(&buf.l2_header.eth));
net_rx_pkt_set_protocols(core->rx_pkt, iov, iovcnt, iov_ofs);

queues = igb_receive_assign(core, &buf.l2_header, size,
&rss_info, external_tx);
queues = igb_receive_assign(core, iov, iovcnt, iov_ofs,
&buf.l2_header, size,
&rss_info, &etqf, &ts, external_tx);
if (!queues) {
trace_e1000e_rx_flt_dropped();
return orig_size;
Expand Down Expand Up @@ -1717,7 +1774,7 @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
causes |= E1000_ICR_RXDW;

igb_rx_fix_l4_csum(core, core->rx_pkt);
igb_write_packet_to_guest(core, core->rx_pkt, &rxr, &rss_info);
igb_write_packet_to_guest(core, core->rx_pkt, &rxr, &rss_info, etqf, ts);

/* Check if receive descriptor minimum threshold hit */
if (igb_rx_descr_threshold_hit(core, rxr.i)) {
Expand Down Expand Up @@ -3305,6 +3362,8 @@ static const readops igb_macreg_readops[] = {
[EIAM] = igb_mac_readreg,
[IVAR0 ... IVAR0 + 7] = igb_mac_readreg,
igb_getreg(IVAR_MISC),
igb_getreg(TSYNCRXCFG),
[ETQF0 ... ETQF0 + 7] = igb_mac_readreg,
igb_getreg(VT_CTL),
[P2VMAILBOX0 ... P2VMAILBOX7] = igb_mac_readreg,
[V2PMAILBOX0 ... V2PMAILBOX7] = igb_mac_vfmailbox_read,
Expand Down Expand Up @@ -3712,6 +3771,8 @@ static const writeops igb_macreg_writeops[] = {
[EIMS] = igb_set_eims,
[IVAR0 ... IVAR0 + 7] = igb_mac_writereg,
igb_putreg(IVAR_MISC),
igb_putreg(TSYNCRXCFG),
[ETQF0 ... ETQF0 + 7] = igb_mac_writereg,
igb_putreg(VT_CTL),
[P2VMAILBOX0 ... P2VMAILBOX7] = igb_set_pfmailbox,
[V2PMAILBOX0 ... V2PMAILBOX7] = igb_set_vfmailbox,
Expand Down
23 changes: 23 additions & 0 deletions hw/net/igb_regs.h
Expand Up @@ -210,6 +210,15 @@ union e1000_adv_rx_desc {
#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */
#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */

/* ETQF register bit definitions */
#define E1000_ETQF_FILTER_ENABLE BIT(26)
#define E1000_ETQF_1588 BIT(30)
#define E1000_ETQF_IMM_INT BIT(29)
#define E1000_ETQF_QUEUE_ENABLE BIT(31)
#define E1000_ETQF_QUEUE_SHIFT 16
#define E1000_ETQF_QUEUE_MASK 0x00070000
#define E1000_ETQF_ETYPE_MASK 0x0000FFFF

#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */
#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */
#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
Expand Down Expand Up @@ -384,6 +393,20 @@ union e1000_adv_rx_desc {
#define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */
#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */

#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */

/* Filtering Registers */
#define E1000_SAQF(_n) (0x5980 + 4 * (_n))
#define E1000_DAQF(_n) (0x59A0 + 4 * (_n))
#define E1000_SPQF(_n) (0x59C0 + 4 * (_n))
#define E1000_FTQF(_n) (0x59E0 + 4 * (_n))
#define E1000_SAQF0 E1000_SAQF(0)
#define E1000_DAQF0 E1000_DAQF(0)
#define E1000_SPQF0 E1000_SPQF(0)
#define E1000_FTQF0 E1000_FTQF(0)
#define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */
#define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */

#define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40))

#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
Expand Down

0 comments on commit 3a9926d

Please sign in to comment.