Also introduce:
- Checks for RXDCTL/TXDCTL queue enable bits
- IGB_NUM_VM_POOLS enum (Sec 1.5: Table 1-7)
Signed-off-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech>
---
hw/net/igb_core.c | 39 +++++++++++++++++++++++++++++++--------
hw/net/igb_core.h | 1 +
hw/net/igb_regs.h | 3 +++
3 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c
index 1ddf54f630..8437cd6829 100644
--- a/hw/net/igb_core.c
+++ b/hw/net/igb_core.c
@@ -780,6 +780,18 @@ igb_txdesc_writeback(IGBCore *core, dma_addr_t base,
return igb_tx_wb_eic(core, txi->idx);
}
+static inline bool
+igb_tx_enabled(IGBCore *core, const E1000E_RingInfo *txi)
+{
+ bool vmdq = core->mac[MRQC] & 1;
+ uint16_t qn = txi->idx;
+ uint16_t pool = qn % IGB_NUM_VM_POOLS;
+
+ return (core->mac[TCTL] & E1000_TCTL_EN) &&
+ (!vmdq || core->mac[VFTE] & BIT(pool)) &&
+ (core->mac[TXDCTL0 + (qn * 16)] & E1000_TXDCTL_QUEUE_ENABLE);
+}
+
static void
igb_start_xmit(IGBCore *core, const IGB_TxRing *txr)
{
@@ -789,8 +801,7 @@ igb_start_xmit(IGBCore *core, const IGB_TxRing *txr)
const E1000E_RingInfo *txi = txr->i;
uint32_t eic = 0;
- /* TODO: check if the queue itself is enabled too. */
- if (!(core->mac[TCTL] & E1000_TCTL_EN)) {
+ if (!igb_tx_enabled(core, txi)) {
trace_e1000e_tx_disabled();
return;
}
@@ -866,6 +877,9 @@ igb_can_receive(IGBCore *core)
for (i = 0; i < IGB_NUM_QUEUES; i++) {
E1000E_RxRing rxr;
+ if (!(core->mac[RXDCTL0 + (i * 16)] & E1000_RXDCTL_QUEUE_ENABLE)) {
+ continue;
+ }
igb_rx_ring_init(core, &rxr, i);
if (igb_ring_enabled(core, rxr.i) && igb_has_rxbufs(core, rxr.i, 1)) {
@@ -932,7 +946,7 @@ static uint16_t igb_receive_assign(IGBCore *core, const struct eth_header *ehdr,
if (core->mac[MRQC] & 1) {
if (is_broadcast_ether_addr(ehdr->h_dest)) {
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
if (core->mac[VMOLR0 + i] & E1000_VMOLR_BAM) {
queues |= BIT(i);
}
@@ -966,7 +980,7 @@ static uint16_t igb_receive_assign(IGBCore *core, const struct eth_header *ehdr,
f = ta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
f = (((ehdr->h_dest[5] << 8) | ehdr->h_dest[4]) >> f) & 0xfff;
if (macp[f >> 5] & (1 << (f & 0x1f))) {
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
if (core->mac[VMOLR0 + i] & E1000_VMOLR_ROMPE) {
queues |= BIT(i);
}
@@ -989,7 +1003,7 @@ static uint16_t igb_receive_assign(IGBCore *core, const struct eth_header *ehdr,
}
}
} else {
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
if (core->mac[VMOLR0 + i] & E1000_VMOLR_AUPE) {
mask |= BIT(i);
}
@@ -1005,6 +1019,7 @@ static uint16_t igb_receive_assign(IGBCore *core, const struct eth_header *ehdr,
queues = BIT(def_pl >> E1000_VT_CTL_DEFAULT_POOL_SHIFT);
}
+ queues &= core->mac[VFRE];
igb_rss_parse_packet(core, core->rx_pkt, external_tx != NULL, rss_info);
if (rss_info->queue & 1) {
queues <<= 8;
@@ -1562,12 +1577,12 @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
igb_rx_fix_l4_csum(core, core->rx_pkt);
for (i = 0; i < IGB_NUM_QUEUES; i++) {
- if (!(queues & BIT(i))) {
+ if (!(queues & BIT(i)) ||
+ !(core->mac[RXDCTL0 + (i * 16)] & E1000_RXDCTL_QUEUE_ENABLE)) {
continue;
}
igb_rx_ring_init(core, &rxr, i);
-
if (!igb_has_rxbufs(core, rxr.i, total_size)) {
n |= E1000_ICS_RXO;
trace_e1000e_rx_not_written_to_guest(rxr.i->idx);
@@ -1966,9 +1981,16 @@ static void igb_set_vfmailbox(IGBCore *core, int index, uint32_t val)
static void igb_vf_reset(IGBCore *core, uint16_t vfn)
{
+ uint16_t qn0 = vfn;
+ uint16_t qn1 = vfn + IGB_NUM_VM_POOLS;
+
/* disable Rx and Tx for the VF*/
- core->mac[VFTE] &= ~BIT(vfn);
+ core->mac[RXDCTL0 + (qn0 * 16)] &= ~E1000_RXDCTL_QUEUE_ENABLE;
+ core->mac[RXDCTL0 + (qn1 * 16)] &= ~E1000_RXDCTL_QUEUE_ENABLE;
+ core->mac[TXDCTL0 + (qn0 * 16)] &= ~E1000_TXDCTL_QUEUE_ENABLE;
+ core->mac[TXDCTL0 + (qn1 * 16)] &= ~E1000_TXDCTL_QUEUE_ENABLE;
core->mac[VFRE] &= ~BIT(vfn);
+ core->mac[VFTE] &= ~BIT(vfn);
/* indicate VF reset to PF */
core->mac[VFLRE] |= BIT(vfn);
/* VFLRE and mailbox use the same interrupt cause */
@@ -3874,6 +3896,7 @@ igb_phy_reg_init[] = {
static const uint32_t igb_mac_reg_init[] = {
[LEDCTL] = 2 | (3 << 8) | BIT(15) | (6 << 16) | (7 << 24),
[EEMNGCTL] = BIT(31),
+ [TXDCTL0] = E1000_TXDCTL_QUEUE_ENABLE,
[RXDCTL0] = E1000_RXDCTL_QUEUE_ENABLE | (1 << 16),
[RXDCTL1] = 1 << 16,
[RXDCTL2] = 1 << 16,
diff --git a/hw/net/igb_core.h b/hw/net/igb_core.h
index cc3b4d1f2b..9938922598 100644
--- a/hw/net/igb_core.h
+++ b/hw/net/igb_core.h
@@ -47,6 +47,7 @@
#define IGB_MSIX_VEC_NUM (10)
#define IGBVF_MSIX_VEC_NUM (3)
#define IGB_NUM_QUEUES (16)
+#define IGB_NUM_VM_POOLS (8)
typedef struct IGBCore IGBCore;
diff --git a/hw/net/igb_regs.h b/hw/net/igb_regs.h
index ddc0f931d6..4d98079906 100644
--- a/hw/net/igb_regs.h
+++ b/hw/net/igb_regs.h
@@ -160,6 +160,9 @@ union e1000_adv_rx_desc {
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
+/* Additional Transmit Descriptor Control definitions */
+#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
+
/* Additional Receive Descriptor Control definitions */
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
--
2.34.1
On 2023/02/02 16:26, Sriram Yagnaraman wrote:
> Also introduce:
> - Checks for RXDCTL/TXDCTL queue enable bits
> - IGB_NUM_VM_POOLS enum (Sec 1.5: Table 1-7)
>
> Signed-off-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech>
> ---
> hw/net/igb_core.c | 39 +++++++++++++++++++++++++++++++--------
> hw/net/igb_core.h | 1 +
> hw/net/igb_regs.h | 3 +++
> 3 files changed, 35 insertions(+), 8 deletions(-)
>
> diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c
> index 1ddf54f630..8437cd6829 100644
> --- a/hw/net/igb_core.c
> +++ b/hw/net/igb_core.c
> @@ -780,6 +780,18 @@ igb_txdesc_writeback(IGBCore *core, dma_addr_t base,
> return igb_tx_wb_eic(core, txi->idx);
> }
>
> +static inline bool
> +igb_tx_enabled(IGBCore *core, const E1000E_RingInfo *txi)
> +{
> + bool vmdq = core->mac[MRQC] & 1;
> + uint16_t qn = txi->idx;
> + uint16_t pool = qn % IGB_NUM_VM_POOLS;
> +
> + return (core->mac[TCTL] & E1000_TCTL_EN) &&
> + (!vmdq || core->mac[VFTE] & BIT(pool)) &&
> + (core->mac[TXDCTL0 + (qn * 16)] & E1000_TXDCTL_QUEUE_ENABLE);
> +}
> +
> static void
> igb_start_xmit(IGBCore *core, const IGB_TxRing *txr)
> {
> @@ -789,8 +801,7 @@ igb_start_xmit(IGBCore *core, const IGB_TxRing *txr)
> const E1000E_RingInfo *txi = txr->i;
> uint32_t eic = 0;
>
> - /* TODO: check if the queue itself is enabled too. */
> - if (!(core->mac[TCTL] & E1000_TCTL_EN)) {
> + if (!igb_tx_enabled(core, txi)) {
> trace_e1000e_tx_disabled();
> return;
> }
> @@ -866,6 +877,9 @@ igb_can_receive(IGBCore *core)
>
> for (i = 0; i < IGB_NUM_QUEUES; i++) {
> E1000E_RxRing rxr;
> + if (!(core->mac[RXDCTL0 + (i * 16)] & E1000_RXDCTL_QUEUE_ENABLE)) {
> + continue;
> + }
>
> igb_rx_ring_init(core, &rxr, i);
> if (igb_ring_enabled(core, rxr.i) && igb_has_rxbufs(core, rxr.i, 1)) {
> @@ -932,7 +946,7 @@ static uint16_t igb_receive_assign(IGBCore *core, const struct eth_header *ehdr,
>
> if (core->mac[MRQC] & 1) {
> if (is_broadcast_ether_addr(ehdr->h_dest)) {
> - for (i = 0; i < 8; i++) {
> + for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
> if (core->mac[VMOLR0 + i] & E1000_VMOLR_BAM) {
> queues |= BIT(i);
> }
> @@ -966,7 +980,7 @@ static uint16_t igb_receive_assign(IGBCore *core, const struct eth_header *ehdr,
> f = ta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
> f = (((ehdr->h_dest[5] << 8) | ehdr->h_dest[4]) >> f) & 0xfff;
> if (macp[f >> 5] & (1 << (f & 0x1f))) {
> - for (i = 0; i < 8; i++) {
> + for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
> if (core->mac[VMOLR0 + i] & E1000_VMOLR_ROMPE) {
> queues |= BIT(i);
> }
> @@ -989,7 +1003,7 @@ static uint16_t igb_receive_assign(IGBCore *core, const struct eth_header *ehdr,
> }
> }
> } else {
> - for (i = 0; i < 8; i++) {
> + for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
> if (core->mac[VMOLR0 + i] & E1000_VMOLR_AUPE) {
> mask |= BIT(i);
> }
> @@ -1005,6 +1019,7 @@ static uint16_t igb_receive_assign(IGBCore *core, const struct eth_header *ehdr,
> queues = BIT(def_pl >> E1000_VT_CTL_DEFAULT_POOL_SHIFT);
> }
>
> + queues &= core->mac[VFRE];
> igb_rss_parse_packet(core, core->rx_pkt, external_tx != NULL, rss_info);
> if (rss_info->queue & 1) {
> queues <<= 8;
> @@ -1562,12 +1577,12 @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
> igb_rx_fix_l4_csum(core, core->rx_pkt);
>
> for (i = 0; i < IGB_NUM_QUEUES; i++) {
> - if (!(queues & BIT(i))) {
> + if (!(queues & BIT(i)) ||
> + !(core->mac[RXDCTL0 + (i * 16)] & E1000_RXDCTL_QUEUE_ENABLE)) {
> continue;
> }
>
> igb_rx_ring_init(core, &rxr, i);
> -
This deletion of line is irrelevant and should be removed.
This is probably the last change I request. I will test this series and
gives Reviewed-by: and Tested-by: after that.
> if (!igb_has_rxbufs(core, rxr.i, total_size)) {
> n |= E1000_ICS_RXO;
> trace_e1000e_rx_not_written_to_guest(rxr.i->idx);
> @@ -1966,9 +1981,16 @@ static void igb_set_vfmailbox(IGBCore *core, int index, uint32_t val)
>
> static void igb_vf_reset(IGBCore *core, uint16_t vfn)
> {
> + uint16_t qn0 = vfn;
> + uint16_t qn1 = vfn + IGB_NUM_VM_POOLS;
> +
> /* disable Rx and Tx for the VF*/
> - core->mac[VFTE] &= ~BIT(vfn);
> + core->mac[RXDCTL0 + (qn0 * 16)] &= ~E1000_RXDCTL_QUEUE_ENABLE;
> + core->mac[RXDCTL0 + (qn1 * 16)] &= ~E1000_RXDCTL_QUEUE_ENABLE;
> + core->mac[TXDCTL0 + (qn0 * 16)] &= ~E1000_TXDCTL_QUEUE_ENABLE;
> + core->mac[TXDCTL0 + (qn1 * 16)] &= ~E1000_TXDCTL_QUEUE_ENABLE;
> core->mac[VFRE] &= ~BIT(vfn);
> + core->mac[VFTE] &= ~BIT(vfn);
> /* indicate VF reset to PF */
> core->mac[VFLRE] |= BIT(vfn);
> /* VFLRE and mailbox use the same interrupt cause */
> @@ -3874,6 +3896,7 @@ igb_phy_reg_init[] = {
> static const uint32_t igb_mac_reg_init[] = {
> [LEDCTL] = 2 | (3 << 8) | BIT(15) | (6 << 16) | (7 << 24),
> [EEMNGCTL] = BIT(31),
> + [TXDCTL0] = E1000_TXDCTL_QUEUE_ENABLE,
> [RXDCTL0] = E1000_RXDCTL_QUEUE_ENABLE | (1 << 16),
> [RXDCTL1] = 1 << 16,
> [RXDCTL2] = 1 << 16,
> diff --git a/hw/net/igb_core.h b/hw/net/igb_core.h
> index cc3b4d1f2b..9938922598 100644
> --- a/hw/net/igb_core.h
> +++ b/hw/net/igb_core.h
> @@ -47,6 +47,7 @@
> #define IGB_MSIX_VEC_NUM (10)
> #define IGBVF_MSIX_VEC_NUM (3)
> #define IGB_NUM_QUEUES (16)
> +#define IGB_NUM_VM_POOLS (8)
>
> typedef struct IGBCore IGBCore;
>
> diff --git a/hw/net/igb_regs.h b/hw/net/igb_regs.h
> index ddc0f931d6..4d98079906 100644
> --- a/hw/net/igb_regs.h
> +++ b/hw/net/igb_regs.h
> @@ -160,6 +160,9 @@ union e1000_adv_rx_desc {
> #define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
> #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
>
> +/* Additional Transmit Descriptor Control definitions */
> +#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
> +
> /* Additional Receive Descriptor Control definitions */
> #define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
>
© 2016 - 2026 Red Hat, Inc.