Skip to content

Commit

Permalink
Merge branch 'net-dunamic-dummy-device'
Browse files Browse the repository at this point in the history
Breno Leitao says:

====================
allocate dummy device dynamically

struct net_device shouldn't be embedded into any structure, instead,
the owner should use the private space to embed their state into
net_device.

But, in some cases the net_device is embedded inside the private
structure, which blocks the usage of zero-length arrays inside
net_device.

Create a helper to allocate a dummy device at dynamically runtime, and
move the Ethernet devices to use it, instead of embedding the dummy
device inside the private structure.

This fixes all the network cases plus some wireless drivers.

PS: Due to lack of hardware, unfortunately most these patches are
compiled tested only, except ath11k that was kindly tested by Kalle Valo.

---
Changelog:

v7:
	* Document the return value of alloc_netdev_dummy()
v6:
	* No code change. Just added Reviewed-by: and fix a commit message
v5:
	* Added a new patch to fix some typos in the previous code
	* Rebased to net-net/main
v4:
	* Added a new patch to add dummy device at free_netdev(), as suggested
	  by Jakub.
	* Added support for some wireless driver.
	* Added some Acked-by and Reviewed-by.
v3:
	* Use free_netdev() instead of kfree() as suggested by Jakub.
	* Change the free_netdev() place in ipa driver, as suggested by
	  Alex Elder.
	* Set err in the error path in the Marvell driver, as suggested
	  by Simon Horman.
v2:
	* Patch 1: Use a pre-defined name ("dummy#") for the dummy
	  net_devices.
	* Patch 2-5: Added users for the new helper.
v1:
	* https://lore.kernel.org/all/[email protected]/
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Apr 24, 2024
2 parents 55972ce + bca592e commit a2d2cad
Show file tree
Hide file tree
Showing 19 changed files with 129 additions and 53 deletions.
14 changes: 11 additions & 3 deletions drivers/net/ethernet/ibm/emac/mal.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,9 +605,13 @@ static int mal_probe(struct platform_device *ofdev)
INIT_LIST_HEAD(&mal->list);
spin_lock_init(&mal->lock);

init_dummy_netdev(&mal->dummy_dev);
mal->dummy_dev = alloc_netdev_dummy(0);
if (!mal->dummy_dev) {
err = -ENOMEM;
goto fail_unmap;
}

netif_napi_add_weight(&mal->dummy_dev, &mal->napi, mal_poll,
netif_napi_add_weight(mal->dummy_dev, &mal->napi, mal_poll,
CONFIG_IBM_EMAC_POLL_WEIGHT);

/* Load power-on reset defaults */
Expand Down Expand Up @@ -637,7 +641,7 @@ static int mal_probe(struct platform_device *ofdev)
GFP_KERNEL);
if (mal->bd_virt == NULL) {
err = -ENOMEM;
goto fail_unmap;
goto fail_dummy;
}

for (i = 0; i < mal->num_tx_chans; ++i)
Expand Down Expand Up @@ -703,6 +707,8 @@ static int mal_probe(struct platform_device *ofdev)
free_irq(mal->serr_irq, mal);
fail2:
dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma);
fail_dummy:
free_netdev(mal->dummy_dev);
fail_unmap:
dcr_unmap(mal->dcr_host, 0x100);
fail:
Expand Down Expand Up @@ -734,6 +740,8 @@ static void mal_remove(struct platform_device *ofdev)

mal_reset(mal);

free_netdev(mal->dummy_dev);

dma_free_coherent(&ofdev->dev,
sizeof(struct mal_descriptor) *
(NUM_TX_BUFF * mal->num_tx_chans +
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/ibm/emac/mal.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ struct mal_instance {
int index;
spinlock_t lock;

struct net_device dummy_dev;
struct net_device *dummy_dev;

unsigned int features;
};
Expand Down
15 changes: 12 additions & 3 deletions drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ struct prestera_sdma {
struct dma_pool *desc_pool;
struct work_struct tx_work;
struct napi_struct rx_napi;
struct net_device napi_dev;
struct net_device *napi_dev;
u32 map_addr;
u64 dma_mask;
/* protect SDMA with concurrent access from multiple CPUs */
Expand Down Expand Up @@ -654,13 +654,21 @@ static int prestera_sdma_switch_init(struct prestera_switch *sw)
if (err)
goto err_evt_register;

init_dummy_netdev(&sdma->napi_dev);
sdma->napi_dev = alloc_netdev_dummy(0);
if (!sdma->napi_dev) {
dev_err(dev, "not able to initialize dummy device\n");
err = -ENOMEM;
goto err_alloc_dummy;
}

netif_napi_add(&sdma->napi_dev, &sdma->rx_napi, prestera_sdma_rx_poll);
netif_napi_add(sdma->napi_dev, &sdma->rx_napi, prestera_sdma_rx_poll);
napi_enable(&sdma->rx_napi);

return 0;

err_alloc_dummy:
prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_RXTX,
prestera_rxtx_handle_event);
err_evt_register:
err_tx_init:
prestera_sdma_tx_fini(sdma);
Expand All @@ -677,6 +685,7 @@ static void prestera_sdma_switch_fini(struct prestera_switch *sw)

napi_disable(&sdma->rx_napi);
netif_napi_del(&sdma->rx_napi);
free_netdev(sdma->napi_dev);
prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_RXTX,
prestera_rxtx_handle_event);
prestera_sdma_tx_fini(sdma);
Expand Down
17 changes: 13 additions & 4 deletions drivers/net/ethernet/mediatek/mtk_eth_soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1710,7 +1710,7 @@ static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth,
if (IS_ERR(pp))
return pp;

err = __xdp_rxq_info_reg(xdp_q, &eth->dummy_dev, id,
err = __xdp_rxq_info_reg(xdp_q, eth->dummy_dev, id,
eth->rx_napi.napi_id, PAGE_SIZE);
if (err < 0)
goto err_free_pp;
Expand Down Expand Up @@ -4188,6 +4188,8 @@ static int mtk_free_dev(struct mtk_eth *eth)
metadata_dst_free(eth->dsa_meta[i]);
}

free_netdev(eth->dummy_dev);

return 0;
}

Expand Down Expand Up @@ -4983,16 +4985,23 @@ static int mtk_probe(struct platform_device *pdev)
/* we run 2 devices on the same DMA ring so we need a dummy device
* for NAPI to work
*/
init_dummy_netdev(&eth->dummy_dev);
netif_napi_add(&eth->dummy_dev, &eth->tx_napi, mtk_napi_tx);
netif_napi_add(&eth->dummy_dev, &eth->rx_napi, mtk_napi_rx);
eth->dummy_dev = alloc_netdev_dummy(0);
if (!eth->dummy_dev) {
err = -ENOMEM;
dev_err(eth->dev, "failed to allocated dummy device\n");
goto err_unreg_netdev;
}
netif_napi_add(eth->dummy_dev, &eth->tx_napi, mtk_napi_tx);
netif_napi_add(eth->dummy_dev, &eth->rx_napi, mtk_napi_rx);

platform_set_drvdata(pdev, eth);
schedule_delayed_work(&eth->reset.monitor_work,
MTK_DMA_MONITOR_TIMEOUT);

return 0;

err_unreg_netdev:
mtk_unreg_dev(eth);
err_deinit_ppe:
mtk_ppe_deinit(eth);
mtk_mdio_cleanup(eth);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mediatek/mtk_eth_soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,7 @@ struct mtk_eth {
spinlock_t page_lock;
spinlock_t tx_irq_lock;
spinlock_t rx_irq_lock;
struct net_device dummy_dev;
struct net_device *dummy_dev;
struct net_device *netdev[MTK_MAX_DEVS];
struct mtk_mac *mac[MTK_MAX_DEVS];
int irq[3];
Expand Down
12 changes: 8 additions & 4 deletions drivers/net/ipa/gsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1728,10 +1728,10 @@ static int gsi_channel_setup_one(struct gsi *gsi, u32 channel_id)
gsi_channel_program(channel, true);

if (channel->toward_ipa)
netif_napi_add_tx(&gsi->dummy_dev, &channel->napi,
netif_napi_add_tx(gsi->dummy_dev, &channel->napi,
gsi_channel_poll);
else
netif_napi_add(&gsi->dummy_dev, &channel->napi,
netif_napi_add(gsi->dummy_dev, &channel->napi,
gsi_channel_poll);

return 0;
Expand Down Expand Up @@ -2367,12 +2367,14 @@ int gsi_init(struct gsi *gsi, struct platform_device *pdev,
/* GSI uses NAPI on all channels. Create a dummy network device
* for the channel NAPI contexts to be associated with.
*/
init_dummy_netdev(&gsi->dummy_dev);
gsi->dummy_dev = alloc_netdev_dummy(0);
if (!gsi->dummy_dev)
return -ENOMEM;
init_completion(&gsi->completion);

ret = gsi_reg_init(gsi, pdev);
if (ret)
return ret;
goto err_reg_exit;

ret = gsi_irq_init(gsi, pdev); /* No matching exit required */
if (ret)
Expand All @@ -2387,6 +2389,7 @@ int gsi_init(struct gsi *gsi, struct platform_device *pdev,
return 0;

err_reg_exit:
free_netdev(gsi->dummy_dev);
gsi_reg_exit(gsi);

return ret;
Expand All @@ -2397,6 +2400,7 @@ void gsi_exit(struct gsi *gsi)
{
mutex_destroy(&gsi->mutex);
gsi_channel_exit(gsi);
free_netdev(gsi->dummy_dev);
gsi_reg_exit(gsi);
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ipa/gsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ struct gsi {
struct mutex mutex; /* protects commands, programming */
struct gsi_channel channel[GSI_CHANNEL_COUNT_MAX];
struct gsi_evt_ring evt_ring[GSI_EVT_RING_COUNT_MAX];
struct net_device dummy_dev; /* needed for NAPI */
struct net_device *dummy_dev; /* needed for NAPI */
};

/**
Expand Down
9 changes: 7 additions & 2 deletions drivers/net/wireless/ath/ath10k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3673,11 +3673,13 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
INIT_WORK(&ar->set_coverage_class_work,
ath10k_core_set_coverage_class_work);

init_dummy_netdev(&ar->napi_dev);
ar->napi_dev = alloc_netdev_dummy(0);
if (!ar->napi_dev)
goto err_free_tx_complete;

ret = ath10k_coredump_create(ar);
if (ret)
goto err_free_tx_complete;
goto err_free_netdev;

ret = ath10k_debug_create(ar);
if (ret)
Expand All @@ -3687,6 +3689,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,

err_free_coredump:
ath10k_coredump_destroy(ar);
err_free_netdev:
free_netdev(ar->napi_dev);
err_free_tx_complete:
destroy_workqueue(ar->workqueue_tx_complete);
err_free_aux_wq:
Expand All @@ -3708,6 +3712,7 @@ void ath10k_core_destroy(struct ath10k *ar)

destroy_workqueue(ar->workqueue_tx_complete);

free_netdev(ar->napi_dev);
ath10k_debug_destroy(ar);
ath10k_coredump_destroy(ar);
ath10k_htt_tx_destroy(&ar->htt);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath10k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,7 @@ struct ath10k {
struct ath10k_per_peer_tx_stats peer_tx_stats;

/* NAPI */
struct net_device napi_dev;
struct net_device *napi_dev;
struct napi_struct napi;

struct work_struct set_coverage_class_work;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath10k/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -3217,7 +3217,7 @@ static void ath10k_pci_free_irq(struct ath10k *ar)

void ath10k_pci_init_napi(struct ath10k *ar)
{
netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_pci_napi_poll);
netif_napi_add(ar->napi_dev, &ar->napi, ath10k_pci_napi_poll);
}

static int ath10k_pci_init_irq(struct ath10k *ar)
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath10k/sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2532,7 +2532,7 @@ static int ath10k_sdio_probe(struct sdio_func *func,
return -ENOMEM;
}

netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_sdio_napi_poll);
netif_napi_add(ar->napi_dev, &ar->napi, ath10k_sdio_napi_poll);

ath10k_dbg(ar, ATH10K_DBG_BOOT,
"sdio new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/ath10k/snoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ static int ath10k_snoc_hif_start(struct ath10k *ar)

bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX);

dev_set_threaded(&ar->napi_dev, true);
dev_set_threaded(ar->napi_dev, true);
ath10k_core_napi_enable(ar);
ath10k_snoc_irq_enable(ar);
ath10k_snoc_rx_post(ar);
Expand Down Expand Up @@ -1253,7 +1253,7 @@ static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget)

static void ath10k_snoc_init_napi(struct ath10k *ar)
{
netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_snoc_napi_poll);
netif_napi_add(ar->napi_dev, &ar->napi, ath10k_snoc_napi_poll);
}

static int ath10k_snoc_request_irq(struct ath10k *ar)
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath10k/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,7 @@ static int ath10k_usb_probe(struct usb_interface *interface,
return -ENOMEM;
}

netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_usb_napi_poll);
netif_napi_add(ar->napi_dev, &ar->napi, ath10k_usb_napi_poll);

usb_get_dev(dev);
vendor_id = le16_to_cpu(dev->descriptor.idVendor);
Expand Down
9 changes: 7 additions & 2 deletions drivers/net/wireless/ath/ath11k/ahb.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);

netif_napi_del(&irq_grp->napi);
free_netdev(irq_grp->napi_ndev);
}
}

Expand Down Expand Up @@ -533,8 +534,12 @@ static int ath11k_ahb_config_ext_irq(struct ath11k_base *ab)

irq_grp->ab = ab;
irq_grp->grp_id = i;
init_dummy_netdev(&irq_grp->napi_ndev);
netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,

irq_grp->napi_ndev = alloc_netdev_dummy(0);
if (!irq_grp->napi_ndev)
return -ENOMEM;

netif_napi_add(irq_grp->napi_ndev, &irq_grp->napi,
ath11k_ahb_ext_grp_napi_poll);

for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/ath11k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ struct ath11k_ext_irq_grp {
u64 timestamp;
bool napi_enabled;
struct napi_struct napi;
struct net_device napi_ndev;
struct net_device *napi_ndev;
};

enum ath11k_smbios_cc_type {
Expand Down
21 changes: 17 additions & 4 deletions drivers/net/wireless/ath/ath11k/pcic.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ static void ath11k_pcic_free_ext_irq(struct ath11k_base *ab)
free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);

netif_napi_del(&irq_grp->napi);
free_netdev(irq_grp->napi_ndev);
}
}

Expand Down Expand Up @@ -558,7 +559,7 @@ ath11k_pcic_get_msi_irq(struct ath11k_base *ab, unsigned int vector)

static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab)
{
int i, j, ret, num_vectors = 0;
int i, j, n, ret, num_vectors = 0;
u32 user_base_data = 0, base_vector = 0;
unsigned long irq_flags;

Expand All @@ -578,8 +579,11 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab)

irq_grp->ab = ab;
irq_grp->grp_id = i;
init_dummy_netdev(&irq_grp->napi_ndev);
netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
irq_grp->napi_ndev = alloc_netdev_dummy(0);
if (!irq_grp->napi_ndev)
return -ENOMEM;

netif_napi_add(irq_grp->napi_ndev, &irq_grp->napi,
ath11k_pcic_ext_grp_napi_poll);

if (ab->hw_params.ring_mask->tx[i] ||
Expand All @@ -601,8 +605,13 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab)
int vector = (i % num_vectors) + base_vector;
int irq = ath11k_pcic_get_msi_irq(ab, vector);

if (irq < 0)
if (irq < 0) {
for (n = 0; n <= i; n++) {
irq_grp = &ab->ext_irq_grp[n];
free_netdev(irq_grp->napi_ndev);
}
return irq;
}

ab->irq_num[irq_idx] = irq;

Expand All @@ -615,6 +624,10 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab)
if (ret) {
ath11k_err(ab, "failed request irq %d: %d\n",
vector, ret);
for (n = 0; n <= i; n++) {
irq_grp = &ab->ext_irq_grp[n];
free_netdev(irq_grp->napi_ndev);
}
return ret;
}
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto error;
}

bus->mux_dev = alloc_netdev(0, "dummy", NET_NAME_UNKNOWN,
init_dummy_netdev);
bus->mux_dev = alloc_netdev_dummy(0);
if (!bus->mux_dev) {
ret = -ENOMEM;
goto error;
Expand Down
3 changes: 3 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -4519,6 +4519,9 @@ static inline void netif_addr_unlock_bh(struct net_device *dev)

void ether_setup(struct net_device *dev);

/* Allocate dummy net_device */
struct net_device *alloc_netdev_dummy(int sizeof_priv);

/* Support for loadable net-drivers */
struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
unsigned char name_assign_type,
Expand Down
Loading

0 comments on commit a2d2cad

Please sign in to comment.