* [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI
@ 2009-10-28 1:49 Jeff Kirsher
2009-10-28 1:49 ` [net-next-2.6 PATCH 02/20] igb: remove rx checksum good counter Jeff Kirsher
` (19 more replies)
0 siblings, 20 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:49 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
Add a new igb_q_vector data structure to handle interrupts and NAPI. This
helps to abstract the rings away from the adapter struct. In addition it
allows for a bit of consolidation since a tx and rx ring can share a
q_vector.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 46 +-
drivers/net/igb/igb_ethtool.c | 8
drivers/net/igb/igb_main.c | 872 ++++++++++++++++++++++++-----------------
3 files changed, 534 insertions(+), 392 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index b805b1c..86492c8 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -55,6 +55,8 @@ struct igb_adapter;
#define IGB_DEFAULT_ITR 3 /* dynamic */
#define IGB_MAX_ITR_USECS 10000
#define IGB_MIN_ITR_USECS 10
+#define NON_Q_VECTORS 1
+#define MAX_Q_VECTORS 8
/* Transmit and receive queues */
#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? \
@@ -149,25 +151,38 @@ struct igb_rx_queue_stats {
u64 drops;
};
-struct igb_ring {
+struct igb_q_vector {
struct igb_adapter *adapter; /* backlink */
- void *desc; /* descriptor ring memory */
- dma_addr_t dma; /* phys address of the ring */
- unsigned int size; /* length of desc. ring in bytes */
- unsigned int count; /* number of desc. in the ring */
+ struct igb_ring *rx_ring;
+ struct igb_ring *tx_ring;
+ struct napi_struct napi;
+
+ u32 eims_value;
+ u16 cpu;
+
+ u16 itr_val;
+ u8 set_itr;
+ u8 itr_shift;
+ void __iomem *itr_register;
+
+ char name[IFNAMSIZ + 9];
+};
+
+struct igb_ring {
+ struct igb_q_vector *q_vector; /* backlink to q_vector */
+ void *desc; /* descriptor ring memory */
+ dma_addr_t dma; /* phys address of the ring */
+ unsigned int size; /* length of desc. ring in bytes */
+ unsigned int count; /* number of desc. in the ring */
u16 next_to_use;
u16 next_to_clean;
u16 head;
u16 tail;
struct igb_buffer *buffer_info; /* array of buffer info structs */
- u32 eims_value;
- u32 itr_val;
- u16 itr_register;
- u16 cpu;
+ u8 queue_index;
+ u8 reg_idx;
- u16 queue_index;
- u16 reg_idx;
unsigned int total_bytes;
unsigned int total_packets;
@@ -181,13 +196,8 @@ struct igb_ring {
struct {
struct igb_rx_queue_stats rx_stats;
u64 rx_queue_drops;
- struct napi_struct napi;
- int set_itr;
- struct igb_ring *buddy;
};
};
-
- char name[IFNAMSIZ + 5];
};
#define E1000_RX_DESC_ADV(R, i) \
@@ -254,7 +264,6 @@ struct igb_adapter {
/* OS defined structs */
struct net_device *netdev;
- struct napi_struct napi;
struct pci_dev *pdev;
struct cyclecounter cycles;
struct timecounter clock;
@@ -272,6 +281,9 @@ struct igb_adapter {
struct igb_ring test_rx_ring;
int msg_enable;
+
+ unsigned int num_q_vectors;
+ struct igb_q_vector *q_vector[MAX_Q_VECTORS];
struct msix_entry *msix_entries;
u32 eims_enable_mask;
u32 eims_other;
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index dafb25b..f71276f 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1907,7 +1907,6 @@ static int igb_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec)
{
struct igb_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
int i;
if ((ec->rx_coalesce_usecs > IGB_MAX_ITR_USECS) ||
@@ -1925,8 +1924,11 @@ static int igb_set_coalesce(struct net_device *netdev,
adapter->itr = adapter->itr_setting;
}
- for (i = 0; i < adapter->num_rx_queues; i++)
- wr32(adapter->rx_ring[i].itr_register, adapter->itr);
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+ q_vector->itr_val = adapter->itr;
+ q_vector->set_itr = 1;
+ }
return 0;
}
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 2ffe099..c15eb4c 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -111,16 +111,14 @@ static void igb_set_uta(struct igb_adapter *adapter);
static irqreturn_t igb_intr(int irq, void *);
static irqreturn_t igb_intr_msi(int irq, void *);
static irqreturn_t igb_msix_other(int irq, void *);
-static irqreturn_t igb_msix_rx(int irq, void *);
-static irqreturn_t igb_msix_tx(int irq, void *);
+static irqreturn_t igb_msix_ring(int irq, void *);
#ifdef CONFIG_IGB_DCA
-static void igb_update_rx_dca(struct igb_ring *);
-static void igb_update_tx_dca(struct igb_ring *);
+static void igb_update_dca(struct igb_q_vector *);
static void igb_setup_dca(struct igb_adapter *);
#endif /* CONFIG_IGB_DCA */
-static bool igb_clean_tx_irq(struct igb_ring *);
+static bool igb_clean_tx_irq(struct igb_q_vector *);
static int igb_poll(struct napi_struct *, int);
-static bool igb_clean_rx_irq_adv(struct igb_ring *, int *, int);
+static bool igb_clean_rx_irq_adv(struct igb_q_vector *, int *, int);
static void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
static void igb_tx_timeout(struct net_device *);
@@ -374,7 +372,7 @@ module_exit(igb_exit_module);
static void igb_cache_ring_register(struct igb_adapter *adapter)
{
int i;
- unsigned int rbase_offset = adapter->vfs_allocated_count;
+ u32 rbase_offset = adapter->vfs_allocated_count;
switch (adapter->hw.mac.type) {
case e1000_82576:
@@ -400,6 +398,18 @@ static void igb_cache_ring_register(struct igb_adapter *adapter)
}
}
+static void igb_free_queues(struct igb_adapter *adapter)
+{
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+
+ adapter->tx_ring = NULL;
+ adapter->rx_ring = NULL;
+
+ adapter->num_rx_queues = 0;
+ adapter->num_tx_queues = 0;
+}
+
/**
* igb_alloc_queues - Allocate memory for all rings
* @adapter: board private structure to initialize
@@ -414,59 +424,48 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
adapter->tx_ring = kcalloc(adapter->num_tx_queues,
sizeof(struct igb_ring), GFP_KERNEL);
if (!adapter->tx_ring)
- return -ENOMEM;
+ goto err;
adapter->rx_ring = kcalloc(adapter->num_rx_queues,
sizeof(struct igb_ring), GFP_KERNEL);
- if (!adapter->rx_ring) {
- kfree(adapter->tx_ring);
- return -ENOMEM;
- }
-
- adapter->rx_ring->buddy = adapter->tx_ring;
+ if (!adapter->rx_ring)
+ goto err;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igb_ring *ring = &(adapter->tx_ring[i]);
ring->count = adapter->tx_ring_count;
- ring->adapter = adapter;
ring->queue_index = i;
}
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = &(adapter->rx_ring[i]);
ring->count = adapter->rx_ring_count;
- ring->adapter = adapter;
ring->queue_index = i;
- ring->itr_register = E1000_ITR;
-
- /* set a default napi handler for each rx_ring */
- netif_napi_add(adapter->netdev, &ring->napi, igb_poll, 64);
}
igb_cache_ring_register(adapter);
- return 0;
-}
-static void igb_free_queues(struct igb_adapter *adapter)
-{
- int i;
-
- for (i = 0; i < adapter->num_rx_queues; i++)
- netif_napi_del(&adapter->rx_ring[i].napi);
+ return 0;
- adapter->num_rx_queues = 0;
- adapter->num_tx_queues = 0;
+err:
+ igb_free_queues(adapter);
- kfree(adapter->tx_ring);
- kfree(adapter->rx_ring);
+ return -ENOMEM;
}
#define IGB_N0_QUEUE -1
-static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue,
- int tx_queue, int msix_vector)
+static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector)
{
u32 msixbm = 0;
+ struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
u32 ivar, index;
+ int rx_queue = IGB_N0_QUEUE;
+ int tx_queue = IGB_N0_QUEUE;
+
+ if (q_vector->rx_ring)
+ rx_queue = q_vector->rx_ring->reg_idx;
+ if (q_vector->tx_ring)
+ tx_queue = q_vector->tx_ring->reg_idx;
switch (hw->mac.type) {
case e1000_82575:
@@ -474,16 +473,12 @@ static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue,
bitmask for the EICR/EIMS/EIMC registers. To assign one
or more queues to a vector, we write the appropriate bits
into the MSIXBM register for that vector. */
- if (rx_queue > IGB_N0_QUEUE) {
+ if (rx_queue > IGB_N0_QUEUE)
msixbm = E1000_EICR_RX_QUEUE0 << rx_queue;
- adapter->rx_ring[rx_queue].eims_value = msixbm;
- }
- if (tx_queue > IGB_N0_QUEUE) {
+ if (tx_queue > IGB_N0_QUEUE)
msixbm |= E1000_EICR_TX_QUEUE0 << tx_queue;
- adapter->tx_ring[tx_queue].eims_value =
- E1000_EICR_TX_QUEUE0 << tx_queue;
- }
array_wr32(E1000_MSIXBM(0), msix_vector, msixbm);
+ q_vector->eims_value = msixbm;
break;
case e1000_82576:
/* 82576 uses a table-based method for assigning vectors.
@@ -491,35 +486,34 @@ static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue,
a vector number along with a "valid" bit. Sadly, the layout
of the table is somewhat counterintuitive. */
if (rx_queue > IGB_N0_QUEUE) {
- index = (rx_queue >> 1) + adapter->vfs_allocated_count;
+ index = (rx_queue & 0x7);
ivar = array_rd32(E1000_IVAR0, index);
- if (rx_queue & 0x1) {
- /* vector goes into third byte of register */
- ivar = ivar & 0xFF00FFFF;
- ivar |= (msix_vector | E1000_IVAR_VALID) << 16;
- } else {
+ if (rx_queue < 8) {
/* vector goes into low byte of register */
ivar = ivar & 0xFFFFFF00;
ivar |= msix_vector | E1000_IVAR_VALID;
+ } else {
+ /* vector goes into third byte of register */
+ ivar = ivar & 0xFF00FFFF;
+ ivar |= (msix_vector | E1000_IVAR_VALID) << 16;
}
- adapter->rx_ring[rx_queue].eims_value= 1 << msix_vector;
array_wr32(E1000_IVAR0, index, ivar);
}
if (tx_queue > IGB_N0_QUEUE) {
- index = (tx_queue >> 1) + adapter->vfs_allocated_count;
+ index = (tx_queue & 0x7);
ivar = array_rd32(E1000_IVAR0, index);
- if (tx_queue & 0x1) {
- /* vector goes into high byte of register */
- ivar = ivar & 0x00FFFFFF;
- ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
- } else {
+ if (tx_queue < 8) {
/* vector goes into second byte of register */
ivar = ivar & 0xFFFF00FF;
ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
+ } else {
+ /* vector goes into high byte of register */
+ ivar = ivar & 0x00FFFFFF;
+ ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
}
- adapter->tx_ring[tx_queue].eims_value= 1 << msix_vector;
array_wr32(E1000_IVAR0, index, ivar);
}
+ q_vector->eims_value = 1 << msix_vector;
break;
default:
BUG();
@@ -540,43 +534,10 @@ static void igb_configure_msix(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
adapter->eims_enable_mask = 0;
- if (hw->mac.type == e1000_82576)
- /* Turn on MSI-X capability first, or our settings
- * won't stick. And it will take days to debug. */
- wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE |
- E1000_GPIE_PBA | E1000_GPIE_EIAME |
- E1000_GPIE_NSICR);
-
- for (i = 0; i < adapter->num_tx_queues; i++) {
- struct igb_ring *tx_ring = &adapter->tx_ring[i];
- igb_assign_vector(adapter, IGB_N0_QUEUE, i, vector++);
- adapter->eims_enable_mask |= tx_ring->eims_value;
- if (tx_ring->itr_val)
- writel(tx_ring->itr_val,
- hw->hw_addr + tx_ring->itr_register);
- else
- writel(1, hw->hw_addr + tx_ring->itr_register);
- }
-
- for (i = 0; i < adapter->num_rx_queues; i++) {
- struct igb_ring *rx_ring = &adapter->rx_ring[i];
- rx_ring->buddy = NULL;
- igb_assign_vector(adapter, i, IGB_N0_QUEUE, vector++);
- adapter->eims_enable_mask |= rx_ring->eims_value;
- if (rx_ring->itr_val)
- writel(rx_ring->itr_val,
- hw->hw_addr + rx_ring->itr_register);
- else
- writel(1, hw->hw_addr + rx_ring->itr_register);
- }
-
/* set vector for other causes, i.e. link changes */
switch (hw->mac.type) {
case e1000_82575:
- array_wr32(E1000_MSIXBM(0), vector++,
- E1000_EIMS_OTHER);
-
tmp = rd32(E1000_CTRL_EXT);
/* enable MSI-X PBA support*/
tmp |= E1000_CTRL_EXT_PBA_CLR;
@@ -586,22 +547,40 @@ static void igb_configure_msix(struct igb_adapter *adapter)
tmp |= E1000_CTRL_EXT_IRCA;
wr32(E1000_CTRL_EXT, tmp);
- adapter->eims_enable_mask |= E1000_EIMS_OTHER;
+
+ /* enable msix_other interrupt */
+ array_wr32(E1000_MSIXBM(0), vector++,
+ E1000_EIMS_OTHER);
adapter->eims_other = E1000_EIMS_OTHER;
break;
case e1000_82576:
+ /* Turn on MSI-X capability first, or our settings
+ * won't stick. And it will take days to debug. */
+ wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE |
+ E1000_GPIE_PBA | E1000_GPIE_EIAME |
+ E1000_GPIE_NSICR);
+
+ /* enable msix_other interrupt */
+ adapter->eims_other = 1 << vector;
tmp = (vector++ | E1000_IVAR_VALID) << 8;
- wr32(E1000_IVAR_MISC, tmp);
- adapter->eims_enable_mask = (1 << (vector)) - 1;
- adapter->eims_other = 1 << (vector - 1);
+ wr32(E1000_IVAR_MISC, tmp);
break;
default:
/* do nothing, since nothing else supports MSI-X */
break;
} /* switch (hw->mac.type) */
+
+ adapter->eims_enable_mask |= adapter->eims_other;
+
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+ igb_assign_vector(q_vector, vector++);
+ adapter->eims_enable_mask |= q_vector->eims_value;
+ }
+
wrfl();
}
@@ -614,43 +593,40 @@ static void igb_configure_msix(struct igb_adapter *adapter)
static int igb_request_msix(struct igb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ struct e1000_hw *hw = &adapter->hw;
int i, err = 0, vector = 0;
- vector = 0;
-
- for (i = 0; i < adapter->num_tx_queues; i++) {
- struct igb_ring *ring = &(adapter->tx_ring[i]);
- sprintf(ring->name, "%s-tx-%d", netdev->name, i);
- err = request_irq(adapter->msix_entries[vector].vector,
- &igb_msix_tx, 0, ring->name,
- &(adapter->tx_ring[i]));
- if (err)
- goto out;
- ring->itr_register = E1000_EITR(0) + (vector << 2);
- ring->itr_val = 976; /* ~4000 ints/sec */
- vector++;
- }
- for (i = 0; i < adapter->num_rx_queues; i++) {
- struct igb_ring *ring = &(adapter->rx_ring[i]);
- if (strlen(netdev->name) < (IFNAMSIZ - 5))
- sprintf(ring->name, "%s-rx-%d", netdev->name, i);
+ err = request_irq(adapter->msix_entries[vector].vector,
+ &igb_msix_other, 0, netdev->name, adapter);
+ if (err)
+ goto out;
+ vector++;
+
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+
+ q_vector->itr_register = hw->hw_addr + E1000_EITR(vector);
+
+ if (q_vector->rx_ring && q_vector->tx_ring)
+ sprintf(q_vector->name, "%s-TxRx-%u", netdev->name,
+ q_vector->rx_ring->queue_index);
+ else if (q_vector->tx_ring)
+ sprintf(q_vector->name, "%s-tx-%u", netdev->name,
+ q_vector->tx_ring->queue_index);
+ else if (q_vector->rx_ring)
+ sprintf(q_vector->name, "%s-rx-%u", netdev->name,
+ q_vector->rx_ring->queue_index);
else
- memcpy(ring->name, netdev->name, IFNAMSIZ);
+ sprintf(q_vector->name, "%s-unused", netdev->name);
+
err = request_irq(adapter->msix_entries[vector].vector,
- &igb_msix_rx, 0, ring->name,
- &(adapter->rx_ring[i]));
+ &igb_msix_ring, 0, q_vector->name,
+ q_vector);
if (err)
goto out;
- ring->itr_register = E1000_EITR(0) + (vector << 2);
- ring->itr_val = adapter->itr;
vector++;
}
- err = request_irq(adapter->msix_entries[vector].vector,
- &igb_msix_other, 0, netdev->name, netdev);
- if (err)
- goto out;
-
igb_configure_msix(adapter);
return 0;
out:
@@ -663,11 +639,44 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
- } else if (adapter->flags & IGB_FLAG_HAS_MSI)
+ } else if (adapter->flags & IGB_FLAG_HAS_MSI) {
pci_disable_msi(adapter->pdev);
- return;
+ }
}
+/**
+ * igb_free_q_vectors - Free memory allocated for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * This function frees the memory allocated to the q_vectors. In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void igb_free_q_vectors(struct igb_adapter *adapter)
+{
+ int v_idx;
+
+ for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+ adapter->q_vector[v_idx] = NULL;
+ netif_napi_del(&q_vector->napi);
+ kfree(q_vector);
+ }
+ adapter->num_q_vectors = 0;
+}
+
+/**
+ * igb_clear_interrupt_scheme - reset the device to a state of no interrupts
+ *
+ * This function resets the device so that it has 0 rx queues, tx queues, and
+ * MSI-X interrupts allocated.
+ */
+static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
+{
+ igb_free_queues(adapter);
+ igb_free_q_vectors(adapter);
+ igb_reset_interrupt_capability(adapter);
+}
/**
* igb_set_interrupt_capability - set MSI or MSI-X if supported
@@ -681,11 +690,20 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter)
int numvecs, i;
/* Number of supported queues. */
- /* Having more queues than CPUs doesn't make sense. */
adapter->num_rx_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
adapter->num_tx_queues = min_t(u32, IGB_MAX_TX_QUEUES, num_online_cpus());
- numvecs = adapter->num_tx_queues + adapter->num_rx_queues + 1;
+ /* start with one vector for every rx queue */
+ numvecs = adapter->num_rx_queues;
+
+ /* if tx handler is seperate add 1 for every tx queue */
+ numvecs += adapter->num_tx_queues;
+
+ /* store the number of vectors reserved for queues */
+ adapter->num_q_vectors = numvecs;
+
+ /* add 1 vector for link status interrupts */
+ numvecs++;
adapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry),
GFP_KERNEL);
if (!adapter->msix_entries)
@@ -721,6 +739,7 @@ msi_only:
#endif
adapter->num_rx_queues = 1;
adapter->num_tx_queues = 1;
+ adapter->num_q_vectors = 1;
if (!pci_enable_msi(adapter->pdev))
adapter->flags |= IGB_FLAG_HAS_MSI;
out:
@@ -730,6 +749,139 @@ out:
}
/**
+ * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one q_vector per queue interrupt. If allocation fails we
+ * return -ENOMEM.
+ **/
+static int igb_alloc_q_vectors(struct igb_adapter *adapter)
+{
+ struct igb_q_vector *q_vector;
+ struct e1000_hw *hw = &adapter->hw;
+ int v_idx;
+
+ for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
+ q_vector = kzalloc(sizeof(struct igb_q_vector), GFP_KERNEL);
+ if (!q_vector)
+ goto err_out;
+ q_vector->adapter = adapter;
+ q_vector->itr_shift = (hw->mac.type == e1000_82575) ? 16 : 0;
+ q_vector->itr_register = hw->hw_addr + E1000_EITR(0);
+ q_vector->itr_val = IGB_START_ITR;
+ q_vector->set_itr = 1;
+ netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64);
+ adapter->q_vector[v_idx] = q_vector;
+ }
+ return 0;
+
+err_out:
+ while (v_idx) {
+ v_idx--;
+ q_vector = adapter->q_vector[v_idx];
+ netif_napi_del(&q_vector->napi);
+ kfree(q_vector);
+ adapter->q_vector[v_idx] = NULL;
+ }
+ return -ENOMEM;
+}
+
+static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter,
+ int ring_idx, int v_idx)
+{
+ struct igb_q_vector *q_vector;
+
+ q_vector = adapter->q_vector[v_idx];
+ q_vector->rx_ring = &adapter->rx_ring[ring_idx];
+ q_vector->rx_ring->q_vector = q_vector;
+ q_vector->itr_val = adapter->itr;
+}
+
+static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter,
+ int ring_idx, int v_idx)
+{
+ struct igb_q_vector *q_vector;
+
+ q_vector = adapter->q_vector[v_idx];
+ q_vector->tx_ring = &adapter->tx_ring[ring_idx];
+ q_vector->tx_ring->q_vector = q_vector;
+ q_vector->itr_val = adapter->itr;
+}
+
+/**
+ * igb_map_ring_to_vector - maps allocated queues to vectors
+ *
+ * This function maps the recently allocated queues to vectors.
+ **/
+static int igb_map_ring_to_vector(struct igb_adapter *adapter)
+{
+ int i;
+ int v_idx = 0;
+
+ if ((adapter->num_q_vectors < adapter->num_rx_queues) ||
+ (adapter->num_q_vectors < adapter->num_tx_queues))
+ return -ENOMEM;
+
+ if (adapter->num_q_vectors >=
+ (adapter->num_rx_queues + adapter->num_tx_queues)) {
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ igb_map_rx_ring_to_vector(adapter, i, v_idx++);
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ igb_map_tx_ring_to_vector(adapter, i, v_idx++);
+ } else {
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ if (i < adapter->num_tx_queues)
+ igb_map_tx_ring_to_vector(adapter, i, v_idx);
+ igb_map_rx_ring_to_vector(adapter, i, v_idx++);
+ }
+ for (; i < adapter->num_tx_queues; i++)
+ igb_map_tx_ring_to_vector(adapter, i, v_idx++);
+ }
+ return 0;
+}
+
+/**
+ * igb_init_interrupt_scheme - initialize interrupts, allocate queues/vectors
+ *
+ * This function initializes the interrupts and allocates all of the queues.
+ **/
+static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int err;
+
+ igb_set_interrupt_capability(adapter);
+
+ err = igb_alloc_q_vectors(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to allocate memory for vectors\n");
+ goto err_alloc_q_vectors;
+ }
+
+ err = igb_alloc_queues(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+ goto err_alloc_queues;
+ }
+
+ err = igb_map_ring_to_vector(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "Invalid q_vector to ring mapping\n");
+ goto err_map_queues;
+ }
+
+
+ return 0;
+err_map_queues:
+ igb_free_queues(adapter);
+err_alloc_queues:
+ igb_free_q_vectors(adapter);
+err_alloc_q_vectors:
+ igb_reset_interrupt_capability(adapter);
+ return err;
+}
+
+/**
* igb_request_irq - initialize interrupts
*
* Attempts to configure interrupts using the best available
@@ -738,6 +890,7 @@ out:
static int igb_request_irq(struct igb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
struct e1000_hw *hw = &adapter->hw;
int err = 0;
@@ -746,18 +899,36 @@ static int igb_request_irq(struct igb_adapter *adapter)
if (!err)
goto request_done;
/* fall back to MSI */
- igb_reset_interrupt_capability(adapter);
+ igb_clear_interrupt_scheme(adapter);
if (!pci_enable_msi(adapter->pdev))
adapter->flags |= IGB_FLAG_HAS_MSI;
igb_free_all_tx_resources(adapter);
igb_free_all_rx_resources(adapter);
+ adapter->num_tx_queues = 1;
adapter->num_rx_queues = 1;
- igb_alloc_queues(adapter);
+ adapter->num_q_vectors = 1;
+ err = igb_alloc_q_vectors(adapter);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Unable to allocate memory for vectors\n");
+ goto request_done;
+ }
+ err = igb_alloc_queues(adapter);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Unable to allocate memory for queues\n");
+ igb_free_q_vectors(adapter);
+ goto request_done;
+ }
+ igb_setup_all_tx_resources(adapter);
+ igb_setup_all_rx_resources(adapter);
} else {
switch (hw->mac.type) {
case e1000_82575:
wr32(E1000_MSIXBM(0),
- (E1000_EICR_RX_QUEUE0 | E1000_EIMS_OTHER));
+ (E1000_EICR_RX_QUEUE0 |
+ E1000_EICR_TX_QUEUE0 |
+ E1000_EIMS_OTHER));
break;
case e1000_82576:
wr32(E1000_IVAR0, E1000_IVAR_VALID);
@@ -769,16 +940,17 @@ static int igb_request_irq(struct igb_adapter *adapter)
if (adapter->flags & IGB_FLAG_HAS_MSI) {
err = request_irq(adapter->pdev->irq, &igb_intr_msi, 0,
- netdev->name, netdev);
+ netdev->name, adapter);
if (!err)
goto request_done;
+
/* fall back to legacy interrupts */
igb_reset_interrupt_capability(adapter);
adapter->flags &= ~IGB_FLAG_HAS_MSI;
}
err = request_irq(adapter->pdev->irq, &igb_intr, IRQF_SHARED,
- netdev->name, netdev);
+ netdev->name, adapter);
if (err)
dev_err(&adapter->pdev->dev, "Error %d getting interrupt\n",
@@ -790,23 +962,19 @@ request_done:
static void igb_free_irq(struct igb_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
-
if (adapter->msix_entries) {
int vector = 0, i;
- for (i = 0; i < adapter->num_tx_queues; i++)
- free_irq(adapter->msix_entries[vector++].vector,
- &(adapter->tx_ring[i]));
- for (i = 0; i < adapter->num_rx_queues; i++)
- free_irq(adapter->msix_entries[vector++].vector,
- &(adapter->rx_ring[i]));
+ free_irq(adapter->msix_entries[vector++].vector, adapter);
- free_irq(adapter->msix_entries[vector++].vector, netdev);
- return;
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+ free_irq(adapter->msix_entries[vector++].vector,
+ q_vector);
+ }
+ } else {
+ free_irq(adapter->pdev->irq, adapter);
}
-
- free_irq(adapter->pdev->irq, netdev);
}
/**
@@ -967,8 +1135,10 @@ int igb_up(struct igb_adapter *adapter)
clear_bit(__IGB_DOWN, &adapter->state);
- for (i = 0; i < adapter->num_rx_queues; i++)
- napi_enable(&adapter->rx_ring[i].napi);
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+ napi_enable(&q_vector->napi);
+ }
if (adapter->msix_entries)
igb_configure_msix(adapter);
@@ -1012,8 +1182,10 @@ void igb_down(struct igb_adapter *adapter)
wrfl();
msleep(10);
- for (i = 0; i < adapter->num_rx_queues; i++)
- napi_disable(&adapter->rx_ring[i].napi);
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+ napi_disable(&q_vector->napi);
+ }
igb_irq_disable(adapter);
@@ -1584,9 +1756,8 @@ err_eeprom:
if (hw->flash_address)
iounmap(hw->flash_address);
-
- igb_free_queues(adapter);
err_sw_init:
+ igb_clear_interrupt_scheme(adapter);
iounmap(hw->hw_addr);
err_ioremap:
free_netdev(netdev);
@@ -1640,9 +1811,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
if (!igb_check_reset_block(&adapter->hw))
igb_reset_phy(&adapter->hw);
- igb_reset_interrupt_capability(adapter);
-
- igb_free_queues(adapter);
+ igb_clear_interrupt_scheme(adapter);
#ifdef CONFIG_PCI_IOV
/* reclaim resources allocated to VFs */
@@ -1696,9 +1865,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
/* This call may decrease the number of queues depending on
* interrupt mode. */
- igb_set_interrupt_capability(adapter);
-
- if (igb_alloc_queues(adapter)) {
+ if (igb_init_interrupt_scheme(adapter)) {
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
return -ENOMEM;
}
@@ -1768,8 +1935,10 @@ static int igb_open(struct net_device *netdev)
/* From here on the code is the same as igb_up() */
clear_bit(__IGB_DOWN, &adapter->state);
- for (i = 0; i < adapter->num_rx_queues; i++)
- napi_enable(&adapter->rx_ring[i].napi);
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+ napi_enable(&q_vector->napi);
+ }
/* Clear any pending interrupts. */
rd32(E1000_ICR);
@@ -1858,14 +2027,13 @@ int igb_setup_tx_resources(struct igb_adapter *adapter,
if (!tx_ring->desc)
goto err;
- tx_ring->adapter = adapter;
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
return 0;
err:
vfree(tx_ring->buffer_info);
- dev_err(&adapter->pdev->dev,
+ dev_err(&pdev->dev,
"Unable to allocate memory for the transmit descriptor ring\n");
return -ENOMEM;
}
@@ -1996,8 +2164,6 @@ int igb_setup_rx_resources(struct igb_adapter *adapter,
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
- rx_ring->adapter = adapter;
-
return 0;
err:
@@ -2308,7 +2474,7 @@ static void igb_configure_rx(struct igb_adapter *adapter)
**/
void igb_free_tx_resources(struct igb_ring *tx_ring)
{
- struct pci_dev *pdev = tx_ring->adapter->pdev;
+ struct pci_dev *pdev = tx_ring->q_vector->adapter->pdev;
igb_clean_tx_ring(tx_ring);
@@ -2354,7 +2520,7 @@ static void igb_unmap_and_free_tx_resource(struct igb_adapter *adapter,
**/
static void igb_clean_tx_ring(struct igb_ring *tx_ring)
{
- struct igb_adapter *adapter = tx_ring->adapter;
+ struct igb_adapter *adapter = tx_ring->q_vector->adapter;
struct igb_buffer *buffer_info;
unsigned long size;
unsigned int i;
@@ -2402,7 +2568,7 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter)
**/
void igb_free_rx_resources(struct igb_ring *rx_ring)
{
- struct pci_dev *pdev = rx_ring->adapter->pdev;
+ struct pci_dev *pdev = rx_ring->q_vector->adapter->pdev;
igb_clean_rx_ring(rx_ring);
@@ -2434,7 +2600,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter)
**/
static void igb_clean_rx_ring(struct igb_ring *rx_ring)
{
- struct igb_adapter *adapter = rx_ring->adapter;
+ struct igb_adapter *adapter = rx_ring->q_vector->adapter;
struct igb_buffer *buffer_info;
struct pci_dev *pdev = adapter->pdev;
unsigned long size;
@@ -2749,7 +2915,6 @@ static void igb_watchdog_task(struct work_struct *work)
struct net_device *netdev = adapter->netdev;
struct igb_ring *tx_ring = adapter->tx_ring;
u32 link;
- u32 eics = 0;
int i;
link = igb_has_link(adapter);
@@ -2848,8 +3013,11 @@ link_up:
/* Cause software interrupt to ensure rx ring is cleaned */
if (adapter->msix_entries) {
- for (i = 0; i < adapter->num_rx_queues; i++)
- eics |= adapter->rx_ring[i].eims_value;
+ u32 eics = 0;
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+ eics |= q_vector->eims_value;
+ }
wr32(E1000_EICS, eics);
} else {
wr32(E1000_ICS, E1000_ICS_RXDMT0);
@@ -2886,25 +3054,37 @@ enum latency_range {
* parameter (see igb_param.c)
* NOTE: This function is called only when operating in a multiqueue
* receive environment.
- * @rx_ring: pointer to ring
+ * @q_vector: pointer to q_vector
**/
-static void igb_update_ring_itr(struct igb_ring *rx_ring)
+static void igb_update_ring_itr(struct igb_q_vector *q_vector)
{
- int new_val = rx_ring->itr_val;
+ int new_val = q_vector->itr_val;
int avg_wire_size = 0;
- struct igb_adapter *adapter = rx_ring->adapter;
-
- if (!rx_ring->total_packets)
- goto clear_counts; /* no packets, so don't do anything */
+ struct igb_adapter *adapter = q_vector->adapter;
/* For non-gigabit speeds, just fix the interrupt rate at 4000
* ints/sec - ITR timer value of 120 ticks.
*/
if (adapter->link_speed != SPEED_1000) {
- new_val = 120;
+ new_val = 976;
goto set_itr_val;
}
- avg_wire_size = rx_ring->total_bytes / rx_ring->total_packets;
+
+ if (q_vector->rx_ring && q_vector->rx_ring->total_packets) {
+ struct igb_ring *ring = q_vector->rx_ring;
+ avg_wire_size = ring->total_bytes / ring->total_packets;
+ }
+
+ if (q_vector->tx_ring && q_vector->tx_ring->total_packets) {
+ struct igb_ring *ring = q_vector->tx_ring;
+ avg_wire_size = max_t(u32, avg_wire_size,
+ (ring->total_bytes /
+ ring->total_packets));
+ }
+
+ /* if avg_wire_size isn't set no work was done */
+ if (!avg_wire_size)
+ goto clear_counts;
/* Add 24 bytes to size to account for CRC, preamble, and gap */
avg_wire_size += 24;
@@ -2919,13 +3099,19 @@ static void igb_update_ring_itr(struct igb_ring *rx_ring)
new_val = avg_wire_size / 2;
set_itr_val:
- if (new_val != rx_ring->itr_val) {
- rx_ring->itr_val = new_val;
- rx_ring->set_itr = 1;
+ if (new_val != q_vector->itr_val) {
+ q_vector->itr_val = new_val;
+ q_vector->set_itr = 1;
}
clear_counts:
- rx_ring->total_bytes = 0;
- rx_ring->total_packets = 0;
+ if (q_vector->rx_ring) {
+ q_vector->rx_ring->total_bytes = 0;
+ q_vector->rx_ring->total_packets = 0;
+ }
+ if (q_vector->tx_ring) {
+ q_vector->tx_ring->total_bytes = 0;
+ q_vector->tx_ring->total_packets = 0;
+ }
}
/**
@@ -2942,7 +3128,7 @@ clear_counts:
* NOTE: These calculations are only valid when operating in a single-
* queue environment.
* @adapter: pointer to adapter
- * @itr_setting: current adapter->itr
+ * @itr_setting: current q_vector->itr_val
* @packets: the number of packets during this measurement interval
* @bytes: the number of bytes during this measurement interval
**/
@@ -2994,8 +3180,9 @@ update_itr_done:
static void igb_set_itr(struct igb_adapter *adapter)
{
+ struct igb_q_vector *q_vector = adapter->q_vector[0];
u16 current_itr;
- u32 new_itr = adapter->itr;
+ u32 new_itr = q_vector->itr_val;
/* for non-gigabit speeds, just fix the interrupt rate at 4000 */
if (adapter->link_speed != SPEED_1000) {
@@ -3009,15 +3196,11 @@ static void igb_set_itr(struct igb_adapter *adapter)
adapter->rx_ring->total_packets,
adapter->rx_ring->total_bytes);
- if (adapter->rx_ring->buddy) {
- adapter->tx_itr = igb_update_itr(adapter,
- adapter->tx_itr,
- adapter->tx_ring->total_packets,
- adapter->tx_ring->total_bytes);
- current_itr = max(adapter->rx_itr, adapter->tx_itr);
- } else {
- current_itr = adapter->rx_itr;
- }
+ adapter->tx_itr = igb_update_itr(adapter,
+ adapter->tx_itr,
+ adapter->tx_ring->total_packets,
+ adapter->tx_ring->total_bytes);
+ current_itr = max(adapter->rx_itr, adapter->tx_itr);
/* conservative mode (itr 3) eliminates the lowest_latency setting */
if (adapter->itr_setting == 3 && current_itr == lowest_latency)
@@ -3041,18 +3224,17 @@ static void igb_set_itr(struct igb_adapter *adapter)
set_itr_now:
adapter->rx_ring->total_bytes = 0;
adapter->rx_ring->total_packets = 0;
- if (adapter->rx_ring->buddy) {
- adapter->rx_ring->buddy->total_bytes = 0;
- adapter->rx_ring->buddy->total_packets = 0;
- }
+ adapter->tx_ring->total_bytes = 0;
+ adapter->tx_ring->total_packets = 0;
- if (new_itr != adapter->itr) {
+ if (new_itr != q_vector->itr_val) {
/* this attempts to bias the interrupt rate towards Bulk
* by adding intermediate steps when interrupt rate is
* increasing */
- new_itr = new_itr > adapter->itr ?
- max((new_itr * adapter->itr) /
- (new_itr + (adapter->itr >> 2)), new_itr) :
+ new_itr = new_itr > q_vector->itr_val ?
+ max((new_itr * q_vector->itr_val) /
+ (new_itr + (q_vector->itr_val >> 2)),
+ new_itr) :
new_itr;
/* Don't write the value here; it resets the adapter's
* internal timer, and causes us to delay far longer than
@@ -3060,15 +3242,13 @@ set_itr_now:
* value at the beginning of the next interrupt so the timing
* ends up being correct.
*/
- adapter->itr = new_itr;
- adapter->rx_ring->itr_val = new_itr;
- adapter->rx_ring->set_itr = 1;
+ q_vector->itr_val = new_itr;
+ q_vector->set_itr = 1;
}
return;
}
-
#define IGB_TX_FLAGS_CSUM 0x00000001
#define IGB_TX_FLAGS_VLAN 0x00000002
#define IGB_TX_FLAGS_TSO 0x00000004
@@ -3781,14 +3961,12 @@ void igb_update_stats(struct igb_adapter *adapter)
static irqreturn_t igb_msix_other(int irq, void *data)
{
- struct net_device *netdev = data;
- struct igb_adapter *adapter = netdev_priv(netdev);
+ struct igb_adapter *adapter = data;
struct e1000_hw *hw = &adapter->hw;
u32 icr = rd32(E1000_ICR);
-
/* reading ICR causes bit 31 of EICR to be cleared */
- if(icr & E1000_ICR_DOUTSYNC) {
+ if (icr & E1000_ICR_DOUTSYNC) {
/* HW is reporting DMA is out of sync */
adapter->stats.doosync++;
}
@@ -3810,119 +3988,79 @@ static irqreturn_t igb_msix_other(int irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t igb_msix_tx(int irq, void *data)
+static void igb_write_itr(struct igb_q_vector *q_vector)
{
- struct igb_ring *tx_ring = data;
- struct igb_adapter *adapter = tx_ring->adapter;
- struct e1000_hw *hw = &adapter->hw;
+ u32 itr_val = q_vector->itr_val & 0x7FFC;
-#ifdef CONFIG_IGB_DCA
- if (adapter->flags & IGB_FLAG_DCA_ENABLED)
- igb_update_tx_dca(tx_ring);
-#endif
+ if (!q_vector->set_itr)
+ return;
- tx_ring->total_bytes = 0;
- tx_ring->total_packets = 0;
+ if (!itr_val)
+ itr_val = 0x4;
- /* auto mask will automatically reenable the interrupt when we write
- * EICS */
- if (!igb_clean_tx_irq(tx_ring))
- /* Ring was not completely cleaned, so fire another interrupt */
- wr32(E1000_EICS, tx_ring->eims_value);
+ if (q_vector->itr_shift)
+ itr_val |= itr_val << q_vector->itr_shift;
else
- wr32(E1000_EIMS, tx_ring->eims_value);
+ itr_val |= 0x8000000;
- return IRQ_HANDLED;
-}
-
-static void igb_write_itr(struct igb_ring *ring)
-{
- struct e1000_hw *hw = &ring->adapter->hw;
- if ((ring->adapter->itr_setting & 3) && ring->set_itr) {
- switch (hw->mac.type) {
- case e1000_82576:
- wr32(ring->itr_register, ring->itr_val |
- 0x80000000);
- break;
- default:
- wr32(ring->itr_register, ring->itr_val |
- (ring->itr_val << 16));
- break;
- }
- ring->set_itr = 0;
- }
+ writel(itr_val, q_vector->itr_register);
+ q_vector->set_itr = 0;
}
-static irqreturn_t igb_msix_rx(int irq, void *data)
+static irqreturn_t igb_msix_ring(int irq, void *data)
{
- struct igb_ring *rx_ring = data;
-
- /* Write the ITR value calculated at the end of the
- * previous interrupt.
- */
+ struct igb_q_vector *q_vector = data;
- igb_write_itr(rx_ring);
+ /* Write the ITR value calculated from the previous interrupt. */
+ igb_write_itr(q_vector);
- if (napi_schedule_prep(&rx_ring->napi))
- __napi_schedule(&rx_ring->napi);
+ napi_schedule(&q_vector->napi);
-#ifdef CONFIG_IGB_DCA
- if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED)
- igb_update_rx_dca(rx_ring);
-#endif
- return IRQ_HANDLED;
+ return IRQ_HANDLED;
}
#ifdef CONFIG_IGB_DCA
-static void igb_update_rx_dca(struct igb_ring *rx_ring)
+static void igb_update_dca(struct igb_q_vector *q_vector)
{
- u32 dca_rxctrl;
- struct igb_adapter *adapter = rx_ring->adapter;
+ struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
int cpu = get_cpu();
- int q = rx_ring->reg_idx;
- if (rx_ring->cpu != cpu) {
- dca_rxctrl = rd32(E1000_DCA_RXCTRL(q));
- if (hw->mac.type == e1000_82576) {
- dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576;
- dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
- E1000_DCA_RXCTRL_CPUID_SHIFT;
+ if (q_vector->cpu == cpu)
+ goto out_no_update;
+
+ if (q_vector->tx_ring) {
+ int q = q_vector->tx_ring->reg_idx;
+ u32 dca_txctrl = rd32(E1000_DCA_TXCTRL(q));
+ if (hw->mac.type == e1000_82575) {
+ dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK;
+ dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
} else {
+ dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576;
+ dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
+ E1000_DCA_TXCTRL_CPUID_SHIFT;
+ }
+ dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN;
+ wr32(E1000_DCA_TXCTRL(q), dca_txctrl);
+ }
+ if (q_vector->rx_ring) {
+ int q = q_vector->rx_ring->reg_idx;
+ u32 dca_rxctrl = rd32(E1000_DCA_RXCTRL(q));
+ if (hw->mac.type == e1000_82575) {
dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK;
dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
+ } else {
+ dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576;
+ dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
+ E1000_DCA_RXCTRL_CPUID_SHIFT;
}
dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN;
dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN;
dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN;
wr32(E1000_DCA_RXCTRL(q), dca_rxctrl);
- rx_ring->cpu = cpu;
- }
- put_cpu();
-}
-
-static void igb_update_tx_dca(struct igb_ring *tx_ring)
-{
- u32 dca_txctrl;
- struct igb_adapter *adapter = tx_ring->adapter;
- struct e1000_hw *hw = &adapter->hw;
- int cpu = get_cpu();
- int q = tx_ring->reg_idx;
-
- if (tx_ring->cpu != cpu) {
- dca_txctrl = rd32(E1000_DCA_TXCTRL(q));
- if (hw->mac.type == e1000_82576) {
- dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576;
- dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
- E1000_DCA_TXCTRL_CPUID_SHIFT;
- } else {
- dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK;
- dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
- }
- dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN;
- wr32(E1000_DCA_TXCTRL(q), dca_txctrl);
- tx_ring->cpu = cpu;
}
+ q_vector->cpu = cpu;
+out_no_update:
put_cpu();
}
@@ -3937,13 +4075,10 @@ static void igb_setup_dca(struct igb_adapter *adapter)
/* Always use CB2 mode, difference is masked in the CB driver. */
wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2);
- for (i = 0; i < adapter->num_tx_queues; i++) {
- adapter->tx_ring[i].cpu = -1;
- igb_update_tx_dca(&adapter->tx_ring[i]);
- }
- for (i = 0; i < adapter->num_rx_queues; i++) {
- adapter->rx_ring[i].cpu = -1;
- igb_update_rx_dca(&adapter->rx_ring[i]);
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+ q_vector->cpu = -1;
+ igb_update_dca(q_vector);
}
}
@@ -3972,7 +4107,7 @@ static int __igb_notify_dca(struct device *dev, void *data)
case DCA_PROVIDER_REMOVE:
if (adapter->flags & IGB_FLAG_DCA_ENABLED) {
/* without this a class_device is left
- * hanging around in the sysfs model */
+ * hanging around in the sysfs model */
dca_remove_requester(dev);
dev_info(&adapter->pdev->dev, "DCA disabled\n");
adapter->flags &= ~IGB_FLAG_DCA_ENABLED;
@@ -4379,15 +4514,15 @@ static void igb_set_uta(struct igb_adapter *adapter)
**/
static irqreturn_t igb_intr_msi(int irq, void *data)
{
- struct net_device *netdev = data;
- struct igb_adapter *adapter = netdev_priv(netdev);
+ struct igb_adapter *adapter = data;
+ struct igb_q_vector *q_vector = adapter->q_vector[0];
struct e1000_hw *hw = &adapter->hw;
/* read ICR disables interrupts using IAM */
u32 icr = rd32(E1000_ICR);
- igb_write_itr(adapter->rx_ring);
+ igb_write_itr(q_vector);
- if(icr & E1000_ICR_DOUTSYNC) {
+ if (icr & E1000_ICR_DOUTSYNC) {
/* HW is reporting DMA is out of sync */
adapter->stats.doosync++;
}
@@ -4398,7 +4533,7 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
- napi_schedule(&adapter->rx_ring[0].napi);
+ napi_schedule(&q_vector->napi);
return IRQ_HANDLED;
}
@@ -4410,8 +4545,8 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
**/
static irqreturn_t igb_intr(int irq, void *data)
{
- struct net_device *netdev = data;
- struct igb_adapter *adapter = netdev_priv(netdev);
+ struct igb_adapter *adapter = data;
+ struct igb_q_vector *q_vector = adapter->q_vector[0];
struct e1000_hw *hw = &adapter->hw;
/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No
* need for the IMC write */
@@ -4419,14 +4554,14 @@ static irqreturn_t igb_intr(int irq, void *data)
if (!icr)
return IRQ_NONE; /* Not our interrupt */
- igb_write_itr(adapter->rx_ring);
+ igb_write_itr(q_vector);
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
* not set, then the adapter didn't send an interrupt */
if (!(icr & E1000_ICR_INT_ASSERTED))
return IRQ_NONE;
- if(icr & E1000_ICR_DOUTSYNC) {
+ if (icr & E1000_ICR_DOUTSYNC) {
/* HW is reporting DMA is out of sync */
adapter->stats.doosync++;
}
@@ -4438,26 +4573,26 @@ static irqreturn_t igb_intr(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
- napi_schedule(&adapter->rx_ring[0].napi);
+ napi_schedule(&q_vector->napi);
return IRQ_HANDLED;
}
-static inline void igb_rx_irq_enable(struct igb_ring *rx_ring)
+static inline void igb_ring_irq_enable(struct igb_q_vector *q_vector)
{
- struct igb_adapter *adapter = rx_ring->adapter;
+ struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
if (adapter->itr_setting & 3) {
- if (adapter->num_rx_queues == 1)
+ if (!adapter->msix_entries)
igb_set_itr(adapter);
else
- igb_update_ring_itr(rx_ring);
+ igb_update_ring_itr(q_vector);
}
if (!test_bit(__IGB_DOWN, &adapter->state)) {
if (adapter->msix_entries)
- wr32(E1000_EIMS, rx_ring->eims_value);
+ wr32(E1000_EIMS, q_vector->eims_value);
else
igb_irq_enable(adapter);
}
@@ -4470,28 +4605,28 @@ static inline void igb_rx_irq_enable(struct igb_ring *rx_ring)
**/
static int igb_poll(struct napi_struct *napi, int budget)
{
- struct igb_ring *rx_ring = container_of(napi, struct igb_ring, napi);
- int work_done = 0;
+ struct igb_q_vector *q_vector = container_of(napi,
+ struct igb_q_vector,
+ napi);
+ int tx_clean_complete = 1, work_done = 0;
#ifdef CONFIG_IGB_DCA
- if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED)
- igb_update_rx_dca(rx_ring);
+ if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
+ igb_update_dca(q_vector);
#endif
- igb_clean_rx_irq_adv(rx_ring, &work_done, budget);
+ if (q_vector->tx_ring)
+ tx_clean_complete = igb_clean_tx_irq(q_vector);
- if (rx_ring->buddy) {
-#ifdef CONFIG_IGB_DCA
- if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED)
- igb_update_tx_dca(rx_ring->buddy);
-#endif
- if (!igb_clean_tx_irq(rx_ring->buddy))
- work_done = budget;
- }
+ if (q_vector->rx_ring)
+ igb_clean_rx_irq_adv(q_vector, &work_done, budget);
+
+ if (!tx_clean_complete)
+ work_done = budget;
/* If not enough Rx work done, exit the polling mode */
if (work_done < budget) {
napi_complete(napi);
- igb_rx_irq_enable(rx_ring);
+ igb_ring_irq_enable(q_vector);
}
return work_done;
@@ -4533,12 +4668,13 @@ static void igb_tx_hwtstamp(struct igb_adapter *adapter, struct sk_buff *skb)
/**
* igb_clean_tx_irq - Reclaim resources after transmit completes
- * @adapter: board private structure
+ * @q_vector: pointer to q_vector containing needed info
* returns true if ring is completely cleaned
**/
-static bool igb_clean_tx_irq(struct igb_ring *tx_ring)
+static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
{
- struct igb_adapter *adapter = tx_ring->adapter;
+ struct igb_adapter *adapter = q_vector->adapter;
+ struct igb_ring *tx_ring = q_vector->tx_ring;
struct net_device *netdev = adapter->netdev;
struct e1000_hw *hw = &adapter->hw;
struct igb_buffer *buffer_info;
@@ -4646,25 +4782,21 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring)
/**
* igb_receive_skb - helper function to handle rx indications
- * @ring: pointer to receive ring receving this packet
- * @status: descriptor status field as written by hardware
- * @rx_desc: receive descriptor containing vlan and type information.
- * @skb: pointer to sk_buff to be indicated to stack
+ * @q_vector: structure containing interrupt and ring information
+ * @skb: packet to send up
+ * @vlan_tag: vlan tag for packet
**/
-static void igb_receive_skb(struct igb_ring *ring, u8 status,
- union e1000_adv_rx_desc * rx_desc,
- struct sk_buff *skb)
-{
- struct igb_adapter * adapter = ring->adapter;
- bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP));
-
- skb_record_rx_queue(skb, ring->queue_index);
- if (vlan_extracted)
- vlan_gro_receive(&ring->napi, adapter->vlgrp,
- le16_to_cpu(rx_desc->wb.upper.vlan),
- skb);
+static void igb_receive_skb(struct igb_q_vector *q_vector,
+ struct sk_buff *skb,
+ u16 vlan_tag)
+{
+ struct igb_adapter *adapter = q_vector->adapter;
+
+ if (vlan_tag)
+ vlan_gro_receive(&q_vector->napi, adapter->vlgrp,
+ vlan_tag, skb);
else
- napi_gro_receive(&ring->napi, skb);
+ napi_gro_receive(&q_vector->napi, skb);
}
static inline void igb_rx_checksum_adv(struct igb_adapter *adapter,
@@ -4712,11 +4844,12 @@ static inline u16 igb_get_hlen(struct igb_adapter *adapter,
return hlen;
}
-static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring,
- int *work_done, int budget)
+static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
+ int *work_done, int budget)
{
- struct igb_adapter *adapter = rx_ring->adapter;
+ struct igb_adapter *adapter = q_vector->adapter;
struct net_device *netdev = adapter->netdev;
+ struct igb_ring *rx_ring = q_vector->rx_ring;
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
union e1000_adv_rx_desc *rx_desc , *next_rxd;
@@ -4728,6 +4861,7 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring,
unsigned int i;
u32 staterr;
u16 length;
+ u16 vlan_tag;
i = rx_ring->next_to_clean;
buffer_info = &rx_ring->buffer_info[i];
@@ -4855,8 +4989,12 @@ send_up:
igb_rx_checksum_adv(adapter, staterr, skb);
skb->protocol = eth_type_trans(skb, netdev);
+ skb_record_rx_queue(skb, rx_ring->queue_index);
+
+ vlan_tag = ((staterr & E1000_RXD_STAT_VP) ?
+ le16_to_cpu(rx_desc->wb.upper.vlan) : 0);
- igb_receive_skb(rx_ring, staterr, rx_desc, skb);
+ igb_receive_skb(q_vector, skb, vlan_tag);
next_desc:
rx_desc->wb.upper.status_error = 0;
@@ -4895,7 +5033,7 @@ next_desc:
static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
int cleaned_count)
{
- struct igb_adapter *adapter = rx_ring->adapter;
+ struct igb_adapter *adapter = rx_ring->q_vector->adapter;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union e1000_adv_rx_desc *rx_desc;
@@ -5360,9 +5498,7 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake)
if (netif_running(netdev))
igb_close(netdev);
- igb_reset_interrupt_capability(adapter);
-
- igb_free_queues(adapter);
+ igb_clear_interrupt_scheme(adapter);
#ifdef CONFIG_PM
retval = pci_save_state(pdev);
@@ -5457,9 +5593,7 @@ static int igb_resume(struct pci_dev *pdev)
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
- igb_set_interrupt_capability(adapter);
-
- if (igb_alloc_queues(adapter)) {
+ if (igb_init_interrupt_scheme(adapter)) {
dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
return -ENOMEM;
}
@@ -5511,22 +5645,16 @@ static void igb_netpoll(struct net_device *netdev)
int i;
if (!adapter->msix_entries) {
+ struct igb_q_vector *q_vector = adapter->q_vector[0];
igb_irq_disable(adapter);
- napi_schedule(&adapter->rx_ring[0].napi);
+ napi_schedule(&q_vector->napi);
return;
}
- for (i = 0; i < adapter->num_tx_queues; i++) {
- struct igb_ring *tx_ring = &adapter->tx_ring[i];
- wr32(E1000_EIMC, tx_ring->eims_value);
- igb_clean_tx_irq(tx_ring);
- wr32(E1000_EIMS, tx_ring->eims_value);
- }
-
- for (i = 0; i < adapter->num_rx_queues; i++) {
- struct igb_ring *rx_ring = &adapter->rx_ring[i];
- wr32(E1000_EIMC, rx_ring->eims_value);
- napi_schedule(&rx_ring->napi);
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ struct igb_q_vector *q_vector = adapter->q_vector[i];
+ wr32(E1000_EIMC, q_vector->eims_value);
+ napi_schedule(&q_vector->napi);
}
}
#endif /* CONFIG_NET_POLL_CONTROLLER */
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 02/20] igb: remove rx checksum good counter
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
@ 2009-10-28 1:49 ` Jeff Kirsher
2009-10-28 1:50 ` [net-next-2.6 PATCH 03/20] igb: increase minimum rx buffer size to 1K Jeff Kirsher
` (18 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:49 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
Counting packets with a good checksum can cause a significant amount of cache
line bouncing due to the shared counter being written to by all of the queues.
In order to avoid this I am removing the counter since we still have the
checksum failed counter which will tell us if there are any issues.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 1 -
drivers/net/igb/igb_ethtool.c | 1 -
drivers/net/igb/igb_main.c | 1 -
3 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 86492c8..d27dcd1 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -254,7 +254,6 @@ struct igb_adapter {
int num_rx_queues;
u64 hw_csum_err;
- u64 hw_csum_good;
u32 alloc_rx_buff_failed;
u32 gorc;
u64 gorc_old;
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index f71276f..2929546 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -95,7 +95,6 @@ static const struct igb_stats igb_gstrings_stats[] = {
{ "tx_flow_control_xon", IGB_STAT(stats.xontxc) },
{ "tx_flow_control_xoff", IGB_STAT(stats.xofftxc) },
{ "rx_long_byte_count", IGB_STAT(stats.gorc) },
- { "rx_csum_offload_good", IGB_STAT(hw_csum_good) },
{ "rx_csum_offload_errors", IGB_STAT(hw_csum_err) },
{ "tx_dma_out_of_sync", IGB_STAT(stats.doosync) },
{ "alloc_rx_buff_failed", IGB_STAT(alloc_rx_buff_failed) },
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index c15eb4c..e1d1c0c 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -4827,7 +4827,6 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter,
skb->ip_summed = CHECKSUM_UNNECESSARY;
dev_dbg(&adapter->pdev->dev, "cksum success: bits %08X\n", status_err);
- adapter->hw_csum_good++;
}
static inline u16 igb_get_hlen(struct igb_adapter *adapter,
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 03/20] igb: increase minimum rx buffer size to 1K
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
2009-10-28 1:49 ` [net-next-2.6 PATCH 02/20] igb: remove rx checksum good counter Jeff Kirsher
@ 2009-10-28 1:50 ` Jeff Kirsher
2009-10-28 1:50 ` [net-next-2.6 PATCH 04/20] igb: move the tx and rx ring specific config into seperate functions Jeff Kirsher
` (17 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:50 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This update increases the minimum rx buffer size to 1K. The reason for this
change is to support SR-IOV and avoid any conflicts with the rings being able
to set their own MTU sizes.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 2 --
drivers/net/igb/igb_main.c | 25 +++----------------------
2 files changed, 3 insertions(+), 24 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index d27dcd1..044ba02 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -96,8 +96,6 @@ struct vf_data_storage {
/* Supported Rx Buffer Sizes */
#define IGB_RXBUFFER_128 128 /* Used for packet split */
-#define IGB_RXBUFFER_256 256 /* Used for packet split */
-#define IGB_RXBUFFER_512 512
#define IGB_RXBUFFER_1024 1024
#define IGB_RXBUFFER_2048 2048
#define IGB_RXBUFFER_16384 16384
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index e1d1c0c..6146f5d 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -2233,18 +2233,8 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
rctl |= E1000_RCTL_LPE;
/* Setup buffer sizes */
- switch (adapter->rx_buffer_len) {
- case IGB_RXBUFFER_256:
- rctl |= E1000_RCTL_SZ_256;
- break;
- case IGB_RXBUFFER_512:
- rctl |= E1000_RCTL_SZ_512;
- break;
- default:
- srrctl = ALIGN(adapter->rx_buffer_len, 1024)
- >> E1000_SRRCTL_BSIZEPKT_SHIFT;
- break;
- }
+ srrctl = ALIGN(adapter->rx_buffer_len, 1024)
+ >> E1000_SRRCTL_BSIZEPKT_SHIFT;
/* 82575 and greater support packet-split where the protocol
* header is placed in skb->data and the packet data is
@@ -3755,11 +3745,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
* i.e. RXBUFFER_2048 --> size-4096 slab
*/
- if (max_frame <= IGB_RXBUFFER_256)
- adapter->rx_buffer_len = IGB_RXBUFFER_256;
- else if (max_frame <= IGB_RXBUFFER_512)
- adapter->rx_buffer_len = IGB_RXBUFFER_512;
- else if (max_frame <= IGB_RXBUFFER_1024)
+ if (max_frame <= IGB_RXBUFFER_1024)
adapter->rx_buffer_len = IGB_RXBUFFER_1024;
else if (max_frame <= IGB_RXBUFFER_2048)
adapter->rx_buffer_len = IGB_RXBUFFER_2048;
@@ -3770,11 +3756,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
adapter->rx_buffer_len = PAGE_SIZE / 2;
#endif
- /* if sr-iov is enabled we need to force buffer size to 1K or larger */
- if (adapter->vfs_allocated_count &&
- (adapter->rx_buffer_len < IGB_RXBUFFER_1024))
- adapter->rx_buffer_len = IGB_RXBUFFER_1024;
-
/* adjust allocation if LPE protects us, and we aren't using SBP */
if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) ||
(max_frame == MAXIMUM_ETHERNET_VLAN_SIZE))
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 04/20] igb: move the tx and rx ring specific config into seperate functions
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
2009-10-28 1:49 ` [net-next-2.6 PATCH 02/20] igb: remove rx checksum good counter Jeff Kirsher
2009-10-28 1:50 ` [net-next-2.6 PATCH 03/20] igb: increase minimum rx buffer size to 1K Jeff Kirsher
@ 2009-10-28 1:50 ` Jeff Kirsher
2009-10-28 1:50 ` [net-next-2.6 PATCH 05/20] igb: remove rx_ps_hdr_len Jeff Kirsher
` (16 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:50 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change makes the tx and rx config a bit cleaner by breaking out the ring
specific configuration from the generic rx and tx configuration.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 6 +
drivers/net/igb/igb_main.c | 179 ++++++++++++++++++++++++++++----------------
2 files changed, 117 insertions(+), 68 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 044ba02..1675f6a 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -87,9 +87,13 @@ struct vf_data_storage {
* descriptors until either it has this many to write back, or the
* ITR timer expires.
*/
-#define IGB_RX_PTHRESH 16
+#define IGB_RX_PTHRESH (hw->mac.type <= e1000_82576 ? 16 : 8)
#define IGB_RX_HTHRESH 8
#define IGB_RX_WTHRESH 1
+#define IGB_TX_PTHRESH 8
+#define IGB_TX_HTHRESH 1
+#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \
+ adapter->msix_entries) ? 0 : 16)
/* this is the size past which hardware will drop packets when setting LPE=0 */
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 6146f5d..61ef4c2 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -90,6 +90,7 @@ static int igb_open(struct net_device *);
static int igb_close(struct net_device *);
static void igb_configure_tx(struct igb_adapter *);
static void igb_configure_rx(struct igb_adapter *);
+static void igb_setup_tctl(struct igb_adapter *);
static void igb_setup_rctl(struct igb_adapter *);
static void igb_clean_all_tx_rings(struct igb_adapter *);
static void igb_clean_all_rx_rings(struct igb_adapter *);
@@ -1101,8 +1102,10 @@ static void igb_configure(struct igb_adapter *adapter)
igb_restore_vlan(adapter);
- igb_configure_tx(adapter);
+ igb_setup_tctl(adapter);
igb_setup_rctl(adapter);
+
+ igb_configure_tx(adapter);
igb_configure_rx(adapter);
igb_rx_fifo_flush_82575(&adapter->hw);
@@ -2069,49 +2072,16 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter)
}
/**
- * igb_configure_tx - Configure transmit Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx unit of the MAC after a reset.
+ * igb_setup_tctl - configure the transmit control registers
+ * @adapter: Board private structure
**/
-static void igb_configure_tx(struct igb_adapter *adapter)
+static void igb_setup_tctl(struct igb_adapter *adapter)
{
- u64 tdba;
struct e1000_hw *hw = &adapter->hw;
u32 tctl;
- u32 txdctl, txctrl;
- int i, j;
-
- for (i = 0; i < adapter->num_tx_queues; i++) {
- struct igb_ring *ring = &adapter->tx_ring[i];
- j = ring->reg_idx;
- wr32(E1000_TDLEN(j),
- ring->count * sizeof(union e1000_adv_tx_desc));
- tdba = ring->dma;
- wr32(E1000_TDBAL(j),
- tdba & 0x00000000ffffffffULL);
- wr32(E1000_TDBAH(j), tdba >> 32);
-
- ring->head = E1000_TDH(j);
- ring->tail = E1000_TDT(j);
- writel(0, hw->hw_addr + ring->tail);
- writel(0, hw->hw_addr + ring->head);
- txdctl = rd32(E1000_TXDCTL(j));
- txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
- wr32(E1000_TXDCTL(j), txdctl);
-
- /* Turn off Relaxed Ordering on head write-backs. The
- * writebacks MUST be delivered in order or it will
- * completely screw up our bookeeping.
- */
- txctrl = rd32(E1000_DCA_TXCTRL(j));
- txctrl &= ~E1000_DCA_TXCTRL_TX_WB_RO_EN;
- wr32(E1000_DCA_TXCTRL(j), txctrl);
- }
- /* disable queue 0 to prevent tail bump w/o re-configuration */
- if (adapter->vfs_allocated_count)
- wr32(E1000_TXDCTL(0), 0);
+ /* disable queue 0 which is enabled by default on 82575 and 82576 */
+ wr32(E1000_TXDCTL(0), 0);
/* Program the Transmit Control Register */
tctl = rd32(E1000_TCTL);
@@ -2121,9 +2091,6 @@ static void igb_configure_tx(struct igb_adapter *adapter)
igb_config_collision_dist(hw);
- /* Setup Transmit Descriptor Settings for eop descriptor */
- adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS;
-
/* Enable transmits */
tctl |= E1000_TCTL_EN;
@@ -2131,6 +2098,64 @@ static void igb_configure_tx(struct igb_adapter *adapter)
}
/**
+ * igb_configure_tx_ring - Configure transmit ring after Reset
+ * @adapter: board private structure
+ * @ring: tx ring to configure
+ *
+ * Configure a transmit ring after a reset.
+ **/
+static void igb_configure_tx_ring(struct igb_adapter *adapter,
+ struct igb_ring *ring)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 txdctl;
+ u64 tdba = ring->dma;
+ int reg_idx = ring->reg_idx;
+
+ /* disable the queue */
+ txdctl = rd32(E1000_TXDCTL(reg_idx));
+ wr32(E1000_TXDCTL(reg_idx),
+ txdctl & ~E1000_TXDCTL_QUEUE_ENABLE);
+ wrfl();
+ mdelay(10);
+
+ wr32(E1000_TDLEN(reg_idx),
+ ring->count * sizeof(union e1000_adv_tx_desc));
+ wr32(E1000_TDBAL(reg_idx),
+ tdba & 0x00000000ffffffffULL);
+ wr32(E1000_TDBAH(reg_idx), tdba >> 32);
+
+ ring->head = E1000_TDH(reg_idx);
+ ring->tail = E1000_TDT(reg_idx);
+ writel(0, hw->hw_addr + ring->tail);
+ writel(0, hw->hw_addr + ring->head);
+
+ txdctl |= IGB_TX_PTHRESH;
+ txdctl |= IGB_TX_HTHRESH << 8;
+ txdctl |= IGB_TX_WTHRESH << 16;
+
+ txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
+ wr32(E1000_TXDCTL(reg_idx), txdctl);
+}
+
+/**
+ * igb_configure_tx - Configure transmit Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+static void igb_configure_tx(struct igb_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ igb_configure_tx_ring(adapter, &adapter->tx_ring[i]);
+
+ /* Setup Transmit Descriptor Settings for eop descriptor */
+ adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS;
+}
+
+/**
* igb_setup_rx_resources - allocate Rx resources (Descriptors)
* @adapter: board private structure
* @rx_ring: rx descriptor ring (for a specific queue) to setup
@@ -2334,6 +2359,49 @@ static void igb_configure_vt_default_pool(struct igb_adapter *adapter)
}
/**
+ * igb_configure_rx_ring - Configure a receive ring after Reset
+ * @adapter: board private structure
+ * @ring: receive ring to be configured
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+static void igb_configure_rx_ring(struct igb_adapter *adapter,
+ struct igb_ring *ring)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u64 rdba = ring->dma;
+ int reg_idx = ring->reg_idx;
+ u32 rxdctl;
+
+ /* disable the queue */
+ rxdctl = rd32(E1000_RXDCTL(reg_idx));
+ wr32(E1000_RXDCTL(reg_idx),
+ rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE);
+
+ /* Set DMA base address registers */
+ wr32(E1000_RDBAL(reg_idx),
+ rdba & 0x00000000ffffffffULL);
+ wr32(E1000_RDBAH(reg_idx), rdba >> 32);
+ wr32(E1000_RDLEN(reg_idx),
+ ring->count * sizeof(union e1000_adv_rx_desc));
+
+ /* initialize head and tail */
+ ring->head = E1000_RDH(reg_idx);
+ ring->tail = E1000_RDT(reg_idx);
+ writel(0, hw->hw_addr + ring->head);
+ writel(0, hw->hw_addr + ring->tail);
+
+ /* enable receive descriptor fetching */
+ rxdctl = rd32(E1000_RXDCTL(reg_idx));
+ rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
+ rxdctl &= 0xFFF00000;
+ rxdctl |= IGB_RX_PTHRESH;
+ rxdctl |= IGB_RX_HTHRESH << 8;
+ rxdctl |= IGB_RX_WTHRESH << 16;
+ wr32(E1000_RXDCTL(reg_idx), rxdctl);
+}
+
+/**
* igb_configure_rx - Configure receive Unit after Reset
* @adapter: board private structure
*
@@ -2341,10 +2409,8 @@ static void igb_configure_vt_default_pool(struct igb_adapter *adapter)
**/
static void igb_configure_rx(struct igb_adapter *adapter)
{
- u64 rdba;
struct e1000_hw *hw = &adapter->hw;
u32 rctl, rxcsum;
- u32 rxdctl;
int i;
/* disable receives while setting up the descriptors */
@@ -2358,29 +2424,8 @@ static void igb_configure_rx(struct igb_adapter *adapter)
/* Setup the HW Rx Head and Tail Descriptor Pointers and
* the Base and Length of the Rx Descriptor Ring */
- for (i = 0; i < adapter->num_rx_queues; i++) {
- struct igb_ring *ring = &adapter->rx_ring[i];
- int j = ring->reg_idx;
- rdba = ring->dma;
- wr32(E1000_RDBAL(j),
- rdba & 0x00000000ffffffffULL);
- wr32(E1000_RDBAH(j), rdba >> 32);
- wr32(E1000_RDLEN(j),
- ring->count * sizeof(union e1000_adv_rx_desc));
-
- ring->head = E1000_RDH(j);
- ring->tail = E1000_RDT(j);
- writel(0, hw->hw_addr + ring->tail);
- writel(0, hw->hw_addr + ring->head);
-
- rxdctl = rd32(E1000_RXDCTL(j));
- rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
- rxdctl &= 0xFFF00000;
- rxdctl |= IGB_RX_PTHRESH;
- rxdctl |= IGB_RX_HTHRESH << 8;
- rxdctl |= IGB_RX_WTHRESH << 16;
- wr32(E1000_RXDCTL(j), rxdctl);
- }
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ igb_configure_rx_ring(adapter, &adapter->rx_ring[i]);
if (adapter->num_rx_queues > 1) {
u32 random[10];
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 05/20] igb: remove rx_ps_hdr_len
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (2 preceding siblings ...)
2009-10-28 1:50 ` [net-next-2.6 PATCH 04/20] igb: move the tx and rx ring specific config into seperate functions Jeff Kirsher
@ 2009-10-28 1:50 ` Jeff Kirsher
2009-10-28 1:51 ` [net-next-2.6 PATCH 06/20] igb: move SRRCTL register configuration into ring specific config Jeff Kirsher
` (15 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:50 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This patch removes the rx_ps_hdr_len which isn't really needed since we can
now use rx_buffer_len less than 1K to indicate that we are in a packet split
mode. We also don't need it since we always use a half page for the data
buffers when receiving so we always know the size to map/unmap.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 1
drivers/net/igb/igb_main.c | 98 +++++++++++++++++---------------------------
2 files changed, 38 insertions(+), 61 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 1675f6a..303df02 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -259,7 +259,6 @@ struct igb_adapter {
u32 alloc_rx_buff_failed;
u32 gorc;
u64 gorc_old;
- u16 rx_ps_hdr_size;
u32 max_frame_size;
u32 min_frame_size;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 61ef4c2..24e502d 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1862,7 +1862,6 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
adapter->tx_ring_count = IGB_DEFAULT_TXD;
adapter->rx_ring_count = IGB_DEFAULT_RXD;
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
- adapter->rx_ps_hdr_size = 0; /* disable packet split */
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
@@ -2254,12 +2253,8 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
*/
rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256);
- /* enable LPE when to prevent packets larger than max_frame_size */
- rctl |= E1000_RCTL_LPE;
-
- /* Setup buffer sizes */
- srrctl = ALIGN(adapter->rx_buffer_len, 1024)
- >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ /* enable LPE to prevent packets larger than max_frame_size */
+ rctl |= E1000_RCTL_LPE;
/* 82575 and greater support packet-split where the protocol
* header is placed in skb->data and the packet data is
@@ -2270,13 +2265,20 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
*/
/* allocations using alloc_page take too long for regular MTU
* so only enable packet split for jumbo frames */
- if (adapter->netdev->mtu > ETH_DATA_LEN) {
- adapter->rx_ps_hdr_size = IGB_RXBUFFER_128;
- srrctl |= adapter->rx_ps_hdr_size <<
- E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
+ if (adapter->rx_buffer_len < IGB_RXBUFFER_1024) {
+ srrctl = ALIGN(adapter->rx_buffer_len, 64) <<
+ E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
+#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
+ srrctl |= IGB_RXBUFFER_16384 >>
+ E1000_SRRCTL_BSIZEPKT_SHIFT;
+#else
+ srrctl |= (PAGE_SIZE / 2) >>
+ E1000_SRRCTL_BSIZEPKT_SHIFT;
+#endif
srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
} else {
- adapter->rx_ps_hdr_size = 0;
+ srrctl = ALIGN(adapter->rx_buffer_len, 1024) >>
+ E1000_SRRCTL_BSIZEPKT_SHIFT;
srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
}
@@ -2647,14 +2649,9 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
for (i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
if (buffer_info->dma) {
- if (adapter->rx_ps_hdr_size)
- pci_unmap_single(pdev, buffer_info->dma,
- adapter->rx_ps_hdr_size,
- PCI_DMA_FROMDEVICE);
- else
- pci_unmap_single(pdev, buffer_info->dma,
- adapter->rx_buffer_len,
- PCI_DMA_FROMDEVICE);
+ pci_unmap_single(pdev, buffer_info->dma,
+ adapter->rx_buffer_len,
+ PCI_DMA_FROMDEVICE);
buffer_info->dma = 0;
}
@@ -2662,14 +2659,15 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
}
+ if (buffer_info->page_dma) {
+ pci_unmap_page(pdev, buffer_info->page_dma,
+ PAGE_SIZE / 2,
+ PCI_DMA_FROMDEVICE);
+ buffer_info->page_dma = 0;
+ }
if (buffer_info->page) {
- if (buffer_info->page_dma)
- pci_unmap_page(pdev, buffer_info->page_dma,
- PAGE_SIZE / 2,
- PCI_DMA_FROMDEVICE);
put_page(buffer_info->page);
buffer_info->page = NULL;
- buffer_info->page_dma = 0;
buffer_info->page_offset = 0;
}
}
@@ -3792,19 +3790,10 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
if (max_frame <= IGB_RXBUFFER_1024)
adapter->rx_buffer_len = IGB_RXBUFFER_1024;
- else if (max_frame <= IGB_RXBUFFER_2048)
- adapter->rx_buffer_len = IGB_RXBUFFER_2048;
- else
-#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
- adapter->rx_buffer_len = IGB_RXBUFFER_16384;
-#else
- adapter->rx_buffer_len = PAGE_SIZE / 2;
-#endif
-
- /* adjust allocation if LPE protects us, and we aren't using SBP */
- if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) ||
- (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE))
+ else if (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE)
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
+ else
+ adapter->rx_buffer_len = IGB_RXBUFFER_128;
dev_info(&adapter->pdev->dev, "changing MTU from %d to %d\n",
netdev->mtu, new_mtu);
@@ -4864,8 +4853,8 @@ static inline u16 igb_get_hlen(struct igb_adapter *adapter,
*/
u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
- if (hlen > adapter->rx_ps_hdr_size)
- hlen = adapter->rx_ps_hdr_size;
+ if (hlen > adapter->rx_buffer_len)
+ hlen = adapter->rx_buffer_len;
return hlen;
}
@@ -4913,23 +4902,16 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
cleaned = true;
cleaned_count++;
- /* this is the fast path for the non-packet split case */
- if (!adapter->rx_ps_hdr_size) {
- pci_unmap_single(pdev, buffer_info->dma,
- adapter->rx_buffer_len,
- PCI_DMA_FROMDEVICE);
- buffer_info->dma = 0;
- skb_put(skb, length);
- goto send_up;
- }
-
if (buffer_info->dma) {
- u16 hlen = igb_get_hlen(adapter, rx_desc);
pci_unmap_single(pdev, buffer_info->dma,
- adapter->rx_ps_hdr_size,
+ adapter->rx_buffer_len,
PCI_DMA_FROMDEVICE);
buffer_info->dma = 0;
- skb_put(skb, hlen);
+ if (adapter->rx_buffer_len >= IGB_RXBUFFER_1024) {
+ skb_put(skb, length);
+ goto send_up;
+ }
+ skb_put(skb, igb_get_hlen(adapter, rx_desc));
}
if (length) {
@@ -4942,8 +4924,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
buffer_info->page_offset,
length);
- if ((adapter->rx_buffer_len > (PAGE_SIZE / 2)) ||
- (page_count(buffer_info->page) != 1))
+ if (page_count(buffer_info->page) != 1)
buffer_info->page = NULL;
else
get_page(buffer_info->page);
@@ -5070,15 +5051,12 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
i = rx_ring->next_to_use;
buffer_info = &rx_ring->buffer_info[i];
- if (adapter->rx_ps_hdr_size)
- bufsz = adapter->rx_ps_hdr_size;
- else
- bufsz = adapter->rx_buffer_len;
+ bufsz = adapter->rx_buffer_len;
while (cleaned_count--) {
rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
- if (adapter->rx_ps_hdr_size && !buffer_info->page_dma) {
+ if ((bufsz < IGB_RXBUFFER_1024) && !buffer_info->page_dma) {
if (!buffer_info->page) {
buffer_info->page = alloc_page(GFP_ATOMIC);
if (!buffer_info->page) {
@@ -5110,7 +5088,7 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
}
/* Refresh the desc even if buffer_addrs didn't change because
* each write-back erases this info. */
- if (adapter->rx_ps_hdr_size) {
+ if (bufsz < IGB_RXBUFFER_1024) {
rx_desc->read.pkt_addr =
cpu_to_le64(buffer_info->page_dma);
rx_desc->read.hdr_addr = cpu_to_le64(buffer_info->dma);
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 06/20] igb: move SRRCTL register configuration into ring specific config
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (3 preceding siblings ...)
2009-10-28 1:50 ` [net-next-2.6 PATCH 05/20] igb: remove rx_ps_hdr_len Jeff Kirsher
@ 2009-10-28 1:51 ` Jeff Kirsher
2009-10-28 1:51 ` [net-next-2.6 PATCH 07/20] igb: change the head and tail offsets into pointers Jeff Kirsher
` (14 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:51 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
The SRRCTL register exists per ring. Instead of configuring all of them in
the RCTL configuration which is meant to be global it makes more sense to move
this out into the ring specific configuration.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb_main.c | 60 +++++++++++++++++---------------------------
1 files changed, 23 insertions(+), 37 deletions(-)
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 24e502d..dfca821 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -2230,8 +2230,6 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 rctl;
- u32 srrctl = 0;
- int i;
rctl = rd32(E1000_RCTL);
@@ -2256,31 +2254,8 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
/* enable LPE to prevent packets larger than max_frame_size */
rctl |= E1000_RCTL_LPE;
- /* 82575 and greater support packet-split where the protocol
- * header is placed in skb->data and the packet data is
- * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
- * In the case of a non-split, skb->data is linearly filled,
- * followed by the page buffers. Therefore, skb->data is
- * sized to hold the largest protocol header.
- */
- /* allocations using alloc_page take too long for regular MTU
- * so only enable packet split for jumbo frames */
- if (adapter->rx_buffer_len < IGB_RXBUFFER_1024) {
- srrctl = ALIGN(adapter->rx_buffer_len, 64) <<
- E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
-#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
- srrctl |= IGB_RXBUFFER_16384 >>
- E1000_SRRCTL_BSIZEPKT_SHIFT;
-#else
- srrctl |= (PAGE_SIZE / 2) >>
- E1000_SRRCTL_BSIZEPKT_SHIFT;
-#endif
- srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
- } else {
- srrctl = ALIGN(adapter->rx_buffer_len, 1024) >>
- E1000_SRRCTL_BSIZEPKT_SHIFT;
- srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
- }
+ /* disable queue 0 to prevent tail write w/o re-config */
+ wr32(E1000_RXDCTL(0), 0);
/* Attention!!! For SR-IOV PF driver operations you must enable
* queue drop for all VF and PF queues to prevent head of line blocking
@@ -2291,10 +2266,6 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
/* set all queue drop enable bits */
wr32(E1000_QDE, ALL_QUEUES);
- srrctl |= E1000_SRRCTL_DROP_EN;
-
- /* disable queue 0 to prevent tail write w/o re-config */
- wr32(E1000_RXDCTL(0), 0);
vmolr = rd32(E1000_VMOLR(adapter->vfs_allocated_count));
if (rctl & E1000_RCTL_LPE)
@@ -2304,11 +2275,6 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
wr32(E1000_VMOLR(adapter->vfs_allocated_count), vmolr);
}
- for (i = 0; i < adapter->num_rx_queues; i++) {
- int j = adapter->rx_ring[i].reg_idx;
- wr32(E1000_SRRCTL(j), srrctl);
- }
-
wr32(E1000_RCTL, rctl);
}
@@ -2373,7 +2339,7 @@ static void igb_configure_rx_ring(struct igb_adapter *adapter,
struct e1000_hw *hw = &adapter->hw;
u64 rdba = ring->dma;
int reg_idx = ring->reg_idx;
- u32 rxdctl;
+ u32 srrctl, rxdctl;
/* disable the queue */
rxdctl = rd32(E1000_RXDCTL(reg_idx));
@@ -2393,6 +2359,26 @@ static void igb_configure_rx_ring(struct igb_adapter *adapter,
writel(0, hw->hw_addr + ring->head);
writel(0, hw->hw_addr + ring->tail);
+ /* set descriptor configuration */
+ if (adapter->rx_buffer_len < IGB_RXBUFFER_1024) {
+ srrctl = ALIGN(adapter->rx_buffer_len, 64) <<
+ E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
+#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
+ srrctl |= IGB_RXBUFFER_16384 >>
+ E1000_SRRCTL_BSIZEPKT_SHIFT;
+#else
+ srrctl |= (PAGE_SIZE / 2) >>
+ E1000_SRRCTL_BSIZEPKT_SHIFT;
+#endif
+ srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+ } else {
+ srrctl = ALIGN(adapter->rx_buffer_len, 1024) >>
+ E1000_SRRCTL_BSIZEPKT_SHIFT;
+ srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
+ }
+
+ wr32(E1000_SRRCTL(reg_idx), srrctl);
+
/* enable receive descriptor fetching */
rxdctl = rd32(E1000_RXDCTL(reg_idx));
rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 07/20] igb: change the head and tail offsets into pointers
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (4 preceding siblings ...)
2009-10-28 1:51 ` [net-next-2.6 PATCH 06/20] igb: move SRRCTL register configuration into ring specific config Jeff Kirsher
@ 2009-10-28 1:51 ` Jeff Kirsher
2009-10-28 1:51 ` [net-next-2.6 PATCH 08/20] igb: add pci device pointer to ring structure Jeff Kirsher
` (13 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:51 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
Since we are writting to the head/tail pointers frequently we might as well
save ourselves some processing time by converting the head and tail offsets
directly to pointers. This will shave a few cycles off the rx/tx path and
allows us to move one step closer to the rings being a bit more independant of
each other.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 4 ++--
drivers/net/igb/igb_main.c | 32 ++++++++++++++++----------------
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 303df02..e52fee4 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -178,8 +178,8 @@ struct igb_ring {
unsigned int count; /* number of desc. in the ring */
u16 next_to_use;
u16 next_to_clean;
- u16 head;
- u16 tail;
+ void __iomem *head;
+ void __iomem *tail;
struct igb_buffer *buffer_info; /* array of buffer info structs */
u8 queue_index;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index dfca821..2728f93 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -2124,10 +2124,10 @@ static void igb_configure_tx_ring(struct igb_adapter *adapter,
tdba & 0x00000000ffffffffULL);
wr32(E1000_TDBAH(reg_idx), tdba >> 32);
- ring->head = E1000_TDH(reg_idx);
- ring->tail = E1000_TDT(reg_idx);
- writel(0, hw->hw_addr + ring->tail);
- writel(0, hw->hw_addr + ring->head);
+ ring->head = hw->hw_addr + E1000_TDH(reg_idx);
+ ring->tail = hw->hw_addr + E1000_TDT(reg_idx);
+ writel(0, ring->head);
+ writel(0, ring->tail);
txdctl |= IGB_TX_PTHRESH;
txdctl |= IGB_TX_HTHRESH << 8;
@@ -2354,10 +2354,10 @@ static void igb_configure_rx_ring(struct igb_adapter *adapter,
ring->count * sizeof(union e1000_adv_rx_desc));
/* initialize head and tail */
- ring->head = E1000_RDH(reg_idx);
- ring->tail = E1000_RDT(reg_idx);
- writel(0, hw->hw_addr + ring->head);
- writel(0, hw->hw_addr + ring->tail);
+ ring->head = hw->hw_addr + E1000_RDH(reg_idx);
+ ring->tail = hw->hw_addr + E1000_RDT(reg_idx);
+ writel(0, ring->head);
+ writel(0, ring->tail);
/* set descriptor configuration */
if (adapter->rx_buffer_len < IGB_RXBUFFER_1024) {
@@ -2567,8 +2567,8 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
- writel(0, adapter->hw.hw_addr + tx_ring->head);
- writel(0, adapter->hw.hw_addr + tx_ring->tail);
+ writel(0, tx_ring->head);
+ writel(0, tx_ring->tail);
}
/**
@@ -2667,8 +2667,8 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
- writel(0, adapter->hw.hw_addr + rx_ring->head);
- writel(0, adapter->hw.hw_addr + rx_ring->tail);
+ writel(0, rx_ring->head);
+ writel(0, rx_ring->tail);
}
/**
@@ -3556,7 +3556,7 @@ static inline void igb_tx_queue_adv(struct igb_adapter *adapter,
wmb();
tx_ring->next_to_use = i;
- writel(i, adapter->hw.hw_addr + tx_ring->tail);
+ writel(i, tx_ring->tail);
/* we need this if more than one processor can write to our tail
* at a time, it syncronizes IO on IA64/Altix systems */
mmiowb();
@@ -4761,8 +4761,8 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
" jiffies <%lx>\n"
" desc.status <%x>\n",
tx_ring->queue_index,
- readl(adapter->hw.hw_addr + tx_ring->head),
- readl(adapter->hw.hw_addr + tx_ring->tail),
+ readl(tx_ring->head),
+ readl(tx_ring->tail),
tx_ring->next_to_use,
tx_ring->next_to_clean,
tx_ring->buffer_info[i].time_stamp,
@@ -5103,7 +5103,7 @@ no_buffers:
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
- writel(i, adapter->hw.hw_addr + rx_ring->tail);
+ writel(i, rx_ring->tail);
}
}
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 08/20] igb: add pci device pointer to ring structure
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (5 preceding siblings ...)
2009-10-28 1:51 ` [net-next-2.6 PATCH 07/20] igb: change the head and tail offsets into pointers Jeff Kirsher
@ 2009-10-28 1:51 ` Jeff Kirsher
2009-10-28 1:52 ` [net-next-2.6 PATCH 09/20] igb: move rx_buffer_len into the " Jeff Kirsher
` (12 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:51 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This patch adds a pci device pointer to the ring structure. The main use of
this pointer is for memory mapping/unmapping of the rings.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 5 ++-
drivers/net/igb/igb_ethtool.c | 4 +-
drivers/net/igb/igb_main.c | 72 ++++++++++++++++++++---------------------
3 files changed, 40 insertions(+), 41 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index e52fee4..de26862 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -173,6 +173,7 @@ struct igb_q_vector {
struct igb_ring {
struct igb_q_vector *q_vector; /* backlink to q_vector */
void *desc; /* descriptor ring memory */
+ struct pci_dev *pdev; /* pci device for dma mapping */
dma_addr_t dma; /* phys address of the ring */
unsigned int size; /* length of desc. ring in bytes */
unsigned int count; /* number of desc. in the ring */
@@ -325,8 +326,8 @@ extern void igb_down(struct igb_adapter *);
extern void igb_reinit_locked(struct igb_adapter *);
extern void igb_reset(struct igb_adapter *);
extern int igb_set_spd_dplx(struct igb_adapter *, u16);
-extern int igb_setup_tx_resources(struct igb_adapter *, struct igb_ring *);
-extern int igb_setup_rx_resources(struct igb_adapter *, struct igb_ring *);
+extern int igb_setup_tx_resources(struct igb_ring *);
+extern int igb_setup_rx_resources(struct igb_ring *);
extern void igb_free_tx_resources(struct igb_ring *);
extern void igb_free_rx_resources(struct igb_ring *);
extern void igb_update_stats(struct igb_adapter *);
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 2929546..c48a555 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -794,7 +794,7 @@ static int igb_set_ringparam(struct net_device *netdev,
for (i = 0; i < adapter->num_tx_queues; i++) {
temp_ring[i].count = new_tx_count;
- err = igb_setup_tx_resources(adapter, &temp_ring[i]);
+ err = igb_setup_tx_resources(&temp_ring[i]);
if (err) {
while (i) {
i--;
@@ -819,7 +819,7 @@ static int igb_set_ringparam(struct net_device *netdev,
for (i = 0; i < adapter->num_rx_queues; i++) {
temp_ring[i].count = new_rx_count;
- err = igb_setup_rx_resources(adapter, &temp_ring[i]);
+ err = igb_setup_rx_resources(&temp_ring[i]);
if (err) {
while (i) {
i--;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 2728f93..ff16b7a 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -436,11 +436,13 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
struct igb_ring *ring = &(adapter->tx_ring[i]);
ring->count = adapter->tx_ring_count;
ring->queue_index = i;
+ ring->pdev = adapter->pdev;
}
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = &(adapter->rx_ring[i]);
ring->count = adapter->rx_ring_count;
ring->queue_index = i;
+ ring->pdev = adapter->pdev;
}
igb_cache_ring_register(adapter);
@@ -2002,15 +2004,13 @@ static int igb_close(struct net_device *netdev)
/**
* igb_setup_tx_resources - allocate Tx resources (Descriptors)
- * @adapter: board private structure
* @tx_ring: tx descriptor ring (for a specific queue) to setup
*
* Return 0 on success, negative on failure
**/
-int igb_setup_tx_resources(struct igb_adapter *adapter,
- struct igb_ring *tx_ring)
+int igb_setup_tx_resources(struct igb_ring *tx_ring)
{
- struct pci_dev *pdev = adapter->pdev;
+ struct pci_dev *pdev = tx_ring->pdev;
int size;
size = sizeof(struct igb_buffer) * tx_ring->count;
@@ -2053,7 +2053,7 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter)
int r_idx;
for (i = 0; i < adapter->num_tx_queues; i++) {
- err = igb_setup_tx_resources(adapter, &adapter->tx_ring[i]);
+ err = igb_setup_tx_resources(&adapter->tx_ring[i]);
if (err) {
dev_err(&adapter->pdev->dev,
"Allocation for Tx Queue %u failed\n", i);
@@ -2156,15 +2156,13 @@ static void igb_configure_tx(struct igb_adapter *adapter)
/**
* igb_setup_rx_resources - allocate Rx resources (Descriptors)
- * @adapter: board private structure
* @rx_ring: rx descriptor ring (for a specific queue) to setup
*
* Returns 0 on success, negative on failure
**/
-int igb_setup_rx_resources(struct igb_adapter *adapter,
- struct igb_ring *rx_ring)
+int igb_setup_rx_resources(struct igb_ring *rx_ring)
{
- struct pci_dev *pdev = adapter->pdev;
+ struct pci_dev *pdev = rx_ring->pdev;
int size, desc_len;
size = sizeof(struct igb_buffer) * rx_ring->count;
@@ -2192,7 +2190,7 @@ int igb_setup_rx_resources(struct igb_adapter *adapter,
err:
vfree(rx_ring->buffer_info);
- dev_err(&adapter->pdev->dev, "Unable to allocate memory for "
+ dev_err(&pdev->dev, "Unable to allocate memory for "
"the receive descriptor ring\n");
return -ENOMEM;
}
@@ -2209,7 +2207,7 @@ static int igb_setup_all_rx_resources(struct igb_adapter *adapter)
int i, err = 0;
for (i = 0; i < adapter->num_rx_queues; i++) {
- err = igb_setup_rx_resources(adapter, &adapter->rx_ring[i]);
+ err = igb_setup_rx_resources(&adapter->rx_ring[i]);
if (err) {
dev_err(&adapter->pdev->dev,
"Allocation for Rx Queue %u failed\n", i);
@@ -2497,14 +2495,13 @@ static void igb_configure_rx(struct igb_adapter *adapter)
**/
void igb_free_tx_resources(struct igb_ring *tx_ring)
{
- struct pci_dev *pdev = tx_ring->q_vector->adapter->pdev;
-
igb_clean_tx_ring(tx_ring);
vfree(tx_ring->buffer_info);
tx_ring->buffer_info = NULL;
- pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
+ pci_free_consistent(tx_ring->pdev, tx_ring->size,
+ tx_ring->desc, tx_ring->dma);
tx_ring->desc = NULL;
}
@@ -2523,12 +2520,13 @@ static void igb_free_all_tx_resources(struct igb_adapter *adapter)
igb_free_tx_resources(&adapter->tx_ring[i]);
}
-static void igb_unmap_and_free_tx_resource(struct igb_adapter *adapter,
+static void igb_unmap_and_free_tx_resource(struct igb_ring *tx_ring,
struct igb_buffer *buffer_info)
{
buffer_info->dma = 0;
if (buffer_info->skb) {
- skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb,
+ skb_dma_unmap(&tx_ring->pdev->dev,
+ buffer_info->skb,
DMA_TO_DEVICE);
dev_kfree_skb_any(buffer_info->skb);
buffer_info->skb = NULL;
@@ -2543,7 +2541,6 @@ static void igb_unmap_and_free_tx_resource(struct igb_adapter *adapter,
**/
static void igb_clean_tx_ring(struct igb_ring *tx_ring)
{
- struct igb_adapter *adapter = tx_ring->q_vector->adapter;
struct igb_buffer *buffer_info;
unsigned long size;
unsigned int i;
@@ -2554,7 +2551,7 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
for (i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
- igb_unmap_and_free_tx_resource(adapter, buffer_info);
+ igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
}
size = sizeof(struct igb_buffer) * tx_ring->count;
@@ -2591,14 +2588,13 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter)
**/
void igb_free_rx_resources(struct igb_ring *rx_ring)
{
- struct pci_dev *pdev = rx_ring->q_vector->adapter->pdev;
-
igb_clean_rx_ring(rx_ring);
vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
- pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
+ pci_free_consistent(rx_ring->pdev, rx_ring->size,
+ rx_ring->desc, rx_ring->dma);
rx_ring->desc = NULL;
}
@@ -2625,7 +2621,6 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
{
struct igb_adapter *adapter = rx_ring->q_vector->adapter;
struct igb_buffer *buffer_info;
- struct pci_dev *pdev = adapter->pdev;
unsigned long size;
unsigned int i;
@@ -2635,7 +2630,8 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
for (i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
if (buffer_info->dma) {
- pci_unmap_single(pdev, buffer_info->dma,
+ pci_unmap_single(rx_ring->pdev,
+ buffer_info->dma,
adapter->rx_buffer_len,
PCI_DMA_FROMDEVICE);
buffer_info->dma = 0;
@@ -2646,7 +2642,8 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
buffer_info->skb = NULL;
}
if (buffer_info->page_dma) {
- pci_unmap_page(pdev, buffer_info->page_dma,
+ pci_unmap_page(rx_ring->pdev,
+ buffer_info->page_dma,
PAGE_SIZE / 2,
PCI_DMA_FROMDEVICE);
buffer_info->page_dma = 0;
@@ -3362,9 +3359,10 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter,
struct sk_buff *skb, u32 tx_flags)
{
struct e1000_adv_tx_context_desc *context_desc;
- unsigned int i;
+ struct pci_dev *pdev = tx_ring->pdev;
struct igb_buffer *buffer_info;
u32 info = 0, tu_cmd = 0;
+ unsigned int i;
if ((skb->ip_summed == CHECKSUM_PARTIAL) ||
(tx_flags & IGB_TX_FLAGS_VLAN)) {
@@ -3411,7 +3409,7 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter,
break;
default:
if (unlikely(net_ratelimit()))
- dev_warn(&adapter->pdev->dev,
+ dev_warn(&pdev->dev,
"partial checksum but proto=%x!\n",
skb->protocol);
break;
@@ -3443,11 +3441,11 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter,
#define IGB_MAX_TXD_PWR 16
#define IGB_MAX_DATA_PER_TXD (1<<IGB_MAX_TXD_PWR)
-static inline int igb_tx_map_adv(struct igb_adapter *adapter,
- struct igb_ring *tx_ring, struct sk_buff *skb,
+static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb,
unsigned int first)
{
struct igb_buffer *buffer_info;
+ struct pci_dev *pdev = tx_ring->pdev;
unsigned int len = skb_headlen(skb);
unsigned int count = 0, i;
unsigned int f;
@@ -3455,8 +3453,8 @@ static inline int igb_tx_map_adv(struct igb_adapter *adapter,
i = tx_ring->next_to_use;
- if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) {
- dev_err(&adapter->pdev->dev, "TX DMA map failed\n");
+ if (skb_dma_map(&pdev->dev, skb, DMA_TO_DEVICE)) {
+ dev_err(&pdev->dev, "TX DMA map failed\n");
return 0;
}
@@ -3667,7 +3665,7 @@ static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
* count reflects descriptors mapped, if 0 then mapping error
* has occured and we need to rewind the descriptor queue
*/
- count = igb_tx_map_adv(adapter, tx_ring, skb, first);
+ count = igb_tx_map_adv(tx_ring, skb, first);
if (count) {
igb_tx_queue_adv(adapter, tx_ring, tx_flags, count,
@@ -4710,7 +4708,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
igb_tx_hwtstamp(adapter, skb);
}
- igb_unmap_and_free_tx_resource(adapter, buffer_info);
+ igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
tx_desc->wb.status = 0;
i++;
@@ -4748,7 +4746,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
E1000_STATUS_TXOFF)) {
/* detected Tx unit hang */
- dev_err(&adapter->pdev->dev,
+ dev_err(&tx_ring->pdev->dev,
"Detected Tx Unit Hang\n"
" Tx Queue <%d>\n"
" TDH <%x>\n"
@@ -4851,7 +4849,7 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
struct net_device *netdev = adapter->netdev;
struct igb_ring *rx_ring = q_vector->rx_ring;
struct e1000_hw *hw = &adapter->hw;
- struct pci_dev *pdev = adapter->pdev;
+ struct pci_dev *pdev = rx_ring->pdev;
union e1000_adv_rx_desc *rx_desc , *next_rxd;
struct igb_buffer *buffer_info , *next_buffer;
struct sk_buff *skb;
@@ -5027,7 +5025,6 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
{
struct igb_adapter *adapter = rx_ring->q_vector->adapter;
struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
union e1000_adv_rx_desc *rx_desc;
struct igb_buffer *buffer_info;
struct sk_buff *skb;
@@ -5054,7 +5051,7 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
buffer_info->page_offset ^= PAGE_SIZE / 2;
}
buffer_info->page_dma =
- pci_map_page(pdev, buffer_info->page,
+ pci_map_page(rx_ring->pdev, buffer_info->page,
buffer_info->page_offset,
PAGE_SIZE / 2,
PCI_DMA_FROMDEVICE);
@@ -5068,7 +5065,8 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
}
buffer_info->skb = skb;
- buffer_info->dma = pci_map_single(pdev, skb->data,
+ buffer_info->dma = pci_map_single(rx_ring->pdev,
+ skb->data,
bufsz,
PCI_DMA_FROMDEVICE);
}
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 09/20] igb: move rx_buffer_len into the ring structure
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (6 preceding siblings ...)
2009-10-28 1:51 ` [net-next-2.6 PATCH 08/20] igb: add pci device pointer to ring structure Jeff Kirsher
@ 2009-10-28 1:52 ` Jeff Kirsher
2009-10-28 1:52 ` [net-next-2.6 PATCH 10/20] igb: move alloc_failed and csum_err stats into per rx-ring stat Jeff Kirsher
` (11 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:52 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This patch moves the rx_buffer_len value into the ring structure. This allows
greater flexibility and the option of doing things such as supporting packet
split only on some queues, or enabling virtualization.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 3 +--
drivers/net/igb/igb_main.c | 41 ++++++++++++++++++++++-------------------
2 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index de26862..00ff274 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -198,7 +198,7 @@ struct igb_ring {
/* RX */
struct {
struct igb_rx_queue_stats rx_stats;
- u64 rx_queue_drops;
+ u32 rx_buffer_len;
};
};
};
@@ -218,7 +218,6 @@ struct igb_adapter {
struct vlan_group *vlgrp;
u16 mng_vlan_id;
u32 bd_number;
- u32 rx_buffer_len;
u32 wol;
u32 en_mng_pt;
u16 link_speed;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index ff16b7a..04e860d 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -443,6 +443,7 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
ring->count = adapter->rx_ring_count;
ring->queue_index = i;
ring->pdev = adapter->pdev;
+ ring->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
}
igb_cache_ring_register(adapter);
@@ -1863,7 +1864,6 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
adapter->tx_ring_count = IGB_DEFAULT_TXD;
adapter->rx_ring_count = IGB_DEFAULT_RXD;
- adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
@@ -2358,8 +2358,8 @@ static void igb_configure_rx_ring(struct igb_adapter *adapter,
writel(0, ring->tail);
/* set descriptor configuration */
- if (adapter->rx_buffer_len < IGB_RXBUFFER_1024) {
- srrctl = ALIGN(adapter->rx_buffer_len, 64) <<
+ if (ring->rx_buffer_len < IGB_RXBUFFER_1024) {
+ srrctl = ALIGN(ring->rx_buffer_len, 64) <<
E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
srrctl |= IGB_RXBUFFER_16384 >>
@@ -2370,7 +2370,7 @@ static void igb_configure_rx_ring(struct igb_adapter *adapter,
#endif
srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
} else {
- srrctl = ALIGN(adapter->rx_buffer_len, 1024) >>
+ srrctl = ALIGN(ring->rx_buffer_len, 1024) >>
E1000_SRRCTL_BSIZEPKT_SHIFT;
srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
}
@@ -2619,7 +2619,6 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter)
**/
static void igb_clean_rx_ring(struct igb_ring *rx_ring)
{
- struct igb_adapter *adapter = rx_ring->q_vector->adapter;
struct igb_buffer *buffer_info;
unsigned long size;
unsigned int i;
@@ -2632,7 +2631,7 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
if (buffer_info->dma) {
pci_unmap_single(rx_ring->pdev,
buffer_info->dma,
- adapter->rx_buffer_len,
+ rx_ring->rx_buffer_len,
PCI_DMA_FROMDEVICE);
buffer_info->dma = 0;
}
@@ -3746,6 +3745,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
{
struct igb_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
+ u32 rx_buffer_len, i;
if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
(max_frame > MAX_JUMBO_FRAME_SIZE)) {
@@ -3763,9 +3763,6 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
/* igb_down has a dependency on max_frame_size */
adapter->max_frame_size = max_frame;
- if (netif_running(netdev))
- igb_down(adapter);
-
/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
* means we reserve 2 more, this pushes us to allocate from the next
* larger slab size.
@@ -3773,16 +3770,22 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
*/
if (max_frame <= IGB_RXBUFFER_1024)
- adapter->rx_buffer_len = IGB_RXBUFFER_1024;
+ rx_buffer_len = IGB_RXBUFFER_1024;
else if (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE)
- adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
+ rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
else
- adapter->rx_buffer_len = IGB_RXBUFFER_128;
+ rx_buffer_len = IGB_RXBUFFER_128;
+
+ if (netif_running(netdev))
+ igb_down(adapter);
dev_info(&adapter->pdev->dev, "changing MTU from %d to %d\n",
netdev->mtu, new_mtu);
netdev->mtu = new_mtu;
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ adapter->rx_ring[i].rx_buffer_len = rx_buffer_len;
+
if (netif_running(netdev))
igb_up(adapter);
else
@@ -4828,7 +4831,7 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter,
dev_dbg(&adapter->pdev->dev, "cksum success: bits %08X\n", status_err);
}
-static inline u16 igb_get_hlen(struct igb_adapter *adapter,
+static inline u16 igb_get_hlen(struct igb_ring *rx_ring,
union e1000_adv_rx_desc *rx_desc)
{
/* HW will not DMA in data larger than the given buffer, even if it
@@ -4837,8 +4840,8 @@ static inline u16 igb_get_hlen(struct igb_adapter *adapter,
*/
u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
- if (hlen > adapter->rx_buffer_len)
- hlen = adapter->rx_buffer_len;
+ if (hlen > rx_ring->rx_buffer_len)
+ hlen = rx_ring->rx_buffer_len;
return hlen;
}
@@ -4888,14 +4891,14 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
if (buffer_info->dma) {
pci_unmap_single(pdev, buffer_info->dma,
- adapter->rx_buffer_len,
+ rx_ring->rx_buffer_len,
PCI_DMA_FROMDEVICE);
buffer_info->dma = 0;
- if (adapter->rx_buffer_len >= IGB_RXBUFFER_1024) {
+ if (rx_ring->rx_buffer_len >= IGB_RXBUFFER_1024) {
skb_put(skb, length);
goto send_up;
}
- skb_put(skb, igb_get_hlen(adapter, rx_desc));
+ skb_put(skb, igb_get_hlen(rx_ring, rx_desc));
}
if (length) {
@@ -5034,7 +5037,7 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
i = rx_ring->next_to_use;
buffer_info = &rx_ring->buffer_info[i];
- bufsz = adapter->rx_buffer_len;
+ bufsz = rx_ring->rx_buffer_len;
while (cleaned_count--) {
rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 10/20] igb: move alloc_failed and csum_err stats into per rx-ring stat
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (7 preceding siblings ...)
2009-10-28 1:52 ` [net-next-2.6 PATCH 09/20] igb: move rx_buffer_len into the " Jeff Kirsher
@ 2009-10-28 1:52 ` Jeff Kirsher
2009-10-28 1:52 ` [net-next-2.6 PATCH 11/20] igb: add a flags value to the ring Jeff Kirsher
` (10 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:52 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
The allocation failed and checksum error stats are currently kept as a
global stat. If we end up allocating the queues to multiple netdevs then
the global counter doesn't make much sense. For this reason I felt it
necessary to move the alloc_rx_buff_failed stat into the rx_stats
portion of the rx_ring.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 6 +++---
drivers/net/igb/igb_ethtool.c | 9 ++++++---
drivers/net/igb/igb_main.c | 17 ++++++++---------
3 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 00ff274..6a67fa2 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -145,12 +145,15 @@ struct igb_buffer {
struct igb_tx_queue_stats {
u64 packets;
u64 bytes;
+ u64 restart_queue;
};
struct igb_rx_queue_stats {
u64 packets;
u64 bytes;
u64 drops;
+ u64 csum_err;
+ u64 alloc_failed;
};
struct igb_q_vector {
@@ -241,7 +244,6 @@ struct igb_adapter {
/* TX */
struct igb_ring *tx_ring; /* One per active queue */
- unsigned int restart_queue;
unsigned long tx_queue_len;
u32 txd_cmd;
u32 gotc;
@@ -255,8 +257,6 @@ struct igb_adapter {
int num_tx_queues;
int num_rx_queues;
- u64 hw_csum_err;
- u32 alloc_rx_buff_failed;
u32 gorc;
u64 gorc_old;
u32 max_frame_size;
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index c48a555..f62430b 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -84,7 +84,6 @@ static const struct igb_stats igb_gstrings_stats[] = {
{ "tx_single_coll_ok", IGB_STAT(stats.scc) },
{ "tx_multi_coll_ok", IGB_STAT(stats.mcc) },
{ "tx_timeout_count", IGB_STAT(tx_timeout_count) },
- { "tx_restart_queue", IGB_STAT(restart_queue) },
{ "rx_long_length_errors", IGB_STAT(stats.roc) },
{ "rx_short_length_errors", IGB_STAT(stats.ruc) },
{ "rx_align_errors", IGB_STAT(stats.algnerrc) },
@@ -95,9 +94,7 @@ static const struct igb_stats igb_gstrings_stats[] = {
{ "tx_flow_control_xon", IGB_STAT(stats.xontxc) },
{ "tx_flow_control_xoff", IGB_STAT(stats.xofftxc) },
{ "rx_long_byte_count", IGB_STAT(stats.gorc) },
- { "rx_csum_offload_errors", IGB_STAT(hw_csum_err) },
{ "tx_dma_out_of_sync", IGB_STAT(stats.doosync) },
- { "alloc_rx_buff_failed", IGB_STAT(alloc_rx_buff_failed) },
{ "tx_smbus", IGB_STAT(stats.mgptc) },
{ "rx_smbus", IGB_STAT(stats.mgprc) },
{ "dropped_smbus", IGB_STAT(stats.mgpdc) },
@@ -2031,6 +2028,8 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
p += ETH_GSTRING_LEN;
sprintf(p, "tx_queue_%u_bytes", i);
p += ETH_GSTRING_LEN;
+ sprintf(p, "tx_queue_%u_restart", i);
+ p += ETH_GSTRING_LEN;
}
for (i = 0; i < adapter->num_rx_queues; i++) {
sprintf(p, "rx_queue_%u_packets", i);
@@ -2039,6 +2038,10 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
p += ETH_GSTRING_LEN;
sprintf(p, "rx_queue_%u_drops", i);
p += ETH_GSTRING_LEN;
+ sprintf(p, "rx_queue_%u_csum_err", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "rx_queue_%u_alloc_failed", i);
+ p += ETH_GSTRING_LEN;
}
/* BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */
break;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 04e860d..bdd7bf0 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -3562,8 +3562,6 @@ static inline void igb_tx_queue_adv(struct igb_adapter *adapter,
static int __igb_maybe_stop_tx(struct net_device *netdev,
struct igb_ring *tx_ring, int size)
{
- struct igb_adapter *adapter = netdev_priv(netdev);
-
netif_stop_subqueue(netdev, tx_ring->queue_index);
/* Herbert's original patch had:
@@ -3578,7 +3576,7 @@ static int __igb_maybe_stop_tx(struct net_device *netdev,
/* A reprieve! */
netif_wake_subqueue(netdev, tx_ring->queue_index);
- ++adapter->restart_queue;
+ tx_ring->tx_stats.restart_queue++;
return 0;
}
@@ -4734,7 +4732,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
!(test_bit(__IGB_DOWN, &adapter->state))) {
netif_wake_subqueue(netdev, tx_ring->queue_index);
- ++adapter->restart_queue;
+ tx_ring->tx_stats.restart_queue++;
}
}
@@ -4801,7 +4799,8 @@ static void igb_receive_skb(struct igb_q_vector *q_vector,
napi_gro_receive(&q_vector->napi, skb);
}
-static inline void igb_rx_checksum_adv(struct igb_adapter *adapter,
+static inline void igb_rx_checksum_adv(struct igb_ring *ring,
+ struct igb_adapter *adapter,
u32 status_err, struct sk_buff *skb)
{
skb->ip_summed = CHECKSUM_NONE;
@@ -4820,7 +4819,7 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter,
*/
if (!((adapter->hw.mac.type == e1000_82576) &&
(skb->len == 60)))
- adapter->hw_csum_err++;
+ ring->rx_stats.csum_err++;
/* let the stack verify checksum errors */
return;
}
@@ -4979,7 +4978,7 @@ send_up:
total_bytes += skb->len;
total_packets++;
- igb_rx_checksum_adv(adapter, staterr, skb);
+ igb_rx_checksum_adv(rx_ring, adapter, staterr, skb);
skb->protocol = eth_type_trans(skb, netdev);
skb_record_rx_queue(skb, rx_ring->queue_index);
@@ -5046,7 +5045,7 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
if (!buffer_info->page) {
buffer_info->page = alloc_page(GFP_ATOMIC);
if (!buffer_info->page) {
- adapter->alloc_rx_buff_failed++;
+ rx_ring->rx_stats.alloc_failed++;
goto no_buffers;
}
buffer_info->page_offset = 0;
@@ -5063,7 +5062,7 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
if (!buffer_info->skb) {
skb = netdev_alloc_skb_ip_align(netdev, bufsz);
if (!skb) {
- adapter->alloc_rx_buff_failed++;
+ rx_ring->rx_stats.alloc_failed++;
goto no_buffers;
}
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 11/20] igb: add a flags value to the ring
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (8 preceding siblings ...)
2009-10-28 1:52 ` [net-next-2.6 PATCH 10/20] igb: move alloc_failed and csum_err stats into per rx-ring stat Jeff Kirsher
@ 2009-10-28 1:52 ` Jeff Kirsher
2009-10-28 1:53 ` [net-next-2.6 PATCH 12/20] igb: place a pointer to the netdev struct in the ring itself Jeff Kirsher
` (9 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:52 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This patch adds a flags value to the ring that cleans up some of the last
remaining items from the ring in order to help seperate it from the adapter
struct. By implementing these flags it becomes possible for different rings
to support different functions such as rx checksumming.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 12 ++++-
drivers/net/igb/igb_ethtool.c | 13 ++++--
drivers/net/igb/igb_main.c | 93 +++++++++++++++++++----------------------
3 files changed, 60 insertions(+), 58 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 6a67fa2..0c30c5e 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -192,6 +192,8 @@ struct igb_ring {
unsigned int total_bytes;
unsigned int total_packets;
+ u32 flags;
+
union {
/* TX */
struct {
@@ -206,6 +208,13 @@ struct igb_ring {
};
};
+#define IGB_RING_FLAG_RX_CSUM 0x00000001 /* RX CSUM enabled */
+#define IGB_RING_FLAG_RX_SCTP_CSUM 0x00000002 /* SCTP CSUM offload enabled */
+
+#define IGB_RING_FLAG_TX_CTX_IDX 0x00000001 /* HW requires context index */
+
+#define IGB_ADVTXD_DCMD (E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS)
+
#define E1000_RX_DESC_ADV(R, i) \
(&(((union e1000_adv_rx_desc *)((R).desc))[i]))
#define E1000_TX_DESC_ADV(R, i) \
@@ -245,7 +254,6 @@ struct igb_adapter {
/* TX */
struct igb_ring *tx_ring; /* One per active queue */
unsigned long tx_queue_len;
- u32 txd_cmd;
u32 gotc;
u64 gotc_old;
u64 tpt_old;
@@ -303,8 +311,6 @@ struct igb_adapter {
#define IGB_FLAG_HAS_MSI (1 << 0)
#define IGB_FLAG_DCA_ENABLED (1 << 1)
#define IGB_FLAG_QUAD_PORT_A (1 << 2)
-#define IGB_FLAG_NEED_CTX_IDX (1 << 3)
-#define IGB_FLAG_RX_CSUM_DISABLED (1 << 4)
enum e1000_state_t {
__IGB_TESTING,
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index f62430b..c44dede 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -279,17 +279,20 @@ static int igb_set_pauseparam(struct net_device *netdev,
static u32 igb_get_rx_csum(struct net_device *netdev)
{
struct igb_adapter *adapter = netdev_priv(netdev);
- return !(adapter->flags & IGB_FLAG_RX_CSUM_DISABLED);
+ return !!(adapter->rx_ring[0].flags & IGB_RING_FLAG_RX_CSUM);
}
static int igb_set_rx_csum(struct net_device *netdev, u32 data)
{
struct igb_adapter *adapter = netdev_priv(netdev);
+ int i;
- if (data)
- adapter->flags &= ~IGB_FLAG_RX_CSUM_DISABLED;
- else
- adapter->flags |= IGB_FLAG_RX_CSUM_DISABLED;
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ if (data)
+ adapter->rx_ring[i].flags |= IGB_RING_FLAG_RX_CSUM;
+ else
+ adapter->rx_ring[i].flags &= ~IGB_RING_FLAG_RX_CSUM;
+ }
return 0;
}
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index bdd7bf0..00f3f2d 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -437,13 +437,21 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
ring->count = adapter->tx_ring_count;
ring->queue_index = i;
ring->pdev = adapter->pdev;
+ /* For 82575, context index must be unique per ring. */
+ if (adapter->hw.mac.type == e1000_82575)
+ ring->flags = IGB_RING_FLAG_TX_CTX_IDX;
}
+
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = &(adapter->rx_ring[i]);
ring->count = adapter->rx_ring_count;
ring->queue_index = i;
ring->pdev = adapter->pdev;
ring->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
+ ring->flags = IGB_RING_FLAG_RX_CSUM; /* enable rx checksum */
+ /* set flag indicating ring supports SCTP checksum offload */
+ if (adapter->hw.mac.type >= e1000_82576)
+ ring->flags |= IGB_RING_FLAG_RX_SCTP_CSUM;
}
igb_cache_ring_register(adapter);
@@ -1517,16 +1525,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
igb_get_bus_info_pcie(hw);
- /* set flags */
- switch (hw->mac.type) {
- case e1000_82575:
- adapter->flags |= IGB_FLAG_NEED_CTX_IDX;
- break;
- case e1000_82576:
- default:
- break;
- }
-
hw->phy.autoneg_wait_to_complete = false;
hw->mac.adaptive_ifs = true;
@@ -2149,9 +2147,6 @@ static void igb_configure_tx(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++)
igb_configure_tx_ring(adapter, &adapter->tx_ring[i]);
-
- /* Setup Transmit Descriptor Settings for eop descriptor */
- adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS;
}
/**
@@ -3272,8 +3267,7 @@ set_itr_now:
#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000
#define IGB_TX_FLAGS_VLAN_SHIFT 16
-static inline int igb_tso_adv(struct igb_adapter *adapter,
- struct igb_ring *tx_ring,
+static inline int igb_tso_adv(struct igb_ring *tx_ring,
struct sk_buff *skb, u32 tx_flags, u8 *hdr_len)
{
struct e1000_adv_tx_context_desc *context_desc;
@@ -3335,8 +3329,8 @@ static inline int igb_tso_adv(struct igb_adapter *adapter,
mss_l4len_idx |= (l4len << E1000_ADVTXD_L4LEN_SHIFT);
/* For 82575, context index must be unique per ring. */
- if (adapter->flags & IGB_FLAG_NEED_CTX_IDX)
- mss_l4len_idx |= tx_ring->queue_index << 4;
+ if (tx_ring->flags & IGB_RING_FLAG_TX_CTX_IDX)
+ mss_l4len_idx |= tx_ring->reg_idx << 4;
context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
context_desc->seqnum_seed = 0;
@@ -3353,9 +3347,8 @@ static inline int igb_tso_adv(struct igb_adapter *adapter,
return true;
}
-static inline bool igb_tx_csum_adv(struct igb_adapter *adapter,
- struct igb_ring *tx_ring,
- struct sk_buff *skb, u32 tx_flags)
+static inline bool igb_tx_csum_adv(struct igb_ring *tx_ring,
+ struct sk_buff *skb, u32 tx_flags)
{
struct e1000_adv_tx_context_desc *context_desc;
struct pci_dev *pdev = tx_ring->pdev;
@@ -3417,11 +3410,9 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter,
context_desc->type_tucmd_mlhl = cpu_to_le32(tu_cmd);
context_desc->seqnum_seed = 0;
- if (adapter->flags & IGB_FLAG_NEED_CTX_IDX)
+ if (tx_ring->flags & IGB_RING_FLAG_TX_CTX_IDX)
context_desc->mss_l4len_idx =
- cpu_to_le32(tx_ring->queue_index << 4);
- else
- context_desc->mss_l4len_idx = 0;
+ cpu_to_le32(tx_ring->reg_idx << 4);
buffer_info->time_stamp = jiffies;
buffer_info->next_to_watch = i;
@@ -3492,8 +3483,7 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb,
return count + 1;
}
-static inline void igb_tx_queue_adv(struct igb_adapter *adapter,
- struct igb_ring *tx_ring,
+static inline void igb_tx_queue_adv(struct igb_ring *tx_ring,
int tx_flags, int count, u32 paylen,
u8 hdr_len)
{
@@ -3525,10 +3515,11 @@ static inline void igb_tx_queue_adv(struct igb_adapter *adapter,
olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
}
- if ((adapter->flags & IGB_FLAG_NEED_CTX_IDX) &&
- (tx_flags & (IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_TSO |
+ if ((tx_ring->flags & IGB_RING_FLAG_TX_CTX_IDX) &&
+ (tx_flags & (IGB_TX_FLAGS_CSUM |
+ IGB_TX_FLAGS_TSO |
IGB_TX_FLAGS_VLAN)))
- olinfo_status |= tx_ring->queue_index << 4;
+ olinfo_status |= tx_ring->reg_idx << 4;
olinfo_status |= ((paylen - hdr_len) << E1000_ADVTXD_PAYLEN_SHIFT);
@@ -3545,7 +3536,7 @@ static inline void igb_tx_queue_adv(struct igb_adapter *adapter,
i = 0;
}
- tx_desc->read.cmd_type_len |= cpu_to_le32(adapter->txd_cmd);
+ tx_desc->read.cmd_type_len |= cpu_to_le32(IGB_ADVTXD_DCMD);
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
* applicable for weak-ordered memory model archs,
@@ -3644,17 +3635,17 @@ static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
tx_flags |= IGB_TX_FLAGS_IPV4;
first = tx_ring->next_to_use;
- tso = skb_is_gso(skb) ? igb_tso_adv(adapter, tx_ring, skb, tx_flags,
- &hdr_len) : 0;
-
- if (tso < 0) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
+ if (skb_is_gso(skb)) {
+ tso = igb_tso_adv(tx_ring, skb, tx_flags, &hdr_len);
+ if (tso < 0) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
}
if (tso)
tx_flags |= IGB_TX_FLAGS_TSO;
- else if (igb_tx_csum_adv(adapter, tx_ring, skb, tx_flags) &&
+ else if (igb_tx_csum_adv(tx_ring, skb, tx_flags) &&
(skb->ip_summed == CHECKSUM_PARTIAL))
tx_flags |= IGB_TX_FLAGS_CSUM;
@@ -3664,17 +3655,18 @@ static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
*/
count = igb_tx_map_adv(tx_ring, skb, first);
- if (count) {
- igb_tx_queue_adv(adapter, tx_ring, tx_flags, count,
- skb->len, hdr_len);
- /* Make sure there is space in the ring for the next send. */
- igb_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 4);
- } else {
+ if (!count) {
dev_kfree_skb_any(skb);
tx_ring->buffer_info[first].time_stamp = 0;
tx_ring->next_to_use = first;
+ return NETDEV_TX_OK;
}
+ igb_tx_queue_adv(tx_ring, tx_flags, count, skb->len, hdr_len);
+
+ /* Make sure there is space in the ring for the next send. */
+ igb_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 4);
+
return NETDEV_TX_OK;
}
@@ -4800,15 +4792,15 @@ static void igb_receive_skb(struct igb_q_vector *q_vector,
}
static inline void igb_rx_checksum_adv(struct igb_ring *ring,
- struct igb_adapter *adapter,
u32 status_err, struct sk_buff *skb)
{
skb->ip_summed = CHECKSUM_NONE;
/* Ignore Checksum bit is set or checksum is disabled through ethtool */
- if ((status_err & E1000_RXD_STAT_IXSM) ||
- (adapter->flags & IGB_FLAG_RX_CSUM_DISABLED))
+ if (!(ring->flags & IGB_RING_FLAG_RX_CSUM) ||
+ (status_err & E1000_RXD_STAT_IXSM))
return;
+
/* TCP/UDP checksum error bit is set */
if (status_err &
(E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) {
@@ -4817,9 +4809,10 @@ static inline void igb_rx_checksum_adv(struct igb_ring *ring,
* L4E bit is set incorrectly on 64 byte (60 byte w/o crc)
* packets, (aka let the stack check the crc32c)
*/
- if (!((adapter->hw.mac.type == e1000_82576) &&
- (skb->len == 60)))
+ if ((skb->len == 60) &&
+ (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM))
ring->rx_stats.csum_err++;
+
/* let the stack verify checksum errors */
return;
}
@@ -4827,7 +4820,7 @@ static inline void igb_rx_checksum_adv(struct igb_ring *ring,
if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))
skb->ip_summed = CHECKSUM_UNNECESSARY;
- dev_dbg(&adapter->pdev->dev, "cksum success: bits %08X\n", status_err);
+ dev_dbg(&ring->pdev->dev, "cksum success: bits %08X\n", status_err);
}
static inline u16 igb_get_hlen(struct igb_ring *rx_ring,
@@ -4978,7 +4971,7 @@ send_up:
total_bytes += skb->len;
total_packets++;
- igb_rx_checksum_adv(rx_ring, adapter, staterr, skb);
+ igb_rx_checksum_adv(rx_ring, staterr, skb);
skb->protocol = eth_type_trans(skb, netdev);
skb_record_rx_queue(skb, rx_ring->queue_index);
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 12/20] igb: place a pointer to the netdev struct in the ring itself
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (9 preceding siblings ...)
2009-10-28 1:52 ` [net-next-2.6 PATCH 11/20] igb: add a flags value to the ring Jeff Kirsher
@ 2009-10-28 1:53 ` Jeff Kirsher
2009-10-28 1:53 ` [net-next-2.6 PATCH 13/20] igb: move the multiple receive queue configuration into seperate function Jeff Kirsher
` (8 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:53 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change adds a pointer to the netdev to the ring itself. The idea being
at some point in the future it will be possible to support multiple netdevs
from a single adapter struct.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 3 ++-
drivers/net/igb/igb_main.c | 29 ++++++++++++++---------------
2 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 0c30c5e..2416c12 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -175,9 +175,10 @@ struct igb_q_vector {
struct igb_ring {
struct igb_q_vector *q_vector; /* backlink to q_vector */
- void *desc; /* descriptor ring memory */
+ struct net_device *netdev; /* back pointer to net_device */
struct pci_dev *pdev; /* pci device for dma mapping */
dma_addr_t dma; /* phys address of the ring */
+ void *desc; /* descriptor ring memory */
unsigned int size; /* length of desc. ring in bytes */
unsigned int count; /* number of desc. in the ring */
u16 next_to_use;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 00f3f2d..3dc8e88 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -101,7 +101,6 @@ static void igb_update_phy_info(unsigned long);
static void igb_watchdog(unsigned long);
static void igb_watchdog_task(struct work_struct *);
static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *,
- struct net_device *,
struct igb_ring *);
static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb,
struct net_device *);
@@ -437,6 +436,7 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
ring->count = adapter->tx_ring_count;
ring->queue_index = i;
ring->pdev = adapter->pdev;
+ ring->netdev = adapter->netdev;
/* For 82575, context index must be unique per ring. */
if (adapter->hw.mac.type == e1000_82575)
ring->flags = IGB_RING_FLAG_TX_CTX_IDX;
@@ -447,6 +447,7 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
ring->count = adapter->rx_ring_count;
ring->queue_index = i;
ring->pdev = adapter->pdev;
+ ring->netdev = adapter->netdev;
ring->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
ring->flags = IGB_RING_FLAG_RX_CSUM; /* enable rx checksum */
/* set flag indicating ring supports SCTP checksum offload */
@@ -3550,9 +3551,10 @@ static inline void igb_tx_queue_adv(struct igb_ring *tx_ring,
mmiowb();
}
-static int __igb_maybe_stop_tx(struct net_device *netdev,
- struct igb_ring *tx_ring, int size)
+static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, int size)
{
+ struct net_device *netdev = tx_ring->netdev;
+
netif_stop_subqueue(netdev, tx_ring->queue_index);
/* Herbert's original patch had:
@@ -3571,19 +3573,17 @@ static int __igb_maybe_stop_tx(struct net_device *netdev,
return 0;
}
-static int igb_maybe_stop_tx(struct net_device *netdev,
- struct igb_ring *tx_ring, int size)
+static int igb_maybe_stop_tx(struct igb_ring *tx_ring, int size)
{
if (igb_desc_unused(tx_ring) >= size)
return 0;
- return __igb_maybe_stop_tx(netdev, tx_ring, size);
+ return __igb_maybe_stop_tx(tx_ring, size);
}
static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
- struct net_device *netdev,
struct igb_ring *tx_ring)
{
- struct igb_adapter *adapter = netdev_priv(netdev);
+ struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
unsigned int first;
unsigned int tx_flags = 0;
u8 hdr_len = 0;
@@ -3606,7 +3606,7 @@ static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
* + 1 desc for skb->data,
* + 1 desc for context descriptor,
* otherwise try next time */
- if (igb_maybe_stop_tx(netdev, tx_ring, skb_shinfo(skb)->nr_frags + 4)) {
+ if (igb_maybe_stop_tx(tx_ring, skb_shinfo(skb)->nr_frags + 4)) {
/* this is a hard error */
return NETDEV_TX_BUSY;
}
@@ -3665,7 +3665,7 @@ static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
igb_tx_queue_adv(tx_ring, tx_flags, count, skb->len, hdr_len);
/* Make sure there is space in the ring for the next send. */
- igb_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 4);
+ igb_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 4);
return NETDEV_TX_OK;
}
@@ -3684,7 +3684,7 @@ static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb,
* to a flow. Right now, performance is impacted slightly negatively
* if using multiple tx queues. If the stack breaks away from a
* single qdisc implementation, we can look at this again. */
- return igb_xmit_frame_ring_adv(skb, netdev, tx_ring);
+ return igb_xmit_frame_ring_adv(skb, tx_ring);
}
/**
@@ -4667,7 +4667,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
{
struct igb_adapter *adapter = q_vector->adapter;
struct igb_ring *tx_ring = q_vector->tx_ring;
- struct net_device *netdev = adapter->netdev;
+ struct net_device *netdev = tx_ring->netdev;
struct e1000_hw *hw = &adapter->hw;
struct igb_buffer *buffer_info;
struct sk_buff *skb;
@@ -4841,8 +4841,8 @@ static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
int *work_done, int budget)
{
struct igb_adapter *adapter = q_vector->adapter;
- struct net_device *netdev = adapter->netdev;
struct igb_ring *rx_ring = q_vector->rx_ring;
+ struct net_device *netdev = rx_ring->netdev;
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = rx_ring->pdev;
union e1000_adv_rx_desc *rx_desc , *next_rxd;
@@ -5018,8 +5018,7 @@ next_desc:
static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
int cleaned_count)
{
- struct igb_adapter *adapter = rx_ring->q_vector->adapter;
- struct net_device *netdev = adapter->netdev;
+ struct net_device *netdev = rx_ring->netdev;
union e1000_adv_rx_desc *rx_desc;
struct igb_buffer *buffer_info;
struct sk_buff *skb;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 13/20] igb: move the multiple receive queue configuration into seperate function
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (10 preceding siblings ...)
2009-10-28 1:53 ` [net-next-2.6 PATCH 12/20] igb: place a pointer to the netdev struct in the ring itself Jeff Kirsher
@ 2009-10-28 1:53 ` Jeff Kirsher
2009-10-28 1:53 ` [net-next-2.6 PATCH 14/20] igb: delay VF reset notification until after interrupts are enabed Jeff Kirsher
` (7 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:53 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This patch moves the multiple receive queue configuration into a seperate
function from igb_configure_rx. We can essentially do the configuration for
the multiple receive queues just prior to enabling the RX and this will allow
us to seperate the queue enablement from the receive queue layout
configuration.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb_main.c | 217 +++++++++++++++++++++++---------------------
1 files changed, 111 insertions(+), 106 deletions(-)
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 3dc8e88..ea05604 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -82,6 +82,7 @@ static int igb_setup_all_tx_resources(struct igb_adapter *);
static int igb_setup_all_rx_resources(struct igb_adapter *);
static void igb_free_all_tx_resources(struct igb_adapter *);
static void igb_free_all_rx_resources(struct igb_adapter *);
+static void igb_setup_mrqc(struct igb_adapter *);
void igb_update_stats(struct igb_adapter *);
static int igb_probe(struct pci_dev *, const struct pci_device_id *);
static void __devexit igb_remove(struct pci_dev *pdev);
@@ -1115,6 +1116,7 @@ static void igb_configure(struct igb_adapter *adapter)
igb_restore_vlan(adapter);
igb_setup_tctl(adapter);
+ igb_setup_mrqc(adapter);
igb_setup_rctl(adapter);
igb_configure_tx(adapter);
@@ -1157,7 +1159,6 @@ int igb_up(struct igb_adapter *adapter)
if (adapter->msix_entries)
igb_configure_msix(adapter);
- igb_vmm_control(adapter);
igb_set_vmolr(hw, adapter->vfs_allocated_count);
/* Clear any pending interrupts. */
@@ -1928,7 +1929,6 @@ static int igb_open(struct net_device *netdev)
* clean_rx handler before we do so. */
igb_configure(adapter);
- igb_vmm_control(adapter);
igb_set_vmolr(hw, adapter->vfs_allocated_count);
err = igb_request_irq(adapter);
@@ -2217,6 +2217,111 @@ static int igb_setup_all_rx_resources(struct igb_adapter *adapter)
}
/**
+ * igb_setup_mrqc - configure the multiple receive queue control registers
+ * @adapter: Board private structure
+ **/
+static void igb_setup_mrqc(struct igb_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 mrqc, rxcsum;
+ u32 j, num_rx_queues, shift = 0, shift2 = 0;
+ union e1000_reta {
+ u32 dword;
+ u8 bytes[4];
+ } reta;
+ static const u8 rsshash[40] = {
+ 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, 0x41, 0x67,
+ 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, 0xd0, 0xca, 0x2b, 0xcb,
+ 0xae, 0x7b, 0x30, 0xb4, 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30,
+ 0xf2, 0x0c, 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa };
+
+ /* Fill out hash function seeds */
+ for (j = 0; j < 10; j++) {
+ u32 rsskey = rsshash[(j * 4)];
+ rsskey |= rsshash[(j * 4) + 1] << 8;
+ rsskey |= rsshash[(j * 4) + 2] << 16;
+ rsskey |= rsshash[(j * 4) + 3] << 24;
+ array_wr32(E1000_RSSRK(0), j, rsskey);
+ }
+
+ num_rx_queues = adapter->num_rx_queues;
+
+ if (adapter->vfs_allocated_count) {
+ /* 82575 and 82576 supports 2 RSS queues for VMDq */
+ switch (hw->mac.type) {
+ case e1000_82576:
+ shift = 3;
+ num_rx_queues = 2;
+ break;
+ case e1000_82575:
+ shift = 2;
+ shift2 = 6;
+ default:
+ break;
+ }
+ } else {
+ if (hw->mac.type == e1000_82575)
+ shift = 6;
+ }
+
+ for (j = 0; j < (32 * 4); j++) {
+ reta.bytes[j & 3] = (j % num_rx_queues) << shift;
+ if (shift2)
+ reta.bytes[j & 3] |= num_rx_queues << shift2;
+ if ((j & 3) == 3)
+ wr32(E1000_RETA(j >> 2), reta.dword);
+ }
+
+ /*
+ * Disable raw packet checksumming so that RSS hash is placed in
+ * descriptor on writeback. No need to enable TCP/UDP/IP checksum
+ * offloads as they are enabled by default
+ */
+ rxcsum = rd32(E1000_RXCSUM);
+ rxcsum |= E1000_RXCSUM_PCSD;
+
+ if (adapter->hw.mac.type >= e1000_82576)
+ /* Enable Receive Checksum Offload for SCTP */
+ rxcsum |= E1000_RXCSUM_CRCOFL;
+
+ /* Don't need to set TUOFL or IPOFL, they default to 1 */
+ wr32(E1000_RXCSUM, rxcsum);
+
+ /* If VMDq is enabled then we set the appropriate mode for that, else
+ * we default to RSS so that an RSS hash is calculated per packet even
+ * if we are only using one queue */
+ if (adapter->vfs_allocated_count) {
+ if (hw->mac.type > e1000_82575) {
+ /* Set the default pool for the PF's first queue */
+ u32 vtctl = rd32(E1000_VT_CTL);
+ vtctl &= ~(E1000_VT_CTL_DEFAULT_POOL_MASK |
+ E1000_VT_CTL_DISABLE_DEF_POOL);
+ vtctl |= adapter->vfs_allocated_count <<
+ E1000_VT_CTL_DEFAULT_POOL_SHIFT;
+ wr32(E1000_VT_CTL, vtctl);
+ }
+ if (adapter->num_rx_queues > 1)
+ mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q;
+ else
+ mrqc = E1000_MRQC_ENABLE_VMDQ;
+ } else {
+ mrqc = E1000_MRQC_ENABLE_RSS_4Q;
+ }
+ igb_vmm_control(adapter);
+
+ mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
+ E1000_MRQC_RSS_FIELD_IPV4_TCP);
+ mrqc |= (E1000_MRQC_RSS_FIELD_IPV6 |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP);
+ mrqc |= (E1000_MRQC_RSS_FIELD_IPV4_UDP |
+ E1000_MRQC_RSS_FIELD_IPV6_UDP);
+ mrqc |= (E1000_MRQC_RSS_FIELD_IPV6_UDP_EX |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP_EX);
+
+ wr32(E1000_MRQC, mrqc);
+}
+
+/**
* igb_setup_rctl - configure the receive control registers
* @adapter: Board private structure
**/
@@ -2298,29 +2403,6 @@ static void igb_rlpml_set(struct igb_adapter *adapter)
}
/**
- * igb_configure_vt_default_pool - Configure VT default pool
- * @adapter: board private structure
- *
- * Configure the default pool
- **/
-static void igb_configure_vt_default_pool(struct igb_adapter *adapter)
-{
- struct e1000_hw *hw = &adapter->hw;
- u16 pf_id = adapter->vfs_allocated_count;
- u32 vtctl;
-
- /* not in sr-iov mode - do nothing */
- if (!pf_id)
- return;
-
- vtctl = rd32(E1000_VT_CTL);
- vtctl &= ~(E1000_VT_CTL_DEFAULT_POOL_MASK |
- E1000_VT_CTL_DISABLE_DEF_POOL);
- vtctl |= pf_id << E1000_VT_CTL_DEFAULT_POOL_SHIFT;
- wr32(E1000_VT_CTL, vtctl);
-}
-
-/**
* igb_configure_rx_ring - Configure a receive ring after Reset
* @adapter: board private structure
* @ring: receive ring to be configured
@@ -2391,85 +2473,8 @@ static void igb_configure_rx_ring(struct igb_adapter *adapter,
**/
static void igb_configure_rx(struct igb_adapter *adapter)
{
- struct e1000_hw *hw = &adapter->hw;
- u32 rctl, rxcsum;
int i;
- /* disable receives while setting up the descriptors */
- rctl = rd32(E1000_RCTL);
- wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN);
- wrfl();
- mdelay(10);
-
- if (adapter->itr_setting > 3)
- wr32(E1000_ITR, adapter->itr);
-
- /* Setup the HW Rx Head and Tail Descriptor Pointers and
- * the Base and Length of the Rx Descriptor Ring */
- for (i = 0; i < adapter->num_rx_queues; i++)
- igb_configure_rx_ring(adapter, &adapter->rx_ring[i]);
-
- if (adapter->num_rx_queues > 1) {
- u32 random[10];
- u32 mrqc;
- u32 j, shift;
- union e1000_reta {
- u32 dword;
- u8 bytes[4];
- } reta;
-
- get_random_bytes(&random[0], 40);
-
- if (hw->mac.type >= e1000_82576)
- shift = 0;
- else
- shift = 6;
- for (j = 0; j < (32 * 4); j++) {
- reta.bytes[j & 3] =
- adapter->rx_ring[(j % adapter->num_rx_queues)].reg_idx << shift;
- if ((j & 3) == 3)
- writel(reta.dword,
- hw->hw_addr + E1000_RETA(0) + (j & ~3));
- }
- if (adapter->vfs_allocated_count)
- mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q;
- else
- mrqc = E1000_MRQC_ENABLE_RSS_4Q;
-
- /* Fill out hash function seeds */
- for (j = 0; j < 10; j++)
- array_wr32(E1000_RSSRK(0), j, random[j]);
-
- mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
- E1000_MRQC_RSS_FIELD_IPV4_TCP);
- mrqc |= (E1000_MRQC_RSS_FIELD_IPV6 |
- E1000_MRQC_RSS_FIELD_IPV6_TCP);
- mrqc |= (E1000_MRQC_RSS_FIELD_IPV4_UDP |
- E1000_MRQC_RSS_FIELD_IPV6_UDP);
- mrqc |= (E1000_MRQC_RSS_FIELD_IPV6_UDP_EX |
- E1000_MRQC_RSS_FIELD_IPV6_TCP_EX);
-
- wr32(E1000_MRQC, mrqc);
- } else if (adapter->vfs_allocated_count) {
- /* Enable multi-queue for sr-iov */
- wr32(E1000_MRQC, E1000_MRQC_ENABLE_VMDQ);
- }
-
- /* Enable Receive Checksum Offload for TCP and UDP */
- rxcsum = rd32(E1000_RXCSUM);
- /* Disable raw packet checksumming */
- rxcsum |= E1000_RXCSUM_PCSD;
-
- if (adapter->hw.mac.type == e1000_82576)
- /* Enable Receive Checksum Offload for SCTP */
- rxcsum |= E1000_RXCSUM_CRCOFL;
-
- /* Don't need to set TUOFL or IPOFL, they default to 1 */
- wr32(E1000_RXCSUM, rxcsum);
-
- /* Set the default pool for the PF's first queue */
- igb_configure_vt_default_pool(adapter);
-
/* set UTA to appropriate mode */
igb_set_uta(adapter);
@@ -2477,10 +2482,10 @@ static void igb_configure_rx(struct igb_adapter *adapter)
igb_rar_set_qsel(adapter, adapter->hw.mac.addr, 0,
adapter->vfs_allocated_count);
- igb_rlpml_set(adapter);
-
- /* Enable Receives */
- wr32(E1000_RCTL, rctl);
+ /* Setup the HW Rx Head and Tail Descriptor Pointers and
+ * the Base and Length of the Rx Descriptor Ring */
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ igb_configure_rx_ring(adapter, &adapter->rx_ring[i]);
}
/**
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 14/20] igb: delay VF reset notification until after interrupts are enabed
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (11 preceding siblings ...)
2009-10-28 1:53 ` [net-next-2.6 PATCH 13/20] igb: move the multiple receive queue configuration into seperate function Jeff Kirsher
@ 2009-10-28 1:53 ` Jeff Kirsher
2009-10-28 1:54 ` [net-next-2.6 PATCH 15/20] igb: setup vlan tag replication stripping in igb_vmm_control Jeff Kirsher
` (6 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:53 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This update delays the VF reset notification until after interrupts are
enabled. Otherwise there is a chance of having the VF try to reset itself too
soon and being ignored by the PF as a result.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb_main.c | 33 +++++++++++++++++++++++----------
1 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index ea05604..24a119e 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1165,6 +1165,13 @@ int igb_up(struct igb_adapter *adapter)
rd32(E1000_ICR);
igb_irq_enable(adapter);
+ /* notify VFs that reset has been completed */
+ if (adapter->vfs_allocated_count) {
+ u32 reg_data = rd32(E1000_CTRL_EXT);
+ reg_data |= E1000_CTRL_EXT_PFRSTD;
+ wr32(E1000_CTRL_EXT, reg_data);
+ }
+
netif_tx_start_all_queues(adapter->netdev);
/* Fire a link change interrupt to start the watchdog. */
@@ -1948,6 +1955,13 @@ static int igb_open(struct net_device *netdev)
igb_irq_enable(adapter);
+ /* notify VFs that reset has been completed */
+ if (adapter->vfs_allocated_count) {
+ u32 reg_data = rd32(E1000_CTRL_EXT);
+ reg_data |= E1000_CTRL_EXT_PFRSTD;
+ wr32(E1000_CTRL_EXT, reg_data);
+ }
+
netif_tx_start_all_queues(netdev);
/* Fire a link status change interrupt to start the watchdog. */
@@ -5785,19 +5799,18 @@ static int igb_set_vf_mac(struct igb_adapter *adapter,
static void igb_vmm_control(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
- u32 reg_data;
- if (!adapter->vfs_allocated_count)
+ /* replication is not supported for 82575 */
+ if (hw->mac.type == e1000_82575)
return;
- /* VF's need PF reset indication before they
- * can send/receive mail */
- reg_data = rd32(E1000_CTRL_EXT);
- reg_data |= E1000_CTRL_EXT_PFRSTD;
- wr32(E1000_CTRL_EXT, reg_data);
-
- igb_vmdq_set_loopback_pf(hw, true);
- igb_vmdq_set_replication_pf(hw, true);
+ if (adapter->vfs_allocated_count) {
+ igb_vmdq_set_loopback_pf(hw, true);
+ igb_vmdq_set_replication_pf(hw, true);
+ } else {
+ igb_vmdq_set_loopback_pf(hw, false);
+ igb_vmdq_set_replication_pf(hw, false);
+ }
}
/* igb_main.c */
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 15/20] igb: setup vlan tag replication stripping in igb_vmm_control
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (12 preceding siblings ...)
2009-10-28 1:53 ` [net-next-2.6 PATCH 14/20] igb: delay VF reset notification until after interrupts are enabed Jeff Kirsher
@ 2009-10-28 1:54 ` Jeff Kirsher
2009-10-28 1:54 ` [net-next-2.6 PATCH 16/20] igb: re-use ring configuration code in ethtool testing Jeff Kirsher
` (5 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:54 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This update adds vlan tag stripping for inter-vf communications to the
igb_vmm_control configuration function.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/e1000_82575.h | 9 +++++++++
drivers/net/igb/igb_main.c | 11 +++++++++++
2 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index 7be3a0b..9418683 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -203,6 +203,15 @@ struct e1000_adv_tx_context_desc {
#define E1000_IOVCTL 0x05BBC
#define E1000_IOVCTL_REUSE_VFQ 0x00000001
+#define E1000_RPLOLR_STRVLAN 0x40000000
+#define E1000_RPLOLR_STRCRC 0x80000000
+
+#define E1000_DTXCTL_8023LL 0x0004
+#define E1000_DTXCTL_VLAN_ADDED 0x0008
+#define E1000_DTXCTL_OOS_ENABLE 0x0010
+#define E1000_DTXCTL_MDP_EN 0x0020
+#define E1000_DTXCTL_SPOOF_INT 0x0040
+
#define ALL_QUEUES 0xFFFF
void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 24a119e..9dd290c 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -5799,11 +5799,22 @@ static int igb_set_vf_mac(struct igb_adapter *adapter,
static void igb_vmm_control(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
+ u32 reg;
/* replication is not supported for 82575 */
if (hw->mac.type == e1000_82575)
return;
+ /* enable replication vlan tag stripping */
+ reg = rd32(E1000_RPLOLR);
+ reg |= E1000_RPLOLR_STRVLAN;
+ wr32(E1000_RPLOLR, reg);
+
+ /* notify HW that the MAC is adding vlan tags */
+ reg = rd32(E1000_DTXCTL);
+ reg |= E1000_DTXCTL_VLAN_ADDED;
+ wr32(E1000_DTXCTL, reg);
+
if (adapter->vfs_allocated_count) {
igb_vmdq_set_loopback_pf(hw, true);
igb_vmdq_set_replication_pf(hw, true);
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 16/20] igb: re-use ring configuration code in ethtool testing
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (13 preceding siblings ...)
2009-10-28 1:54 ` [net-next-2.6 PATCH 15/20] igb: setup vlan tag replication stripping in igb_vmm_control Jeff Kirsher
@ 2009-10-28 1:54 ` Jeff Kirsher
2009-10-28 1:54 ` [net-next-2.6 PATCH 17/20] igb: make tx ring map and free functionality non-static Jeff Kirsher
` (4 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:54 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
Since all of the ring code is now specific to the ring instead of the adapter
struct it is possible to cut a large section of code out of the ethtool
testing configuraiton since we can just use the existing functions to
configure the rings.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 14 +++
drivers/net/igb/igb_ethtool.c | 185 +++++++++--------------------------------
drivers/net/igb/igb_main.c | 29 ++----
3 files changed, 60 insertions(+), 168 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 2416c12..8b189a0 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -223,6 +223,15 @@ struct igb_ring {
#define E1000_TX_CTXTDESC_ADV(R, i) \
(&(((struct e1000_adv_tx_context_desc *)((R).desc))[i]))
+/* igb_desc_unused - calculate if we have unused descriptors */
+static inline int igb_desc_unused(struct igb_ring *ring)
+{
+ if (ring->next_to_clean > ring->next_to_use)
+ return ring->next_to_clean - ring->next_to_use - 1;
+
+ return ring->count + ring->next_to_clean - ring->next_to_use - 1;
+}
+
/* board specific private data structure */
struct igb_adapter {
@@ -336,6 +345,11 @@ extern int igb_setup_tx_resources(struct igb_ring *);
extern int igb_setup_rx_resources(struct igb_ring *);
extern void igb_free_tx_resources(struct igb_ring *);
extern void igb_free_rx_resources(struct igb_ring *);
+extern void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
+extern void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
+extern void igb_setup_tctl(struct igb_adapter *);
+extern void igb_setup_rctl(struct igb_adapter *);
+extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
extern void igb_update_stats(struct igb_adapter *);
extern void igb_set_ethtool_ops(struct net_device *);
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index c44dede..80afd8a 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1245,116 +1245,49 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
static void igb_free_desc_rings(struct igb_adapter *adapter)
{
- struct igb_ring *tx_ring = &adapter->test_tx_ring;
- struct igb_ring *rx_ring = &adapter->test_rx_ring;
- struct pci_dev *pdev = adapter->pdev;
- int i;
-
- if (tx_ring->desc && tx_ring->buffer_info) {
- for (i = 0; i < tx_ring->count; i++) {
- struct igb_buffer *buf = &(tx_ring->buffer_info[i]);
- if (buf->dma)
- pci_unmap_single(pdev, buf->dma, buf->length,
- PCI_DMA_TODEVICE);
- if (buf->skb)
- dev_kfree_skb(buf->skb);
- }
- }
-
- if (rx_ring->desc && rx_ring->buffer_info) {
- for (i = 0; i < rx_ring->count; i++) {
- struct igb_buffer *buf = &(rx_ring->buffer_info[i]);
- if (buf->dma)
- pci_unmap_single(pdev, buf->dma,
- IGB_RXBUFFER_2048,
- PCI_DMA_FROMDEVICE);
- if (buf->skb)
- dev_kfree_skb(buf->skb);
- }
- }
-
- if (tx_ring->desc) {
- pci_free_consistent(pdev, tx_ring->size, tx_ring->desc,
- tx_ring->dma);
- tx_ring->desc = NULL;
- }
- if (rx_ring->desc) {
- pci_free_consistent(pdev, rx_ring->size, rx_ring->desc,
- rx_ring->dma);
- rx_ring->desc = NULL;
- }
-
- kfree(tx_ring->buffer_info);
- tx_ring->buffer_info = NULL;
- kfree(rx_ring->buffer_info);
- rx_ring->buffer_info = NULL;
-
- return;
+ igb_free_tx_resources(&adapter->test_tx_ring);
+ igb_free_rx_resources(&adapter->test_rx_ring);
}
static int igb_setup_desc_rings(struct igb_adapter *adapter)
{
- struct e1000_hw *hw = &adapter->hw;
struct igb_ring *tx_ring = &adapter->test_tx_ring;
struct igb_ring *rx_ring = &adapter->test_rx_ring;
- struct pci_dev *pdev = adapter->pdev;
- struct igb_buffer *buffer_info;
- u32 rctl;
+ struct e1000_hw *hw = &adapter->hw;
int i, ret_val;
/* Setup Tx descriptor ring and Tx buffers */
+ tx_ring->count = IGB_DEFAULT_TXD;
+ tx_ring->pdev = adapter->pdev;
+ tx_ring->netdev = adapter->netdev;
+ tx_ring->reg_idx = adapter->vfs_allocated_count;
- if (!tx_ring->count)
- tx_ring->count = IGB_DEFAULT_TXD;
-
- tx_ring->buffer_info = kcalloc(tx_ring->count,
- sizeof(struct igb_buffer),
- GFP_KERNEL);
- if (!tx_ring->buffer_info) {
+ if (igb_setup_tx_resources(tx_ring)) {
ret_val = 1;
goto err_nomem;
}
- tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
- tx_ring->size = ALIGN(tx_ring->size, 4096);
- tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size,
- &tx_ring->dma);
- if (!tx_ring->desc) {
- ret_val = 2;
- goto err_nomem;
- }
- tx_ring->next_to_use = tx_ring->next_to_clean = 0;
-
- wr32(E1000_TDBAL(0),
- ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
- wr32(E1000_TDBAH(0), ((u64) tx_ring->dma >> 32));
- wr32(E1000_TDLEN(0),
- tx_ring->count * sizeof(union e1000_adv_tx_desc));
- wr32(E1000_TDH(0), 0);
- wr32(E1000_TDT(0), 0);
- wr32(E1000_TCTL,
- E1000_TCTL_PSP | E1000_TCTL_EN |
- E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
- E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
+ igb_setup_tctl(adapter);
+ igb_configure_tx_ring(adapter, tx_ring);
for (i = 0; i < tx_ring->count; i++) {
union e1000_adv_tx_desc *tx_desc;
- struct sk_buff *skb;
unsigned int size = 1024;
+ struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
- tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
- skb = alloc_skb(size, GFP_KERNEL);
if (!skb) {
- ret_val = 3;
+ ret_val = 2;
goto err_nomem;
}
skb_put(skb, size);
- buffer_info = &tx_ring->buffer_info[i];
- buffer_info->skb = skb;
- buffer_info->length = skb->len;
- buffer_info->dma = pci_map_single(pdev, skb->data, skb->len,
- PCI_DMA_TODEVICE);
- tx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
+ tx_ring->buffer_info[i].skb = skb;
+ tx_ring->buffer_info[i].length = skb->len;
+ tx_ring->buffer_info[i].dma =
+ pci_map_single(tx_ring->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
+ tx_desc->read.buffer_addr =
+ cpu_to_le64(tx_ring->buffer_info[i].dma);
tx_desc->read.olinfo_status = cpu_to_le32(skb->len) <<
E1000_ADVTXD_PAYLEN_SHIFT;
tx_desc->read.cmd_type_len = cpu_to_le32(skb->len);
@@ -1366,62 +1299,25 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter)
}
/* Setup Rx descriptor ring and Rx buffers */
-
- if (!rx_ring->count)
- rx_ring->count = IGB_DEFAULT_RXD;
-
- rx_ring->buffer_info = kcalloc(rx_ring->count,
- sizeof(struct igb_buffer),
- GFP_KERNEL);
- if (!rx_ring->buffer_info) {
- ret_val = 4;
- goto err_nomem;
- }
-
- rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc);
- rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size,
- &rx_ring->dma);
- if (!rx_ring->desc) {
- ret_val = 5;
+ rx_ring->count = IGB_DEFAULT_RXD;
+ rx_ring->pdev = adapter->pdev;
+ rx_ring->netdev = adapter->netdev;
+ rx_ring->rx_buffer_len = IGB_RXBUFFER_2048;
+ rx_ring->reg_idx = adapter->vfs_allocated_count;
+
+ if (igb_setup_rx_resources(rx_ring)) {
+ ret_val = 3;
goto err_nomem;
}
- rx_ring->next_to_use = rx_ring->next_to_clean = 0;
- rctl = rd32(E1000_RCTL);
- wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN);
- wr32(E1000_RDBAL(0),
- ((u64) rx_ring->dma & 0xFFFFFFFF));
- wr32(E1000_RDBAH(0),
- ((u64) rx_ring->dma >> 32));
- wr32(E1000_RDLEN(0), rx_ring->size);
- wr32(E1000_RDH(0), 0);
- wr32(E1000_RDT(0), 0);
- rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
- rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF |
- (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
- wr32(E1000_RCTL, rctl);
- wr32(E1000_SRRCTL(0), E1000_SRRCTL_DESCTYPE_ADV_ONEBUF);
+ /* set the default queue to queue 0 of PF */
+ wr32(E1000_MRQC, adapter->vfs_allocated_count << 3);
- for (i = 0; i < rx_ring->count; i++) {
- union e1000_adv_rx_desc *rx_desc;
- struct sk_buff *skb;
+ /* enable receive ring */
+ igb_setup_rctl(adapter);
+ igb_configure_rx_ring(adapter, rx_ring);
- buffer_info = &rx_ring->buffer_info[i];
- rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
- skb = alloc_skb(IGB_RXBUFFER_2048 + NET_IP_ALIGN,
- GFP_KERNEL);
- if (!skb) {
- ret_val = 6;
- goto err_nomem;
- }
- skb_reserve(skb, NET_IP_ALIGN);
- buffer_info->skb = skb;
- buffer_info->dma = pci_map_single(pdev, skb->data,
- IGB_RXBUFFER_2048,
- PCI_DMA_FROMDEVICE);
- rx_desc->read.pkt_addr = cpu_to_le64(buffer_info->dma);
- memset(skb->data, 0x00, skb->len);
- }
+ igb_alloc_rx_buffers_adv(rx_ring, igb_desc_unused(rx_ring));
return 0;
@@ -1576,15 +1472,12 @@ static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
static int igb_run_loopback_test(struct igb_adapter *adapter)
{
- struct e1000_hw *hw = &adapter->hw;
struct igb_ring *tx_ring = &adapter->test_tx_ring;
struct igb_ring *rx_ring = &adapter->test_rx_ring;
- struct pci_dev *pdev = adapter->pdev;
- int i, j, k, l, lc, good_cnt;
- int ret_val = 0;
+ int i, j, k, l, lc, good_cnt, ret_val = 0;
unsigned long time;
- wr32(E1000_RDT(0), rx_ring->count - 1);
+ writel(rx_ring->count - 1, rx_ring->tail);
/* Calculate the loop count based on the largest descriptor ring
* The idea is to wrap the largest ring a number of times using 64
@@ -1601,7 +1494,7 @@ static int igb_run_loopback_test(struct igb_adapter *adapter)
for (i = 0; i < 64; i++) { /* send the packets */
igb_create_lbtest_frame(tx_ring->buffer_info[k].skb,
1024);
- pci_dma_sync_single_for_device(pdev,
+ pci_dma_sync_single_for_device(tx_ring->pdev,
tx_ring->buffer_info[k].dma,
tx_ring->buffer_info[k].length,
PCI_DMA_TODEVICE);
@@ -1609,12 +1502,12 @@ static int igb_run_loopback_test(struct igb_adapter *adapter)
if (k == tx_ring->count)
k = 0;
}
- wr32(E1000_TDT(0), k);
+ writel(k, tx_ring->tail);
msleep(200);
time = jiffies; /* set the start time for the receive */
good_cnt = 0;
do { /* receive the sent packets */
- pci_dma_sync_single_for_cpu(pdev,
+ pci_dma_sync_single_for_cpu(rx_ring->pdev,
rx_ring->buffer_info[l].dma,
IGB_RXBUFFER_2048,
PCI_DMA_FROMDEVICE);
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 9dd290c..576a4fa 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -91,8 +91,6 @@ static int igb_open(struct net_device *);
static int igb_close(struct net_device *);
static void igb_configure_tx(struct igb_adapter *);
static void igb_configure_rx(struct igb_adapter *);
-static void igb_setup_tctl(struct igb_adapter *);
-static void igb_setup_rctl(struct igb_adapter *);
static void igb_clean_all_tx_rings(struct igb_adapter *);
static void igb_clean_all_rx_rings(struct igb_adapter *);
static void igb_clean_tx_ring(struct igb_ring *);
@@ -120,7 +118,6 @@ static void igb_setup_dca(struct igb_adapter *);
static bool igb_clean_tx_irq(struct igb_q_vector *);
static int igb_poll(struct napi_struct *, int);
static bool igb_clean_rx_irq_adv(struct igb_q_vector *, int *, int);
-static void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
static void igb_tx_timeout(struct net_device *);
static void igb_reset_task(struct work_struct *);
@@ -310,17 +307,6 @@ static char *igb_get_time_str(struct igb_adapter *adapter,
#endif
/**
- * igb_desc_unused - calculate if we have unused descriptors
- **/
-static int igb_desc_unused(struct igb_ring *ring)
-{
- if (ring->next_to_clean > ring->next_to_use)
- return ring->next_to_clean - ring->next_to_use - 1;
-
- return ring->count + ring->next_to_clean - ring->next_to_use - 1;
-}
-
-/**
* igb_init_module - Driver Registration Routine
*
* igb_init_module is the first routine called when the driver is
@@ -2087,7 +2073,7 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter)
* igb_setup_tctl - configure the transmit control registers
* @adapter: Board private structure
**/
-static void igb_setup_tctl(struct igb_adapter *adapter)
+void igb_setup_tctl(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 tctl;
@@ -2116,8 +2102,8 @@ static void igb_setup_tctl(struct igb_adapter *adapter)
*
* Configure a transmit ring after a reset.
**/
-static void igb_configure_tx_ring(struct igb_adapter *adapter,
- struct igb_ring *ring)
+void igb_configure_tx_ring(struct igb_adapter *adapter,
+ struct igb_ring *ring)
{
struct e1000_hw *hw = &adapter->hw;
u32 txdctl;
@@ -2339,7 +2325,7 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
* igb_setup_rctl - configure the receive control registers
* @adapter: Board private structure
**/
-static void igb_setup_rctl(struct igb_adapter *adapter)
+void igb_setup_rctl(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 rctl;
@@ -2423,8 +2409,8 @@ static void igb_rlpml_set(struct igb_adapter *adapter)
*
* Configure the Rx unit of the MAC after a reset.
**/
-static void igb_configure_rx_ring(struct igb_adapter *adapter,
- struct igb_ring *ring)
+void igb_configure_rx_ring(struct igb_adapter *adapter,
+ struct igb_ring *ring)
{
struct e1000_hw *hw = &adapter->hw;
u64 rdba = ring->dma;
@@ -5034,8 +5020,7 @@ next_desc:
* igb_alloc_rx_buffers_adv - Replace used receive buffers; packet split
* @adapter: address of board private structure
**/
-static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
- int cleaned_count)
+void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count)
{
struct net_device *netdev = rx_ring->netdev;
union e1000_adv_rx_desc *rx_desc;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 17/20] igb: make tx ring map and free functionality non-static
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (14 preceding siblings ...)
2009-10-28 1:54 ` [net-next-2.6 PATCH 16/20] igb: re-use ring configuration code in ethtool testing Jeff Kirsher
@ 2009-10-28 1:54 ` Jeff Kirsher
2009-10-28 1:55 ` [net-next-2.6 PATCH 18/20] igb: make ethtool use core xmit map and free functionality Jeff Kirsher
` (3 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:54 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change makes a minor change to the xmit_frame_ring_adv funcition in that
it moves 2 checks from it into the xmit_frame_adv since the checks were not
ring specific. In addition it exports the xmit_frame_ring_adv and the
unmap_and_free_tx_resource calls so that they can be used by other code such
as the ethtool loopback testing calls.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb.h | 3 +++
drivers/net/igb/igb_main.c | 35 ++++++++++++++++-------------------
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 8b189a0..6c35c90 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -349,6 +349,9 @@ extern void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
extern void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
extern void igb_setup_tctl(struct igb_adapter *);
extern void igb_setup_rctl(struct igb_adapter *);
+extern netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *, struct igb_ring *);
+extern void igb_unmap_and_free_tx_resource(struct igb_ring *,
+ struct igb_buffer *);
extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
extern void igb_update_stats(struct igb_adapter *);
extern void igb_set_ethtool_ops(struct net_device *);
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 576a4fa..c9fda11 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -99,10 +99,7 @@ static void igb_set_rx_mode(struct net_device *);
static void igb_update_phy_info(unsigned long);
static void igb_watchdog(unsigned long);
static void igb_watchdog_task(struct work_struct *);
-static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *,
- struct igb_ring *);
-static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb,
- struct net_device *);
+static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *);
static struct net_device_stats *igb_get_stats(struct net_device *);
static int igb_change_mtu(struct net_device *, int);
static int igb_set_mac(struct net_device *, void *);
@@ -2521,8 +2518,8 @@ static void igb_free_all_tx_resources(struct igb_adapter *adapter)
igb_free_tx_resources(&adapter->tx_ring[i]);
}
-static void igb_unmap_and_free_tx_resource(struct igb_ring *tx_ring,
- struct igb_buffer *buffer_info)
+void igb_unmap_and_free_tx_resource(struct igb_ring *tx_ring,
+ struct igb_buffer *buffer_info)
{
buffer_info->dma = 0;
if (buffer_info->skb) {
@@ -3585,8 +3582,8 @@ static int igb_maybe_stop_tx(struct igb_ring *tx_ring, int size)
return __igb_maybe_stop_tx(tx_ring, size);
}
-static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
- struct igb_ring *tx_ring)
+netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
+ struct igb_ring *tx_ring)
{
struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
unsigned int first;
@@ -3596,16 +3593,6 @@ static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
int tso = 0;
union skb_shared_tx *shtx;
- if (test_bit(__IGB_DOWN, &adapter->state)) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
-
- if (skb->len <= 0) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
-
/* need: 1 descriptor per page,
* + 2 desc gap to keep tail from touching head,
* + 1 desc for skb->data,
@@ -3680,8 +3667,18 @@ static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb,
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct igb_ring *tx_ring;
-
int r_idx = 0;
+
+ if (test_bit(__IGB_DOWN, &adapter->state)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (skb->len <= 0) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
r_idx = skb->queue_mapping & (IGB_ABS_MAX_TX_QUEUES - 1);
tx_ring = adapter->multi_tx_table[r_idx];
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 18/20] igb: make ethtool use core xmit map and free functionality
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (15 preceding siblings ...)
2009-10-28 1:54 ` [net-next-2.6 PATCH 17/20] igb: make tx ring map and free functionality non-static Jeff Kirsher
@ 2009-10-28 1:55 ` Jeff Kirsher
2009-10-28 1:55 ` [net-next-2.6 PATCH 19/20] igb: add single vector msi-x testing to interrupt test Jeff Kirsher
` (2 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:55 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change adds a clean_rx/tx_irq type function call to the ethtool loopback
testing which allows us to test the core transmit and receive functionality in
the driver.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb_ethtool.c | 156 +++++++++++++++++++++++------------------
1 files changed, 89 insertions(+), 67 deletions(-)
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 80afd8a..aa05f00 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1254,7 +1254,7 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter)
struct igb_ring *tx_ring = &adapter->test_tx_ring;
struct igb_ring *rx_ring = &adapter->test_rx_ring;
struct e1000_hw *hw = &adapter->hw;
- int i, ret_val;
+ int ret_val;
/* Setup Tx descriptor ring and Tx buffers */
tx_ring->count = IGB_DEFAULT_TXD;
@@ -1270,34 +1270,6 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter)
igb_setup_tctl(adapter);
igb_configure_tx_ring(adapter, tx_ring);
- for (i = 0; i < tx_ring->count; i++) {
- union e1000_adv_tx_desc *tx_desc;
- unsigned int size = 1024;
- struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
-
- if (!skb) {
- ret_val = 2;
- goto err_nomem;
- }
- skb_put(skb, size);
- tx_ring->buffer_info[i].skb = skb;
- tx_ring->buffer_info[i].length = skb->len;
- tx_ring->buffer_info[i].dma =
- pci_map_single(tx_ring->pdev, skb->data, skb->len,
- PCI_DMA_TODEVICE);
- tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
- tx_desc->read.buffer_addr =
- cpu_to_le64(tx_ring->buffer_info[i].dma);
- tx_desc->read.olinfo_status = cpu_to_le32(skb->len) <<
- E1000_ADVTXD_PAYLEN_SHIFT;
- tx_desc->read.cmd_type_len = cpu_to_le32(skb->len);
- tx_desc->read.cmd_type_len |= cpu_to_le32(E1000_TXD_CMD_EOP |
- E1000_TXD_CMD_IFCS |
- E1000_TXD_CMD_RS |
- E1000_ADVTXD_DTYP_DATA |
- E1000_ADVTXD_DCMD_DEXT);
- }
-
/* Setup Rx descriptor ring and Rx buffers */
rx_ring->count = IGB_DEFAULT_RXD;
rx_ring->pdev = adapter->pdev;
@@ -1470,14 +1442,78 @@ static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
return 13;
}
+static int igb_clean_test_rings(struct igb_ring *rx_ring,
+ struct igb_ring *tx_ring,
+ unsigned int size)
+{
+ union e1000_adv_rx_desc *rx_desc;
+ struct igb_buffer *buffer_info;
+ int rx_ntc, tx_ntc, count = 0;
+ u32 staterr;
+
+ /* initialize next to clean and descriptor values */
+ rx_ntc = rx_ring->next_to_clean;
+ tx_ntc = tx_ring->next_to_clean;
+ rx_desc = E1000_RX_DESC_ADV(*rx_ring, rx_ntc);
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+
+ while (staterr & E1000_RXD_STAT_DD) {
+ /* check rx buffer */
+ buffer_info = &rx_ring->buffer_info[rx_ntc];
+
+ /* unmap rx buffer, will be remapped by alloc_rx_buffers */
+ pci_unmap_single(rx_ring->pdev,
+ buffer_info->dma,
+ rx_ring->rx_buffer_len,
+ PCI_DMA_FROMDEVICE);
+ buffer_info->dma = 0;
+
+ /* verify contents of skb */
+ if (!igb_check_lbtest_frame(buffer_info->skb, size))
+ count++;
+
+ /* unmap buffer on tx side */
+ buffer_info = &tx_ring->buffer_info[tx_ntc];
+ igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
+
+ /* increment rx/tx next to clean counters */
+ rx_ntc++;
+ if (rx_ntc == rx_ring->count)
+ rx_ntc = 0;
+ tx_ntc++;
+ if (tx_ntc == tx_ring->count)
+ tx_ntc = 0;
+
+ /* fetch next descriptor */
+ rx_desc = E1000_RX_DESC_ADV(*rx_ring, rx_ntc);
+ staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+ }
+
+ /* re-map buffers to ring, store next to clean values */
+ igb_alloc_rx_buffers_adv(rx_ring, count);
+ rx_ring->next_to_clean = rx_ntc;
+ tx_ring->next_to_clean = tx_ntc;
+
+ return count;
+}
+
static int igb_run_loopback_test(struct igb_adapter *adapter)
{
struct igb_ring *tx_ring = &adapter->test_tx_ring;
struct igb_ring *rx_ring = &adapter->test_rx_ring;
- int i, j, k, l, lc, good_cnt, ret_val = 0;
- unsigned long time;
+ int i, j, lc, good_cnt, ret_val = 0;
+ unsigned int size = 1024;
+ netdev_tx_t tx_ret_val;
+ struct sk_buff *skb;
+
+ /* allocate test skb */
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb)
+ return 11;
- writel(rx_ring->count - 1, rx_ring->tail);
+ /* place data into test skb */
+ igb_create_lbtest_frame(skb, size);
+ skb_put(skb, size);
/* Calculate the loop count based on the largest descriptor ring
* The idea is to wrap the largest ring a number of times using 64
@@ -1489,50 +1525,36 @@ static int igb_run_loopback_test(struct igb_adapter *adapter)
else
lc = ((rx_ring->count / 64) * 2) + 1;
- k = l = 0;
for (j = 0; j <= lc; j++) { /* loop count loop */
- for (i = 0; i < 64; i++) { /* send the packets */
- igb_create_lbtest_frame(tx_ring->buffer_info[k].skb,
- 1024);
- pci_dma_sync_single_for_device(tx_ring->pdev,
- tx_ring->buffer_info[k].dma,
- tx_ring->buffer_info[k].length,
- PCI_DMA_TODEVICE);
- k++;
- if (k == tx_ring->count)
- k = 0;
- }
- writel(k, tx_ring->tail);
- msleep(200);
- time = jiffies; /* set the start time for the receive */
+ /* reset count of good packets */
good_cnt = 0;
- do { /* receive the sent packets */
- pci_dma_sync_single_for_cpu(rx_ring->pdev,
- rx_ring->buffer_info[l].dma,
- IGB_RXBUFFER_2048,
- PCI_DMA_FROMDEVICE);
-
- ret_val = igb_check_lbtest_frame(
- rx_ring->buffer_info[l].skb, 1024);
- if (!ret_val)
+
+ /* place 64 packets on the transmit queue*/
+ for (i = 0; i < 64; i++) {
+ skb_get(skb);
+ tx_ret_val = igb_xmit_frame_ring_adv(skb, tx_ring);
+ if (tx_ret_val == NETDEV_TX_OK)
good_cnt++;
- l++;
- if (l == rx_ring->count)
- l = 0;
- /* time + 20 msecs (200 msecs on 2.4) is more than
- * enough time to complete the receives, if it's
- * exceeded, break and error off
- */
- } while (good_cnt < 64 && jiffies < (time + 20));
+ }
+
if (good_cnt != 64) {
- ret_val = 13; /* ret_val is the same as mis-compare */
+ ret_val = 12;
break;
}
- if (jiffies >= (time + 20)) {
- ret_val = 14; /* error code for time out error */
+
+ /* allow 200 milliseconds for packets to go from tx to rx */
+ msleep(200);
+
+ good_cnt = igb_clean_test_rings(rx_ring, tx_ring, size);
+ if (good_cnt != 64) {
+ ret_val = 13;
break;
}
} /* end loop count loop */
+
+ /* free the original skb */
+ kfree_skb(skb);
+
return ret_val;
}
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 19/20] igb: add single vector msi-x testing to interrupt test
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (16 preceding siblings ...)
2009-10-28 1:55 ` [net-next-2.6 PATCH 18/20] igb: make ethtool use core xmit map and free functionality Jeff Kirsher
@ 2009-10-28 1:55 ` Jeff Kirsher
2009-10-28 1:55 ` [net-next-2.6 PATCH 20/20] igb: cleanup "todo" code found in igb_ethtool.c Jeff Kirsher
2009-10-28 8:28 ` [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI David Miller
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:55 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change adds testing of the first msix vector to the interrupt testing.
This should help with determining the cause of interrupt issues when they are
encountered.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/igb_ethtool.c | 27 +++++++++++++++++----------
1 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index aa05f00..65c538f 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1123,32 +1123,36 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
*data = 0;
/* Hook up test interrupt handler just for this test */
- if (adapter->msix_entries)
- /* NOTE: we don't test MSI-X interrupts here, yet */
- return 0;
+ if (adapter->msix_entries) {
+ if (request_irq(adapter->msix_entries[0].vector,
+ &igb_test_intr, 0, netdev->name, adapter)) {
+ *data = 1;
+ return -1;
+ }
- if (adapter->flags & IGB_FLAG_HAS_MSI) {
+ } else if (adapter->flags & IGB_FLAG_HAS_MSI) {
shared_int = false;
- if (request_irq(irq, &igb_test_intr, 0, netdev->name, netdev)) {
+ if (request_irq(irq,
+ &igb_test_intr, 0, netdev->name, adapter)) {
*data = 1;
return -1;
}
} else if (!request_irq(irq, &igb_test_intr, IRQF_PROBE_SHARED,
- netdev->name, netdev)) {
+ netdev->name, adapter)) {
shared_int = false;
} else if (request_irq(irq, &igb_test_intr, IRQF_SHARED,
- netdev->name, netdev)) {
+ netdev->name, adapter)) {
*data = 1;
return -1;
}
dev_info(&adapter->pdev->dev, "testing %s interrupt\n",
(shared_int ? "shared" : "unshared"));
/* Disable all the interrupts */
- wr32(E1000_IMC, 0xFFFFFFFF);
+ wr32(E1000_IMC, ~0);
msleep(10);
/* Define all writable bits for ICS */
- switch(hw->mac.type) {
+ switch (hw->mac.type) {
case e1000_82575:
ics_mask = 0x37F47EDD;
break;
@@ -1238,7 +1242,10 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
msleep(10);
/* Unhook test interrupt handler */
- free_irq(irq, netdev);
+ if (adapter->msix_entries)
+ free_irq(adapter->msix_entries[0].vector, adapter);
+ else
+ free_irq(irq, adapter);
return *data;
}
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [net-next-2.6 PATCH 20/20] igb: cleanup "todo" code found in igb_ethtool.c
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (17 preceding siblings ...)
2009-10-28 1:55 ` [net-next-2.6 PATCH 19/20] igb: add single vector msi-x testing to interrupt test Jeff Kirsher
@ 2009-10-28 1:55 ` Jeff Kirsher
2009-10-28 8:28 ` [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI David Miller
19 siblings, 0 replies; 21+ messages in thread
From: Jeff Kirsher @ 2009-10-28 1:55 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Alexander Duyck, Jeff Kirsher
From: Alexander Duyck <alexander.h.duyck@intel.com>
This patch moves some defines into the e1000_regs.h file since this is the
correct place for register defines and not inside of igb_ethtool.c
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/e1000_regs.h | 7 +++++++
drivers/net/igb/igb_ethtool.c | 11 +----------
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 76c3389..e06c3b7 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -288,10 +288,17 @@ enum {
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
#define E1000_RA 0x05400 /* Receive Address - RW Array */
#define E1000_RA2 0x054E0 /* 2nd half of receive address array - RW Array */
+#define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4))
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
(0x054E0 + ((_i - 16) * 8)))
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
(0x054E4 + ((_i - 16) * 8)))
+#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
+#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
+#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
+#define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
+#define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
+#define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
#define E1000_VT_CTL 0x0581C /* VMDq Control - RW */
#define E1000_WUC 0x05800 /* Wakeup Control - RW */
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 65c538f..048a615 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -502,19 +502,10 @@ static void igb_get_regs(struct net_device *netdev,
regs_buff[119] = adapter->stats.scvpc;
regs_buff[120] = adapter->stats.hrmpc;
- /* These should probably be added to e1000_regs.h instead */
- #define E1000_PSRTYPE_REG(_i) (0x05480 + ((_i) * 4))
- #define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
- #define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
- #define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
- #define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8))
- #define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8))
- #define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
-
for (i = 0; i < 4; i++)
regs_buff[121 + i] = rd32(E1000_SRRCTL(i));
for (i = 0; i < 4; i++)
- regs_buff[125 + i] = rd32(E1000_PSRTYPE_REG(i));
+ regs_buff[125 + i] = rd32(E1000_PSRTYPE(i));
for (i = 0; i < 4; i++)
regs_buff[129 + i] = rd32(E1000_RDBAL(i));
for (i = 0; i < 4; i++)
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
` (18 preceding siblings ...)
2009-10-28 1:55 ` [net-next-2.6 PATCH 20/20] igb: cleanup "todo" code found in igb_ethtool.c Jeff Kirsher
@ 2009-10-28 8:28 ` David Miller
19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2009-10-28 8:28 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, alexander.h.duyck
All 20 patches applied, thanks a lot.
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2009-10-28 8:28 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-28 1:49 [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI Jeff Kirsher
2009-10-28 1:49 ` [net-next-2.6 PATCH 02/20] igb: remove rx checksum good counter Jeff Kirsher
2009-10-28 1:50 ` [net-next-2.6 PATCH 03/20] igb: increase minimum rx buffer size to 1K Jeff Kirsher
2009-10-28 1:50 ` [net-next-2.6 PATCH 04/20] igb: move the tx and rx ring specific config into seperate functions Jeff Kirsher
2009-10-28 1:50 ` [net-next-2.6 PATCH 05/20] igb: remove rx_ps_hdr_len Jeff Kirsher
2009-10-28 1:51 ` [net-next-2.6 PATCH 06/20] igb: move SRRCTL register configuration into ring specific config Jeff Kirsher
2009-10-28 1:51 ` [net-next-2.6 PATCH 07/20] igb: change the head and tail offsets into pointers Jeff Kirsher
2009-10-28 1:51 ` [net-next-2.6 PATCH 08/20] igb: add pci device pointer to ring structure Jeff Kirsher
2009-10-28 1:52 ` [net-next-2.6 PATCH 09/20] igb: move rx_buffer_len into the " Jeff Kirsher
2009-10-28 1:52 ` [net-next-2.6 PATCH 10/20] igb: move alloc_failed and csum_err stats into per rx-ring stat Jeff Kirsher
2009-10-28 1:52 ` [net-next-2.6 PATCH 11/20] igb: add a flags value to the ring Jeff Kirsher
2009-10-28 1:53 ` [net-next-2.6 PATCH 12/20] igb: place a pointer to the netdev struct in the ring itself Jeff Kirsher
2009-10-28 1:53 ` [net-next-2.6 PATCH 13/20] igb: move the multiple receive queue configuration into seperate function Jeff Kirsher
2009-10-28 1:53 ` [net-next-2.6 PATCH 14/20] igb: delay VF reset notification until after interrupts are enabed Jeff Kirsher
2009-10-28 1:54 ` [net-next-2.6 PATCH 15/20] igb: setup vlan tag replication stripping in igb_vmm_control Jeff Kirsher
2009-10-28 1:54 ` [net-next-2.6 PATCH 16/20] igb: re-use ring configuration code in ethtool testing Jeff Kirsher
2009-10-28 1:54 ` [net-next-2.6 PATCH 17/20] igb: make tx ring map and free functionality non-static Jeff Kirsher
2009-10-28 1:55 ` [net-next-2.6 PATCH 18/20] igb: make ethtool use core xmit map and free functionality Jeff Kirsher
2009-10-28 1:55 ` [net-next-2.6 PATCH 19/20] igb: add single vector msi-x testing to interrupt test Jeff Kirsher
2009-10-28 1:55 ` [net-next-2.6 PATCH 20/20] igb: cleanup "todo" code found in igb_ethtool.c Jeff Kirsher
2009-10-28 8:28 ` [net-next-2.6 PATCH 01/20] igb: add new data structure for handling interrupts and NAPI David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).