[dpdk-dev,v3,01/10] vmxnet3: fix link state handling
Commit Message
From: Stephen Hemminger <shemming@brocade.com>
The Intel version of VMXNET3 driver does not handle link state properly.
The VMXNET3 API returns 1 if connected and 0 if disconnected.
Also need to return correct value to indicate state change.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Yong Wang <yongwang@vmware.com>
---
lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c | 54 ++++++++++++++++++++++++---------
1 file changed, 39 insertions(+), 15 deletions(-)
Comments
Hi Stephen,
Have you considered supporting LSC interrupts in vmxnet3?
--
Thanks,
Robert
>From: Stephen Hemminger <shemming@brocade.com>
>
>The Intel version of VMXNET3 driver does not handle link state properly.
>The VMXNET3 API returns 1 if connected and 0 if disconnected.
>Also need to return correct value to indicate state change.
>
>Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
>Acked-by: Yong Wang <yongwang@vmware.com>
>---
> lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c | 54
>++++++++++++++++++++++++---------
> 1 file changed, 39 insertions(+), 15 deletions(-)
>
>diff --git a/lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c
>b/lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c
>index 6068c60..4c882ee 100644
>--- a/lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c
>+++ b/lib/librte_pmd_vmxnet3/vmxnet3_ethdev.c
>@@ -149,9 +149,36 @@ gpa_zone_reserve(struct rte_eth_dev *dev, uint32_t
>size,
> * - On success, zero.
> * - On failure, negative value.
> */
>-static inline int
>-rte_vmxnet3_dev_atomic_write_link_status(struct rte_eth_dev *dev,
>- struct rte_eth_link *link)
>+
>+static int
>+vmxnet3_dev_atomic_read_link_status(struct rte_eth_dev *dev,
>+ struct rte_eth_link *link)
>+{
>+ struct rte_eth_link *dst = link;
>+ struct rte_eth_link *src = &(dev->data->dev_link);
>+
>+ if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
>+ *(uint64_t *)src) == 0)
>+ return -1;
>+
>+ return 0;
>+}
>+
>+/**
>+ * Atomically writes the link status information into global
>+ * structure rte_eth_dev.
>+ *
>+ * @param dev
>+ * - Pointer to the structure rte_eth_dev to write to.
>+ * - Pointer to the buffer to be saved with the link status.
>+ *
>+ * @return
>+ * - On success, zero.
>+ * - On failure, negative value.
>+ */
>+static int
>+vmxnet3_dev_atomic_write_link_status(struct rte_eth_dev *dev,
>+ struct rte_eth_link *link)
> {
> struct rte_eth_link *dst = &(dev->data->dev_link);
> struct rte_eth_link *src = link;
>@@ -384,6 +411,7 @@ vmxnet3_setup_driver_shared(struct rte_eth_dev *dev)
> devRead->misc.driverInfo.vmxnet3RevSpt = 1;
> devRead->misc.driverInfo.uptVerSpt = 1;
>
>+ devRead->misc.mtu = rte_le_to_cpu_32(dev->data->mtu);
> devRead->misc.queueDescPA = hw->queueDescPA;
> devRead->misc.queueDescLen = hw->queue_desc_len;
> devRead->misc.mtu = hw->cur_mtu;
>@@ -570,7 +598,7 @@ vmxnet3_dev_stop(struct rte_eth_dev *dev)
>
> /* Clear recorded link status */
> memset(&link, 0, sizeof(link));
>- rte_vmxnet3_dev_atomic_write_link_status(dev, &link);
>+ vmxnet3_dev_atomic_write_link_status(dev, &link);
> }
>
> /*
>@@ -653,28 +681,24 @@ static int
> vmxnet3_dev_link_update(struct rte_eth_dev *dev, __attribute__((unused))
>int wait_to_complete)
> {
> struct vmxnet3_hw *hw = dev->data->dev_private;
>- struct rte_eth_link link;
>+ struct rte_eth_link old, link;
> uint32_t ret;
>
>+ memset(&link, 0, sizeof(link));
>+ vmxnet3_dev_atomic_read_link_status(dev, &old);
>+
> VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
> ret = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
>
>- if (!ret) {
>- PMD_INIT_LOG(ERR, "Link Status Negative : %s()", __func__);
>- return -1;
>- }
>-
> if (ret & 0x1) {
> link.link_status = 1;
> link.link_duplex = ETH_LINK_FULL_DUPLEX;
> link.link_speed = ETH_LINK_SPEED_10000;
>-
>- rte_vmxnet3_dev_atomic_write_link_status(dev, &link);
>-
>- return 0;
> }
>
>- return -1;
>+ vmxnet3_dev_atomic_write_link_status(dev, &link);
>+
>+ return (old.link_status == link.link_status) ? -1 : 0;
> }
>
> /* Updating rxmode through Vmxnet3_DriverShared structure in adapter */
>--
>2.1.4
>
On Fri, 6 Mar 2015 17:21:36 +0000
"Sanford, Robert" <rsanford@akamai.com> wrote:
> Hi Stephen,
>
> Have you considered supporting LSC interrupts in vmxnet3?
>
> --
> Thanks,
> Robert
I tried implementing it but it is not possible since the VMXNET3 device
API does not have an interrupt mask. Therefore there is no way to get
Link State interrupts but not get an interrupt for every packet received.
@@ -149,9 +149,36 @@ gpa_zone_reserve(struct rte_eth_dev *dev, uint32_t size,
* - On success, zero.
* - On failure, negative value.
*/
-static inline int
-rte_vmxnet3_dev_atomic_write_link_status(struct rte_eth_dev *dev,
- struct rte_eth_link *link)
+
+static int
+vmxnet3_dev_atomic_read_link_status(struct rte_eth_dev *dev,
+ struct rte_eth_link *link)
+{
+ struct rte_eth_link *dst = link;
+ struct rte_eth_link *src = &(dev->data->dev_link);
+
+ if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
+ *(uint64_t *)src) == 0)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * Atomically writes the link status information into global
+ * structure rte_eth_dev.
+ *
+ * @param dev
+ * - Pointer to the structure rte_eth_dev to write to.
+ * - Pointer to the buffer to be saved with the link status.
+ *
+ * @return
+ * - On success, zero.
+ * - On failure, negative value.
+ */
+static int
+vmxnet3_dev_atomic_write_link_status(struct rte_eth_dev *dev,
+ struct rte_eth_link *link)
{
struct rte_eth_link *dst = &(dev->data->dev_link);
struct rte_eth_link *src = link;
@@ -384,6 +411,7 @@ vmxnet3_setup_driver_shared(struct rte_eth_dev *dev)
devRead->misc.driverInfo.vmxnet3RevSpt = 1;
devRead->misc.driverInfo.uptVerSpt = 1;
+ devRead->misc.mtu = rte_le_to_cpu_32(dev->data->mtu);
devRead->misc.queueDescPA = hw->queueDescPA;
devRead->misc.queueDescLen = hw->queue_desc_len;
devRead->misc.mtu = hw->cur_mtu;
@@ -570,7 +598,7 @@ vmxnet3_dev_stop(struct rte_eth_dev *dev)
/* Clear recorded link status */
memset(&link, 0, sizeof(link));
- rte_vmxnet3_dev_atomic_write_link_status(dev, &link);
+ vmxnet3_dev_atomic_write_link_status(dev, &link);
}
/*
@@ -653,28 +681,24 @@ static int
vmxnet3_dev_link_update(struct rte_eth_dev *dev, __attribute__((unused)) int wait_to_complete)
{
struct vmxnet3_hw *hw = dev->data->dev_private;
- struct rte_eth_link link;
+ struct rte_eth_link old, link;
uint32_t ret;
+ memset(&link, 0, sizeof(link));
+ vmxnet3_dev_atomic_read_link_status(dev, &old);
+
VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
ret = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
- if (!ret) {
- PMD_INIT_LOG(ERR, "Link Status Negative : %s()", __func__);
- return -1;
- }
-
if (ret & 0x1) {
link.link_status = 1;
link.link_duplex = ETH_LINK_FULL_DUPLEX;
link.link_speed = ETH_LINK_SPEED_10000;
-
- rte_vmxnet3_dev_atomic_write_link_status(dev, &link);
-
- return 0;
}
- return -1;
+ vmxnet3_dev_atomic_write_link_status(dev, &link);
+
+ return (old.link_status == link.link_status) ? -1 : 0;
}
/* Updating rxmode through Vmxnet3_DriverShared structure in adapter */