This is an implementation of the idea provided by Jakub here
https://lore.kernel.org/netdev/[email protected]/
The set_rx_mode callback is invoked under the addr_lock spinlock which
makes it illegal to sleep. This means set_rx_mode is prone to
sleep-in-atomic bugs as drivers have a tendency to do the I/O directly
in the callback.
This problem can be avoided if set_rx_mode were done in 2 stages: snapshot
and commit. A handful of drivers implement this idea by implementing the
rx_mode setting as work and scheduling it in the set_rx_mode callback.
This series moves that work to net/core by introducing a new async
netdev op set_rx_mode_async.
In the process of doing this, I encountered problems described in the
the first patch of the series. In brief, the patch introduces a state
variable to keep track of the current netdev state. This should be
useful for async netdev ops in general as nothing about these problems
was specific to set_rx_mode_async.
The rx_mode refactor has the secondary benefit of preventing RX mode
update requests from building up as only the most recent request
(before the work has run) will be committed.
In brief, the new RX mode update flow will look something like:
set_rx_mode():
ndo_set_rx_mode();
prepare_snapshot();
set_rx_mode_async():
fetch_snapshot();
ndo_set_rx_mode_async();
ndo_set_rx_mode_async() is called from a work item and the handler
doesn't hold the netif_addr_lock spin lock during its execution
making execution sleepable in that part.
This model should work correctly if the following conditions hold:
1. ndo_set_rx_mode_async should use the rx_mode set by the most recent
call to prepare_rx_mode() before its execution.
2. If a prepare_snapshot() call happens during execution of the work,
the work should be rescheduled.
3. All calls to modify rx_mode should pass through a new helper
netif_set_rx_mode (which requires the instance lock or RTNL if the
driver doesn't use it).
1 is guaranteed by the implementation and 2 by workqueue properties.
Drivers need to ensure 3.
---
v1:
Link:
https://lore.kernel.org/netdev/[email protected]/
v2:
- Exported set_and_schedule_rx_config as a symbol for use in modules
- Fixed incorrect cleanup for the case of rx_work alloc failing in
alloc_netdev_mqs
- Removed the locked version (cp_set_rx_mode) and renamed __cp_set_rx_mode to
cp_set_rx_mode
Link:
https://lore.kernel.org/netdev/[email protected]/
v3:
- Added RFT tag
- Corrected mangled patch
Link:
https://lore.kernel.org/netdev/[email protected]/
v4:
- Completely reworked the snapshot mechanism as per v3 comments
- Implemented the callback for virtio-net instead of 8139cp driver
- Removed RFC tag
Link:
https://lore.kernel.org/netdev/[email protected]/
v5:
- Fix broken code and titles
- Remove RFT tag
Link:
https://lore.kernel.org/netdev/[email protected]/
v6:
- Added struct netif_deferred_work_cleanup and members needs_deferred_cleanup
and deferred_work_cleanup in net_device
- Moved out ctrl bits from netif_rx_mode_config to netif_rx_mode_work_ctx
Link:
https://lore.kernel.org/netdev/[email protected]/
v7:
- Improved function, enum and struct names
Link:
https://lore.kernel.org/netdev/[email protected]/
v8:
- Implemented the callback for drivers e1000, 8139cp, vmxnet3 and pcnet32
- Moved the rx_mode config set calls (for prom and allmulti) in prepare_rx_mode
to the ndo_set_rx_mode callback for consistency
- Improved commit messages
Link:
https://lore.kernel.org/netdev/[email protected]/
v9:
- Removed cleanup_work and simplified resource cleanup
- Added netif_async_ctx (which includes netdev state tracking) for async ndo
handling in general
- Converted netif_schedule_mode_work to a synchronous function netif_set_rx_mode
- Renamed *_write_rx_mode functions to *_set_rx_mode_async
I Viswanath (7):
net: core: Add state tracking for async netdev ops
net: core: Introduce callback ndo_set_rx_mode_async
virtio-net: Implement ndo_set_rx_mode_async callback
e1000: Implement ndo_set_rx_mode_async callback
8139cp: Implement ndo_set_rx_mode_async callback
vmxnet3: Implement ndo_set_rx_mode_async callback
pcnet32: Implement ndo_set_rx_mode_async callback
drivers/net/ethernet/amd/pcnet32.c | 65 +++-
drivers/net/ethernet/intel/e1000/e1000_main.c | 77 +++-
drivers/net/ethernet/realtek/8139cp.c | 49 ++-
drivers/net/virtio_net.c | 85 ++---
drivers/net/vmxnet3/vmxnet3_drv.c | 46 ++-
include/linux/netdevice.h | 123 ++++++-
include/net/netdev_lock.h | 8 +
net/core/dev.c | 335 +++++++++++++++++-
8 files changed, 663 insertions(+), 125 deletions(-)
--
2.47.3