net/e1000: always enable receive and transmit

The transmit and receive controller state machines are only enabled after
receiving an interrupt and the link status is now valid.  If an adapter
is being used in conjunction with NC-SI, network controller sideband
interface, the adapter may never get a link state change interrupt since
the adapter's PHY is always link up and never changes state.

To fix this, always enable and disable the transmit and receive with
.dev_start and .dev_stop.  This is a better match for what is typically
done with the other PMD's.  Since we may never get an interrupt to check
the link state, we also poll once at the end of .dev_start to get the
current link status.

Signed-off-by: Chas Williams <chas3@att.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
This commit is contained in:
Chas Williams 2017-10-19 23:23:39 -04:00 committed by Ferruh Yigit
parent cde1f02528
commit a2efa4f660
2 changed files with 58 additions and 31 deletions

View File

@ -560,6 +560,30 @@ em_set_pba(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_PBA, pba);
}
static void
eth_em_rxtx_control(struct rte_eth_dev *dev,
bool enable)
{
struct e1000_hw *hw =
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
uint32_t tctl, rctl;
tctl = E1000_READ_REG(hw, E1000_TCTL);
rctl = E1000_READ_REG(hw, E1000_RCTL);
if (enable) {
/* enable Tx/Rx */
tctl |= E1000_TCTL_EN;
rctl |= E1000_RCTL_EN;
} else {
/* disable Tx/Rx */
tctl &= ~E1000_TCTL_EN;
rctl &= ~E1000_RCTL_EN;
}
E1000_WRITE_REG(hw, E1000_TCTL, tctl);
E1000_WRITE_REG(hw, E1000_RCTL, rctl);
E1000_WRITE_FLUSH(hw);
}
static int
eth_em_start(struct rte_eth_dev *dev)
{
@ -733,6 +757,9 @@ eth_em_start(struct rte_eth_dev *dev)
adapter->stopped = 0;
eth_em_rxtx_control(dev, true);
eth_em_link_update(dev, 0);
PMD_INIT_LOG(DEBUG, "<<");
return 0;
@ -758,6 +785,7 @@ eth_em_stop(struct rte_eth_dev *dev)
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
eth_em_rxtx_control(dev, false);
em_rxq_intr_disable(hw);
em_lsc_intr_disable(hw);
@ -1584,7 +1612,6 @@ eth_em_interrupt_action(struct rte_eth_dev *dev,
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct e1000_interrupt *intr =
E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
uint32_t tctl, rctl;
struct rte_eth_link link;
int ret;
@ -1616,21 +1643,6 @@ eth_em_interrupt_action(struct rte_eth_dev *dev,
pci_dev->addr.domain, pci_dev->addr.bus,
pci_dev->addr.devid, pci_dev->addr.function);
tctl = E1000_READ_REG(hw, E1000_TCTL);
rctl = E1000_READ_REG(hw, E1000_RCTL);
if (link.link_status) {
/* enable Tx/Rx */
tctl |= E1000_TCTL_EN;
rctl |= E1000_RCTL_EN;
} else {
/* disable Tx/Rx */
tctl &= ~E1000_TCTL_EN;
rctl &= ~E1000_RCTL_EN;
}
E1000_WRITE_REG(hw, E1000_TCTL, tctl);
E1000_WRITE_REG(hw, E1000_RCTL, rctl);
E1000_WRITE_FLUSH(hw);
return 0;
}

View File

@ -1277,6 +1277,31 @@ eth_igb_configure(struct rte_eth_dev *dev)
return 0;
}
static void
eth_igb_rxtx_control(struct rte_eth_dev *dev,
bool enable)
{
struct e1000_hw *hw =
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
uint32_t tctl, rctl;
tctl = E1000_READ_REG(hw, E1000_TCTL);
rctl = E1000_READ_REG(hw, E1000_RCTL);
if (enable) {
/* enable Tx/Rx */
tctl |= E1000_TCTL_EN;
rctl |= E1000_RCTL_EN;
} else {
/* disable Tx/Rx */
tctl &= ~E1000_TCTL_EN;
rctl &= ~E1000_RCTL_EN;
}
E1000_WRITE_REG(hw, E1000_TCTL, tctl);
E1000_WRITE_REG(hw, E1000_RCTL, rctl);
E1000_WRITE_FLUSH(hw);
}
static int
eth_igb_start(struct rte_eth_dev *dev)
{
@ -1480,6 +1505,9 @@ eth_igb_start(struct rte_eth_dev *dev)
/* restore all types filter */
igb_filter_restore(dev);
eth_igb_rxtx_control(dev, true);
eth_igb_link_update(dev, 0);
PMD_INIT_LOG(DEBUG, "<<");
return 0;
@ -1505,6 +1533,8 @@ eth_igb_stop(struct rte_eth_dev *dev)
struct rte_eth_link link;
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
eth_igb_rxtx_control(dev, false);
igb_intr_disable(hw);
/* disable intr eventfd mapping */
@ -2835,7 +2865,6 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev,
struct e1000_interrupt *intr =
E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
uint32_t tctl, rctl;
struct rte_eth_link link;
int ret;
@ -2877,20 +2906,6 @@ eth_igb_interrupt_action(struct rte_eth_dev *dev,
pci_dev->addr.bus,
pci_dev->addr.devid,
pci_dev->addr.function);
tctl = E1000_READ_REG(hw, E1000_TCTL);
rctl = E1000_READ_REG(hw, E1000_RCTL);
if (link.link_status) {
/* enable Tx/Rx */
tctl |= E1000_TCTL_EN;
rctl |= E1000_RCTL_EN;
} else {
/* disable Tx/Rx */
tctl &= ~E1000_TCTL_EN;
rctl &= ~E1000_RCTL_EN;
}
E1000_WRITE_REG(hw, E1000_TCTL, tctl);
E1000_WRITE_REG(hw, E1000_RCTL, rctl);
E1000_WRITE_FLUSH(hw);
_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
NULL);
}