[v3,5/5] failsafe: make sub-device remove flag thread-safe
Checks
Commit Message
For each sub-device, there's a remove flag that's used to indicate if
the sub-device has been removed or not. This flag is currently a
volatile bit field. Even if it's marked as volatile, a bit field is not
thread-safe according to the C standard.
The remove flag is now an unsigned int rather than a bit field. We also
now use the atomic built-ins to read/write the value of the remove flag
to ensure thread-safety.
Fixes: 598fb8aec6f6 ("net/failsafe: support device removal")
Cc: Gaetan Rivet <grive@u256.net>
Cc: stable@dpdk.org
Signed-off-by: Luc Pelletier <lucp.at.work@gmail.com>
---
drivers/net/failsafe/failsafe_ether.c | 8 ++++----
drivers/net/failsafe/failsafe_ops.c | 2 +-
drivers/net/failsafe/failsafe_private.h | 4 ++--
drivers/net/failsafe/failsafe_rxtx.c | 2 +-
4 files changed, 8 insertions(+), 8 deletions(-)
@@ -311,7 +311,7 @@ fs_dev_remove(struct sub_device *sdev)
/* the end */
break;
}
- sdev->remove = 0;
+ __atomic_store_n(&sdev->remove, 0, __ATOMIC_RELEASE);
failsafe_hotplug_alarm_install(fs_dev(sdev));
}
@@ -388,7 +388,7 @@ failsafe_dev_remove(struct rte_eth_dev *dev)
uint8_t i;
FOREACH_SUBDEV(sdev, i, dev) {
- if (!sdev->remove)
+ if (!__atomic_load_n(&sdev->remove, __ATOMIC_ACQUIRE))
continue;
/* Active devices must have finished their burst and
@@ -556,7 +556,7 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)
err_remove:
FOREACH_SUBDEV(sdev, i, dev)
if (sdev->state != PRIV(dev)->state)
- sdev->remove = 1;
+ __atomic_store_n(&sdev->remove, 1, __ATOMIC_RELEASE);
return ret;
}
@@ -597,7 +597,7 @@ failsafe_eth_rmv_event_callback(uint16_t port_id __rte_unused,
* Async removal, the sub-PMD will try to unregister
* the callback at the source of the current thread context.
*/
- sdev->remove = 1;
+ __atomic_store_n(&sdev->remove, 1, __ATOMIC_RELEASE);
fs_unlock(fs_dev(sdev), 0);
return 0;
}
@@ -838,7 +838,7 @@ fs_link_update(struct rte_eth_dev *dev,
if (TX_SUBDEV(dev) == sdev)
ret = rte_eth_linkstatus_set(dev, &link_info);
}
- else if (sdev->remove == 0 &&
+ else if (__atomic_load_n(&sdev->remove, __ATOMIC_ACQUIRE) == 0 &&
rte_eth_dev_is_removed(PORT_ID(sdev)) == 0) {
ERROR("Link get failed for sub_device %d with error %d",
i, sdev_link_ret);
@@ -131,7 +131,7 @@ struct sub_device {
/* sub device port id*/
uint16_t sdev_port_id; /* shared between processes */
/* flag calling for recollection */
- volatile unsigned int remove:1;
+ unsigned int remove;
/* flow isolation state */
int flow_isolated:1;
/* RMV callback registration state */
@@ -490,7 +490,7 @@ static inline int
fs_err(struct sub_device *sdev, int err)
{
/* A device removal shouldn't be reported as an error. */
- if (sdev->remove == 1 || err == -EIO)
+ if (__atomic_load_n(&sdev->remove, __ATOMIC_ACQUIRE) == 1 || err == -EIO)
return rte_errno = 0;
return err;
}
@@ -16,7 +16,7 @@ fs_rx_unsafe(struct sub_device *sdev)
return (ETH(sdev) == NULL) ||
(ETH(sdev)->rx_pkt_burst == NULL) ||
(sdev->state != DEV_STARTED) ||
- (sdev->remove != 0);
+ (__atomic_load_n(&sdev->remove, __ATOMIC_ACQUIRE) != 0);
}
static inline int