summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/drivers/net/intel.c63
-rw-r--r--src/drivers/net/intel.h4
-rw-r--r--src/drivers/net/intelxvf.c23
-rw-r--r--src/drivers/net/intelxvf.h14
4 files changed, 91 insertions, 13 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 );
diff --git a/src/drivers/net/intel.h b/src/drivers/net/intel.h
index 16a72a11..630eaf84 100644
--- a/src/drivers/net/intel.h
+++ b/src/drivers/net/intel.h
@@ -185,6 +185,9 @@ struct intel_descriptor {
#define INTEL_xDCTL 0x28
#define INTEL_xDCTL_ENABLE 0x02000000UL /**< Queue enable */
+/** Maximum time to wait for queue disable, in milliseconds */
+#define INTEL_DISABLE_MAX_WAIT_MS 100
+
/** Receive Address Low */
#define INTEL_RAL0 0x05400UL
@@ -330,6 +333,7 @@ extern void intel_describe_tx_adv ( struct intel_descriptor *tx,
physaddr_t addr, size_t len );
extern void intel_describe_rx ( struct intel_descriptor *rx,
physaddr_t addr, size_t len );
+extern void intel_reset_ring ( struct intel_nic *intel, unsigned int reg );
extern int intel_create_ring ( struct intel_nic *intel,
struct intel_ring *ring );
extern void intel_destroy_ring ( struct intel_nic *intel,
diff --git a/src/drivers/net/intelxvf.c b/src/drivers/net/intelxvf.c
index 91a10b10..2caeec27 100644
--- a/src/drivers/net/intelxvf.c
+++ b/src/drivers/net/intelxvf.c
@@ -216,6 +216,7 @@ static int intelxvf_open ( struct net_device *netdev ) {
uint32_t rxdctl;
uint32_t srrctl;
uint32_t dca_rxctrl;
+ unsigned int i;
int vlan_thing;
int rc;
@@ -252,6 +253,15 @@ static int intelxvf_open ( struct net_device *netdev ) {
goto err_mbox_set_mtu;
}
+ /* Reset all descriptor rings */
+ for ( i = 0 ; i < INTELXVF_NUM_RINGS ; i++ ) {
+ intel_reset_ring ( intel, INTELXVF_TD ( i ) );
+ intel_reset_ring ( intel, INTELXVF_RD ( i ) );
+ }
+
+ /* Reset packet split receive type register */
+ writel ( 0, intel->regs + INTELXVF_PSRTYPE );
+
/* Get queue configuration. Ignore failures, since the host
* may not support this message.
*/
@@ -260,9 +270,9 @@ static int intelxvf_open ( struct net_device *netdev ) {
if ( vlan_thing ) {
DBGC ( intel, "INTEL %p stripping VLAN tags (thing=%d)\n",
intel, vlan_thing );
- rxdctl = readl ( intel->regs + INTELXVF_RD + INTEL_xDCTL );
+ rxdctl = readl ( intel->regs + INTELXVF_RD(0) + INTEL_xDCTL );
rxdctl |= INTELX_RXDCTL_VME;
- writel ( rxdctl, intel->regs + INTELXVF_RD + INTEL_xDCTL );
+ writel ( rxdctl, intel->regs + INTELXVF_RD(0) + INTEL_xDCTL );
}
/* Create transmit descriptor ring */
@@ -283,9 +293,12 @@ static int intelxvf_open ( struct net_device *netdev ) {
/* Configure receive buffer sizes and set receive descriptor type */
srrctl = readl ( intel->regs + INTELXVF_SRRCTL );
srrctl &= ~( INTELXVF_SRRCTL_BSIZE_MASK |
+ INTELXVF_SRRCTL_BHDRSIZE_MASK |
INTELXVF_SRRCTL_DESCTYPE_MASK );
srrctl |= ( INTELXVF_SRRCTL_BSIZE_DEFAULT |
- INTELXVF_SRRCTL_DESCTYPE_DEFAULT );
+ INTELXVF_SRRCTL_BHDRSIZE_DEFAULT |
+ INTELXVF_SRRCTL_DESCTYPE_DEFAULT |
+ INTELXVF_SRRCTL_DROP_EN );
writel ( srrctl, intel->regs + INTELXVF_SRRCTL );
/* Clear "must-be-zero" bit for direct cache access (DCA). We
@@ -434,9 +447,9 @@ static int intelxvf_probe ( struct pci_device *pci ) {
netdev->dev = &pci->dev;
memset ( intel, 0, sizeof ( *intel ) );
intel_init_mbox ( &intel->mbox, INTELXVF_MBCTRL, INTELXVF_MBMEM );
- intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELXVF_TD,
+ intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELXVF_TD(0),
intel_describe_tx_adv );
- intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELXVF_RD,
+ intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELXVF_RD(0),
intel_describe_rx );
/* Fix up PCI device */
diff --git a/src/drivers/net/intelxvf.h b/src/drivers/net/intelxvf.h
index ad046a65..4663272a 100644
--- a/src/drivers/net/intelxvf.h
+++ b/src/drivers/net/intelxvf.h
@@ -55,8 +55,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Mailbox Control Register */
#define INTELXVF_MBCTRL 0x02fcUL
+/** Packet Split Receive Type */
+#define INTELXVF_PSRTYPE 0x0300UL
+
/** Receive Descriptor register block */
-#define INTELXVF_RD 0x1000UL
+#define INTELXVF_RD(n) ( 0x1000UL + ( 0x40 * (n) ) )
/** RX DCA Control Register */
#define INTELXVF_DCA_RXCTRL 0x100cUL
@@ -67,9 +70,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define INTELXVF_SRRCTL_BSIZE(kb) ( (kb) << 0 ) /**< Receive buffer size */
#define INTELXVF_SRRCTL_BSIZE_DEFAULT INTELXVF_SRRCTL_BSIZE ( 0x02 )
#define INTELXVF_SRRCTL_BSIZE_MASK INTELXVF_SRRCTL_BSIZE ( 0x1f )
+#define INTELXVF_SRRCTL_BHDRSIZE(kb) ( (kb) << 8 ) /**< Header size */
+#define INTELXVF_SRRCTL_BHDRSIZE_DEFAULT INTELXVF_SRRCTL_BHDRSIZE ( 0x04 )
+#define INTELXVF_SRRCTL_BHDRSIZE_MASK INTELXVF_SRRCTL_BHDRSIZE ( 0x0f )
#define INTELXVF_SRRCTL_DESCTYPE(typ) ( (typ) << 25 ) /**< Descriptor type */
#define INTELXVF_SRRCTL_DESCTYPE_DEFAULT INTELXVF_SRRCTL_DESCTYPE ( 0x00 )
#define INTELXVF_SRRCTL_DESCTYPE_MASK INTELXVF_SRRCTL_DESCTYPE ( 0x07 )
+#define INTELXVF_SRRCTL_DROP_EN 0x10000000UL
/** Good Packets Received Count */
#define INTELXVF_GPRC 0x101c
@@ -84,7 +91,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define INTELXVF_MPRC 0x1034
/** Transmit Descriptor register block */
-#define INTELXVF_TD 0x2000UL
+#define INTELXVF_TD(n) ( 0x2000UL + ( 0x40 * (n) ) )
/** Good Packets Transmitted Count */
#define INTELXVF_GPTC 0x201c
@@ -101,4 +108,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** API version 1.1 */
#define INTELXVF_MSG_VERSION_1_1 0x00000002UL
+/** Number of queues */
+#define INTELXVF_NUM_RINGS 8
+
#endif /* _INTELXVF_H */