igb: Implement Rx PTP2 timestamp
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
parent
bb97003e73
commit
3a9926d939
@ -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)
|
||||
@ -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),
|
||||
@ -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),
|
||||
|
||||
|
@ -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);
|
||||
@ -989,9 +1007,11 @@ 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;
|
||||
@ -999,11 +1019,13 @@ static uint16_t igb_receive_assign(IGBCore *core, const L2Header *l2_header,
|
||||
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;
|
||||
@ -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;
|
||||
@ -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,
|
||||
@ -1289,29 +1331,33 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1319,6 +1365,10 @@ igb_build_rx_metadata(IGBCore *core,
|
||||
*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();
|
||||
@ -1374,7 +1424,7 @@ func_exit:
|
||||
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;
|
||||
@ -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);
|
||||
@ -1396,7 +1446,7 @@ 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));
|
||||
@ -1404,7 +1454,7 @@ igb_write_adv_rx_descr(IGBCore *core, union e1000_adv_rx_desc *desc,
|
||||
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,
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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);
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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)) {
|
||||
@ -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,
|
||||
@ -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,
|
||||
|
@ -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 */
|
||||
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user