summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/intel.c
diff options
context:
space:
mode:
authorVishvananda Ishaya2017-03-09 14:54:13 +0100
committerMichael Brown2017-03-09 14:56:22 +0100
commit1d049002622da6a5a9cc98c42fd4dd27dc741b96 (patch)
treef5ef75498ab111610a6ed1a759d272053ba0786d /src/drivers/net/intel.c
parent[scsi] Avoid duplicate calls to scsicmd_close() (diff)
downloadipxe-1d049002622da6a5a9cc98c42fd4dd27dc741b96.tar.gz
ipxe-1d049002622da6a5a9cc98c42fd4dd27dc741b96.tar.xz
ipxe-1d049002622da6a5a9cc98c42fd4dd27dc741b96.zip
[intel] Reset all virtual function settings
Some VF data is not cleared with reset, so make sure to return all the settings to default before configuring the VF. This fixes an issue where network packets would fail to be received if the VF was previously used by the linux ixgbevf driver. Modified-by: Michael Brown <mcb30@ipxe.org> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/intel.c')
-rw-r--r--src/drivers/net/intel.c63
1 files changed, 57 insertions, 6 deletions
diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c
index ab6defde..534252ba 100644
--- a/src/drivers/net/intel.c
+++ b/src/drivers/net/intel.c
@@ -425,6 +425,61 @@ void intel_describe_rx ( struct intel_descriptor *rx, physaddr_t addr,
*/
/**
+ * Disable descriptor ring
+ *
+ * @v intel Intel device
+ * @v reg Register block
+ * @ret rc Return status code
+ */
+static int intel_disable_ring ( struct intel_nic *intel, unsigned int reg ) {
+ uint32_t dctl;
+ unsigned int i;
+
+ /* Disable ring */
+ writel ( 0, ( intel->regs + reg + INTEL_xDCTL ) );
+
+ /* Wait for disable to complete */
+ for ( i = 0 ; i < INTEL_DISABLE_MAX_WAIT_MS ; i++ ) {
+
+ /* Check if ring is disabled */
+ dctl = readl ( intel->regs + reg + INTEL_xDCTL );
+ if ( ! ( dctl & INTEL_xDCTL_ENABLE ) )
+ return 0;
+
+ /* Delay */
+ mdelay ( 1 );
+ }
+
+ DBGC ( intel, "INTEL %p ring %05x timed out waiting for disable "
+ "(dctl %08x)\n", intel, reg, dctl );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Reset descriptor ring
+ *
+ * @v intel Intel device
+ * @v reg Register block
+ * @ret rc Return status code
+ */
+void intel_reset_ring ( struct intel_nic *intel, unsigned int reg ) {
+
+ /* Disable ring. Ignore errors and continue to reset the ring anyway */
+ intel_disable_ring ( intel, reg );
+
+ /* Clear ring length */
+ writel ( 0, ( intel->regs + reg + INTEL_xDLEN ) );
+
+ /* Clear ring address */
+ writel ( 0, ( intel->regs + reg + INTEL_xDBAH ) );
+ writel ( 0, ( intel->regs + reg + INTEL_xDBAL ) );
+
+ /* Reset head and tail pointers */
+ writel ( 0, ( intel->regs + reg + INTEL_xDH ) );
+ writel ( 0, ( intel->regs + reg + INTEL_xDT ) );
+}
+
+/**
* Create descriptor ring
*
* @v intel Intel device
@@ -484,12 +539,8 @@ int intel_create_ring ( struct intel_nic *intel, struct intel_ring *ring ) {
*/
void intel_destroy_ring ( struct intel_nic *intel, struct intel_ring *ring ) {
- /* Clear ring length */
- writel ( 0, ( intel->regs + ring->reg + INTEL_xDLEN ) );
-
- /* Clear ring address */
- writel ( 0, ( intel->regs + ring->reg + INTEL_xDBAL ) );
- writel ( 0, ( intel->regs + ring->reg + INTEL_xDBAH ) );
+ /* Reset ring */
+ intel_reset_ring ( intel, ring->reg );
/* Free descriptor ring */
free_dma ( ring->desc, ring->len );