From: Alex Williamson <alex@shazbot.org>
To: Josh Hilke <jrhilke@google.com>
Cc: David Matlack <dmatlack@google.com>,
Shuah Khan <shuah@kernel.org>,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
linux-kselftest@vger.kernel.org,
Vipin Sharma <vipinsh@google.com>,
Alex Williamson <alex.williamson@nvidia.com>,
alex@shazbot.org
Subject: Re: [PATCH v9 1/5] vfio: selftests: igb: Add driver for Intel 82576 device
Date: Fri, 31 Jul 2026 12:15:02 -0600 [thread overview]
Message-ID: <20260731121502.3e5416ca@shazbot.org> (raw)
In-Reply-To: <20260730-igb_v3_b4-v9-1-9e4d8682437e@google.com>
On Thu, 30 Jul 2026 23:31:29 +0000
Josh Hilke <jrhilke@google.com> wrote:
> +static void igb_init(struct vfio_pci_device *device)
> +{
> + struct igb *igb = to_igb_state(device);
> + u64 iova_tx, iova_rx;
> + u32 ctrl, rctl;
> + u16 cmd_reg;
> + int retries;
> +
> + VFIO_ASSERT_GE(device->driver.region.size, sizeof(struct igb));
> +
> + /* Set up rings and calculate IOVAs */
> + igb->bar0 = device->bars[0].vaddr;
> +
> + iova_tx = to_iova(device, igb->tx_ring);
> + iova_rx = to_iova(device, igb->rx_ring);
> +
> + igb_reset(igb);
> +
> + /* Signal that the driver is loaded */
> + ctrl = igb_read32(igb, E1000_CTRL_EXT);
> + ctrl |= E1000_CTRL_EXT_DRV_LOAD;
> + ctrl &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
> + igb_write32(igb, E1000_CTRL_EXT, ctrl);
> +
> + /* Enable PCI Bus Master. */
> + cmd_reg = vfio_pci_config_readw(device, PCI_COMMAND);
> + if ((cmd_reg & (PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY)) !=
> + (PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY)) {
> + cmd_reg |= (PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
> + vfio_pci_config_writew(device, PCI_COMMAND, cmd_reg);
> + }
> +
> + /* Configure PHY internal loopback for testing. */
> + igb_setup_loopback(igb);
> +
> + /*
> + * Disable DMA re-send on PCIe completion timeout (82576 datasheet
> + * section 8.6.1, GCR.Completion_Timeout_Resend, bit 16). The
> + * mix_and_match test intentionally submits descriptors targeting
> + * unmapped IOVAs; with the default (set) value, the device keeps
> + * retrying the failed read indefinitely, which keeps PCIe AER and
> + * IOMMU error handling busy and interferes with reset recovery.
> + */
> + ctrl = igb_read32(igb, E1000_GCR);
> + ctrl &= ~E1000_GCR_CMPL_TMOUT_RESEND;
> + igb_write32(igb, E1000_GCR, ctrl);
> +
> + /* Configure TX and RX descriptor rings */
> + igb_write32(igb, E1000_TDBAL(0), (u32)iova_tx);
> + igb_write32(igb, E1000_TDBAH(0), (u32)(iova_tx >> 32));
> + igb_write32(igb, E1000_TDLEN(0), RING_SIZE * sizeof(struct igb_tx_desc));
> + igb_write32(igb, E1000_TDH(0), 0);
> + igb_write32(igb, E1000_TDT(0), 0);
> + igb_write32(igb, E1000_TXDCTL(0), E1000_TXDCTL_QUEUE_ENABLE);
> +
> + igb_write32(igb, E1000_RDBAL(0), (u32)iova_rx);
> + igb_write32(igb, E1000_RDBAH(0), (u32)(iova_rx >> 32));
> + igb_write32(igb, E1000_RDLEN(0), RING_SIZE * sizeof(struct igb_rx_desc));
> + igb_write32(igb, E1000_RDH(0), 0);
> + igb_write32(igb, E1000_RDT(0), 0);
> +
> + /*
> + * Select the advanced one-buffer descriptor format. Per 82576
> + * datasheet section 7.1.5.2: "SRRCTL[n].DESCTYPE must be set to a
> + * value other than 000b for the 82576 to write back the special
> + * descriptors." struct igb_rx_desc matches the advanced one-buffer
> + * writeback layout (section 7.1.5.2), so polling rx.wb.status_error
> + * requires this format. Section 8.10.2 specifies DESCTYPE[27:25].
> + *
> + * The direct write also zeroes SRRCTL.BSIZEPACKET, which is
> + * intentional: per section 7.1.3.1 a zero BSIZEPACKET falls back to
> + * the RCTL.BSIZE buffer size, whose reset default (00b) is 2048
> + * bytes -- ample for the loopback frames here.
> + */
> + igb_write32(igb, E1000_SRRCTL(0), E1000_SRRCTL_DESCTYPE_ADV_ONEBUF);
> +
> + igb_write32(igb, E1000_RXDCTL(0), E1000_RXDCTL_QUEUE_ENABLE);
> +
> + /* Wait for TX and RX queues to be enabled */
> + retries = 2000;
> + while (retries-- > 0) {
> + if ((igb_read32(igb, E1000_TXDCTL(0)) & E1000_TXDCTL_QUEUE_ENABLE) &&
> + (igb_read32(igb, E1000_RXDCTL(0)) & E1000_RXDCTL_QUEUE_ENABLE))
> + break;
> + usleep(10);
> + }
> + VFIO_ASSERT_GE(retries, 0);
I'm not sure how I missed this in the previous iteration, but this
new-ish assert exposes a latent ordering issue on real hardware. As per
the below referenced register definitions, the per-queue enable bits are
zero until the global enable bits are set.
diff --git a/tools/testing/selftests/vfio/lib/drivers/igb/igb.c b/tools/testing/selftests/vfio/lib/drivers/igb/igb.c
index 97a2f29aade3..fae523059f86 100644
--- a/tools/testing/selftests/vfio/lib/drivers/igb/igb.c
+++ b/tools/testing/selftests/vfio/lib/drivers/igb/igb.c
@@ -303,16 +303,6 @@ static void igb_hw_init(struct vfio_pci_device *device)
igb_write32(igb, E1000_RXDCTL(0), E1000_RXDCTL_QUEUE_ENABLE);
- /* Wait for TX and RX queues to be enabled */
- retries = 2000;
- while (retries-- > 0) {
- if ((igb_read32(igb, E1000_TXDCTL(0)) & E1000_TXDCTL_QUEUE_ENABLE) &&
- (igb_read32(igb, E1000_RXDCTL(0)) & E1000_RXDCTL_QUEUE_ENABLE))
- break;
- usleep(10);
- }
- VFIO_ASSERT_GE(retries, 0);
-
/*
* Enable Receiver and Transmitter. RCTL.LBM_MAC is set in addition
* to PHY loopback as a QEMU-only accommodation: QEMU's emulated igb
@@ -335,6 +325,21 @@ static void igb_hw_init(struct vfio_pci_device *device)
igb_write32(igb, E1000_RCTL, rctl);
igb_write32(igb, E1000_TCTL, E1000_TCTL_EN | E1000_TCTL_PSP);
+ /*
+ * Wait for TX and RX queues to be enabled. Per the RXDCTL/TXDCTL
+ * register definitions (8.10.10/8.12.13), the per-queue enable bit
+ * "remains zero" until the global RCTL.RXEN/TCTL.TXEN are set, so
+ * E1000_RCTL_EN and E1000_TCTL_EN must already be written above.
+ */
+ retries = 2000;
+ while (retries-- > 0) {
+ if ((igb_read32(igb, E1000_TXDCTL(0)) & E1000_TXDCTL_QUEUE_ENABLE) &&
+ (igb_read32(igb, E1000_RXDCTL(0)) & E1000_RXDCTL_QUEUE_ENABLE))
+ break;
+ usleep(10);
+ }
+ VFIO_ASSERT_GE(retries, 0);
+
/*
* Program MSI-X interrupt routing per 82576 datasheet:
*
Back to 35/35 on real hardware with this. NB, patch is against fully
applied series, so lands in igb_hw_init() but the source of the
ordering issue is in patch 1 here, where it's igb_init(). Thanks,
Alex
> +
> + /*
> + * Enable Receiver and Transmitter. RCTL.LBM_MAC is set in addition
> + * to PHY loopback as a QEMU-only accommodation: QEMU's emulated igb
> + * does not honor PHY register 0 bit 14 (PHY internal loopback) and
> + * relies on RCTL.LBM_MAC to wrap TX descriptors back to the RX
> + * queue. Datasheet 8.10.1 (RCTL register) advises "When using the
> + * internal PHY, LBM should remain set to 00b", so setting LBM_MAC
> + * here deviates from datasheet guidance; empirically the bit has
> + * no observable effect on real 82576 hardware because MAC loopback
> + * is not implemented (datasheet 3.5.6.2). Setting both lets the
> + * selftest work on both real hardware and QEMU without conditional
> + * code paths.
> + */
> + rctl = E1000_RCTL_EN | /* Receiver Enable */
> + E1000_RCTL_UPE | /* Unicast Promiscuous (for dummy MAC) */
> + E1000_RCTL_MPE | /* Multicast Promiscuous */
> + E1000_RCTL_BAM | /* Broadcast Accept Mode */
> + E1000_RCTL_LBM_MAC | /* MAC Loopback - for QEMU emulation only */
> + E1000_RCTL_SECRC; /* Strip CRC (needed for memcmp) */
> + igb_write32(igb, E1000_RCTL, rctl);
> + igb_write32(igb, E1000_TCTL, E1000_TCTL_EN | E1000_TCTL_PSP);
next prev parent reply other threads:[~2026-07-31 18:15 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-30 23:31 [PATCH v9 0/5] vfio: selftests: Add driver for Intel Ethernet Gigabit Controller (IGB) Josh Hilke
2026-07-30 23:31 ` [PATCH v9 1/5] vfio: selftests: igb: Add driver for Intel 82576 device Josh Hilke
2026-07-30 23:46 ` sashiko-bot
2026-07-31 18:15 ` Alex Williamson [this message]
2026-07-30 23:31 ` [PATCH v9 2/5] vfio: selftests: Add helpers to re-enable interrupts Josh Hilke
2026-07-30 23:31 ` [PATCH v9 3/5] vfio: selftests: igb: Factor hardware programming into igb_hw_init() Josh Hilke
2026-07-30 23:31 ` [PATCH v9 4/5] vfio: selftests: Retry on EAGAIN during device reset Josh Hilke
2026-07-30 23:31 ` [PATCH v9 5/5] vfio: selftests: igb: Recover after DMA-read faults Josh Hilke
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=20260731121502.3e5416ca@shazbot.org \
--to=alex@shazbot.org \
--cc=alex.williamson@nvidia.com \
--cc=dmatlack@google.com \
--cc=jrhilke@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=shuah@kernel.org \
--cc=vipinsh@google.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.