[PATCH] ath10k: allocate dummy net_device dynamically

2024-03-19 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath10k by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath10k_core_create(). The free of the device occurs
at ath10k_core_destroy().

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/ath/ath10k/core.c | 10 --
 drivers/net/wireless/ath/ath10k/core.h |  2 +-
 drivers/net/wireless/ath/ath10k/pci.c  |  2 +-
 drivers/net/wireless/ath/ath10k/sdio.c |  2 +-
 drivers/net/wireless/ath/ath10k/snoc.c |  4 ++--
 drivers/net/wireless/ath/ath10k/usb.c  |  2 +-
 6 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 9ce6f49ab261..3736517002f6 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -3673,11 +3673,14 @@ 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(0, "dummy", NET_NAME_UNKNOWN,
+   init_dummy_netdev);
+   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)
@@ -3687,6 +3690,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:
@@ -3708,6 +3713,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);
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index c110d15528bd..26003b519574 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -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;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c 
b/drivers/net/wireless/ath/ath10k/pci.c
index 5c34b156b4ff..558bec96ae40 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 0ab5433f6cf6..e28f2fe1101b 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -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",
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c 
b/drivers/net/wireless/ath/ath10k/snoc.c
index 2c39bad7ebfb..0449b9ffc32d 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -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);
@@ -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)
diff --git a/d

Re: [PATCH] ath10k: allocate dummy net_device dynamically

2024-03-19 Thread Breno Leitao
On Tue, Mar 19, 2024 at 09:05:24AM -0700, Jeff Johnson wrote:
> On 3/19/2024 3:47 AM, Breno Leitao wrote:
> > @@ -3687,6 +3690,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:
> > @@ -3708,6 +3713,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);
> 
> looks like there is a pre-existing issue that the order of operations in
> _destroy() doesn't match the order of operations in the _create() error path.

Right. I found it weird as well. Basically "ath10k_coredump" and
"ath10k_debug" operations are swapped between ath10k_core_create() and
ath10k_core_destroy().

If you wish, I can submit a patch ordering it properly.

> but the placement of your changes looks ok to me

Right. It is done in-between the workqueues and the coredump/debug
creation/destroy.

Thanks for the review.



Re: [PATCH] ath10k: allocate dummy net_device dynamically

2024-03-20 Thread Breno Leitao
On Wed, Mar 20, 2024 at 05:25:52PM +0200, Kalle Valo wrote:
> Jeff Johnson  writes:
> 
> > On 3/19/2024 3:47 AM, Breno Leitao wrote:
> >> Embedding net_device into structures prohibits the usage of flexible
> >> arrays in the net_device structure. For more details, see the discussion
> >> at [1].
> >> 
> >> Un-embed the net_device from struct ath10k by converting it
> >> into a pointer. Then use the leverage alloc_netdev() to allocate the
> >> net_device object at ath10k_core_create(). The free of the device occurs
> >> at ath10k_core_destroy().
> >> 
> >> [1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/
> >> 
> >> Signed-off-by: Breno Leitao 
> >
> > NAK this based upon the ath11k patch results.
> >
> > As suggested there we should just use kmalloc/kfree to match the existing 
> > logic.
> 
> BTW if the patch is not tested on a real device then it's good to
> document that in the commit message with "Compile tested only" or
> similar.

Good to know. Thanks. I will add it to the next patches.



Re: [PATCH] ath10k: allocate dummy net_device dynamically

2024-03-22 Thread Breno Leitao
Hello Jakub,

On Thu, Mar 21, 2024 at 03:17:44PM -0700, Jakub Kicinski wrote:
> On Thu, 21 Mar 2024 15:02:39 -0700 Jeff Johnson wrote:
> > >> As suggested there we should just use kmalloc/kfree to match the 
> > >> existing logic.  
> > > 
> > > Please no. There is no magic here. alloc + free must match whether
> > > you're using magic object alloc wrapper (alloc_netdev()) or straight
> > > up kzalloc().  
> > 
> > Based upon the ath11k patch there must be something going on with
> > alloc_netdev()/free_netdev() that doesn't occur when these aren't used.
> 
> Looks like init_dummy_netdev wipes the netdev structure clean, so I
> don't think we can use it directly as the setup function, Breno :(

Before my patch,  init_dummy_netdev was being also used. The patch was
basically replacing the init_dummy_netdev by alloc_netdev() with will
call "setup(dev);" later. 

-   init_dummy_netdev(&irq_grp->napi_ndev);
+   irq_grp->napi_ndev = alloc_netdev(0, "dummy", NET_NAME_UNKNOWN,
+ init_dummy_netdev);

I am wondering if alloc_netdev() is messing with something instead of
init_dummy_netdev().

Also, Kalle's crash is during rmmod, and not during initialization.
getting NULL after free_netdev() is called.

> Maybe we should add a new helper to "alloc dummy netdev" which can
> call alloc_netdev() with right arguments and do necessary init?

What are the right arguments in this case?

Thanks!



Re: [PATCH] ath10k: allocate dummy net_device dynamically

2024-03-27 Thread Breno Leitao
Hello Jakub,

On Fri, Mar 22, 2024 at 08:23:36AM -0700, Jakub Kicinski wrote:
> > > Maybe we should add a new helper to "alloc dummy netdev" which can
> > > call alloc_netdev() with right arguments and do necessary init?  
> > 
> > What are the right arguments in this case?
> 
> I'm not sure we have a noop setup() callback today. If you define a
> wrapper to allocate a dummy netdev you can define a new empty function
> next to it and pass that as init? Hope I got the question right.

Thanks for the explanation, it is clear now. I've been working on it,
and this is what I came up with. This is compile-tested by now, and, if
this is what you had in mind, I will do more extensive testing.

  commit db794d99950f68731884a67d911094d94179c522
  Author: Breno Leitao 
  Date:   Wed Mar 27 07:20:03 2024 -0700
  
  net: Create net_device allocator for dummy
  
  Create a helper to allocate and initialize dummy netdevices. This
  function basically simplify the allocation of dummy devices, by
  allocating and initializing it.
  
  Suggested-by: Jakub Kicinski 
  Signed-off-by: Breno Leitao 
  
  diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
  index 643d2b469c49..9d1a5383c23f 100644
  --- a/include/linux/netdevice.h
  +++ b/include/linux/netdevice.h
  @@ -4546,6 +4546,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, const char *name);
  +
   /* Support for loadable net-drivers */
   struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
unsigned char name_assign_type,
  diff --git a/net/core/dev.c b/net/core/dev.c
  index a08d698fe45c..628f35c3cfa2 100644
  --- a/net/core/dev.c
  +++ b/net/core/dev.c
  @@ -10998,6 +10998,13 @@ void free_netdev(struct net_device *dev)
   }
   EXPORT_SYMBOL(free_netdev);
   
  +struct net_device *alloc_netdev_dummy(int sizeof_priv, const char *name)
  +{
  + return alloc_netdev(sizeof_priv, name, NET_NAME_UNKNOWN,
  + init_dummy_netdev_core);
  +}
  +EXPORT_SYMBOL_GPL(alloc_netdev_dummy);
  +
   /**
*   synchronize_net -  Synchronize with packet receive processing
*
  
  commit 35500cd6a5db0bbdedbc1067758948769c7ce57e
  Author: Breno Leitao 
  Date:   Wed Mar 27 07:07:40 2024 -0700
  
  net: Split init_dummy_netdev
  
  It is impossible to use init_dummy_netdev together with alloc_netdev()
  as the 'setup' argument.
  
  This is because alloc_netdev() initializes some fields in the net_device
  structure, and later init_dummy_netdev() memzero them all. This casues
  some problems as reported here:
  
  https://lore.kernel.org/all/20240322082336.49f11...@kernel.org/
  
  Split the function in two. Create a new function called
  init_dummy_netdev_core() that does not memset the net_device structure.
  Then have init_dummy_netdev() memseting and calling
  init_dummy_netdev_core().
  
  init_dummy_netdev_core() will be the function that could be called as
  an argument for alloc_netdev().
  
  Signed-off-by: Breno Leitao 
  
  diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
  index c6f6ac779b34..643d2b469c49 100644
  --- a/include/linux/netdevice.h
  +++ b/include/linux/netdevice.h
  @@ -3119,6 +3119,7 @@ int netdev_refcnt_read(const struct net_device *dev);
   void free_netdev(struct net_device *dev);
   void netdev_freemem(struct net_device *dev);
   void init_dummy_netdev(struct net_device *dev);
  +void init_dummy_netdev_core(struct net_device *dev);
   
   struct net_device *netdev_get_xmit_slave(struct net_device *dev,
 struct sk_buff *skb,
  diff --git a/net/core/dev.c b/net/core/dev.c
  index 0766a245816b..a08d698fe45c 100644
  --- a/net/core/dev.c
  +++ b/net/core/dev.c
  @@ -10340,25 +10340,11 @@ int register_netdevice(struct net_device *dev)
   }
   EXPORT_SYMBOL(register_netdevice);
   
  -/**
  - *   init_dummy_netdev   - init a dummy network device for NAPI
  - *   @dev: device to init
  - *
  - *   This takes a network device structure and initialize the minimum
  - *   amount of fields so it can be used to schedule NAPI polls without
  - *   registering a full blown interface. This is to be used by drivers
  - *   that need to tie several hardware interfaces to a single NAPI
  - *   poll scheduler due to HW limitations.
  +/* Same as init_dummy_netdev, but, basically do not call memset.
  + * This is useful if you are calling this function after alloc_netdev()
*/
  -void init_dummy_netdev(struct net_device *dev)
  +void init_dummy_netdev_core(struct net_device *dev)
   {
  - /* Clear everything. Note we don't initialize spinlocks
  -  

[PATCH 1/3] wifi: qtnfmac: Use netdev dummy allocator helper

2024-04-05 Thread Breno Leitao
There is a new dummy netdev allocator, use it instead of
alloc_netdev()/init_dummy_netdev combination.

Using alloc_netdev() with init_dummy_netdev might cause some memory
corruption at the driver removal side.

Fixes: 61cdb09ff760 ("wifi: qtnfmac: allocate dummy net_device dynamically")
Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index f8f55db2f454..f66eb43094d4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -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;
-- 
2.43.0




[PATCH 0/3] wifi: Un-embed ath10k and ath11k dummy netdev

2024-04-05 Thread Breno Leitao
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.

This patch set fixes the problem above for ath10k and ath11k. This also
fixes the conversion of qtnfmac driver to the new helper.

This patch set depends on a series that is still under review:
https://lore.kernel.org/all/20240404114854.2498663-1-lei...@debian.org/#t

If it helps, I've pushed the tree to
https://github.com/leitao/linux/tree/wireless-dummy

PS: Due to lack of hardware, unfortunately all these patches are
compiled tested only.

Breno Leitao (3):
  wifi: qtnfmac: Use netdev dummy allocator helper
  wifi: ath10k: allocate dummy net_device dynamically
  wifi: ath11k: allocate dummy net_device dynamically

 drivers/net/wireless/ath/ath10k/core.c|  9 ++--
 drivers/net/wireless/ath/ath10k/core.h|  2 +-
 drivers/net/wireless/ath/ath10k/pci.c |  2 +-
 drivers/net/wireless/ath/ath10k/sdio.c|  2 +-
 drivers/net/wireless/ath/ath10k/snoc.c|  4 ++--
 drivers/net/wireless/ath/ath10k/usb.c |  2 +-
 drivers/net/wireless/ath/ath11k/ahb.c |  9 ++--
 drivers/net/wireless/ath/ath11k/core.h|  2 +-
 drivers/net/wireless/ath/ath11k/pcic.c| 21 +++
 .../wireless/quantenna/qtnfmac/pcie/pcie.c|  3 +--
 10 files changed, 39 insertions(+), 17 deletions(-)

-- 
2.43.0




[PATCH 2/3] wifi: ath10k: allocate dummy net_device dynamically

2024-04-05 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath10k by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath10k_core_create(). The free of the device occurs
at ath10k_core_destroy().

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/ath/ath10k/core.c | 9 +++--
 drivers/net/wireless/ath/ath10k/core.h | 2 +-
 drivers/net/wireless/ath/ath10k/pci.c  | 2 +-
 drivers/net/wireless/ath/ath10k/sdio.c | 2 +-
 drivers/net/wireless/ath/ath10k/snoc.c | 4 ++--
 drivers/net/wireless/ath/ath10k/usb.c  | 2 +-
 6 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 9ce6f49ab261..8663822e0b8d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -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)
@@ -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:
@@ -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);
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index c110d15528bd..26003b519574 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -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;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c 
b/drivers/net/wireless/ath/ath10k/pci.c
index 5c34b156b4ff..558bec96ae40 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 0ab5433f6cf6..e28f2fe1101b 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -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",
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c 
b/drivers/net/wireless/ath/ath10k/snoc.c
index 2c39bad7ebfb..0449b9ffc32d 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -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);
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/usb.c 
b/drivers/net/wireless/ath/ath10k/usb.c
index 3c482b

[PATCH 3/3] wifi: ath11k: allocate dummy net_device dynamically

2024-04-05 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath11k_ext_irq_grp by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath11k_ahb_config_ext_irq() for ahb, and
ath11k_pcic_ext_irq_config() for pcic.

The free of the device occurs at ath11k_ahb_free_ext_irq() for the ahb
case, and ath11k_pcic_free_ext_irq() for the pcic case.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/ath/ath11k/ahb.c  |  9 +++--
 drivers/net/wireless/ath/ath11k/core.h |  2 +-
 drivers/net/wireless/ath/ath11k/pcic.c | 21 +
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/ahb.c 
b/drivers/net/wireless/ath/ath11k/ahb.c
index 7c0a23517949..7f3f6479d553 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -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);
}
 }
 
@@ -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++) {
diff --git a/drivers/net/wireless/ath/ath11k/core.h 
b/drivers/net/wireless/ath/ath11k/core.h
index b3fb74a226fb..590307ca7a11 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -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 {
diff --git a/drivers/net/wireless/ath/ath11k/pcic.c 
b/drivers/net/wireless/ath/ath11k/pcic.c
index add4db4c50bc..79eb3f9c902f 100644
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
@@ -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);
}
 }
 
@@ -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;
 
@@ -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] ||
@@ -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;
 
@@ -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 = 

Re: [PATCH 0/3] wifi: Un-embed ath10k and ath11k dummy netdev

2024-04-08 Thread Breno Leitao
Hello Kalle,

On Fri, Apr 05, 2024 at 06:15:05PM +0300, Kalle Valo wrote:
> Breno Leitao  writes:
> 
> > 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.
> >
> > This patch set fixes the problem above for ath10k and ath11k. This also
> > fixes the conversion of qtnfmac driver to the new helper.
> >
> > This patch set depends on a series that is still under review:
> > https://lore.kernel.org/all/20240404114854.2498663-1-lei...@debian.org/#t
> >
> > If it helps, I've pushed the tree to
> > https://github.com/leitao/linux/tree/wireless-dummy
> >
> > PS: Due to lack of hardware, unfortunately all these patches are
> > compiled tested only.
> >
> > Breno Leitao (3):
> >   wifi: qtnfmac: Use netdev dummy allocator helper
> >   wifi: ath10k: allocate dummy net_device dynamically
> >   wifi: ath11k: allocate dummy net_device dynamically
> 
> Thanks for setting up the branch, that makes the testing very easy. I
> now tested the branch using the commit below with ath11k WCN6855 hw2.0
> on an x86 box:
> 
> 5be9a125d8e7 wifi: ath11k: allocate dummy net_device dynamically
> 
> But unfortunately it crashes, the stack trace below. I can easily test
> your branches, just let me know what to test. A direct 'git pull'
> command is the best.

Thanks for the test.

Reading the issue, I am afraid that freeing netdev explicitly
(free_netdev()) might not be the best approach at the exit path.

I would like to try to leverage the ->needs_free_netdev netdev
mechanism to do the clean-up, if that makes sense. I've updated the
ath11k patch, and I am curious if that is what we want.

Would you mind testing a net patch I have, please?

  https://github.com/leitao/linux/tree/wireless-dummy_v2

PS: I didn't updated the other drivers (ath10k, qtnfmac, etc).

Thank you!



Re: [PATCH 0/3] wifi: Un-embed ath10k and ath11k dummy netdev

2024-04-08 Thread Breno Leitao
On Mon, Apr 08, 2024 at 07:43:42PM +0300, Kalle Valo wrote:
> Breno Leitao  writes:
> > On Fri, Apr 05, 2024 at 06:15:05PM +0300, Kalle Valo wrote:
> >> Breno Leitao  writes:
> >> 
> >> > 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.
> >> >
> >> > This patch set fixes the problem above for ath10k and ath11k. This also
> >> > fixes the conversion of qtnfmac driver to the new helper.
> >> >
> >> > This patch set depends on a series that is still under review:
> >> > https://lore.kernel.org/all/20240404114854.2498663-1-lei...@debian.org/#t
> >> >
> >> > If it helps, I've pushed the tree to
> >> > https://github.com/leitao/linux/tree/wireless-dummy
> >> >
> >> > PS: Due to lack of hardware, unfortunately all these patches are
> >> > compiled tested only.
> >> >
> >> > Breno Leitao (3):
> >> >   wifi: qtnfmac: Use netdev dummy allocator helper
> >> >   wifi: ath10k: allocate dummy net_device dynamically
> >> >   wifi: ath11k: allocate dummy net_device dynamically
> >> 
> >> Thanks for setting up the branch, that makes the testing very easy. I
> >> now tested the branch using the commit below with ath11k WCN6855 hw2.0
> >> on an x86 box:
> >> 
> >> 5be9a125d8e7 wifi: ath11k: allocate dummy net_device dynamically
> >> 
> >> But unfortunately it crashes, the stack trace below. I can easily test
> >> your branches, just let me know what to test. A direct 'git pull'
> >> command is the best.
> >
> > Thanks for the test.
> >
> > Reading the issue, I am afraid that freeing netdev explicitly
> > (free_netdev()) might not be the best approach at the exit path.
> >
> > I would like to try to leverage the ->needs_free_netdev netdev
> > mechanism to do the clean-up, if that makes sense. I've updated the
> > ath11k patch, and I am curious if that is what we want.
> >
> > Would you mind testing a net patch I have, please?
> >
> >   https://github.com/leitao/linux/tree/wireless-dummy_v2
> 
> I tested this again with my WCN6855 hw2.0 x86 test box on this commit:
> 
> a87674ac820e wifi: ath11k: allocate dummy net_device dynamically
> 
> It passes my tests and doesn't crash, but I see this kmemleak warning a
> lot:

Thanks Kalle, that was helpful. The device is not being clean-up
automatically.

Chatting with Jakub, he suggested coming back to the original approach,
but, adding a additional patch, at the free_netdev().

Would you mind running another test, please?

https://github.com/leitao/linux/tree/wireless-dummy_v3

The branch above is basically the original branch (as in this patch
series), with this additional patch:

Author: Breno Leitao 
Date:   Mon Apr 8 11:37:32 2024 -0700

net: free_netdev: exit earlier if dummy

For dummy devices, exit earlier at free_netdev() instead of 
executing
the whole function. This is necessary, because dummy devices are
special, and shouldn't have the second part of the function 
executed.

Otherwise reg_state, which is NETREG_DUMMY, will be overwritten and
there will be no way to identify that this is a dummy device. Also, 
this
device do not need the final put_device(), since dummy devices are 
not
registered (through register_netdevice()), where the device 
reference is
increased (at netdev_register_kobject()/device_add()).

Suggested-by: Jakub Kicinski 
Signed-off-by: Breno Leitao 

diff --git a/net/core/dev.c b/net/core/dev.c
index 2b82bd1cd2f8..5d2cb97d0ae6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11058,7 +11058,8 @@ void free_netdev(struct net_device *dev)
dev->xdp_bulkq = NULL;

/*  Compatibility with error handling in drivers */
-   if (dev->reg_state == NETREG_UNINITIALIZED) {
+   if (dev->reg_state == NETREG_UNINITIALIZED ||
+   dev->reg_state == NETREG_DUMMY) {
netdev_freemem(dev);
return;
}



Re: [PATCH 0/3] wifi: Un-embed ath10k and ath11k dummy netdev

2024-04-09 Thread Breno Leitao
On Tue, Apr 09, 2024 at 01:03:21PM +0300, Kalle Valo wrote:
> Breno Leitao  writes:
> 
> >> > Reading the issue, I am afraid that freeing netdev explicitly
> >> > (free_netdev()) might not be the best approach at the exit path.
> >> >
> >> > I would like to try to leverage the ->needs_free_netdev netdev
> >> > mechanism to do the clean-up, if that makes sense. I've updated the
> >> > ath11k patch, and I am curious if that is what we want.
> >> >
> >> > Would you mind testing a net patch I have, please?
> >> >
> >> >   https://github.com/leitao/linux/tree/wireless-dummy_v2
> >> 
> >> I tested this again with my WCN6855 hw2.0 x86 test box on this commit:
> >> 
> >> a87674ac820e wifi: ath11k: allocate dummy net_device dynamically
> >> 
> >> It passes my tests and doesn't crash, but I see this kmemleak warning a
> >> lot:
> >
> > Thanks Kalle, that was helpful. The device is not being clean-up
> > automatically.
> >
> > Chatting with Jakub, he suggested coming back to the original approach,
> > but, adding a additional patch, at the free_netdev().
> >
> > Would you mind running another test, please?
> >
> > https://github.com/leitao/linux/tree/wireless-dummy_v3
> >
> > The branch above is basically the original branch (as in this patch
> > series), with this additional patch:
> >
> > Author: Breno Leitao 
> > Date:   Mon Apr 8 11:37:32 2024 -0700
> >
> > net: free_netdev: exit earlier if dummy
> 
> I tested with the same ath11k hardware and this one passes all my
> (simple) ath11k tests, no issues found. I used this commit:
> 
> 1c10aebaa8ce net: free_netdev: exit earlier if dummy

Thank you so much for the test.

I will respin a v2 of this patchset with the additional patch included.



[PATCH net-next v4 1/9] net: free_netdev: exit earlier if dummy

2024-04-09 Thread Breno Leitao
For dummy devices, exit earlier at free_netdev() instead of executing
the whole function. This is necessary, because dummy devices are
special, and shouldn't have the second part of the function executed.

Otherwise reg_state, which is NETREG_DUMMY for dummy devices, will be
overwritten and there will be no way to identify that this is a dummy
device. Also, this device do not need the final put_device(), since
dummy devices are not registered (through register_netdevice()), where
the device reference is increased (at netdev_register_kobject() ->
device_add()).

Suggested-by: Jakub Kicinski 
Signed-off-by: Breno Leitao 
---
 net/core/dev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 92f5bddbc2de..bf0a335781aa 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11051,7 +11051,8 @@ void free_netdev(struct net_device *dev)
dev->xdp_bulkq = NULL;
 
/*  Compatibility with error handling in drivers */
-   if (dev->reg_state == NETREG_UNINITIALIZED) {
+   if (dev->reg_state == NETREG_UNINITIALIZED ||
+   dev->reg_state == NETREG_DUMMY) {
netdev_freemem(dev);
return;
}
-- 
2.43.0




[PATCH net-next v4 3/9] net: marvell: prestera: allocate dummy net_device dynamically

2024-04-09 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
Acked-by: Elad Nachman 
---
 .../net/ethernet/marvell/prestera/prestera_rxtx.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c 
b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
index cc2a9ae794be..39d9bf82c115 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
@@ -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 */
@@ -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);
@@ -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);
-- 
2.43.0




[PATCH net-next v4 0/9] allocate dummy device dynamically

2024-04-09 Thread Breno Leitao
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:

v1:
* https://lore.kernel.org/all/20240327200809.512867-1-lei...@debian.org/

v2:
* Patch 1: Use a pre-defined name ("dummy#") for the dummy
  net_devices.
* Patch 2-5: Added users for the new helper.
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.
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.


Breno Leitao (9):
  net: free_netdev: exit earlier if dummy
  net: create a dummy net_device allocator
  net: marvell: prestera: allocate dummy net_device dynamically
  net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically
  net: ipa: allocate dummy net_device dynamically
  net: ibm/emac: allocate dummy net_device dynamically
  wifi: qtnfmac: Use netdev dummy allocator helper
  wifi: ath10k: allocate dummy net_device dynamically
  wifi: ath11k: allocate dummy net_device dynamically

 drivers/net/ethernet/ibm/emac/mal.c   | 14 -
 drivers/net/ethernet/ibm/emac/mal.h   |  2 +-
 .../ethernet/marvell/prestera/prestera_rxtx.c | 15 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 17 --
 drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  2 +-
 drivers/net/ipa/gsi.c | 12 ++--
 drivers/net/ipa/gsi.h |  2 +-
 drivers/net/wireless/ath/ath10k/core.c|  9 ++-
 drivers/net/wireless/ath/ath10k/core.h|  2 +-
 drivers/net/wireless/ath/ath10k/pci.c |  2 +-
 drivers/net/wireless/ath/ath10k/sdio.c|  2 +-
 drivers/net/wireless/ath/ath10k/snoc.c|  4 +-
 drivers/net/wireless/ath/ath10k/usb.c |  2 +-
 drivers/net/wireless/ath/ath11k/ahb.c |  9 ++-
 drivers/net/wireless/ath/ath11k/core.h|  2 +-
 drivers/net/wireless/ath/ath11k/pcic.c| 21 +--
 .../wireless/quantenna/qtnfmac/pcie/pcie.c|  3 +-
 include/linux/netdevice.h |  3 +
 net/core/dev.c| 57 ---
 19 files changed, 127 insertions(+), 53 deletions(-)

-- 
2.43.0




[PATCH net-next v4 2/9] net: create a dummy net_device allocator

2024-04-09 Thread Breno Leitao
It is impossible to use init_dummy_netdev together with alloc_netdev()
as the 'setup' argument.

This is because alloc_netdev() initializes some fields in the net_device
structure, and later init_dummy_netdev() memzero them all. This causes
some problems as reported here:

https://lore.kernel.org/all/20240322082336.49f11...@kernel.org/

Split the init_dummy_netdev() function in two. Create a new function called
init_dummy_netdev_core() that does not memzero the net_device structure.
Then have init_dummy_netdev() memzero-ing and calling
init_dummy_netdev_core(), keeping the old behaviour.

init_dummy_netdev_core() is the new function that could be called as an
argument for alloc_netdev().

Also, create a helper to allocate and initialize dummy net devices,
leveraging init_dummy_netdev_core() as the setup argument. This function
basically simplify the allocation of dummy devices, by allocating and
initializing it. Freeing the device continue to be done through
free_netdev()

Suggested-by: Jakub Kicinski 
Signed-off-by: Breno Leitao 
---
 include/linux/netdevice.h |  3 +++
 net/core/dev.c| 54 ++-
 2 files changed, 39 insertions(+), 18 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 0c198620ac93..544767d218c0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4517,6 +4517,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,
diff --git a/net/core/dev.c b/net/core/dev.c
index bf0a335781aa..5d2cb97d0ae6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10413,25 +10413,12 @@ int register_netdevice(struct net_device *dev)
 }
 EXPORT_SYMBOL(register_netdevice);
 
-/**
- * init_dummy_netdev   - init a dummy network device for NAPI
- * @dev: device to init
- *
- * This takes a network device structure and initialize the minimum
- * amount of fields so it can be used to schedule NAPI polls without
- * registering a full blown interface. This is to be used by drivers
- * that need to tie several hardware interfaces to a single NAPI
- * poll scheduler due to HW limitations.
+/* Initialize the core of a dummy net device.
+ * This is useful if you are calling this function after alloc_netdev(),
+ * since it does not memset the net_device fields.
  */
-void init_dummy_netdev(struct net_device *dev)
+static void init_dummy_netdev_core(struct net_device *dev)
 {
-   /* Clear everything. Note we don't initialize spinlocks
-* are they aren't supposed to be taken by any of the
-* NAPI code and this dummy netdev is supposed to be
-* only ever used for NAPI polls
-*/
-   memset(dev, 0, sizeof(struct net_device));
-
/* make sure we BUG if trying to hit standard
 * register/unregister code path
 */
@@ -10452,8 +10439,28 @@ void init_dummy_netdev(struct net_device *dev)
 * its refcount.
 */
 }
-EXPORT_SYMBOL_GPL(init_dummy_netdev);
 
+/**
+ * init_dummy_netdev   - init a dummy network device for NAPI
+ * @dev: device to init
+ *
+ * This takes a network device structure and initialize the minimum
+ * amount of fields so it can be used to schedule NAPI polls without
+ * registering a full blown interface. This is to be used by drivers
+ * that need to tie several hardware interfaces to a single NAPI
+ * poll scheduler due to HW limitations.
+ */
+void init_dummy_netdev(struct net_device *dev)
+{
+   /* Clear everything. Note we don't initialize spinlocks
+* are they aren't supposed to be taken by any of the
+* NAPI code and this dummy netdev is supposed to be
+* only ever used for NAPI polls
+*/
+   memset(dev, 0, sizeof(struct net_device));
+   init_dummy_netdev_core(dev);
+}
+EXPORT_SYMBOL_GPL(init_dummy_netdev);
 
 /**
  * register_netdev - register a network device
@@ -11065,6 +11072,17 @@ void free_netdev(struct net_device *dev)
 }
 EXPORT_SYMBOL(free_netdev);
 
+/**
+ * alloc_netdev_dummy - Allocate and initialize a dummy net device.
+ * @sizeof_priv: size of private data to allocate space for
+ */
+struct net_device *alloc_netdev_dummy(int sizeof_priv)
+{
+   return alloc_netdev(sizeof_priv, "dummy#", NET_NAME_UNKNOWN,
+   init_dummy_netdev_core);
+}
+EXPORT_SYMBOL_GPL(alloc_netdev_dummy);
+
 /**
  * synchronize_net -  Synchronize with packet receive processing
  *
-- 
2.43.0




[PATCH net-next v4 4/9] net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically

2024-04-09 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 17 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  2 +-
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index caa13b9cedff..d7a96dc11c07 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -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, ð->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;
@@ -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;
 }
 
@@ -4983,9 +4985,14 @@ 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(ð->dummy_dev);
-   netif_napi_add(ð->dummy_dev, ð->tx_napi, mtk_napi_tx);
-   netif_napi_add(ð->dummy_dev, ð->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, ð->tx_napi, mtk_napi_tx);
+   netif_napi_add(eth->dummy_dev, ð->rx_napi, mtk_napi_rx);
 
platform_set_drvdata(pdev, eth);
schedule_delayed_work(ð->reset.monitor_work,
@@ -4993,6 +5000,8 @@ static int mtk_probe(struct platform_device *pdev)
 
return 0;
 
+err_unreg_netdev:
+   mtk_unreg_dev(eth);
 err_deinit_ppe:
mtk_ppe_deinit(eth);
mtk_mdio_cleanup(eth);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 9ae3b8a71d0e..723fc637027c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -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];
-- 
2.43.0




[PATCH net-next v4 5/9] net: ipa: allocate dummy net_device dynamically

2024-04-09 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ipa/gsi.c | 12 
 drivers/net/ipa/gsi.h |  2 +-
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c
index 9a0b1fe4a93a..d70be15e95a6 100644
--- a/drivers/net/ipa/gsi.c
+++ b/drivers/net/ipa/gsi.c
@@ -1730,10 +1730,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;
@@ -2369,12 +2369,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)
@@ -2389,6 +2391,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;
@@ -2399,6 +2402,7 @@ void gsi_exit(struct gsi *gsi)
 {
mutex_destroy(&gsi->mutex);
gsi_channel_exit(gsi);
+   free_netdev(gsi->dummy_dev);
gsi_reg_exit(gsi);
 }
 
diff --git a/drivers/net/ipa/gsi.h b/drivers/net/ipa/gsi.h
index 42063b227c18..6b7ec2a39676 100644
--- a/drivers/net/ipa/gsi.h
+++ b/drivers/net/ipa/gsi.h
@@ -155,7 +155,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 */
 };
 
 /**
-- 
2.43.0




[PATCH net-next v4 9/9] wifi: ath11k: allocate dummy net_device dynamically

2024-04-09 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath11k_ext_irq_grp by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath11k_ahb_config_ext_irq() for ahb, and
ath11k_pcic_ext_irq_config() for pcic.

The free of the device occurs at ath11k_ahb_free_ext_irq() for the ahb
case, and ath11k_pcic_free_ext_irq() for the pcic case.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
Tested-by: Kalle Valo 
---
 drivers/net/wireless/ath/ath11k/ahb.c  |  9 +++--
 drivers/net/wireless/ath/ath11k/core.h |  2 +-
 drivers/net/wireless/ath/ath11k/pcic.c | 21 +
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/ahb.c 
b/drivers/net/wireless/ath/ath11k/ahb.c
index 7c0a23517949..7f3f6479d553 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -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);
}
 }
 
@@ -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++) {
diff --git a/drivers/net/wireless/ath/ath11k/core.h 
b/drivers/net/wireless/ath/ath11k/core.h
index b3fb74a226fb..590307ca7a11 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -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 {
diff --git a/drivers/net/wireless/ath/ath11k/pcic.c 
b/drivers/net/wireless/ath/ath11k/pcic.c
index add4db4c50bc..79eb3f9c902f 100644
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
@@ -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);
}
 }
 
@@ -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;
 
@@ -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] ||
@@ -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;
 
@@ -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 = 

[PATCH net-next v4 8/9] wifi: ath10k: allocate dummy net_device dynamically

2024-04-09 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath10k by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath10k_core_create(). The free of the device occurs
at ath10k_core_destroy().

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/ath/ath10k/core.c | 9 +++--
 drivers/net/wireless/ath/ath10k/core.h | 2 +-
 drivers/net/wireless/ath/ath10k/pci.c  | 2 +-
 drivers/net/wireless/ath/ath10k/sdio.c | 2 +-
 drivers/net/wireless/ath/ath10k/snoc.c | 4 ++--
 drivers/net/wireless/ath/ath10k/usb.c  | 2 +-
 6 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 9ce6f49ab261..8663822e0b8d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -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)
@@ -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:
@@ -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);
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index c110d15528bd..26003b519574 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -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;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c 
b/drivers/net/wireless/ath/ath10k/pci.c
index 5c34b156b4ff..558bec96ae40 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 0ab5433f6cf6..e28f2fe1101b 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -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",
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c 
b/drivers/net/wireless/ath/ath10k/snoc.c
index 2c39bad7ebfb..0449b9ffc32d 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -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);
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/usb.c 
b/drivers/net/wireless/ath/ath10k/usb.c
index 3c482b

[PATCH net-next v4 7/9] wifi: qtnfmac: Use netdev dummy allocator helper

2024-04-09 Thread Breno Leitao
There is a new dummy netdev allocator, use it instead of
alloc_netdev()/init_dummy_netdev combination.

Using alloc_netdev() with init_dummy_netdev might cause some memory
corruption at the driver removal side.

Fixes: 61cdb09ff760 ("wifi: qtnfmac: allocate dummy net_device dynamically")
Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index f8f55db2f454..f66eb43094d4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -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;
-- 
2.43.0




[PATCH net-next v4 6/9] net: ibm/emac: allocate dummy net_device dynamically

2024-04-09 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ethernet/ibm/emac/mal.c | 14 +++---
 drivers/net/ethernet/ibm/emac/mal.h |  2 +-
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/ibm/emac/mal.c 
b/drivers/net/ethernet/ibm/emac/mal.c
index 2439f7e96e05..d92dd9c83031 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -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 */
@@ -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)
@@ -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:
@@ -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 +
diff --git a/drivers/net/ethernet/ibm/emac/mal.h 
b/drivers/net/ethernet/ibm/emac/mal.h
index d212373a72e7..e0ddc41186a2 100644
--- a/drivers/net/ethernet/ibm/emac/mal.h
+++ b/drivers/net/ethernet/ibm/emac/mal.h
@@ -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;
 };
-- 
2.43.0




Re: [PATCH net-next v4 2/9] net: create a dummy net_device allocator

2024-04-10 Thread Breno Leitao
On Wed, Apr 10, 2024 at 02:10:04PM +0300, Ido Schimmel wrote:
> On Tue, Apr 09, 2024 at 05:57:16AM -0700, Breno Leitao wrote:
> > It is impossible to use init_dummy_netdev together with alloc_netdev()
> > as the 'setup' argument.
> > 
> > This is because alloc_netdev() initializes some fields in the net_device
> > structure, and later init_dummy_netdev() memzero them all. This causes
> > some problems as reported here:
> > 
> > https://lore.kernel.org/all/20240322082336.49f11...@kernel.org/
> > 
> > Split the init_dummy_netdev() function in two. Create a new function called
> > init_dummy_netdev_core() that does not memzero the net_device structure.
> > Then have init_dummy_netdev() memzero-ing and calling
> > init_dummy_netdev_core(), keeping the old behaviour.
> > 
> > init_dummy_netdev_core() is the new function that could be called as an
> > argument for alloc_netdev().
> > 
> > Also, create a helper to allocate and initialize dummy net devices,
> > leveraging init_dummy_netdev_core() as the setup argument. This function
> > basically simplify the allocation of dummy devices, by allocating and
> > initializing it. Freeing the device continue to be done through
> > free_netdev()
> > 
> > Suggested-by: Jakub Kicinski 
> > Signed-off-by: Breno Leitao 
> 
> Reviewed-by: Ido Schimmel 
> 
> We were about to submit another user of init_dummy_netdev() when I
> noticed this patch. Converted the code to use alloc_netdev_dummy() [1]
> and it seems to be working fine. Will submit after your patch is
> accepted.

Thanks. It seems that this patch is close to get accepted. Let's see...

> See a few minor comments below.
> 
> [...]
> 
> > +/**
> > + * init_dummy_netdev   - init a dummy network device for NAPI
> > + * @dev: device to init
> > + *
> > + * This takes a network device structure and initialize the minimum
> 
> s/initialize/initializes/
> 
> > + * amount of fields so it can be used to schedule NAPI polls without
> > + * registering a full blown interface. This is to be used by drivers
> > + * that need to tie several hardware interfaces to a single NAPI
> > + * poll scheduler due to HW limitations.
> > + */
> > +void init_dummy_netdev(struct net_device *dev)
> > +{
> > +   /* Clear everything. Note we don't initialize spinlocks
> > +* are they aren't supposed to be taken by any of the
> 
> I assume you meant s/are/as/ ?

Thanks for the feedback, I agree with all of them.

Since these lines were not introduced by this patch, and this patch is
just moving code (and comments) around, I would add a new patch to the
patch series fixing the grammar errors.



[PATCH net-next v5 00/10] allocate dummy device dynamically

2024-04-10 Thread Breno Leitao
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:

v1:
* https://lore.kernel.org/all/20240327200809.512867-1-lei...@debian.org/

v2:
* Patch 1: Use a pre-defined name ("dummy#") for the dummy
  net_devices.
* Patch 2-5: Added users for the new helper.
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.
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.
v5:
* Added a new patch to fix some typos in the previous code,
  suggested by Ido.
* Rebased to net-net/main


Breno Leitao (10):
  net: core: Fix documentation
  net: free_netdev: exit earlier if dummy
  net: create a dummy net_device allocator
  net: marvell: prestera: allocate dummy net_device dynamically
  net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically
  net: ipa: allocate dummy net_device dynamically
  net: ibm/emac: allocate dummy net_device dynamically
  wifi: qtnfmac: Use netdev dummy allocator helper
  wifi: ath10k: allocate dummy net_device dynamically
  wifi: ath11k: allocate dummy net_device dynamically

 drivers/net/ethernet/ibm/emac/mal.c   | 14 -
 drivers/net/ethernet/ibm/emac/mal.h   |  2 +-
 .../ethernet/marvell/prestera/prestera_rxtx.c | 15 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 17 --
 drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  2 +-
 drivers/net/ipa/gsi.c | 12 ++--
 drivers/net/ipa/gsi.h |  2 +-
 drivers/net/wireless/ath/ath10k/core.c|  9 ++-
 drivers/net/wireless/ath/ath10k/core.h|  2 +-
 drivers/net/wireless/ath/ath10k/pci.c |  2 +-
 drivers/net/wireless/ath/ath10k/sdio.c|  2 +-
 drivers/net/wireless/ath/ath10k/snoc.c|  4 +-
 drivers/net/wireless/ath/ath10k/usb.c |  2 +-
 drivers/net/wireless/ath/ath11k/ahb.c |  9 ++-
 drivers/net/wireless/ath/ath11k/core.h|  2 +-
 drivers/net/wireless/ath/ath11k/pcic.c| 21 +--
 .../wireless/quantenna/qtnfmac/pcie/pcie.c|  3 +-
 include/linux/netdevice.h |  3 +
 net/core/dev.c| 57 ---
 19 files changed, 127 insertions(+), 53 deletions(-)

-- 
2.43.0




[PATCH net-next v5 02/10] net: free_netdev: exit earlier if dummy

2024-04-10 Thread Breno Leitao
For dummy devices, exit earlier at free_netdev() instead of executing
the whole function. This is necessary, because dummy devices are
special, and shouldn't have the second part of the function executed.

Otherwise reg_state, which is NETREG_DUMMY, will be overwritten and
there will be no way to identify that this is a dummy device. Also, this
device do not need the final put_device(), since dummy devices are not
registered (through register_netdevice()), where the device reference is
increased (at netdev_register_kobject()/device_add()).

Suggested-by: Jakub Kicinski 
Signed-off-by: Breno Leitao 
---
 net/core/dev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 987039ffa63c..c74b42bc6888 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11060,7 +11060,8 @@ void free_netdev(struct net_device *dev)
phy_link_topo_destroy(dev->link_topo);
 
/*  Compatibility with error handling in drivers */
-   if (dev->reg_state == NETREG_UNINITIALIZED) {
+   if (dev->reg_state == NETREG_UNINITIALIZED ||
+   dev->reg_state == NETREG_DUMMY) {
netdev_freemem(dev);
return;
}
-- 
2.43.0




[PATCH net-next v5 03/10] net: create a dummy net_device allocator

2024-04-10 Thread Breno Leitao
It is impossible to use init_dummy_netdev together with alloc_netdev()
as the 'setup' argument.

This is because alloc_netdev() initializes some fields in the net_device
structure, and later init_dummy_netdev() memzero them all. This causes
some problems as reported here:

https://lore.kernel.org/all/20240322082336.49f11...@kernel.org/

Split the init_dummy_netdev() function in two. Create a new function called
init_dummy_netdev_core() that does not memzero the net_device structure.
Then have init_dummy_netdev() memzero-ing and calling
init_dummy_netdev_core(), keeping the old behaviour.

init_dummy_netdev_core() is the new function that could be called as an
argument for alloc_netdev().

Also, create a helper to allocate and initialize dummy net devices,
leveraging init_dummy_netdev_core() as the setup argument. This function
basically simplify the allocation of dummy devices, by allocating and
initializing it. Freeing the device continue to be done through
free_netdev()

Suggested-by: Jakub Kicinski 
Signed-off-by: Breno Leitao 
Reviewed-by: Ido Schimmel 
---
 include/linux/netdevice.h |  3 +++
 net/core/dev.c| 54 ++-
 2 files changed, 39 insertions(+), 18 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d45f330d083d..f849e7d110ed 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -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,
diff --git a/net/core/dev.c b/net/core/dev.c
index c74b42bc6888..417abfd12871 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10414,25 +10414,12 @@ int register_netdevice(struct net_device *dev)
 }
 EXPORT_SYMBOL(register_netdevice);
 
-/**
- * init_dummy_netdev   - init a dummy network device for NAPI
- * @dev: device to init
- *
- * This takes a network device structure and initializes the minimum
- * amount of fields so it can be used to schedule NAPI polls without
- * registering a full blown interface. This is to be used by drivers
- * that need to tie several hardware interfaces to a single NAPI
- * poll scheduler due to HW limitations.
+/* Initialize the core of a dummy net device.
+ * This is useful if you are calling this function after alloc_netdev(),
+ * since it does not memset the net_device fields.
  */
-void init_dummy_netdev(struct net_device *dev)
+static void init_dummy_netdev_core(struct net_device *dev)
 {
-   /* Clear everything. Note we don't initialize spinlocks
-* as they aren't supposed to be taken by any of the
-* NAPI code and this dummy netdev is supposed to be
-* only ever used for NAPI polls
-*/
-   memset(dev, 0, sizeof(struct net_device));
-
/* make sure we BUG if trying to hit standard
 * register/unregister code path
 */
@@ -10453,8 +10440,28 @@ void init_dummy_netdev(struct net_device *dev)
 * its refcount.
 */
 }
-EXPORT_SYMBOL_GPL(init_dummy_netdev);
 
+/**
+ * init_dummy_netdev   - init a dummy network device for NAPI
+ * @dev: device to init
+ *
+ * This takes a network device structure and initializes the minimum
+ * amount of fields so it can be used to schedule NAPI polls without
+ * registering a full blown interface. This is to be used by drivers
+ * that need to tie several hardware interfaces to a single NAPI
+ * poll scheduler due to HW limitations.
+ */
+void init_dummy_netdev(struct net_device *dev)
+{
+   /* Clear everything. Note we don't initialize spinlocks
+* as they aren't supposed to be taken by any of the
+* NAPI code and this dummy netdev is supposed to be
+* only ever used for NAPI polls
+*/
+   memset(dev, 0, sizeof(struct net_device));
+   init_dummy_netdev_core(dev);
+}
+EXPORT_SYMBOL_GPL(init_dummy_netdev);
 
 /**
  * register_netdev - register a network device
@@ -11074,6 +11081,17 @@ void free_netdev(struct net_device *dev)
 }
 EXPORT_SYMBOL(free_netdev);
 
+/**
+ * alloc_netdev_dummy - Allocate and initialize a dummy net device.
+ * @sizeof_priv: size of private data to allocate space for
+ */
+struct net_device *alloc_netdev_dummy(int sizeof_priv)
+{
+   return alloc_netdev(sizeof_priv, "dummy#", NET_NAME_UNKNOWN,
+   init_dummy_netdev_core);
+}
+EXPORT_SYMBOL_GPL(alloc_netdev_dummy);
+
 /**
  * synchronize_net -  Synchronize with packet receive processing
  *
-- 
2.43.0




[PATCH net-next v5 01/10] net: core: Fix documentation

2024-04-10 Thread Breno Leitao
Fix bad grammer in description of init_dummy_netdev() functio.  This
topic showed up in the review of the "allocate dummy device dynamically"
patchset.

Suggested-by: Ido Schimmel 
Signed-off-by: Breno Leitao 
---
 net/core/dev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 854a3a28a8d8..987039ffa63c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10418,7 +10418,7 @@ EXPORT_SYMBOL(register_netdevice);
  * init_dummy_netdev   - init a dummy network device for NAPI
  * @dev: device to init
  *
- * This takes a network device structure and initialize the minimum
+ * This takes a network device structure and initializes the minimum
  * amount of fields so it can be used to schedule NAPI polls without
  * registering a full blown interface. This is to be used by drivers
  * that need to tie several hardware interfaces to a single NAPI
@@ -10427,7 +10427,7 @@ EXPORT_SYMBOL(register_netdevice);
 void init_dummy_netdev(struct net_device *dev)
 {
/* Clear everything. Note we don't initialize spinlocks
-* are they aren't supposed to be taken by any of the
+* as they aren't supposed to be taken by any of the
 * NAPI code and this dummy netdev is supposed to be
 * only ever used for NAPI polls
 */
-- 
2.43.0




[PATCH net-next v5 04/10] net: marvell: prestera: allocate dummy net_device dynamically

2024-04-10 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
Acked-by: Elad Nachman 
---
 .../net/ethernet/marvell/prestera/prestera_rxtx.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c 
b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
index cc2a9ae794be..39d9bf82c115 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
@@ -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 */
@@ -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);
@@ -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);
-- 
2.43.0




[PATCH net-next v5 06/10] net: ipa: allocate dummy net_device dynamically

2024-04-10 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ipa/gsi.c | 12 
 drivers/net/ipa/gsi.h |  2 +-
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c
index 9a0b1fe4a93a..d70be15e95a6 100644
--- a/drivers/net/ipa/gsi.c
+++ b/drivers/net/ipa/gsi.c
@@ -1730,10 +1730,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;
@@ -2369,12 +2369,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)
@@ -2389,6 +2391,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;
@@ -2399,6 +2402,7 @@ void gsi_exit(struct gsi *gsi)
 {
mutex_destroy(&gsi->mutex);
gsi_channel_exit(gsi);
+   free_netdev(gsi->dummy_dev);
gsi_reg_exit(gsi);
 }
 
diff --git a/drivers/net/ipa/gsi.h b/drivers/net/ipa/gsi.h
index 42063b227c18..6b7ec2a39676 100644
--- a/drivers/net/ipa/gsi.h
+++ b/drivers/net/ipa/gsi.h
@@ -155,7 +155,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 */
 };
 
 /**
-- 
2.43.0




[PATCH net-next v5 05/10] net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically

2024-04-10 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 17 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  2 +-
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index caa13b9cedff..d7a96dc11c07 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -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, ð->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;
@@ -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;
 }
 
@@ -4983,9 +4985,14 @@ 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(ð->dummy_dev);
-   netif_napi_add(ð->dummy_dev, ð->tx_napi, mtk_napi_tx);
-   netif_napi_add(ð->dummy_dev, ð->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, ð->tx_napi, mtk_napi_tx);
+   netif_napi_add(eth->dummy_dev, ð->rx_napi, mtk_napi_rx);
 
platform_set_drvdata(pdev, eth);
schedule_delayed_work(ð->reset.monitor_work,
@@ -4993,6 +5000,8 @@ static int mtk_probe(struct platform_device *pdev)
 
return 0;
 
+err_unreg_netdev:
+   mtk_unreg_dev(eth);
 err_deinit_ppe:
mtk_ppe_deinit(eth);
mtk_mdio_cleanup(eth);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 9ae3b8a71d0e..723fc637027c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -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];
-- 
2.43.0




[PATCH net-next v5 09/10] wifi: ath10k: allocate dummy net_device dynamically

2024-04-10 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath10k by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath10k_core_create(). The free of the device occurs
at ath10k_core_destroy().

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/ath/ath10k/core.c | 9 +++--
 drivers/net/wireless/ath/ath10k/core.h | 2 +-
 drivers/net/wireless/ath/ath10k/pci.c  | 2 +-
 drivers/net/wireless/ath/ath10k/sdio.c | 2 +-
 drivers/net/wireless/ath/ath10k/snoc.c | 4 ++--
 drivers/net/wireless/ath/ath10k/usb.c  | 2 +-
 6 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 9ce6f49ab261..8663822e0b8d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -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)
@@ -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:
@@ -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);
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index c110d15528bd..26003b519574 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -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;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c 
b/drivers/net/wireless/ath/ath10k/pci.c
index 5c34b156b4ff..558bec96ae40 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 0ab5433f6cf6..e28f2fe1101b 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -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",
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c 
b/drivers/net/wireless/ath/ath10k/snoc.c
index 2c39bad7ebfb..0449b9ffc32d 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -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);
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/usb.c 
b/drivers/net/wireless/ath/ath10k/usb.c
index 3c482b

[PATCH net-next v5 08/10] wifi: qtnfmac: Use netdev dummy allocator helper

2024-04-10 Thread Breno Leitao
There is a new dummy netdev allocator, use it instead of
alloc_netdev()/init_dummy_netdev combination.

Using alloc_netdev() with init_dummy_netdev might cause some memory
corruption at the driver removal side.

Fixes: 61cdb09ff760 ("wifi: qtnfmac: allocate dummy net_device dynamically")
Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index f8f55db2f454..f66eb43094d4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -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;
-- 
2.43.0




[PATCH net-next v5 07/10] net: ibm/emac: allocate dummy net_device dynamically

2024-04-10 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ethernet/ibm/emac/mal.c | 14 +++---
 drivers/net/ethernet/ibm/emac/mal.h |  2 +-
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/ibm/emac/mal.c 
b/drivers/net/ethernet/ibm/emac/mal.c
index 2439f7e96e05..d92dd9c83031 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -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 */
@@ -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)
@@ -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:
@@ -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 +
diff --git a/drivers/net/ethernet/ibm/emac/mal.h 
b/drivers/net/ethernet/ibm/emac/mal.h
index d212373a72e7..e0ddc41186a2 100644
--- a/drivers/net/ethernet/ibm/emac/mal.h
+++ b/drivers/net/ethernet/ibm/emac/mal.h
@@ -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;
 };
-- 
2.43.0




Re: [PATCH net-next v5 00/10] allocate dummy device dynamically

2024-04-11 Thread Breno Leitao
On Thu, Apr 11, 2024 at 06:09:26AM -0700, Jakub Kicinski wrote:
> On Wed, 10 Apr 2024 06:13:41 -0700 Breno Leitao wrote:
> >   wifi: ath11k: allocate dummy net_device dynamically
> 
> Sorry Breno, I didn't notice earlier, patch 10 didn't make it
> to the list. The series wasn't ingested by CI and tested because 
> of this. Could you repost?

Thanks for the heads-up. I debugged it and it was my mistake, this is
how I've sent it.

git send-email patches/v5-000*

I will repost.



[PATCH net-next v6 00/10] allocate dummy device dynamically

2024-04-11 Thread Breno Leitao
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:

v6:
* No code change. Just added Reviewed-by: tags 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/20240327200809.512867-1-lei...@debian.org/

Breno Leitao (10):
  net: core: Fix documentation
  net: free_netdev: exit earlier if dummy
  net: create a dummy net_device allocator
  net: marvell: prestera: allocate dummy net_device dynamically
  net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically
  net: ipa: allocate dummy net_device dynamically
  net: ibm/emac: allocate dummy net_device dynamically
  wifi: qtnfmac: Use netdev dummy allocator helper
  wifi: ath10k: allocate dummy net_device dynamically
  wifi: ath11k: allocate dummy net_device dynamically

 drivers/net/ethernet/ibm/emac/mal.c   | 14 -
 drivers/net/ethernet/ibm/emac/mal.h   |  2 +-
 .../ethernet/marvell/prestera/prestera_rxtx.c | 15 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 17 --
 drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  2 +-
 drivers/net/ipa/gsi.c | 12 ++--
 drivers/net/ipa/gsi.h |  2 +-
 drivers/net/wireless/ath/ath10k/core.c|  9 ++-
 drivers/net/wireless/ath/ath10k/core.h|  2 +-
 drivers/net/wireless/ath/ath10k/pci.c |  2 +-
 drivers/net/wireless/ath/ath10k/sdio.c|  2 +-
 drivers/net/wireless/ath/ath10k/snoc.c|  4 +-
 drivers/net/wireless/ath/ath10k/usb.c |  2 +-
 drivers/net/wireless/ath/ath11k/ahb.c |  9 ++-
 drivers/net/wireless/ath/ath11k/core.h|  2 +-
 drivers/net/wireless/ath/ath11k/pcic.c| 21 +--
 .../wireless/quantenna/qtnfmac/pcie/pcie.c|  3 +-
 include/linux/netdevice.h |  3 +
 net/core/dev.c| 57 ---
 19 files changed, 127 insertions(+), 53 deletions(-)

-- 
2.43.0




[PATCH net-next v6 01/10] net: core: Fix documentation

2024-04-11 Thread Breno Leitao
Fix bad grammar in description of init_dummy_netdev() function.  This
topic showed up in the review of the "allocate dummy device dynamically"
patch set.

Suggested-by: Ido Schimmel 
Signed-off-by: Breno Leitao 
Reviewed-by: Ido Schimmel 
---
 net/core/dev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 854a3a28a8d8..987039ffa63c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10418,7 +10418,7 @@ EXPORT_SYMBOL(register_netdevice);
  * init_dummy_netdev   - init a dummy network device for NAPI
  * @dev: device to init
  *
- * This takes a network device structure and initialize the minimum
+ * This takes a network device structure and initializes the minimum
  * amount of fields so it can be used to schedule NAPI polls without
  * registering a full blown interface. This is to be used by drivers
  * that need to tie several hardware interfaces to a single NAPI
@@ -10427,7 +10427,7 @@ EXPORT_SYMBOL(register_netdevice);
 void init_dummy_netdev(struct net_device *dev)
 {
/* Clear everything. Note we don't initialize spinlocks
-* are they aren't supposed to be taken by any of the
+* as they aren't supposed to be taken by any of the
 * NAPI code and this dummy netdev is supposed to be
 * only ever used for NAPI polls
 */
-- 
2.43.0




[PATCH net-next v6 02/10] net: free_netdev: exit earlier if dummy

2024-04-11 Thread Breno Leitao
For dummy devices, exit earlier at free_netdev() instead of executing
the whole function. This is necessary, because dummy devices are
special, and shouldn't have the second part of the function executed.

Otherwise reg_state, which is NETREG_DUMMY, will be overwritten and
there will be no way to identify that this is a dummy device. Also, this
device do not need the final put_device(), since dummy devices are not
registered (through register_netdevice()), where the device reference is
increased (at netdev_register_kobject()/device_add()).

Suggested-by: Jakub Kicinski 
Signed-off-by: Breno Leitao 
Reviewed-by: Ido Schimmel 
---
 net/core/dev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 987039ffa63c..c74b42bc6888 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11060,7 +11060,8 @@ void free_netdev(struct net_device *dev)
phy_link_topo_destroy(dev->link_topo);
 
/*  Compatibility with error handling in drivers */
-   if (dev->reg_state == NETREG_UNINITIALIZED) {
+   if (dev->reg_state == NETREG_UNINITIALIZED ||
+   dev->reg_state == NETREG_DUMMY) {
netdev_freemem(dev);
return;
}
-- 
2.43.0




[PATCH net-next v6 03/10] net: create a dummy net_device allocator

2024-04-11 Thread Breno Leitao
It is impossible to use init_dummy_netdev together with alloc_netdev()
as the 'setup' argument.

This is because alloc_netdev() initializes some fields in the net_device
structure, and later init_dummy_netdev() memzero them all. This causes
some problems as reported here:

https://lore.kernel.org/all/20240322082336.49f11...@kernel.org/

Split the init_dummy_netdev() function in two. Create a new function called
init_dummy_netdev_core() that does not memzero the net_device structure.
Then have init_dummy_netdev() memzero-ing and calling
init_dummy_netdev_core(), keeping the old behaviour.

init_dummy_netdev_core() is the new function that could be called as an
argument for alloc_netdev().

Also, create a helper to allocate and initialize dummy net devices,
leveraging init_dummy_netdev_core() as the setup argument. This function
basically simplify the allocation of dummy devices, by allocating and
initializing it. Freeing the device continue to be done through
free_netdev()

Suggested-by: Jakub Kicinski 
Signed-off-by: Breno Leitao 
Reviewed-by: Ido Schimmel 
---
 include/linux/netdevice.h |  3 +++
 net/core/dev.c| 54 ++-
 2 files changed, 39 insertions(+), 18 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d45f330d083d..f849e7d110ed 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -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,
diff --git a/net/core/dev.c b/net/core/dev.c
index c74b42bc6888..417abfd12871 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10414,25 +10414,12 @@ int register_netdevice(struct net_device *dev)
 }
 EXPORT_SYMBOL(register_netdevice);
 
-/**
- * init_dummy_netdev   - init a dummy network device for NAPI
- * @dev: device to init
- *
- * This takes a network device structure and initializes the minimum
- * amount of fields so it can be used to schedule NAPI polls without
- * registering a full blown interface. This is to be used by drivers
- * that need to tie several hardware interfaces to a single NAPI
- * poll scheduler due to HW limitations.
+/* Initialize the core of a dummy net device.
+ * This is useful if you are calling this function after alloc_netdev(),
+ * since it does not memset the net_device fields.
  */
-void init_dummy_netdev(struct net_device *dev)
+static void init_dummy_netdev_core(struct net_device *dev)
 {
-   /* Clear everything. Note we don't initialize spinlocks
-* as they aren't supposed to be taken by any of the
-* NAPI code and this dummy netdev is supposed to be
-* only ever used for NAPI polls
-*/
-   memset(dev, 0, sizeof(struct net_device));
-
/* make sure we BUG if trying to hit standard
 * register/unregister code path
 */
@@ -10453,8 +10440,28 @@ void init_dummy_netdev(struct net_device *dev)
 * its refcount.
 */
 }
-EXPORT_SYMBOL_GPL(init_dummy_netdev);
 
+/**
+ * init_dummy_netdev   - init a dummy network device for NAPI
+ * @dev: device to init
+ *
+ * This takes a network device structure and initializes the minimum
+ * amount of fields so it can be used to schedule NAPI polls without
+ * registering a full blown interface. This is to be used by drivers
+ * that need to tie several hardware interfaces to a single NAPI
+ * poll scheduler due to HW limitations.
+ */
+void init_dummy_netdev(struct net_device *dev)
+{
+   /* Clear everything. Note we don't initialize spinlocks
+* as they aren't supposed to be taken by any of the
+* NAPI code and this dummy netdev is supposed to be
+* only ever used for NAPI polls
+*/
+   memset(dev, 0, sizeof(struct net_device));
+   init_dummy_netdev_core(dev);
+}
+EXPORT_SYMBOL_GPL(init_dummy_netdev);
 
 /**
  * register_netdev - register a network device
@@ -11074,6 +11081,17 @@ void free_netdev(struct net_device *dev)
 }
 EXPORT_SYMBOL(free_netdev);
 
+/**
+ * alloc_netdev_dummy - Allocate and initialize a dummy net device.
+ * @sizeof_priv: size of private data to allocate space for
+ */
+struct net_device *alloc_netdev_dummy(int sizeof_priv)
+{
+   return alloc_netdev(sizeof_priv, "dummy#", NET_NAME_UNKNOWN,
+   init_dummy_netdev_core);
+}
+EXPORT_SYMBOL_GPL(alloc_netdev_dummy);
+
 /**
  * synchronize_net -  Synchronize with packet receive processing
  *
-- 
2.43.0




[PATCH net-next v6 06/10] net: ipa: allocate dummy net_device dynamically

2024-04-11 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ipa/gsi.c | 12 
 drivers/net/ipa/gsi.h |  2 +-
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c
index 9a0b1fe4a93a..d70be15e95a6 100644
--- a/drivers/net/ipa/gsi.c
+++ b/drivers/net/ipa/gsi.c
@@ -1730,10 +1730,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;
@@ -2369,12 +2369,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)
@@ -2389,6 +2391,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;
@@ -2399,6 +2402,7 @@ void gsi_exit(struct gsi *gsi)
 {
mutex_destroy(&gsi->mutex);
gsi_channel_exit(gsi);
+   free_netdev(gsi->dummy_dev);
gsi_reg_exit(gsi);
 }
 
diff --git a/drivers/net/ipa/gsi.h b/drivers/net/ipa/gsi.h
index 42063b227c18..6b7ec2a39676 100644
--- a/drivers/net/ipa/gsi.h
+++ b/drivers/net/ipa/gsi.h
@@ -155,7 +155,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 */
 };
 
 /**
-- 
2.43.0




[PATCH net-next v6 04/10] net: marvell: prestera: allocate dummy net_device dynamically

2024-04-11 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
Acked-by: Elad Nachman 
---
 .../net/ethernet/marvell/prestera/prestera_rxtx.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c 
b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
index cc2a9ae794be..39d9bf82c115 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
@@ -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 */
@@ -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);
@@ -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);
-- 
2.43.0




[PATCH net-next v6 08/10] wifi: qtnfmac: Use netdev dummy allocator helper

2024-04-11 Thread Breno Leitao
There is a new dummy netdev allocator, use it instead of
alloc_netdev()/init_dummy_netdev combination.

Using alloc_netdev() with init_dummy_netdev might cause some memory
corruption at the driver removal side.

Fixes: 61cdb09ff760 ("wifi: qtnfmac: allocate dummy net_device dynamically")
Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index f8f55db2f454..f66eb43094d4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -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;
-- 
2.43.0




[PATCH net-next v6 05/10] net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically

2024-04-11 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 17 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  2 +-
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index caa13b9cedff..d7a96dc11c07 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -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, ð->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;
@@ -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;
 }
 
@@ -4983,9 +4985,14 @@ 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(ð->dummy_dev);
-   netif_napi_add(ð->dummy_dev, ð->tx_napi, mtk_napi_tx);
-   netif_napi_add(ð->dummy_dev, ð->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, ð->tx_napi, mtk_napi_tx);
+   netif_napi_add(eth->dummy_dev, ð->rx_napi, mtk_napi_rx);
 
platform_set_drvdata(pdev, eth);
schedule_delayed_work(ð->reset.monitor_work,
@@ -4993,6 +5000,8 @@ static int mtk_probe(struct platform_device *pdev)
 
return 0;
 
+err_unreg_netdev:
+   mtk_unreg_dev(eth);
 err_deinit_ppe:
mtk_ppe_deinit(eth);
mtk_mdio_cleanup(eth);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 9ae3b8a71d0e..723fc637027c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -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];
-- 
2.43.0




[PATCH net-next v6 09/10] wifi: ath10k: allocate dummy net_device dynamically

2024-04-11 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath10k by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath10k_core_create(). The free of the device occurs
at ath10k_core_destroy().

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/ath/ath10k/core.c | 9 +++--
 drivers/net/wireless/ath/ath10k/core.h | 2 +-
 drivers/net/wireless/ath/ath10k/pci.c  | 2 +-
 drivers/net/wireless/ath/ath10k/sdio.c | 2 +-
 drivers/net/wireless/ath/ath10k/snoc.c | 4 ++--
 drivers/net/wireless/ath/ath10k/usb.c  | 2 +-
 6 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 9ce6f49ab261..8663822e0b8d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -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)
@@ -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:
@@ -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);
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index c110d15528bd..26003b519574 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -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;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c 
b/drivers/net/wireless/ath/ath10k/pci.c
index 5c34b156b4ff..558bec96ae40 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 0ab5433f6cf6..e28f2fe1101b 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -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",
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c 
b/drivers/net/wireless/ath/ath10k/snoc.c
index 2c39bad7ebfb..0449b9ffc32d 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -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);
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/usb.c 
b/drivers/net/wireless/ath/ath10k/usb.c
index 3c482b

[PATCH net-next v6 07/10] net: ibm/emac: allocate dummy net_device dynamically

2024-04-11 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ethernet/ibm/emac/mal.c | 14 +++---
 drivers/net/ethernet/ibm/emac/mal.h |  2 +-
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/ibm/emac/mal.c 
b/drivers/net/ethernet/ibm/emac/mal.c
index 2439f7e96e05..d92dd9c83031 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -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 */
@@ -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)
@@ -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:
@@ -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 +
diff --git a/drivers/net/ethernet/ibm/emac/mal.h 
b/drivers/net/ethernet/ibm/emac/mal.h
index d212373a72e7..e0ddc41186a2 100644
--- a/drivers/net/ethernet/ibm/emac/mal.h
+++ b/drivers/net/ethernet/ibm/emac/mal.h
@@ -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;
 };
-- 
2.43.0




[PATCH net-next v6 10/10] wifi: ath11k: allocate dummy net_device dynamically

2024-04-11 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath11k_ext_irq_grp by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath11k_ahb_config_ext_irq() for ahb, and
ath11k_pcic_ext_irq_config() for pcic.

The free of the device occurs at ath11k_ahb_free_ext_irq() for the ahb
case, and ath11k_pcic_free_ext_irq() for the pcic case.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
Tested-by: Kalle Valo 
---
 drivers/net/wireless/ath/ath11k/ahb.c  |  9 +++--
 drivers/net/wireless/ath/ath11k/core.h |  2 +-
 drivers/net/wireless/ath/ath11k/pcic.c | 21 +
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/ahb.c 
b/drivers/net/wireless/ath/ath11k/ahb.c
index 7c0a23517949..7f3f6479d553 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -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);
}
 }
 
@@ -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++) {
diff --git a/drivers/net/wireless/ath/ath11k/core.h 
b/drivers/net/wireless/ath/ath11k/core.h
index b3fb74a226fb..590307ca7a11 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -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 {
diff --git a/drivers/net/wireless/ath/ath11k/pcic.c 
b/drivers/net/wireless/ath/ath11k/pcic.c
index add4db4c50bc..79eb3f9c902f 100644
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
@@ -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);
}
 }
 
@@ -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;
 
@@ -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] ||
@@ -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;
 
@@ -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 = 

[PATCH net-next v7 00/10] allocate dummy device dynamically

2024-04-22 Thread Breno Leitao
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/20240327200809.512867-1-lei...@debian.org/

Breno Leitao (10):
  net: core: Fix documentation
  net: free_netdev: exit earlier if dummy
  net: create a dummy net_device allocator
  net: marvell: prestera: allocate dummy net_device dynamically
  net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically
  net: ipa: allocate dummy net_device dynamically
  net: ibm/emac: allocate dummy net_device dynamically
  wifi: qtnfmac: Use netdev dummy allocator helper
  wifi: ath10k: allocate dummy net_device dynamically
  wifi: ath11k: allocate dummy net_device dynamically

 drivers/net/ethernet/ibm/emac/mal.c   | 14 -
 drivers/net/ethernet/ibm/emac/mal.h   |  2 +-
 .../ethernet/marvell/prestera/prestera_rxtx.c | 15 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   | 17 --
 drivers/net/ethernet/mediatek/mtk_eth_soc.h   |  2 +-
 drivers/net/ipa/gsi.c | 12 ++--
 drivers/net/ipa/gsi.h |  2 +-
 drivers/net/wireless/ath/ath10k/core.c|  9 ++-
 drivers/net/wireless/ath/ath10k/core.h|  2 +-
 drivers/net/wireless/ath/ath10k/pci.c |  2 +-
 drivers/net/wireless/ath/ath10k/sdio.c|  2 +-
 drivers/net/wireless/ath/ath10k/snoc.c|  4 +-
 drivers/net/wireless/ath/ath10k/usb.c |  2 +-
 drivers/net/wireless/ath/ath11k/ahb.c |  9 ++-
 drivers/net/wireless/ath/ath11k/core.h|  2 +-
 drivers/net/wireless/ath/ath11k/pcic.c| 21 +--
 .../wireless/quantenna/qtnfmac/pcie/pcie.c|  3 +-
 include/linux/netdevice.h |  3 +
 net/core/dev.c| 59 +--
 19 files changed, 129 insertions(+), 53 deletions(-)

-- 
2.43.0




[PATCH net-next v7 01/10] net: core: Fix documentation

2024-04-22 Thread Breno Leitao
Fix bad grammar in description of init_dummy_netdev() function.  This
topic showed up in the review of the "allocate dummy device dynamically"
patch set.

Suggested-by: Ido Schimmel 
Signed-off-by: Breno Leitao 
Reviewed-by: Ido Schimmel 
---
 net/core/dev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 8bdc59074b29..44c2d698fd1b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10424,7 +10424,7 @@ EXPORT_SYMBOL(register_netdevice);
  * init_dummy_netdev   - init a dummy network device for NAPI
  * @dev: device to init
  *
- * This takes a network device structure and initialize the minimum
+ * This takes a network device structure and initializes the minimum
  * amount of fields so it can be used to schedule NAPI polls without
  * registering a full blown interface. This is to be used by drivers
  * that need to tie several hardware interfaces to a single NAPI
@@ -10433,7 +10433,7 @@ EXPORT_SYMBOL(register_netdevice);
 void init_dummy_netdev(struct net_device *dev)
 {
/* Clear everything. Note we don't initialize spinlocks
-* are they aren't supposed to be taken by any of the
+* as they aren't supposed to be taken by any of the
 * NAPI code and this dummy netdev is supposed to be
 * only ever used for NAPI polls
 */
-- 
2.43.0




[PATCH net-next v7 02/10] net: free_netdev: exit earlier if dummy

2024-04-22 Thread Breno Leitao
For dummy devices, exit earlier at free_netdev() instead of executing
the whole function. This is necessary, because dummy devices are
special, and shouldn't have the second part of the function executed.

Otherwise reg_state, which is NETREG_DUMMY, will be overwritten and
there will be no way to identify that this is a dummy device. Also, this
device do not need the final put_device(), since dummy devices are not
registered (through register_netdevice()), where the device reference is
increased (at netdev_register_kobject()/device_add()).

Suggested-by: Jakub Kicinski 
Signed-off-by: Breno Leitao 
Reviewed-by: Ido Schimmel 
---
 net/core/dev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 44c2d698fd1b..62b39d6b1d8f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -11066,7 +11066,8 @@ void free_netdev(struct net_device *dev)
phy_link_topo_destroy(dev->link_topo);
 
/*  Compatibility with error handling in drivers */
-   if (dev->reg_state == NETREG_UNINITIALIZED) {
+   if (dev->reg_state == NETREG_UNINITIALIZED ||
+   dev->reg_state == NETREG_DUMMY) {
netdev_freemem(dev);
return;
}
-- 
2.43.0




[PATCH net-next v7 03/10] net: create a dummy net_device allocator

2024-04-22 Thread Breno Leitao
It is impossible to use init_dummy_netdev together with alloc_netdev()
as the 'setup' argument.

This is because alloc_netdev() initializes some fields in the net_device
structure, and later init_dummy_netdev() memzero them all. This causes
some problems as reported here:

https://lore.kernel.org/all/20240322082336.49f11...@kernel.org/

Split the init_dummy_netdev() function in two. Create a new function called
init_dummy_netdev_core() that does not memzero the net_device structure.
Then have init_dummy_netdev() memzero-ing and calling
init_dummy_netdev_core(), keeping the old behaviour.

init_dummy_netdev_core() is the new function that could be called as an
argument for alloc_netdev().

Also, create a helper to allocate and initialize dummy net devices,
leveraging init_dummy_netdev_core() as the setup argument. This function
basically simplify the allocation of dummy devices, by allocating and
initializing it. Freeing the device continue to be done through
free_netdev()

Suggested-by: Jakub Kicinski 
Signed-off-by: Breno Leitao 
Reviewed-by: Ido Schimmel 
---
 include/linux/netdevice.h |  3 +++
 net/core/dev.c| 56 ++-
 2 files changed, 41 insertions(+), 18 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d45f330d083d..f849e7d110ed 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -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,
diff --git a/net/core/dev.c b/net/core/dev.c
index 62b39d6b1d8f..e09aa3785c15 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10420,25 +10420,12 @@ int register_netdevice(struct net_device *dev)
 }
 EXPORT_SYMBOL(register_netdevice);
 
-/**
- * init_dummy_netdev   - init a dummy network device for NAPI
- * @dev: device to init
- *
- * This takes a network device structure and initializes the minimum
- * amount of fields so it can be used to schedule NAPI polls without
- * registering a full blown interface. This is to be used by drivers
- * that need to tie several hardware interfaces to a single NAPI
- * poll scheduler due to HW limitations.
+/* Initialize the core of a dummy net device.
+ * This is useful if you are calling this function after alloc_netdev(),
+ * since it does not memset the net_device fields.
  */
-void init_dummy_netdev(struct net_device *dev)
+static void init_dummy_netdev_core(struct net_device *dev)
 {
-   /* Clear everything. Note we don't initialize spinlocks
-* as they aren't supposed to be taken by any of the
-* NAPI code and this dummy netdev is supposed to be
-* only ever used for NAPI polls
-*/
-   memset(dev, 0, sizeof(struct net_device));
-
/* make sure we BUG if trying to hit standard
 * register/unregister code path
 */
@@ -10459,8 +10446,28 @@ void init_dummy_netdev(struct net_device *dev)
 * its refcount.
 */
 }
-EXPORT_SYMBOL_GPL(init_dummy_netdev);
 
+/**
+ * init_dummy_netdev   - init a dummy network device for NAPI
+ * @dev: device to init
+ *
+ * This takes a network device structure and initializes the minimum
+ * amount of fields so it can be used to schedule NAPI polls without
+ * registering a full blown interface. This is to be used by drivers
+ * that need to tie several hardware interfaces to a single NAPI
+ * poll scheduler due to HW limitations.
+ */
+void init_dummy_netdev(struct net_device *dev)
+{
+   /* Clear everything. Note we don't initialize spinlocks
+* as they aren't supposed to be taken by any of the
+* NAPI code and this dummy netdev is supposed to be
+* only ever used for NAPI polls
+*/
+   memset(dev, 0, sizeof(struct net_device));
+   init_dummy_netdev_core(dev);
+}
+EXPORT_SYMBOL_GPL(init_dummy_netdev);
 
 /**
  * register_netdev - register a network device
@@ -11080,6 +11087,19 @@ void free_netdev(struct net_device *dev)
 }
 EXPORT_SYMBOL(free_netdev);
 
+/**
+ * alloc_netdev_dummy - Allocate and initialize a dummy net device.
+ * @sizeof_priv: size of private data to allocate space for
+ *
+ * Return: the allocated net_device on success, NULL otherwise
+ */
+struct net_device *alloc_netdev_dummy(int sizeof_priv)
+{
+   return alloc_netdev(sizeof_priv, "dummy#", NET_NAME_UNKNOWN,
+   init_dummy_netdev_core);
+}
+EXPORT_SYMBOL_GPL(alloc_netdev_dummy);
+
 /**
  * synchronize_net -  Synchronize with packet receive processing
  *
-- 
2.43.0




[PATCH net-next v7 06/10] net: ipa: allocate dummy net_device dynamically

2024-04-22 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ipa/gsi.c | 12 
 drivers/net/ipa/gsi.h |  2 +-
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c
index 6c8feb640a97..4c3227e77898 100644
--- a/drivers/net/ipa/gsi.c
+++ b/drivers/net/ipa/gsi.c
@@ -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;
@@ -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)
@@ -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;
@@ -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);
 }
 
diff --git a/drivers/net/ipa/gsi.h b/drivers/net/ipa/gsi.h
index 833135b35380..9d8e05d950e3 100644
--- a/drivers/net/ipa/gsi.h
+++ b/drivers/net/ipa/gsi.h
@@ -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 */
 };
 
 /**
-- 
2.43.0




[PATCH net-next v7 05/10] net: mediatek: mtk_eth_sock: allocate dummy net_device dynamically

2024-04-22 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 17 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  2 +-
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index caa13b9cedff..d7a96dc11c07 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -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, ð->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;
@@ -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;
 }
 
@@ -4983,9 +4985,14 @@ 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(ð->dummy_dev);
-   netif_napi_add(ð->dummy_dev, ð->tx_napi, mtk_napi_tx);
-   netif_napi_add(ð->dummy_dev, ð->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, ð->tx_napi, mtk_napi_tx);
+   netif_napi_add(eth->dummy_dev, ð->rx_napi, mtk_napi_rx);
 
platform_set_drvdata(pdev, eth);
schedule_delayed_work(ð->reset.monitor_work,
@@ -4993,6 +5000,8 @@ static int mtk_probe(struct platform_device *pdev)
 
return 0;
 
+err_unreg_netdev:
+   mtk_unreg_dev(eth);
 err_deinit_ppe:
mtk_ppe_deinit(eth);
mtk_mdio_cleanup(eth);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 9ae3b8a71d0e..723fc637027c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -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];
-- 
2.43.0




[PATCH net-next v7 07/10] net: ibm/emac: allocate dummy net_device dynamically

2024-04-22 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/ethernet/ibm/emac/mal.c | 14 +++---
 drivers/net/ethernet/ibm/emac/mal.h |  2 +-
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/ibm/emac/mal.c 
b/drivers/net/ethernet/ibm/emac/mal.c
index 2439f7e96e05..d92dd9c83031 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -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 */
@@ -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)
@@ -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:
@@ -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 +
diff --git a/drivers/net/ethernet/ibm/emac/mal.h 
b/drivers/net/ethernet/ibm/emac/mal.h
index d212373a72e7..e0ddc41186a2 100644
--- a/drivers/net/ethernet/ibm/emac/mal.h
+++ b/drivers/net/ethernet/ibm/emac/mal.h
@@ -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;
 };
-- 
2.43.0




[PATCH net-next v7 08/10] wifi: qtnfmac: Use netdev dummy allocator helper

2024-04-22 Thread Breno Leitao
There is a new dummy netdev allocator, use it instead of
alloc_netdev()/init_dummy_netdev combination.

Using alloc_netdev() with init_dummy_netdev might cause some memory
corruption at the driver removal side.

Fixes: 61cdb09ff760 ("wifi: qtnfmac: allocate dummy net_device dynamically")
Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c 
b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
index f8f55db2f454..f66eb43094d4 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -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;
-- 
2.43.0




[PATCH net-next v7 09/10] wifi: ath10k: allocate dummy net_device dynamically

2024-04-22 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath10k by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath10k_core_create(). The free of the device occurs
at ath10k_core_destroy().

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
---
 drivers/net/wireless/ath/ath10k/core.c | 9 +++--
 drivers/net/wireless/ath/ath10k/core.h | 2 +-
 drivers/net/wireless/ath/ath10k/pci.c  | 2 +-
 drivers/net/wireless/ath/ath10k/sdio.c | 2 +-
 drivers/net/wireless/ath/ath10k/snoc.c | 4 ++--
 drivers/net/wireless/ath/ath10k/usb.c  | 2 +-
 6 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c 
b/drivers/net/wireless/ath/ath10k/core.c
index 9ce6f49ab261..8663822e0b8d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -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)
@@ -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:
@@ -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);
diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index c110d15528bd..26003b519574 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -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;
diff --git a/drivers/net/wireless/ath/ath10k/pci.c 
b/drivers/net/wireless/ath/ath10k/pci.c
index 5c34b156b4ff..558bec96ae40 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c 
b/drivers/net/wireless/ath/ath10k/sdio.c
index 0ab5433f6cf6..e28f2fe1101b 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -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",
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c 
b/drivers/net/wireless/ath/ath10k/snoc.c
index 2c39bad7ebfb..0449b9ffc32d 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -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);
@@ -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)
diff --git a/drivers/net/wireless/ath/ath10k/usb.c 
b/drivers/net/wireless/ath/ath10k/usb.c
index 3c482b

[PATCH net-next v7 10/10] wifi: ath11k: allocate dummy net_device dynamically

2024-04-22 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from struct ath11k_ext_irq_grp by converting it
into a pointer. Then use the leverage alloc_netdev() to allocate the
net_device object at ath11k_ahb_config_ext_irq() for ahb, and
ath11k_pcic_ext_irq_config() for pcic.

The free of the device occurs at ath11k_ahb_free_ext_irq() for the ahb
case, and ath11k_pcic_free_ext_irq() for the pcic case.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
Tested-by: Kalle Valo 
---
 drivers/net/wireless/ath/ath11k/ahb.c  |  9 +++--
 drivers/net/wireless/ath/ath11k/core.h |  2 +-
 drivers/net/wireless/ath/ath11k/pcic.c | 21 +
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/ahb.c 
b/drivers/net/wireless/ath/ath11k/ahb.c
index 7c0a23517949..7f3f6479d553 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -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);
}
 }
 
@@ -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++) {
diff --git a/drivers/net/wireless/ath/ath11k/core.h 
b/drivers/net/wireless/ath/ath11k/core.h
index b3fb74a226fb..590307ca7a11 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -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 {
diff --git a/drivers/net/wireless/ath/ath11k/pcic.c 
b/drivers/net/wireless/ath/ath11k/pcic.c
index add4db4c50bc..79eb3f9c902f 100644
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
@@ -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);
}
 }
 
@@ -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;
 
@@ -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] ||
@@ -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;
 
@@ -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 = 

[PATCH net-next v7 04/10] net: marvell: prestera: allocate dummy net_device dynamically

2024-04-22 Thread Breno Leitao
Embedding net_device into structures prohibits the usage of flexible
arrays in the net_device structure. For more details, see the discussion
at [1].

Un-embed the net_device from the private struct by converting it
into a pointer. Then use the leverage the new alloc_netdev_dummy()
helper to allocate and initialize dummy devices.

[1] https://lore.kernel.org/all/20240229225910.79e22...@kernel.org/

Signed-off-by: Breno Leitao 
Acked-by: Elad Nachman 
---
 .../net/ethernet/marvell/prestera/prestera_rxtx.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c 
b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
index cc2a9ae794be..39d9bf82c115 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_rxtx.c
@@ -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 */
@@ -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);
@@ -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);
-- 
2.43.0