Commit 844290e5 authored by PJ Waskiewicz's avatar PJ Waskiewicz Committed by Jeff Garzik

igb: add NAPI Rx queue support

Update the NAPI implementation to use the new napi_struct infrstructure.
This removes the need of multiple net_device structs to implement a
multiqueue NAPI.
Signed-off-by: default avatarPJ Waskiewicz <peter.p.waskiewicz.jr.@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 662d7205
...@@ -150,6 +150,7 @@ struct igb_ring { ...@@ -150,6 +150,7 @@ struct igb_ring {
u16 itr_register; u16 itr_register;
u16 cpu; u16 cpu;
int queue_index;
unsigned int total_bytes; unsigned int total_bytes;
unsigned int total_packets; unsigned int total_packets;
...@@ -265,6 +266,7 @@ struct igb_adapter { ...@@ -265,6 +266,7 @@ struct igb_adapter {
int msg_enable; int msg_enable;
struct msix_entry *msix_entries; struct msix_entry *msix_entries;
u32 eims_enable_mask; u32 eims_enable_mask;
u32 eims_other;
/* to not mess up cache alignment, always add to the bottom */ /* to not mess up cache alignment, always add to the bottom */
unsigned long state; unsigned long state;
......
...@@ -227,12 +227,11 @@ static int igb_alloc_queues(struct igb_adapter *adapter) ...@@ -227,12 +227,11 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_rx_queues; i++) { for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = &(adapter->rx_ring[i]); struct igb_ring *ring = &(adapter->rx_ring[i]);
ring->adapter = adapter; ring->adapter = adapter;
ring->queue_index = i;
ring->itr_register = E1000_ITR; ring->itr_register = E1000_ITR;
if (!ring->napi.poll) /* set a default napi handler for each rx_ring */
netif_napi_add(adapter->netdev, &ring->napi, igb_clean, netif_napi_add(adapter->netdev, &ring->napi, igb_clean, 64);
adapter->napi.weight /
adapter->num_rx_queues);
} }
return 0; return 0;
} }
...@@ -300,9 +299,6 @@ static void igb_configure_msix(struct igb_adapter *adapter) ...@@ -300,9 +299,6 @@ static void igb_configure_msix(struct igb_adapter *adapter)
array_wr32(E1000_MSIXBM(0), vector++, array_wr32(E1000_MSIXBM(0), vector++,
E1000_EIMS_OTHER); E1000_EIMS_OTHER);
/* disable IAM for ICR interrupt bits */
wr32(E1000_IAM, 0);
tmp = rd32(E1000_CTRL_EXT); tmp = rd32(E1000_CTRL_EXT);
/* enable MSI-X PBA support*/ /* enable MSI-X PBA support*/
tmp |= E1000_CTRL_EXT_PBA_CLR; tmp |= E1000_CTRL_EXT_PBA_CLR;
...@@ -313,6 +309,7 @@ static void igb_configure_msix(struct igb_adapter *adapter) ...@@ -313,6 +309,7 @@ static void igb_configure_msix(struct igb_adapter *adapter)
wr32(E1000_CTRL_EXT, tmp); wr32(E1000_CTRL_EXT, tmp);
adapter->eims_enable_mask |= E1000_EIMS_OTHER; adapter->eims_enable_mask |= E1000_EIMS_OTHER;
adapter->eims_other = E1000_EIMS_OTHER;
wrfl(); wrfl();
} }
...@@ -355,6 +352,9 @@ static int igb_request_msix(struct igb_adapter *adapter) ...@@ -355,6 +352,9 @@ static int igb_request_msix(struct igb_adapter *adapter)
goto out; goto out;
ring->itr_register = E1000_EITR(0) + (vector << 2); ring->itr_register = E1000_EITR(0) + (vector << 2);
ring->itr_val = adapter->itr; ring->itr_val = adapter->itr;
/* overwrite the poll routine for MSIX, we've already done
* netif_napi_add */
ring->napi.poll = &igb_clean_rx_ring_msix;
vector++; vector++;
} }
...@@ -363,9 +363,6 @@ static int igb_request_msix(struct igb_adapter *adapter) ...@@ -363,9 +363,6 @@ static int igb_request_msix(struct igb_adapter *adapter)
if (err) if (err)
goto out; goto out;
adapter->napi.poll = igb_clean_rx_ring_msix;
for (i = 0; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i].napi.poll = adapter->napi.poll;
igb_configure_msix(adapter); igb_configure_msix(adapter);
return 0; return 0;
out: out:
...@@ -434,12 +431,8 @@ static int igb_request_irq(struct igb_adapter *adapter) ...@@ -434,12 +431,8 @@ static int igb_request_irq(struct igb_adapter *adapter)
if (adapter->msix_entries) { if (adapter->msix_entries) {
err = igb_request_msix(adapter); err = igb_request_msix(adapter);
if (!err) { if (!err)
/* enable IAM, auto-mask,
* DO NOT USE EIAM or IAM in legacy mode */
wr32(E1000_IAM, IMS_ENABLE_MASK);
goto request_done; goto request_done;
}
/* fall back to MSI */ /* fall back to MSI */
igb_reset_interrupt_capability(adapter); igb_reset_interrupt_capability(adapter);
if (!pci_enable_msi(adapter->pdev)) if (!pci_enable_msi(adapter->pdev))
...@@ -448,7 +441,11 @@ static int igb_request_irq(struct igb_adapter *adapter) ...@@ -448,7 +441,11 @@ static int igb_request_irq(struct igb_adapter *adapter)
igb_free_all_rx_resources(adapter); igb_free_all_rx_resources(adapter);
adapter->num_rx_queues = 1; adapter->num_rx_queues = 1;
igb_alloc_queues(adapter); igb_alloc_queues(adapter);
} else {
wr32(E1000_MSIXBM(0), (E1000_EICR_RX_QUEUE0 |
E1000_EIMS_OTHER));
} }
if (adapter->msi_enabled) { if (adapter->msi_enabled) {
err = request_irq(adapter->pdev->irq, &igb_intr_msi, 0, err = request_irq(adapter->pdev->irq, &igb_intr_msi, 0,
netdev->name, netdev); netdev->name, netdev);
...@@ -500,9 +497,12 @@ static void igb_irq_disable(struct igb_adapter *adapter) ...@@ -500,9 +497,12 @@ static void igb_irq_disable(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
if (adapter->msix_entries) { if (adapter->msix_entries) {
wr32(E1000_EIAM, 0);
wr32(E1000_EIMC, ~0); wr32(E1000_EIMC, ~0);
wr32(E1000_EIAC, 0); wr32(E1000_EIAC, 0);
} }
wr32(E1000_IAM, 0);
wr32(E1000_IMC, ~0); wr32(E1000_IMC, ~0);
wrfl(); wrfl();
synchronize_irq(adapter->pdev->irq); synchronize_irq(adapter->pdev->irq);
...@@ -517,13 +517,14 @@ static void igb_irq_enable(struct igb_adapter *adapter) ...@@ -517,13 +517,14 @@ static void igb_irq_enable(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
if (adapter->msix_entries) { if (adapter->msix_entries) {
wr32(E1000_EIMS, wr32(E1000_EIAC, adapter->eims_enable_mask);
adapter->eims_enable_mask); wr32(E1000_EIAM, adapter->eims_enable_mask);
wr32(E1000_EIAC, wr32(E1000_EIMS, adapter->eims_enable_mask);
adapter->eims_enable_mask);
wr32(E1000_IMS, E1000_IMS_LSC); wr32(E1000_IMS, E1000_IMS_LSC);
} else } else {
wr32(E1000_IMS, IMS_ENABLE_MASK); wr32(E1000_IMS, IMS_ENABLE_MASK);
wr32(E1000_IAM, IMS_ENABLE_MASK);
}
} }
static void igb_update_mng_vlan(struct igb_adapter *adapter) static void igb_update_mng_vlan(struct igb_adapter *adapter)
...@@ -661,13 +662,10 @@ int igb_up(struct igb_adapter *adapter) ...@@ -661,13 +662,10 @@ int igb_up(struct igb_adapter *adapter)
clear_bit(__IGB_DOWN, &adapter->state); clear_bit(__IGB_DOWN, &adapter->state);
napi_enable(&adapter->napi);
if (adapter->msix_entries) {
for (i = 0; i < adapter->num_rx_queues; i++) for (i = 0; i < adapter->num_rx_queues; i++)
napi_enable(&adapter->rx_ring[i].napi); napi_enable(&adapter->rx_ring[i].napi);
if (adapter->msix_entries)
igb_configure_msix(adapter); igb_configure_msix(adapter);
}
/* Clear any pending interrupts. */ /* Clear any pending interrupts. */
rd32(E1000_ICR); rd32(E1000_ICR);
...@@ -704,11 +702,9 @@ void igb_down(struct igb_adapter *adapter) ...@@ -704,11 +702,9 @@ void igb_down(struct igb_adapter *adapter)
wrfl(); wrfl();
msleep(10); msleep(10);
napi_disable(&adapter->napi);
if (adapter->msix_entries)
for (i = 0; i < adapter->num_rx_queues; i++) for (i = 0; i < adapter->num_rx_queues; i++)
napi_disable(&adapter->rx_ring[i].napi); napi_disable(&adapter->rx_ring[i].napi);
igb_irq_disable(adapter); igb_irq_disable(adapter);
del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->watchdog_timer);
...@@ -933,7 +929,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, ...@@ -933,7 +929,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
igb_set_ethtool_ops(netdev); igb_set_ethtool_ops(netdev);
netdev->tx_timeout = &igb_tx_timeout; netdev->tx_timeout = &igb_tx_timeout;
netdev->watchdog_timeo = 5 * HZ; netdev->watchdog_timeo = 5 * HZ;
netif_napi_add(netdev, &adapter->napi, igb_clean, 64);
netdev->vlan_rx_register = igb_vlan_rx_register; netdev->vlan_rx_register = igb_vlan_rx_register;
netdev->vlan_rx_add_vid = igb_vlan_rx_add_vid; netdev->vlan_rx_add_vid = igb_vlan_rx_add_vid;
netdev->vlan_rx_kill_vid = igb_vlan_rx_kill_vid; netdev->vlan_rx_kill_vid = igb_vlan_rx_kill_vid;
...@@ -1298,15 +1293,14 @@ static int igb_open(struct net_device *netdev) ...@@ -1298,15 +1293,14 @@ static int igb_open(struct net_device *netdev)
/* From here on the code is the same as igb_up() */ /* From here on the code is the same as igb_up() */
clear_bit(__IGB_DOWN, &adapter->state); clear_bit(__IGB_DOWN, &adapter->state);
napi_enable(&adapter->napi);
if (adapter->msix_entries)
for (i = 0; i < adapter->num_rx_queues; i++) for (i = 0; i < adapter->num_rx_queues; i++)
napi_enable(&adapter->rx_ring[i].napi); napi_enable(&adapter->rx_ring[i].napi);
igb_irq_enable(adapter);
/* Clear any pending interrupts. */ /* Clear any pending interrupts. */
rd32(E1000_ICR); rd32(E1000_ICR);
igb_irq_enable(adapter);
/* Fire a link status change interrupt to start the watchdog. */ /* Fire a link status change interrupt to start the watchdog. */
wr32(E1000_ICS, E1000_ICS_LSC); wr32(E1000_ICS, E1000_ICS_LSC);
...@@ -1534,8 +1528,6 @@ int igb_setup_rx_resources(struct igb_adapter *adapter, ...@@ -1534,8 +1528,6 @@ int igb_setup_rx_resources(struct igb_adapter *adapter,
rx_ring->pending_skb = NULL; rx_ring->pending_skb = NULL;
rx_ring->adapter = adapter; rx_ring->adapter = adapter;
/* FIXME: do we want to setup ring->napi->poll here? */
rx_ring->napi.poll = adapter->napi.poll;
return 0; return 0;
...@@ -3034,14 +3026,8 @@ static irqreturn_t igb_msix_other(int irq, void *data) ...@@ -3034,14 +3026,8 @@ static irqreturn_t igb_msix_other(int irq, void *data)
struct net_device *netdev = data; struct net_device *netdev = data;
struct igb_adapter *adapter = netdev_priv(netdev); struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 eicr;
/* disable interrupts from the "other" bit, avoid re-entry */
wr32(E1000_EIMC, E1000_EIMS_OTHER);
eicr = rd32(E1000_EICR);
if (eicr & E1000_EIMS_OTHER) {
u32 icr = rd32(E1000_ICR); u32 icr = rd32(E1000_ICR);
/* reading ICR causes bit 31 of EICR to be cleared */ /* reading ICR causes bit 31 of EICR to be cleared */
if (!(icr & E1000_ICR_LSC)) if (!(icr & E1000_ICR_LSC))
goto no_link_interrupt; goto no_link_interrupt;
...@@ -3049,11 +3035,10 @@ static irqreturn_t igb_msix_other(int irq, void *data) ...@@ -3049,11 +3035,10 @@ static irqreturn_t igb_msix_other(int irq, void *data)
/* guard against interrupt when we're going down */ /* guard against interrupt when we're going down */
if (!test_bit(__IGB_DOWN, &adapter->state)) if (!test_bit(__IGB_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer, jiffies + 1); mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
no_link_interrupt: no_link_interrupt:
wr32(E1000_IMS, E1000_IMS_LSC); wr32(E1000_IMS, E1000_IMS_LSC);
wr32(E1000_EIMS, E1000_EIMS_OTHER); wr32(E1000_EIMS, adapter->eims_other);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -3084,21 +3069,19 @@ static irqreturn_t igb_msix_rx(int irq, void *data) ...@@ -3084,21 +3069,19 @@ static irqreturn_t igb_msix_rx(int irq, void *data)
struct igb_adapter *adapter = rx_ring->adapter; struct igb_adapter *adapter = rx_ring->adapter;
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
if (!rx_ring->itr_val) /* Write the ITR value calculated at the end of the
wr32(E1000_EIMC, rx_ring->eims_value); * previous interrupt.
*/
if (netif_rx_schedule_prep(adapter->netdev, &rx_ring->napi)) { if (adapter->set_itr) {
rx_ring->total_bytes = 0; wr32(rx_ring->itr_register,
rx_ring->total_packets = 0; 1000000000 / (rx_ring->itr_val * 256));
rx_ring->no_itr_adjust = 0; adapter->set_itr = 0;
__netif_rx_schedule(adapter->netdev, &rx_ring->napi);
} else {
if (!rx_ring->no_itr_adjust) {
igb_lower_rx_eitr(adapter, rx_ring);
rx_ring->no_itr_adjust = 1;
}
} }
if (netif_rx_schedule_prep(adapter->netdev, &rx_ring->napi))
__netif_rx_schedule(adapter->netdev, &rx_ring->napi);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -3112,7 +3095,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data) ...@@ -3112,7 +3095,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
{ {
struct net_device *netdev = data; struct net_device *netdev = data;
struct igb_adapter *adapter = netdev_priv(netdev); struct igb_adapter *adapter = netdev_priv(netdev);
struct napi_struct *napi = &adapter->napi;
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
/* read ICR disables interrupts using IAM */ /* read ICR disables interrupts using IAM */
u32 icr = rd32(E1000_ICR); u32 icr = rd32(E1000_ICR);
...@@ -3121,25 +3103,17 @@ static irqreturn_t igb_intr_msi(int irq, void *data) ...@@ -3121,25 +3103,17 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
* previous interrupt. * previous interrupt.
*/ */
if (adapter->set_itr) { if (adapter->set_itr) {
wr32(E1000_ITR, wr32(E1000_ITR, 1000000000 / (adapter->itr * 256));
1000000000 / (adapter->itr * 256));
adapter->set_itr = 0; adapter->set_itr = 0;
} }
/* read ICR disables interrupts using IAM */
if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
hw->mac.get_link_status = 1; hw->mac.get_link_status = 1;
if (!test_bit(__IGB_DOWN, &adapter->state)) if (!test_bit(__IGB_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer, jiffies + 1); mod_timer(&adapter->watchdog_timer, jiffies + 1);
} }
if (netif_rx_schedule_prep(netdev, napi)) { netif_rx_schedule(netdev, &adapter->rx_ring[0].napi);
adapter->tx_ring->total_bytes = 0;
adapter->tx_ring->total_packets = 0;
adapter->rx_ring->total_bytes = 0;
adapter->rx_ring->total_packets = 0;
__netif_rx_schedule(netdev, napi);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -3153,7 +3127,6 @@ static irqreturn_t igb_intr(int irq, void *data) ...@@ -3153,7 +3127,6 @@ static irqreturn_t igb_intr(int irq, void *data)
{ {
struct net_device *netdev = data; struct net_device *netdev = data;
struct igb_adapter *adapter = netdev_priv(netdev); struct igb_adapter *adapter = netdev_priv(netdev);
struct napi_struct *napi = &adapter->napi;
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No
* need for the IMC write */ * need for the IMC write */
...@@ -3166,8 +3139,7 @@ static irqreturn_t igb_intr(int irq, void *data) ...@@ -3166,8 +3139,7 @@ static irqreturn_t igb_intr(int irq, void *data)
* previous interrupt. * previous interrupt.
*/ */
if (adapter->set_itr) { if (adapter->set_itr) {
wr32(E1000_ITR, wr32(E1000_ITR, 1000000000 / (adapter->itr * 256));
1000000000 / (adapter->itr * 256));
adapter->set_itr = 0; adapter->set_itr = 0;
} }
...@@ -3185,13 +3157,7 @@ static irqreturn_t igb_intr(int irq, void *data) ...@@ -3185,13 +3157,7 @@ static irqreturn_t igb_intr(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1); mod_timer(&adapter->watchdog_timer, jiffies + 1);
} }
if (netif_rx_schedule_prep(netdev, napi)) { netif_rx_schedule(netdev, &adapter->rx_ring[0].napi);
adapter->tx_ring->total_bytes = 0;
adapter->rx_ring->total_bytes = 0;
adapter->tx_ring->total_packets = 0;
adapter->rx_ring->total_packets = 0;
__netif_rx_schedule(netdev, napi);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -3274,6 +3240,10 @@ quit_polling: ...@@ -3274,6 +3240,10 @@ quit_polling:
else if (mean_size > IGB_DYN_ITR_LENGTH_HIGH) else if (mean_size > IGB_DYN_ITR_LENGTH_HIGH)
igb_lower_rx_eitr(adapter, rx_ring); igb_lower_rx_eitr(adapter, rx_ring);
} }
if (!test_bit(__IGB_DOWN, &adapter->state))
wr32(E1000_EIMS, rx_ring->eims_value);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment