linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 00/35] net: in_interrupt() cleanup and fixes
@ 2020-09-27 19:48 Thomas Gleixner
  2020-09-27 19:48 ` [patch 01/35] net: enic: Cure the enic api locking trainwreck Thomas Gleixner
                   ` (36 more replies)
  0 siblings, 37 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jakub Kicinski, netdev, David S. Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Sebastian Andrzej Siewior,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

Folks,

in the discussion about preempt count consistency accross kernel configurations:

  https://lore.kernel.org/r/20200914204209.256266093@linutronix.de/

Linus clearly requested that code in drivers and libraries which changes
behaviour based on execution context should either be split up so that
e.g. task context invocations and BH invocations have different interfaces
or if that's not possible the context information has to be provided by the
caller which knows in which context it is executing.

This includes conditional locking, allocation mode (GFP_*) decisions and
avoidance of code paths which might sleep.

In the long run, usage of 'preemptible, in_*irq etc.' should be banned from
driver code completely.

Our team started to dig through drivers and this it the first batch of
cleanups in drivers/net/. It's not yet complete, so expect further patches
in the next days.

The series contains:

    - A couple of bug fixes

    - Removal of the bitrotting CAIF SPI driver which has never had a
      matching driver providing the necessary platform device support.

    - Removal of WARN/BUG(in_interrupt()) en masse as most of them are
      incomplete because they won't detect other non-preemptible
      context. All of the functions which have these WARN/BUG invoke core
      code functions which can sleep. These have plenty of checks to catch
      _all_ invalid contexts. So it's pointless to have incomplete WARN/BUG
      in the drivers.

      If a driver wants to have such a check for paranoia reasons, then
      e.g. lockdep_assert_preemtion_enabled() is the right mechanism to
      chose because lockdep guarantees to catch all invalid contexts
      independent of kernel configuration while e.g. preemptible() does
      not.

    - Conversion of in_interrupt() checks to use either different functions
      or to hand the context information in from the caller.

    - For some drivers handing the context into functions which decided
      between netif_rx() and netif_rx_ni() turned out to be impossible due
      to lack of driver knowledge and convoluted code pathes with multiple
      indirections. For those a core code function netif_rx_any_context()
      is provided which contains an in_interrupt() check as a stop
      gap. This allows to make progess on the driver side cleanup and
      the function should go away once the driver wizards have fixed it
      up proper.

    - Simplifcation and cleanups in various places where code pointlessly
      contains in_interrupt() conditionals which are mostly leftovers from
      calling conventions in older kernels and have never been cleaned up.

      Along with removing if from the horrible DBG_FOO() macro mess which
      probably should be removed completely as the kernel today provides
      way more sensible mechanisms to do function tracing and similar.

    - A few other cleanups which were obvious when chasing the
      in_interrupt() usage.

The pile is also available from:

    git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git softirq

The diffstat summary is:

 86 files changed, 300 insertions(+), 2233 deletions(-)

which is biased by the CAIF SPI removal. Without that it is:

 79 files changed, 300 insertions(+), 697 deletions(-)

Thanks,

	tglx
---
 Documentation/networking/caif/spi_porting.rst                   |  229 --
 b/Documentation/networking/caif/index.rst                       |    1 
 b/drivers/net/caif/Kconfig                                      |   19 
 b/drivers/net/caif/Makefile                                     |    4 
 b/drivers/net/caif/caif_hsi.c                                   |   19 
 b/drivers/net/ethernet/amd/sun3lance.c                          |   11 
 b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c               |    1 
 b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c               |    2 
 b/drivers/net/ethernet/atheros/atlx/atl2.c                      |    1 
 b/drivers/net/ethernet/chelsio/cxgb3/adapter.h                  |    1 
 b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c               |    2 
 b/drivers/net/ethernet/chelsio/cxgb3/sge.c                      |   44 
 b/drivers/net/ethernet/chelsio/cxgb4/sge.c                      |    3 
 b/drivers/net/ethernet/cisco/enic/enic.h                        |    1 
 b/drivers/net/ethernet/cisco/enic/enic_api.c                    |    6 
 b/drivers/net/ethernet/cisco/enic/enic_main.c                   |   27 
 b/drivers/net/ethernet/freescale/fec_mpc52xx.c                  |   10 
 b/drivers/net/ethernet/intel/e100.c                             |    4 
 b/drivers/net/ethernet/intel/e1000/e1000_main.c                 |    1 
 b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c                  |    2 
 b/drivers/net/ethernet/intel/i40e/i40e_main.c                   |    4 
 b/drivers/net/ethernet/intel/ice/ice_main.c                     |    1 
 b/drivers/net/ethernet/intel/igb/igb_main.c                     |    1 
 b/drivers/net/ethernet/intel/igc/igc_main.c                     |    1 
 b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c                 |    1 
 b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c             |    2 
 b/drivers/net/ethernet/natsemi/sonic.c                          |   24 
 b/drivers/net/ethernet/natsemi/sonic.h                          |    2 
 b/drivers/net/ethernet/neterion/vxge/vxge-config.c              |    9 
 b/drivers/net/ethernet/neterion/vxge/vxge-config.h              |    7 
 b/drivers/net/ethernet/pensando/ionic/ionic_dev.c               |    2 
 b/drivers/net/ethernet/pensando/ionic/ionic_lif.c               |   43 
 b/drivers/net/ethernet/pensando/ionic/ionic_lif.h               |    2 
 b/drivers/net/ethernet/pensando/ionic/ionic_main.c              |    4 
 b/drivers/net/ethernet/sfc/ef10.c                               |   18 
 b/drivers/net/ethernet/sfc/ef100_nic.c                          |    3 
 b/drivers/net/ethernet/sfc/efx_common.c                         |    6 
 b/drivers/net/ethernet/sfc/ethtool_common.c                     |    2 
 b/drivers/net/ethernet/sfc/net_driver.h                         |    3 
 b/drivers/net/ethernet/sfc/siena.c                              |    3 
 b/drivers/net/ethernet/sun/sunbmac.c                            |   18 
 b/drivers/net/phy/mdio_bus.c                                    |   15 
 b/drivers/net/usb/kaweth.c                                      |  261 --
 b/drivers/net/usb/net1080.c                                     |    1 
 b/drivers/net/wan/lmc/lmc_debug.c                               |   18 
 b/drivers/net/wan/lmc/lmc_debug.h                               |    1 
 b/drivers/net/wan/lmc/lmc_main.c                                |  105 -
 b/drivers/net/wan/lmc/lmc_media.c                               |    4 
 b/drivers/net/wan/lmc/lmc_proto.c                               |   16 
 b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c     |    4 
 b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h        |    5 
 b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c       |   20 
 b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c       |    8 
 b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h       |    7 
 b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c     |    2 
 b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c       |   12 
 b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h       |    2 
 b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c        |    2 
 b/drivers/net/wireless/intel/ipw2x00/ipw2100.c                  |    3 
 b/drivers/net/wireless/intel/ipw2x00/ipw2200.h                  |    6 
 b/drivers/net/wireless/intel/ipw2x00/libipw.h                   |    3 
 b/drivers/net/wireless/intel/iwlegacy/common.h                  |    4 
 b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c                |    5 
 b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h         |    6 
 b/drivers/net/wireless/intersil/hostap/hostap_hw.c              |   12 
 b/drivers/net/wireless/marvell/libertas/defs.h                  |    3 
 b/drivers/net/wireless/marvell/libertas/rx.c                    |   11 
 b/drivers/net/wireless/marvell/libertas_tf/deb_defs.h           |    3 
 b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c               |    6 
 b/drivers/net/wireless/marvell/mwifiex/util.c                   |    6 
 b/drivers/net/wireless/realtek/rtlwifi/base.c                   |   47 
 b/drivers/net/wireless/realtek/rtlwifi/base.h                   |    3 
 b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c |   12 
 b/drivers/net/wireless/realtek/rtlwifi/core.c                   |    6 
 b/drivers/net/wireless/realtek/rtlwifi/debug.c                  |   20 
 b/drivers/net/wireless/realtek/rtlwifi/debug.h                  |    6 
 b/drivers/net/wireless/realtek/rtlwifi/pci.c                    |    4 
 b/drivers/net/wireless/realtek/rtlwifi/ps.c                     |   27 
 b/drivers/net/wireless/realtek/rtlwifi/ps.h                     |   10 
 b/drivers/net/wireless/realtek/rtlwifi/wifi.h                   |    3 
 b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c                  |    1 
 b/include/linux/netdevice.h                                     |    1 
 b/net/core/dev.c                                                |   15 
 drivers/net/caif/caif_spi.c                                     |  874 ----------
 drivers/net/caif/caif_spi_slave.c                               |  254 --
 include/net/caif/caif_spi.h                                     |  155 -
 86 files changed, 300 insertions(+), 2233 deletions(-)

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 01/35] net: enic: Cure the enic api locking trainwreck
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 19:48 ` [patch 02/35] net: caif: Remove unused caif SPI driver Thomas Gleixner
                   ` (35 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jakub Kicinski, netdev, David S. Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Sebastian Andrzej Siewior,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Thomas Gleixner <tglx@linutronix.de>

enic_dev_wait() has a BUG_ON(in_interrupt()).

Chasing the callers of enic_dev_wait() revealed the gems of enic_reset()
and enic_tx_hang_reset() which are both invoked through work queues in
order to be able to call rtnl_lock(). So far so good.

After locking rtnl both functions acquire enic::enic_api_lock which
serializes against the (ab)use from infiniband. This is where the
trainwreck starts.

enic::enic_api_lock is a spin_lock() which implicitly disables preemption,
but both functions invoke a ton of functions under that lock which can
sleep. The BUG_ON(in_interrupt()) does not trigger in that case because it
can't detect the preempt disabled condition.

This clearly has never been tested with any of the mandatory debug options
for 7+ years, which would have caught that for sure.

Cure it by adding a enic_api_busy member to struct enic, which is modified
and evaluated with enic::enic_api_lock held.

If enic_api_devcmd_proxy_by_index() observes enic::enic_api_busy as true,
it drops enic::enic_api_lock and busy waits for enic::enic_api_busy to
become false.

It would be smarter to wait for a completion of that busy period, but
enic_api_devcmd_proxy_by_index() is called with other spin locks held which
obviously can't sleep.

Remove the BUG_ON(in_interrupt()) check as well because it's incomplete and
with proper debugging enabled the problem would have been caught from the
debug checks in schedule_timeout().

Fixes: 0b038566c0ea ("drivers/net: enic: Add an interface for USNIC to interact with firmware")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Christian Benvenuti <benve@cisco.com>
Cc: Govindarajulu Varadarajan <_govind@gmx.com>
Cc: Dave Miller <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/cisco/enic/enic.h      |    1 +
 drivers/net/ethernet/cisco/enic/enic_api.c  |    6 ++++++
 drivers/net/ethernet/cisco/enic/enic_main.c |   27 +++++++++++++++++++++------
 3 files changed, 28 insertions(+), 6 deletions(-)

--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -169,6 +169,7 @@ struct enic {
 	u16 num_vfs;
 #endif
 	spinlock_t enic_api_lock;
+	bool enic_api_busy;
 	struct enic_port_profile *pp;
 
 	/* work queue cache line section */
--- a/drivers/net/ethernet/cisco/enic/enic_api.c
+++ b/drivers/net/ethernet/cisco/enic/enic_api.c
@@ -34,6 +34,12 @@ int enic_api_devcmd_proxy_by_index(struc
 	struct vnic_dev *vdev = enic->vdev;
 
 	spin_lock(&enic->enic_api_lock);
+	while (enic->enic_api_busy) {
+		spin_unlock(&enic->enic_api_lock);
+		cpu_relax();
+		spin_lock(&enic->enic_api_lock);
+	}
+
 	spin_lock_bh(&enic->devcmd_lock);
 
 	vnic_dev_cmd_proxy_by_index_start(vdev, vf);
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2106,8 +2106,6 @@ static int enic_dev_wait(struct vnic_dev
 	int done;
 	int err;
 
-	BUG_ON(in_interrupt());
-
 	err = start(vdev, arg);
 	if (err)
 		return err;
@@ -2295,6 +2293,13 @@ static int enic_set_rss_nic_cfg(struct e
 		rss_hash_bits, rss_base_cpu, rss_enable);
 }
 
+static void enic_set_api_busy(struct enic *enic, bool busy)
+{
+	spin_lock(&enic->enic_api_lock);
+	enic->enic_api_busy = busy;
+	spin_unlock(&enic->enic_api_lock);
+}
+
 static void enic_reset(struct work_struct *work)
 {
 	struct enic *enic = container_of(work, struct enic, reset);
@@ -2304,7 +2309,9 @@ static void enic_reset(struct work_struc
 
 	rtnl_lock();
 
-	spin_lock(&enic->enic_api_lock);
+	/* Stop any activity from infiniband */
+	enic_set_api_state(enic, true);
+
 	enic_stop(enic->netdev);
 	enic_dev_soft_reset(enic);
 	enic_reset_addr_lists(enic);
@@ -2312,7 +2319,10 @@ static void enic_reset(struct work_struc
 	enic_set_rss_nic_cfg(enic);
 	enic_dev_set_ig_vlan_rewrite_mode(enic);
 	enic_open(enic->netdev);
-	spin_unlock(&enic->enic_api_lock);
+
+	/* Allow infiniband to fiddle with the device again */
+	enic_set_api_state(enic, false);
+
 	call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev);
 
 	rtnl_unlock();
@@ -2324,7 +2334,9 @@ static void enic_tx_hang_reset(struct wo
 
 	rtnl_lock();
 
-	spin_lock(&enic->enic_api_lock);
+	/* Stop any activity from infiniband */
+	enic_set_api_state(enic, true);
+
 	enic_dev_hang_notify(enic);
 	enic_stop(enic->netdev);
 	enic_dev_hang_reset(enic);
@@ -2333,7 +2345,10 @@ static void enic_tx_hang_reset(struct wo
 	enic_set_rss_nic_cfg(enic);
 	enic_dev_set_ig_vlan_rewrite_mode(enic);
 	enic_open(enic->netdev);
-	spin_unlock(&enic->enic_api_lock);
+
+	/* Allow infiniband to fiddle with the device again */
+	enic_set_api_state(enic, false);
+
 	call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev);
 
 	rtnl_unlock();


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 02/35] net: caif: Remove unused caif SPI driver
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
  2020-09-27 19:48 ` [patch 01/35] net: enic: Cure the enic api locking trainwreck Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 19:48 ` [patch 03/35] net: Add netif_rx_any_context() Thomas Gleixner
                   ` (34 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	David S. Miller, Jakub Kicinski, Jonathan Corbet,
	Mauro Carvalho Chehab, netdev, linux-doc, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller,
	Sebastian Andrzej Siewior, Luc Van Oostenryck, Jay Cliburn,
	Chris Snook, Vishal Kulkarni, Jeff Kirsher, intel-wired-lan,
	Shannon Nelson, Pensando Drivers, Andrew Lunn, Heiner Kallweit,
	Russell King, Thomas Bogendoerfer, Solarflare linux maintainers,
	Edward Cree, Martin Habets, Jon Mason, Daniel Drake,
	Ulrich Kunitz, Kalle Valo, linux-wireless, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Thomas Gleixner <tglx@linutronix.de>

While chasing in_interrupt() (ab)use in drivers it turned out that the
caif_spi driver has never been in use since the driver was merged 10 years
ago. There never was any matching code which provides a platform device.

The driver has not seen any update (asided of treewide changes and
cleanups) since 8 years and the maintainers vanished from the planet.

So analysing the potential contexts and the (in)correctness of
in_interrupt() usage is just a pointless exercise.

Remove the cruft.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Cc: netdev@vger.kernel.org
Cc: linux-doc@vger.kernel.org
---
 Documentation/networking/caif/index.rst       |    1 
 Documentation/networking/caif/spi_porting.rst |  229 ------
 drivers/net/caif/Kconfig                      |   19 
 drivers/net/caif/Makefile                     |    4 
 drivers/net/caif/caif_spi.c                   |  874 --------------------------
 drivers/net/caif/caif_spi_slave.c             |  254 -------
 include/net/caif/caif_spi.h                   |  155 ----
 7 files changed, 1536 deletions(-)

--- a/Documentation/networking/caif/index.rst
+++ b/Documentation/networking/caif/index.rst
@@ -10,4 +10,3 @@ CAIF
 
    linux_caif
    caif
-   spi_porting
--- a/Documentation/networking/caif/spi_porting.rst
+++ /dev/null
@@ -1,229 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-================
-CAIF SPI porting
-================
-
-CAIF SPI basics
-===============
-
-Running CAIF over SPI needs some extra setup, owing to the nature of SPI.
-Two extra GPIOs have been added in order to negotiate the transfers
-between the master and the slave. The minimum requirement for running
-CAIF over SPI is a SPI slave chip and two GPIOs (more details below).
-Please note that running as a slave implies that you need to keep up
-with the master clock. An overrun or underrun event is fatal.
-
-CAIF SPI framework
-==================
-
-To make porting as easy as possible, the CAIF SPI has been divided in
-two parts. The first part (called the interface part) deals with all
-generic functionality such as length framing, SPI frame negotiation
-and SPI frame delivery and transmission. The other part is the CAIF
-SPI slave device part, which is the module that you have to write if
-you want to run SPI CAIF on a new hardware. This part takes care of
-the physical hardware, both with regard to SPI and to GPIOs.
-
-- Implementing a CAIF SPI device:
-
-	- Functionality provided by the CAIF SPI slave device:
-
-	In order to implement a SPI device you will, as a minimum,
-	need to implement the following
-	functions:
-
-	::
-
-	    int (*init_xfer) (struct cfspi_xfer * xfer, struct cfspi_dev *dev):
-
-	This function is called by the CAIF SPI interface to give
-	you a chance to set up your hardware to be ready to receive
-	a stream of data from the master. The xfer structure contains
-	both physical and logical addresses, as well as the total length
-	of the transfer in both directions.The dev parameter can be used
-	to map to different CAIF SPI slave devices.
-
-	::
-
-	    void (*sig_xfer) (bool xfer, struct cfspi_dev *dev):
-
-	This function is called by the CAIF SPI interface when the output
-	(SPI_INT) GPIO needs to change state. The boolean value of the xfer
-	variable indicates whether the GPIO should be asserted (HIGH) or
-	deasserted (LOW). The dev parameter can be used to map to different CAIF
-	SPI slave devices.
-
-	- Functionality provided by the CAIF SPI interface:
-
-	::
-
-	    void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
-
-	This function is called by the CAIF SPI slave device in order to
-	signal a change of state of the input GPIO (SS) to the interface.
-	Only active edges are mandatory to be reported.
-	This function can be called from IRQ context (recommended in order
-	not to introduce latency). The ifc parameter should be the pointer
-	returned from the platform probe function in the SPI device structure.
-
-	::
-
-	    void (*xfer_done_cb) (struct cfspi_ifc *ifc);
-
-	This function is called by the CAIF SPI slave device in order to
-	report that a transfer is completed. This function should only be
-	called once both the transmission and the reception are completed.
-	This function can be called from IRQ context (recommended in order
-	not to introduce latency). The ifc parameter should be the pointer
-	returned from the platform probe function in the SPI device structure.
-
-	- Connecting the bits and pieces:
-
-		- Filling in the SPI slave device structure:
-
-		  Connect the necessary callback functions.
-
-		  Indicate clock speed (used to calculate toggle delays).
-
-		  Chose a suitable name (helps debugging if you use several CAIF
-		  SPI slave devices).
-
-		  Assign your private data (can be used to map to your
-		  structure).
-
-		- Filling in the SPI slave platform device structure:
-
-		  Add name of driver to connect to ("cfspi_sspi").
-
-		  Assign the SPI slave device structure as platform data.
-
-Padding
-=======
-
-In order to optimize throughput, a number of SPI padding options are provided.
-Padding can be enabled independently for uplink and downlink transfers.
-Padding can be enabled for the head, the tail and for the total frame size.
-The padding needs to be correctly configured on both sides of the link.
-The padding can be changed via module parameters in cfspi_sspi.c or via
-the sysfs directory of the cfspi_sspi driver (before device registration).
-
-- CAIF SPI device template::
-
-    /*
-    *	Copyright (C) ST-Ericsson AB 2010
-    *	Author: Daniel Martensson / Daniel.Martensson@stericsson.com
-    *	License terms: GNU General Public License (GPL), version 2.
-    *
-    */
-
-    #include <linux/init.h>
-    #include <linux/module.h>
-    #include <linux/device.h>
-    #include <linux/wait.h>
-    #include <linux/interrupt.h>
-    #include <linux/dma-mapping.h>
-    #include <net/caif/caif_spi.h>
-
-    MODULE_LICENSE("GPL");
-
-    struct sspi_struct {
-	    struct cfspi_dev sdev;
-	    struct cfspi_xfer *xfer;
-    };
-
-    static struct sspi_struct slave;
-    static struct platform_device slave_device;
-
-    static irqreturn_t sspi_irq(int irq, void *arg)
-    {
-	    /* You only need to trigger on an edge to the active state of the
-	    * SS signal. Once a edge is detected, the ss_cb() function should be
-	    * called with the parameter assert set to true. It is OK
-	    * (and even advised) to call the ss_cb() function in IRQ context in
-	    * order not to add any delay. */
-
-	    return IRQ_HANDLED;
-    }
-
-    static void sspi_complete(void *context)
-    {
-	    /* Normally the DMA or the SPI framework will call you back
-	    * in something similar to this. The only thing you need to
-	    * do is to call the xfer_done_cb() function, providing the pointer
-	    * to the CAIF SPI interface. It is OK to call this function
-	    * from IRQ context. */
-    }
-
-    static int sspi_init_xfer(struct cfspi_xfer *xfer, struct cfspi_dev *dev)
-    {
-	    /* Store transfer info. For a normal implementation you should
-	    * set up your DMA here and make sure that you are ready to
-	    * receive the data from the master SPI. */
-
-	    struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
-
-	    sspi->xfer = xfer;
-
-	    return 0;
-    }
-
-    void sspi_sig_xfer(bool xfer, struct cfspi_dev *dev)
-    {
-	    /* If xfer is true then you should assert the SPI_INT to indicate to
-	    * the master that you are ready to receive the data from the master
-	    * SPI. If xfer is false then you should de-assert SPI_INT to indicate
-	    * that the transfer is done.
-	    */
-
-	    struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
-    }
-
-    static void sspi_release(struct device *dev)
-    {
-	    /*
-	    * Here you should release your SPI device resources.
-	    */
-    }
-
-    static int __init sspi_init(void)
-    {
-	    /* Here you should initialize your SPI device by providing the
-	    * necessary functions, clock speed, name and private data. Once
-	    * done, you can register your device with the
-	    * platform_device_register() function. This function will return
-	    * with the CAIF SPI interface initialized. This is probably also
-	    * the place where you should set up your GPIOs, interrupts and SPI
-	    * resources. */
-
-	    int res = 0;
-
-	    /* Initialize slave device. */
-	    slave.sdev.init_xfer = sspi_init_xfer;
-	    slave.sdev.sig_xfer = sspi_sig_xfer;
-	    slave.sdev.clk_mhz = 13;
-	    slave.sdev.priv = &slave;
-	    slave.sdev.name = "spi_sspi";
-	    slave_device.dev.release = sspi_release;
-
-	    /* Initialize platform device. */
-	    slave_device.name = "cfspi_sspi";
-	    slave_device.dev.platform_data = &slave.sdev;
-
-	    /* Register platform device. */
-	    res = platform_device_register(&slave_device);
-	    if (res) {
-		    printk(KERN_WARNING "sspi_init: failed to register dev.\n");
-		    return -ENODEV;
-	    }
-
-	    return res;
-    }
-
-    static void __exit sspi_exit(void)
-    {
-	    platform_device_del(&slave_device);
-    }
-
-    module_init(sspi_init);
-    module_exit(sspi_exit);
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -20,25 +20,6 @@ config CAIF_TTY
 	  identified as N_CAIF. When this ldisc is opened from user space
 	  it will redirect the TTY's traffic into the CAIF stack.
 
-config CAIF_SPI_SLAVE
-	tristate "CAIF SPI transport driver for slave interface"
-	depends on CAIF && HAS_DMA
-	default n
-	help
-	  The CAIF Link layer SPI Protocol driver for Slave SPI interface.
-	  This driver implements a platform driver to accommodate for a
-	  platform specific SPI device. A sample CAIF SPI Platform device is
-	  provided in <file:Documentation/networking/caif/spi_porting.rst>.
-
-config CAIF_SPI_SYNC
-	bool "Next command and length in start of frame"
-	depends on CAIF_SPI_SLAVE
-	default n
-	help
-	  Putting the next command and length in the start of the frame can
-	  help to synchronize to the next transfer in case of over or under-runs.
-	  This option also needs to be enabled on the modem.
-
 config CAIF_HSI
 	tristate "CAIF HSI transport driver"
 	depends on CAIF
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -4,10 +4,6 @@ ccflags-$(CONFIG_CAIF_DEBUG) := -DDEBUG
 # Serial interface
 obj-$(CONFIG_CAIF_TTY) += caif_serial.o
 
-# SPI slave physical interfaces module
-cfspi_slave-objs := caif_spi.o caif_spi_slave.o
-obj-$(CONFIG_CAIF_SPI_SLAVE) += cfspi_slave.o
-
 # HSI interface
 obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
 
--- a/drivers/net/caif/caif_spi.c
+++ /dev/null
@@ -1,874 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) ST-Ericsson AB 2010
- * Author:  Daniel Martensson
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/string.h>
-#include <linux/workqueue.h>
-#include <linux/completion.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/debugfs.h>
-#include <linux/if_arp.h>
-#include <net/caif/caif_layer.h>
-#include <net/caif/caif_spi.h>
-
-#ifndef CONFIG_CAIF_SPI_SYNC
-#define FLAVOR "Flavour: Vanilla.\n"
-#else
-#define FLAVOR "Flavour: Master CMD&LEN at start.\n"
-#endif /* CONFIG_CAIF_SPI_SYNC */
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Daniel Martensson");
-MODULE_DESCRIPTION("CAIF SPI driver");
-
-/* Returns the number of padding bytes for alignment. */
-#define PAD_POW2(x, pow) ((((x)&((pow)-1))==0) ? 0 : (((pow)-((x)&((pow)-1)))))
-
-static bool spi_loop;
-module_param(spi_loop, bool, 0444);
-MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode.");
-
-/* SPI frame alignment. */
-module_param(spi_frm_align, int, 0444);
-MODULE_PARM_DESC(spi_frm_align, "SPI frame alignment.");
-
-/*
- * SPI padding options.
- * Warning: must be a base of 2 (& operation used) and can not be zero !
- */
-module_param(spi_up_head_align, int, 0444);
-MODULE_PARM_DESC(spi_up_head_align, "SPI uplink head alignment.");
-
-module_param(spi_up_tail_align, int, 0444);
-MODULE_PARM_DESC(spi_up_tail_align, "SPI uplink tail alignment.");
-
-module_param(spi_down_head_align, int, 0444);
-MODULE_PARM_DESC(spi_down_head_align, "SPI downlink head alignment.");
-
-module_param(spi_down_tail_align, int, 0444);
-MODULE_PARM_DESC(spi_down_tail_align, "SPI downlink tail alignment.");
-
-#ifdef CONFIG_ARM
-#define BYTE_HEX_FMT "%02X"
-#else
-#define BYTE_HEX_FMT "%02hhX"
-#endif
-
-#define SPI_MAX_PAYLOAD_SIZE 4096
-/*
- * Threshold values for the SPI packet queue. Flowcontrol will be asserted
- * when the number of packets exceeds HIGH_WATER_MARK. It will not be
- * deasserted before the number of packets drops below LOW_WATER_MARK.
- */
-#define LOW_WATER_MARK   100
-#define HIGH_WATER_MARK  (LOW_WATER_MARK*5)
-
-#ifndef CONFIG_HAS_DMA
-
-/*
- * We sometimes use UML for debugging, but it cannot handle
- * dma_alloc_coherent so we have to wrap it.
- */
-static inline void *dma_alloc(struct cfspi *cfspi, dma_addr_t *daddr)
-{
-	return kmalloc(SPI_DMA_BUF_LEN, GFP_KERNEL);
-}
-
-static inline void dma_free(struct cfspi *cfspi, void *cpu_addr,
-		dma_addr_t handle)
-{
-	kfree(cpu_addr);
-}
-
-#else
-
-static inline void *dma_alloc(struct cfspi *cfspi, dma_addr_t *daddr)
-{
-	return dma_alloc_coherent(&cfspi->pdev->dev, SPI_DMA_BUF_LEN, daddr,
-				GFP_KERNEL);
-}
-
-static inline void dma_free(struct cfspi *cfspi, void *cpu_addr,
-		dma_addr_t handle)
-{
-	dma_free_coherent(&cfspi->pdev->dev, SPI_DMA_BUF_LEN, cpu_addr, handle);
-}
-#endif	/* CONFIG_HAS_DMA */
-
-#ifdef CONFIG_DEBUG_FS
-
-#define DEBUGFS_BUF_SIZE	4096
-
-static struct dentry *dbgfs_root;
-
-static inline void driver_debugfs_create(void)
-{
-	dbgfs_root = debugfs_create_dir(cfspi_spi_driver.driver.name, NULL);
-}
-
-static inline void driver_debugfs_remove(void)
-{
-	debugfs_remove(dbgfs_root);
-}
-
-static inline void dev_debugfs_rem(struct cfspi *cfspi)
-{
-	debugfs_remove(cfspi->dbgfs_frame);
-	debugfs_remove(cfspi->dbgfs_state);
-	debugfs_remove(cfspi->dbgfs_dir);
-}
-
-static ssize_t dbgfs_state(struct file *file, char __user *user_buf,
-			   size_t count, loff_t *ppos)
-{
-	char *buf;
-	int len = 0;
-	ssize_t size;
-	struct cfspi *cfspi = file->private_data;
-
-	buf = kzalloc(DEBUGFS_BUF_SIZE, GFP_KERNEL);
-	if (!buf)
-		return 0;
-
-	/* Print out debug information. */
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "CAIF SPI debug information:\n");
-
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len), FLAVOR);
-
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "STATE: %d\n", cfspi->dbg_state);
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Previous CMD: 0x%x\n", cfspi->pcmd);
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Current CMD: 0x%x\n", cfspi->cmd);
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Previous TX len: %d\n", cfspi->tx_ppck_len);
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Previous RX len: %d\n", cfspi->rx_ppck_len);
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Current TX len: %d\n", cfspi->tx_cpck_len);
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Current RX len: %d\n", cfspi->rx_cpck_len);
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Next TX len: %d\n", cfspi->tx_npck_len);
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Next RX len: %d\n", cfspi->rx_npck_len);
-
-	if (len > DEBUGFS_BUF_SIZE)
-		len = DEBUGFS_BUF_SIZE;
-
-	size = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-	kfree(buf);
-
-	return size;
-}
-
-static ssize_t print_frame(char *buf, size_t size, char *frm,
-			   size_t count, size_t cut)
-{
-	int len = 0;
-	int i;
-	for (i = 0; i < count; i++) {
-		len += scnprintf((buf + len), (size - len),
-					"[0x" BYTE_HEX_FMT "]",
-					frm[i]);
-		if ((i == cut) && (count > (cut * 2))) {
-			/* Fast forward. */
-			i = count - cut;
-			len += scnprintf((buf + len), (size - len),
-					 "--- %zu bytes skipped ---\n",
-					 count - (cut * 2));
-		}
-
-		if ((!(i % 10)) && i) {
-			len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-					 "\n");
-		}
-	}
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len), "\n");
-	return len;
-}
-
-static ssize_t dbgfs_frame(struct file *file, char __user *user_buf,
-			   size_t count, loff_t *ppos)
-{
-	char *buf;
-	int len = 0;
-	ssize_t size;
-	struct cfspi *cfspi;
-
-	cfspi = file->private_data;
-	buf = kzalloc(DEBUGFS_BUF_SIZE, GFP_KERNEL);
-	if (!buf)
-		return 0;
-
-	/* Print out debug information. */
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Current frame:\n");
-
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Tx data (Len: %d):\n", cfspi->tx_cpck_len);
-
-	len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len),
-			   cfspi->xfer.va_tx[0],
-			   (cfspi->tx_cpck_len + SPI_CMD_SZ), 100);
-
-	len += scnprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
-			 "Rx data (Len: %d):\n", cfspi->rx_cpck_len);
-
-	len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len),
-			   cfspi->xfer.va_rx,
-			   (cfspi->rx_cpck_len + SPI_CMD_SZ), 100);
-
-	size = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-	kfree(buf);
-
-	return size;
-}
-
-static const struct file_operations dbgfs_state_fops = {
-	.open = simple_open,
-	.read = dbgfs_state,
-	.owner = THIS_MODULE
-};
-
-static const struct file_operations dbgfs_frame_fops = {
-	.open = simple_open,
-	.read = dbgfs_frame,
-	.owner = THIS_MODULE
-};
-
-static inline void dev_debugfs_add(struct cfspi *cfspi)
-{
-	cfspi->dbgfs_dir = debugfs_create_dir(cfspi->pdev->name, dbgfs_root);
-	cfspi->dbgfs_state = debugfs_create_file("state", 0444,
-						 cfspi->dbgfs_dir, cfspi,
-						 &dbgfs_state_fops);
-	cfspi->dbgfs_frame = debugfs_create_file("frame", 0444,
-						 cfspi->dbgfs_dir, cfspi,
-						 &dbgfs_frame_fops);
-}
-
-inline void cfspi_dbg_state(struct cfspi *cfspi, int state)
-{
-	cfspi->dbg_state = state;
-};
-#else
-
-static inline void driver_debugfs_create(void)
-{
-}
-
-static inline void driver_debugfs_remove(void)
-{
-}
-
-static inline void dev_debugfs_add(struct cfspi *cfspi)
-{
-}
-
-static inline void dev_debugfs_rem(struct cfspi *cfspi)
-{
-}
-
-inline void cfspi_dbg_state(struct cfspi *cfspi, int state)
-{
-}
-#endif				/* CONFIG_DEBUG_FS */
-
-static LIST_HEAD(cfspi_list);
-static spinlock_t cfspi_list_lock;
-
-/* SPI uplink head alignment. */
-static ssize_t up_head_align_show(struct device_driver *driver, char *buf)
-{
-	return sprintf(buf, "%d\n", spi_up_head_align);
-}
-
-static DRIVER_ATTR_RO(up_head_align);
-
-/* SPI uplink tail alignment. */
-static ssize_t up_tail_align_show(struct device_driver *driver, char *buf)
-{
-	return sprintf(buf, "%d\n", spi_up_tail_align);
-}
-
-static DRIVER_ATTR_RO(up_tail_align);
-
-/* SPI downlink head alignment. */
-static ssize_t down_head_align_show(struct device_driver *driver, char *buf)
-{
-	return sprintf(buf, "%d\n", spi_down_head_align);
-}
-
-static DRIVER_ATTR_RO(down_head_align);
-
-/* SPI downlink tail alignment. */
-static ssize_t down_tail_align_show(struct device_driver *driver, char *buf)
-{
-	return sprintf(buf, "%d\n", spi_down_tail_align);
-}
-
-static DRIVER_ATTR_RO(down_tail_align);
-
-/* SPI frame alignment. */
-static ssize_t frame_align_show(struct device_driver *driver, char *buf)
-{
-	return sprintf(buf, "%d\n", spi_frm_align);
-}
-
-static DRIVER_ATTR_RO(frame_align);
-
-int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len)
-{
-	u8 *dst = buf;
-	caif_assert(buf);
-
-	if (cfspi->slave && !cfspi->slave_talked)
-		cfspi->slave_talked = true;
-
-	do {
-		struct sk_buff *skb;
-		struct caif_payload_info *info;
-		int spad = 0;
-		int epad;
-
-		skb = skb_dequeue(&cfspi->chead);
-		if (!skb)
-			break;
-
-		/*
-		 * Calculate length of frame including SPI padding.
-		 * The payload position is found in the control buffer.
-		 */
-		info = (struct caif_payload_info *)&skb->cb;
-
-		/*
-		 * Compute head offset i.e. number of bytes to add to
-		 * get the start of the payload aligned.
-		 */
-		if (spi_up_head_align > 1) {
-			spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align);
-			*dst = (u8)(spad - 1);
-			dst += spad;
-		}
-
-		/* Copy in CAIF frame. */
-		skb_copy_bits(skb, 0, dst, skb->len);
-		dst += skb->len;
-		cfspi->ndev->stats.tx_packets++;
-		cfspi->ndev->stats.tx_bytes += skb->len;
-
-		/*
-		 * Compute tail offset i.e. number of bytes to add to
-		 * get the complete CAIF frame aligned.
-		 */
-		epad = PAD_POW2((skb->len + spad), spi_up_tail_align);
-		dst += epad;
-
-		dev_kfree_skb(skb);
-
-	} while ((dst - buf) < len);
-
-	return dst - buf;
-}
-
-int cfspi_xmitlen(struct cfspi *cfspi)
-{
-	struct sk_buff *skb = NULL;
-	int frm_len = 0;
-	int pkts = 0;
-
-	/*
-	 * Decommit previously committed frames.
-	 * skb_queue_splice_tail(&cfspi->chead,&cfspi->qhead)
-	 */
-	while (skb_peek(&cfspi->chead)) {
-		skb = skb_dequeue_tail(&cfspi->chead);
-		skb_queue_head(&cfspi->qhead, skb);
-	}
-
-	do {
-		struct caif_payload_info *info = NULL;
-		int spad = 0;
-		int epad = 0;
-
-		skb = skb_dequeue(&cfspi->qhead);
-		if (!skb)
-			break;
-
-		/*
-		 * Calculate length of frame including SPI padding.
-		 * The payload position is found in the control buffer.
-		 */
-		info = (struct caif_payload_info *)&skb->cb;
-
-		/*
-		 * Compute head offset i.e. number of bytes to add to
-		 * get the start of the payload aligned.
-		 */
-		if (spi_up_head_align > 1)
-			spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align);
-
-		/*
-		 * Compute tail offset i.e. number of bytes to add to
-		 * get the complete CAIF frame aligned.
-		 */
-		epad = PAD_POW2((skb->len + spad), spi_up_tail_align);
-
-		if ((skb->len + spad + epad + frm_len) <= CAIF_MAX_SPI_FRAME) {
-			skb_queue_tail(&cfspi->chead, skb);
-			pkts++;
-			frm_len += skb->len + spad + epad;
-		} else {
-			/* Put back packet. */
-			skb_queue_head(&cfspi->qhead, skb);
-			break;
-		}
-	} while (pkts <= CAIF_MAX_SPI_PKTS);
-
-	/*
-	 * Send flow on if previously sent flow off
-	 * and now go below the low water mark
-	 */
-	if (cfspi->flow_off_sent && cfspi->qhead.qlen < cfspi->qd_low_mark &&
-		cfspi->cfdev.flowctrl) {
-		cfspi->flow_off_sent = 0;
-		cfspi->cfdev.flowctrl(cfspi->ndev, 1);
-	}
-
-	return frm_len;
-}
-
-static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc)
-{
-	struct cfspi *cfspi = (struct cfspi *)ifc->priv;
-
-	/*
-	 * The slave device is the master on the link. Interrupts before the
-	 * slave has transmitted are considered spurious.
-	 */
-	if (cfspi->slave && !cfspi->slave_talked) {
-		printk(KERN_WARNING "CFSPI: Spurious SS interrupt.\n");
-		return;
-	}
-
-	if (!in_interrupt())
-		spin_lock(&cfspi->lock);
-	if (assert) {
-		set_bit(SPI_SS_ON, &cfspi->state);
-		set_bit(SPI_XFER, &cfspi->state);
-	} else {
-		set_bit(SPI_SS_OFF, &cfspi->state);
-	}
-	if (!in_interrupt())
-		spin_unlock(&cfspi->lock);
-
-	/* Wake up the xfer thread. */
-	if (assert)
-		wake_up_interruptible(&cfspi->wait);
-}
-
-static void cfspi_xfer_done_cb(struct cfspi_ifc *ifc)
-{
-	struct cfspi *cfspi = (struct cfspi *)ifc->priv;
-
-	/* Transfer done, complete work queue */
-	complete(&cfspi->comp);
-}
-
-static netdev_tx_t cfspi_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct cfspi *cfspi = NULL;
-	unsigned long flags;
-	if (!dev)
-		return -EINVAL;
-
-	cfspi = netdev_priv(dev);
-
-	skb_queue_tail(&cfspi->qhead, skb);
-
-	spin_lock_irqsave(&cfspi->lock, flags);
-	if (!test_and_set_bit(SPI_XFER, &cfspi->state)) {
-		/* Wake up xfer thread. */
-		wake_up_interruptible(&cfspi->wait);
-	}
-	spin_unlock_irqrestore(&cfspi->lock, flags);
-
-	/* Send flow off if number of bytes is above high water mark */
-	if (!cfspi->flow_off_sent &&
-		cfspi->qhead.qlen > cfspi->qd_high_mark &&
-		cfspi->cfdev.flowctrl) {
-		cfspi->flow_off_sent = 1;
-		cfspi->cfdev.flowctrl(cfspi->ndev, 0);
-	}
-
-	return NETDEV_TX_OK;
-}
-
-int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len)
-{
-	u8 *src = buf;
-
-	caif_assert(buf != NULL);
-
-	do {
-		int res;
-		struct sk_buff *skb = NULL;
-		int spad = 0;
-		int epad = 0;
-		int pkt_len = 0;
-
-		/*
-		 * Compute head offset i.e. number of bytes added to
-		 * get the start of the payload aligned.
-		 */
-		if (spi_down_head_align > 1) {
-			spad = 1 + *src;
-			src += spad;
-		}
-
-		/* Read length of CAIF frame (little endian). */
-		pkt_len = *src;
-		pkt_len |= ((*(src+1)) << 8) & 0xFF00;
-		pkt_len += 2;	/* Add FCS fields. */
-
-		/* Get a suitable caif packet and copy in data. */
-
-		skb = netdev_alloc_skb(cfspi->ndev, pkt_len + 1);
-		caif_assert(skb != NULL);
-
-		skb_put_data(skb, src, pkt_len);
-		src += pkt_len;
-
-		skb->protocol = htons(ETH_P_CAIF);
-		skb_reset_mac_header(skb);
-
-		/*
-		 * Push received packet up the stack.
-		 */
-		if (!spi_loop)
-			res = netif_rx_ni(skb);
-		else
-			res = cfspi_xmit(skb, cfspi->ndev);
-
-		if (!res) {
-			cfspi->ndev->stats.rx_packets++;
-			cfspi->ndev->stats.rx_bytes += pkt_len;
-		} else
-			cfspi->ndev->stats.rx_dropped++;
-
-		/*
-		 * Compute tail offset i.e. number of bytes added to
-		 * get the complete CAIF frame aligned.
-		 */
-		epad = PAD_POW2((pkt_len + spad), spi_down_tail_align);
-		src += epad;
-	} while ((src - buf) < len);
-
-	return src - buf;
-}
-
-static int cfspi_open(struct net_device *dev)
-{
-	netif_wake_queue(dev);
-	return 0;
-}
-
-static int cfspi_close(struct net_device *dev)
-{
-	netif_stop_queue(dev);
-	return 0;
-}
-
-static int cfspi_init(struct net_device *dev)
-{
-	int res = 0;
-	struct cfspi *cfspi = netdev_priv(dev);
-
-	/* Set flow info. */
-	cfspi->flow_off_sent = 0;
-	cfspi->qd_low_mark = LOW_WATER_MARK;
-	cfspi->qd_high_mark = HIGH_WATER_MARK;
-
-	/* Set slave info. */
-	if (!strncmp(cfspi_spi_driver.driver.name, "cfspi_sspi", 10)) {
-		cfspi->slave = true;
-		cfspi->slave_talked = false;
-	} else {
-		cfspi->slave = false;
-		cfspi->slave_talked = false;
-	}
-
-	/* Allocate DMA buffers. */
-	cfspi->xfer.va_tx[0] = dma_alloc(cfspi, &cfspi->xfer.pa_tx[0]);
-	if (!cfspi->xfer.va_tx[0]) {
-		res = -ENODEV;
-		goto err_dma_alloc_tx_0;
-	}
-
-	cfspi->xfer.va_rx = dma_alloc(cfspi, &cfspi->xfer.pa_rx);
-
-	if (!cfspi->xfer.va_rx) {
-		res = -ENODEV;
-		goto err_dma_alloc_rx;
-	}
-
-	/* Initialize the work queue. */
-	INIT_WORK(&cfspi->work, cfspi_xfer);
-
-	/* Initialize spin locks. */
-	spin_lock_init(&cfspi->lock);
-
-	/* Initialize flow control state. */
-	cfspi->flow_stop = false;
-
-	/* Initialize wait queue. */
-	init_waitqueue_head(&cfspi->wait);
-
-	/* Create work thread. */
-	cfspi->wq = create_singlethread_workqueue(dev->name);
-	if (!cfspi->wq) {
-		printk(KERN_WARNING "CFSPI: failed to create work queue.\n");
-		res = -ENODEV;
-		goto err_create_wq;
-	}
-
-	/* Initialize work queue. */
-	init_completion(&cfspi->comp);
-
-	/* Create debugfs entries. */
-	dev_debugfs_add(cfspi);
-
-	/* Set up the ifc. */
-	cfspi->ifc.ss_cb = cfspi_ss_cb;
-	cfspi->ifc.xfer_done_cb = cfspi_xfer_done_cb;
-	cfspi->ifc.priv = cfspi;
-
-	/* Add CAIF SPI device to list. */
-	spin_lock(&cfspi_list_lock);
-	list_add_tail(&cfspi->list, &cfspi_list);
-	spin_unlock(&cfspi_list_lock);
-
-	/* Schedule the work queue. */
-	queue_work(cfspi->wq, &cfspi->work);
-
-	return 0;
-
- err_create_wq:
-	dma_free(cfspi, cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
- err_dma_alloc_rx:
-	dma_free(cfspi, cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
- err_dma_alloc_tx_0:
-	return res;
-}
-
-static void cfspi_uninit(struct net_device *dev)
-{
-	struct cfspi *cfspi = netdev_priv(dev);
-
-	/* Remove from list. */
-	spin_lock(&cfspi_list_lock);
-	list_del(&cfspi->list);
-	spin_unlock(&cfspi_list_lock);
-
-	cfspi->ndev = NULL;
-	/* Free DMA buffers. */
-	dma_free(cfspi, cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
-	dma_free(cfspi, cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]);
-	set_bit(SPI_TERMINATE, &cfspi->state);
-	wake_up_interruptible(&cfspi->wait);
-	destroy_workqueue(cfspi->wq);
-	/* Destroy debugfs directory and files. */
-	dev_debugfs_rem(cfspi);
-	return;
-}
-
-static const struct net_device_ops cfspi_ops = {
-	.ndo_open = cfspi_open,
-	.ndo_stop = cfspi_close,
-	.ndo_init = cfspi_init,
-	.ndo_uninit = cfspi_uninit,
-	.ndo_start_xmit = cfspi_xmit
-};
-
-static void cfspi_setup(struct net_device *dev)
-{
-	struct cfspi *cfspi = netdev_priv(dev);
-	dev->features = 0;
-	dev->netdev_ops = &cfspi_ops;
-	dev->type = ARPHRD_CAIF;
-	dev->flags = IFF_NOARP | IFF_POINTOPOINT;
-	dev->priv_flags |= IFF_NO_QUEUE;
-	dev->mtu = SPI_MAX_PAYLOAD_SIZE;
-	dev->needs_free_netdev = true;
-	skb_queue_head_init(&cfspi->qhead);
-	skb_queue_head_init(&cfspi->chead);
-	cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
-	cfspi->cfdev.use_frag = false;
-	cfspi->cfdev.use_stx = false;
-	cfspi->cfdev.use_fcs = false;
-	cfspi->ndev = dev;
-}
-
-int cfspi_spi_probe(struct platform_device *pdev)
-{
-	struct cfspi *cfspi = NULL;
-	struct net_device *ndev;
-	struct cfspi_dev *dev;
-	int res;
-	dev = (struct cfspi_dev *)pdev->dev.platform_data;
-
-	if (!dev)
-		return -ENODEV;
-
-	ndev = alloc_netdev(sizeof(struct cfspi), "cfspi%d",
-			    NET_NAME_UNKNOWN, cfspi_setup);
-	if (!ndev)
-		return -ENOMEM;
-
-	cfspi = netdev_priv(ndev);
-	netif_stop_queue(ndev);
-	cfspi->ndev = ndev;
-	cfspi->pdev = pdev;
-
-	/* Assign the SPI device. */
-	cfspi->dev = dev;
-	/* Assign the device ifc to this SPI interface. */
-	dev->ifc = &cfspi->ifc;
-
-	/* Register network device. */
-	res = register_netdev(ndev);
-	if (res) {
-		printk(KERN_ERR "CFSPI: Reg. error: %d.\n", res);
-		goto err_net_reg;
-	}
-	return res;
-
- err_net_reg:
-	free_netdev(ndev);
-
-	return res;
-}
-
-int cfspi_spi_remove(struct platform_device *pdev)
-{
-	/* Everything is done in cfspi_uninit(). */
-	return 0;
-}
-
-static void __exit cfspi_exit_module(void)
-{
-	struct list_head *list_node;
-	struct list_head *n;
-	struct cfspi *cfspi = NULL;
-
-	list_for_each_safe(list_node, n, &cfspi_list) {
-		cfspi = list_entry(list_node, struct cfspi, list);
-		unregister_netdev(cfspi->ndev);
-	}
-
-	/* Destroy sysfs files. */
-	driver_remove_file(&cfspi_spi_driver.driver,
-			   &driver_attr_up_head_align);
-	driver_remove_file(&cfspi_spi_driver.driver,
-			   &driver_attr_up_tail_align);
-	driver_remove_file(&cfspi_spi_driver.driver,
-			   &driver_attr_down_head_align);
-	driver_remove_file(&cfspi_spi_driver.driver,
-			   &driver_attr_down_tail_align);
-	driver_remove_file(&cfspi_spi_driver.driver, &driver_attr_frame_align);
-	/* Unregister platform driver. */
-	platform_driver_unregister(&cfspi_spi_driver);
-	/* Destroy debugfs root directory. */
-	driver_debugfs_remove();
-}
-
-static int __init cfspi_init_module(void)
-{
-	int result;
-
-	/* Initialize spin lock. */
-	spin_lock_init(&cfspi_list_lock);
-
-	/* Register platform driver. */
-	result = platform_driver_register(&cfspi_spi_driver);
-	if (result) {
-		printk(KERN_ERR "Could not register platform SPI driver.\n");
-		goto err_dev_register;
-	}
-
-	/* Create sysfs files. */
-	result =
-	    driver_create_file(&cfspi_spi_driver.driver,
-			       &driver_attr_up_head_align);
-	if (result) {
-		printk(KERN_ERR "Sysfs creation failed 1.\n");
-		goto err_create_up_head_align;
-	}
-
-	result =
-	    driver_create_file(&cfspi_spi_driver.driver,
-			       &driver_attr_up_tail_align);
-	if (result) {
-		printk(KERN_ERR "Sysfs creation failed 2.\n");
-		goto err_create_up_tail_align;
-	}
-
-	result =
-	    driver_create_file(&cfspi_spi_driver.driver,
-			       &driver_attr_down_head_align);
-	if (result) {
-		printk(KERN_ERR "Sysfs creation failed 3.\n");
-		goto err_create_down_head_align;
-	}
-
-	result =
-	    driver_create_file(&cfspi_spi_driver.driver,
-			       &driver_attr_down_tail_align);
-	if (result) {
-		printk(KERN_ERR "Sysfs creation failed 4.\n");
-		goto err_create_down_tail_align;
-	}
-
-	result =
-	    driver_create_file(&cfspi_spi_driver.driver,
-			       &driver_attr_frame_align);
-	if (result) {
-		printk(KERN_ERR "Sysfs creation failed 5.\n");
-		goto err_create_frame_align;
-	}
-	driver_debugfs_create();
-	return result;
-
- err_create_frame_align:
-	driver_remove_file(&cfspi_spi_driver.driver,
-			   &driver_attr_down_tail_align);
- err_create_down_tail_align:
-	driver_remove_file(&cfspi_spi_driver.driver,
-			   &driver_attr_down_head_align);
- err_create_down_head_align:
-	driver_remove_file(&cfspi_spi_driver.driver,
-			   &driver_attr_up_tail_align);
- err_create_up_tail_align:
-	driver_remove_file(&cfspi_spi_driver.driver,
-			   &driver_attr_up_head_align);
- err_create_up_head_align:
-	platform_driver_unregister(&cfspi_spi_driver);
- err_dev_register:
-	return result;
-}
-
-module_init(cfspi_init_module);
-module_exit(cfspi_exit_module);
--- a/drivers/net/caif/caif_spi_slave.c
+++ /dev/null
@@ -1,254 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) ST-Ericsson AB 2010
- * Author:  Daniel Martensson
- */
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/string.h>
-#include <linux/semaphore.h>
-#include <linux/workqueue.h>
-#include <linux/completion.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/debugfs.h>
-#include <net/caif/caif_spi.h>
-
-#ifndef CONFIG_CAIF_SPI_SYNC
-#define SPI_DATA_POS 0
-static inline int forward_to_spi_cmd(struct cfspi *cfspi)
-{
-	return cfspi->rx_cpck_len;
-}
-#else
-#define SPI_DATA_POS SPI_CMD_SZ
-static inline int forward_to_spi_cmd(struct cfspi *cfspi)
-{
-	return 0;
-}
-#endif
-
-int spi_frm_align = 2;
-
-/*
- * SPI padding options.
- * Warning: must be a base of 2 (& operation used) and can not be zero !
- */
-int spi_up_head_align   = 1 << 1;
-int spi_up_tail_align   = 1 << 0;
-int spi_down_head_align = 1 << 2;
-int spi_down_tail_align = 1 << 1;
-
-#ifdef CONFIG_DEBUG_FS
-static inline void debugfs_store_prev(struct cfspi *cfspi)
-{
-	/* Store previous command for debugging reasons.*/
-	cfspi->pcmd = cfspi->cmd;
-	/* Store previous transfer. */
-	cfspi->tx_ppck_len = cfspi->tx_cpck_len;
-	cfspi->rx_ppck_len = cfspi->rx_cpck_len;
-}
-#else
-static inline void debugfs_store_prev(struct cfspi *cfspi)
-{
-}
-#endif
-
-void cfspi_xfer(struct work_struct *work)
-{
-	struct cfspi *cfspi;
-	u8 *ptr = NULL;
-	unsigned long flags;
-	int ret;
-	cfspi = container_of(work, struct cfspi, work);
-
-	/* Initialize state. */
-	cfspi->cmd = SPI_CMD_EOT;
-
-	for (;;) {
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_WAITING);
-
-		/* Wait for master talk or transmit event. */
-		wait_event_interruptible(cfspi->wait,
-				 test_bit(SPI_XFER, &cfspi->state) ||
-				 test_bit(SPI_TERMINATE, &cfspi->state));
-
-		if (test_bit(SPI_TERMINATE, &cfspi->state))
-			return;
-
-#if CFSPI_DBG_PREFILL
-		/* Prefill buffers for easier debugging. */
-		memset(cfspi->xfer.va_tx, 0xFF, SPI_DMA_BUF_LEN);
-		memset(cfspi->xfer.va_rx, 0xFF, SPI_DMA_BUF_LEN);
-#endif	/* CFSPI_DBG_PREFILL */
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_AWAKE);
-
-	/* Check whether we have a committed frame. */
-		if (cfspi->tx_cpck_len) {
-			int len;
-
-			cfspi_dbg_state(cfspi, CFSPI_STATE_FETCH_PKT);
-
-			/* Copy committed SPI frames after the SPI indication. */
-			ptr = (u8 *) cfspi->xfer.va_tx;
-			ptr += SPI_IND_SZ;
-			len = cfspi_xmitfrm(cfspi, ptr, cfspi->tx_cpck_len);
-			WARN_ON(len != cfspi->tx_cpck_len);
-	}
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_GET_NEXT);
-
-		/* Get length of next frame to commit. */
-		cfspi->tx_npck_len = cfspi_xmitlen(cfspi);
-
-		WARN_ON(cfspi->tx_npck_len > SPI_DMA_BUF_LEN);
-
-		/*
-		 * Add indication and length at the beginning of the frame,
-		 * using little endian.
-		 */
-		ptr = (u8 *) cfspi->xfer.va_tx;
-		*ptr++ = SPI_CMD_IND;
-		*ptr++ = (SPI_CMD_IND  & 0xFF00) >> 8;
-		*ptr++ = cfspi->tx_npck_len & 0x00FF;
-		*ptr++ = (cfspi->tx_npck_len & 0xFF00) >> 8;
-
-		/* Calculate length of DMAs. */
-		cfspi->xfer.tx_dma_len = cfspi->tx_cpck_len + SPI_IND_SZ;
-		cfspi->xfer.rx_dma_len = cfspi->rx_cpck_len + SPI_CMD_SZ;
-
-		/* Add SPI TX frame alignment padding, if necessary. */
-		if (cfspi->tx_cpck_len &&
-			(cfspi->xfer.tx_dma_len % spi_frm_align)) {
-
-			cfspi->xfer.tx_dma_len += spi_frm_align -
-			    (cfspi->xfer.tx_dma_len % spi_frm_align);
-		}
-
-		/* Add SPI RX frame alignment padding, if necessary. */
-		if (cfspi->rx_cpck_len &&
-			(cfspi->xfer.rx_dma_len % spi_frm_align)) {
-
-			cfspi->xfer.rx_dma_len += spi_frm_align -
-			    (cfspi->xfer.rx_dma_len % spi_frm_align);
-		}
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_INIT_XFER);
-
-		/* Start transfer. */
-		ret = cfspi->dev->init_xfer(&cfspi->xfer, cfspi->dev);
-		WARN_ON(ret);
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_ACTIVE);
-
-		/*
-		 * TODO: We might be able to make an assumption if this is the
-		 * first loop. Make sure that minimum toggle time is respected.
-		 */
-		udelay(MIN_TRANSITION_TIME_USEC);
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_ACTIVE);
-
-		/* Signal that we are ready to receive data. */
-		cfspi->dev->sig_xfer(true, cfspi->dev);
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_XFER_DONE);
-
-		/* Wait for transfer completion. */
-		wait_for_completion(&cfspi->comp);
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_XFER_DONE);
-
-		if (cfspi->cmd == SPI_CMD_EOT) {
-			/*
-			 * Clear the master talk bit. A xfer is always at
-			 *  least two bursts.
-			 */
-			clear_bit(SPI_SS_ON, &cfspi->state);
-		}
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_INACTIVE);
-
-		/* Make sure that the minimum toggle time is respected. */
-		if (SPI_XFER_TIME_USEC(cfspi->xfer.tx_dma_len,
-					cfspi->dev->clk_mhz) <
-			MIN_TRANSITION_TIME_USEC) {
-
-			udelay(MIN_TRANSITION_TIME_USEC -
-				SPI_XFER_TIME_USEC
-				(cfspi->xfer.tx_dma_len, cfspi->dev->clk_mhz));
-		}
-
-		cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_INACTIVE);
-
-		/* De-assert transfer signal. */
-		cfspi->dev->sig_xfer(false, cfspi->dev);
-
-		/* Check whether we received a CAIF packet. */
-		if (cfspi->rx_cpck_len) {
-			int len;
-
-			cfspi_dbg_state(cfspi, CFSPI_STATE_DELIVER_PKT);
-
-			/* Parse SPI frame. */
-			ptr = ((u8 *)(cfspi->xfer.va_rx + SPI_DATA_POS));
-
-			len = cfspi_rxfrm(cfspi, ptr, cfspi->rx_cpck_len);
-			WARN_ON(len != cfspi->rx_cpck_len);
-		}
-
-		/* Check the next SPI command and length. */
-		ptr = (u8 *) cfspi->xfer.va_rx;
-
-		ptr += forward_to_spi_cmd(cfspi);
-
-		cfspi->cmd = *ptr++;
-		cfspi->cmd |= ((*ptr++) << 8) & 0xFF00;
-		cfspi->rx_npck_len = *ptr++;
-		cfspi->rx_npck_len |= ((*ptr++) << 8) & 0xFF00;
-
-		WARN_ON(cfspi->rx_npck_len > SPI_DMA_BUF_LEN);
-		WARN_ON(cfspi->cmd > SPI_CMD_EOT);
-
-		debugfs_store_prev(cfspi);
-
-		/* Check whether the master issued an EOT command. */
-		if (cfspi->cmd == SPI_CMD_EOT) {
-			/* Reset state. */
-			cfspi->tx_cpck_len = 0;
-			cfspi->rx_cpck_len = 0;
-		} else {
-			/* Update state. */
-			cfspi->tx_cpck_len = cfspi->tx_npck_len;
-			cfspi->rx_cpck_len = cfspi->rx_npck_len;
-		}
-
-		/*
-		 * Check whether we need to clear the xfer bit.
-		 * Spin lock needed for packet insertion.
-		 * Test and clear of different bits
-		 * are not supported.
-		 */
-		spin_lock_irqsave(&cfspi->lock, flags);
-		if (cfspi->cmd == SPI_CMD_EOT && !cfspi_xmitlen(cfspi)
-			&& !test_bit(SPI_SS_ON, &cfspi->state))
-			clear_bit(SPI_XFER, &cfspi->state);
-
-		spin_unlock_irqrestore(&cfspi->lock, flags);
-	}
-}
-
-struct platform_driver cfspi_spi_driver = {
-	.probe = cfspi_spi_probe,
-	.remove = cfspi_spi_remove,
-	.driver = {
-		   .name = "cfspi_sspi",
-		   .owner = THIS_MODULE,
-		   },
-};
--- a/include/net/caif/caif_spi.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) ST-Ericsson AB 2010
- * Author:	Daniel Martensson / Daniel.Martensson@stericsson.com
- */
-
-#ifndef CAIF_SPI_H_
-#define CAIF_SPI_H_
-
-#include <net/caif/caif_device.h>
-
-#define SPI_CMD_WR			0x00
-#define SPI_CMD_RD			0x01
-#define SPI_CMD_EOT			0x02
-#define SPI_CMD_IND			0x04
-
-#define SPI_DMA_BUF_LEN			8192
-
-#define WL_SZ				2	/* 16 bits. */
-#define SPI_CMD_SZ			4	/* 32 bits. */
-#define SPI_IND_SZ			4	/* 32 bits. */
-
-#define SPI_XFER			0
-#define SPI_SS_ON			1
-#define SPI_SS_OFF			2
-#define SPI_TERMINATE			3
-
-/* Minimum time between different levels is 50 microseconds. */
-#define MIN_TRANSITION_TIME_USEC	50
-
-/* Defines for calculating duration of SPI transfers for a particular
- * number of bytes.
- */
-#define SPI_MASTER_CLK_MHZ		13
-#define SPI_XFER_TIME_USEC(bytes, clk) (((bytes) * 8) / clk)
-
-/* Normally this should be aligned on the modem in order to benefit from full
- * duplex transfers. However a size of 8188 provokes errors when running with
- * the modem. These errors occur when packet sizes approaches 4 kB of data.
- */
-#define CAIF_MAX_SPI_FRAME 4092
-
-/* Maximum number of uplink CAIF frames that can reside in the same SPI frame.
- * This number should correspond with the modem setting. The application side
- * CAIF accepts any number of embedded downlink CAIF frames.
- */
-#define CAIF_MAX_SPI_PKTS 9
-
-/* Decides if SPI buffers should be prefilled with 0xFF pattern for easier
- * debugging. Both TX and RX buffers will be filled before the transfer.
- */
-#define CFSPI_DBG_PREFILL		0
-
-/* Structure describing a SPI transfer. */
-struct cfspi_xfer {
-	u16 tx_dma_len;
-	u16 rx_dma_len;
-	void *va_tx[2];
-	dma_addr_t pa_tx[2];
-	void *va_rx;
-	dma_addr_t pa_rx;
-};
-
-/* Structure implemented by the SPI interface. */
-struct cfspi_ifc {
-	void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
-	void (*xfer_done_cb) (struct cfspi_ifc *ifc);
-	void *priv;
-};
-
-/* Structure implemented by SPI clients. */
-struct cfspi_dev {
-	int (*init_xfer) (struct cfspi_xfer *xfer, struct cfspi_dev *dev);
-	void (*sig_xfer) (bool xfer, struct cfspi_dev *dev);
-	struct cfspi_ifc *ifc;
-	char *name;
-	u32 clk_mhz;
-	void *priv;
-};
-
-/* Enumeration describing the CAIF SPI state. */
-enum cfspi_state {
-	CFSPI_STATE_WAITING = 0,
-	CFSPI_STATE_AWAKE,
-	CFSPI_STATE_FETCH_PKT,
-	CFSPI_STATE_GET_NEXT,
-	CFSPI_STATE_INIT_XFER,
-	CFSPI_STATE_WAIT_ACTIVE,
-	CFSPI_STATE_SIG_ACTIVE,
-	CFSPI_STATE_WAIT_XFER_DONE,
-	CFSPI_STATE_XFER_DONE,
-	CFSPI_STATE_WAIT_INACTIVE,
-	CFSPI_STATE_SIG_INACTIVE,
-	CFSPI_STATE_DELIVER_PKT,
-	CFSPI_STATE_MAX,
-};
-
-/* Structure implemented by SPI physical interfaces. */
-struct cfspi {
-	struct caif_dev_common cfdev;
-	struct net_device *ndev;
-	struct platform_device *pdev;
-	struct sk_buff_head qhead;
-	struct sk_buff_head chead;
-	u16 cmd;
-	u16 tx_cpck_len;
-	u16 tx_npck_len;
-	u16 rx_cpck_len;
-	u16 rx_npck_len;
-	struct cfspi_ifc ifc;
-	struct cfspi_xfer xfer;
-	struct cfspi_dev *dev;
-	unsigned long state;
-	struct work_struct work;
-	struct workqueue_struct *wq;
-	struct list_head list;
-	int    flow_off_sent;
-	u32 qd_low_mark;
-	u32 qd_high_mark;
-	struct completion comp;
-	wait_queue_head_t wait;
-	spinlock_t lock;
-	bool flow_stop;
-	bool slave;
-	bool slave_talked;
-#ifdef CONFIG_DEBUG_FS
-	enum cfspi_state dbg_state;
-	u16 pcmd;
-	u16 tx_ppck_len;
-	u16 rx_ppck_len;
-	struct dentry *dbgfs_dir;
-	struct dentry *dbgfs_state;
-	struct dentry *dbgfs_frame;
-#endif				/* CONFIG_DEBUG_FS */
-};
-
-extern int spi_frm_align;
-extern int spi_up_head_align;
-extern int spi_up_tail_align;
-extern int spi_down_head_align;
-extern int spi_down_tail_align;
-extern struct platform_driver cfspi_spi_driver;
-
-void cfspi_dbg_state(struct cfspi *cfspi, int state);
-int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
-int cfspi_xmitlen(struct cfspi *cfspi);
-int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
-int cfspi_spi_remove(struct platform_device *pdev);
-int cfspi_spi_probe(struct platform_device *pdev);
-int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
-int cfspi_xmitlen(struct cfspi *cfspi);
-int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
-void cfspi_xfer(struct work_struct *work);
-
-#endif				/* CAIF_SPI_H_ */


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 03/35] net: Add netif_rx_any_context()
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
  2020-09-27 19:48 ` [patch 01/35] net: enic: Cure the enic api locking trainwreck Thomas Gleixner
  2020-09-27 19:48 ` [patch 02/35] net: caif: Remove unused caif SPI driver Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 19:48 ` [patch 04/35] net: caif: Use netif_rx_any_context() Thomas Gleixner
                   ` (33 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, David S. Miller, Jakub Kicinski,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Quite some drivers make conditional decisions based on in_interrupt() to
invoke either netif_rx() or netif_rx_ni().

Conditionals based on in_interrupt() or other variants of preempt count
checks in drivers should not exist for various reasons and Linus clearly
requested to either split the code pathes or pass an argument to the
common functions which provides the context.

This is obviously the correct solution, but for some of the affected
drivers this needs a major rewrite due to their convoluted structure.

As in_interrupt() usage in drivers needs to be phased out, provide
netif_rx_any_context() as a stop gap for these drivers.

This confines the in_interrupt() conditional to core code which in turn
allows to remove the access to this check for driver code and provides one
central place to do further modifications once the driver maze is cleaned
up.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org
---
 include/linux/netdevice.h |    1 +
 net/core/dev.c            |   15 +++++++++++++++
 2 files changed, 16 insertions(+)

--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3764,6 +3764,7 @@ void generic_xdp_tx(struct sk_buff *skb,
 int do_xdp_generic(struct bpf_prog *xdp_prog, struct sk_buff *skb);
 int netif_rx(struct sk_buff *skb);
 int netif_rx_ni(struct sk_buff *skb);
+int netif_rx_any_context(struct sk_buff *skb);
 int netif_receive_skb(struct sk_buff *skb);
 int netif_receive_skb_core(struct sk_buff *skb);
 void netif_receive_skb_list(struct list_head *head);
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4840,6 +4840,21 @@ int netif_rx_ni(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(netif_rx_ni);
 
+int netif_rx_any_context(struct sk_buff *skb)
+{
+	/*
+	 * If invoked from contexts which do not invoke bottom half
+	 * processing either at return from interrupt or when softrqs are
+	 * reenabled, use netif_rx_ni() which invokes bottomhalf processing
+	 * directly.
+	 */
+	if (in_interrupt())
+		return netif_rx(skb);
+	else
+		return netif_rx_ni(skb);
+}
+EXPORT_SYMBOL(netif_rx_any_context);
+
 static __latent_entropy void net_tx_action(struct softirq_action *h)
 {
 	struct softnet_data *sd = this_cpu_ptr(&softnet_data);


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 04/35] net: caif: Use netif_rx_any_context()
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (2 preceding siblings ...)
  2020-09-27 19:48 ` [patch 03/35] net: Add netif_rx_any_context() Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 19:48 ` [patch 05/35] net: atheros: Remove WARN_ON(in_interrupt()) Thomas Gleixner
                   ` (32 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, David S. Miller, Jakub Kicinski,
	Luc Van Oostenryck, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Jay Cliburn, Chris Snook,
	Vishal Kulkarni, Jeff Kirsher, intel-wired-lan, Shannon Nelson,
	Pensando Drivers, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The usage of in_interrupt() in non-core code is phased out. Ideally the
information of the calling context should be passed by the callers or the
functions be split as appropriate.

cfhsi_rx_desc() and cfhsi_rx_pld() use in_interrupt() to distinguish if
they should use netif_rx() or netif_rx_ni() for receiving packets.

The attempt to consolidate the code by passing an arguemnt or by
distangling it failed due lack of knowledge about this driver and because
the call chains are hard to follow.

As a stop gap use netif_rx_any_context() which invokes the correct code path
depending on context and confines the in_interrupt() usage to core code.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Cc: netdev@vger.kernel.org
---
 drivers/net/caif/caif_hsi.c |   19 ++-----------------
 1 file changed, 2 insertions(+), 17 deletions(-)

--- a/drivers/net/caif/caif_hsi.c
+++ b/drivers/net/caif/caif_hsi.c
@@ -458,15 +458,7 @@ static int cfhsi_rx_desc(struct cfhsi_de
 		skb_reset_mac_header(skb);
 		skb->dev = cfhsi->ndev;
 
-		/*
-		 * We are in a callback handler and
-		 * unfortunately we don't know what context we're
-		 * running in.
-		 */
-		if (in_interrupt())
-			netif_rx(skb);
-		else
-			netif_rx_ni(skb);
+		netif_rx_any_context(skb);
 
 		/* Update network statistics. */
 		cfhsi->ndev->stats.rx_packets++;
@@ -587,14 +579,7 @@ static int cfhsi_rx_pld(struct cfhsi_des
 		skb_reset_mac_header(skb);
 		skb->dev = cfhsi->ndev;
 
-		/*
-		 * We're called in callback from HSI
-		 * and don't know the context we're running in.
-		 */
-		if (in_interrupt())
-			netif_rx(skb);
-		else
-			netif_rx_ni(skb);
+		netif_rx_any_context(skb);
 
 		/* Update network statistics. */
 		cfhsi->ndev->stats.rx_packets++;


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 05/35] net: atheros: Remove WARN_ON(in_interrupt())
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (3 preceding siblings ...)
  2020-09-27 19:48 ` [patch 04/35] net: caif: Use netif_rx_any_context() Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 19:48 ` [patch 06/35] net: cxgb3: Cleanup in_interrupt() usage Thomas Gleixner
                   ` (31 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	David S. Miller, Jay Cliburn, Chris Snook, Jakub Kicinski,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Sebastian Andrzej Siewior, Luc Van Oostenryck, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Thomas Gleixner <tglx@linutronix.de>

in_interrupt() is ill defined and does not provide what the name
suggests. The usage especially in driver code is deprecated and a tree wide
effort to clean up and consolidate the (ab)usage of in_interrupt() and
related checks is happening.

In this case the check covers only parts of the contexts in which these
functions cannot be called. It fails to detect preemption or interrupt
disabled invocations.

As the functions which are invoked from at*_reinit_locked() contain a broad
variety of checks (always enabled or debug option dependent) which cover
all invalid conditions already, there is no point in having inconsistent
warnings in those drivers.

Just remove them.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jay Cliburn <jcliburn@gmail.com>
Cc: Chris Snook <chris.snook@gmail.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org

---
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |    1 -
 drivers/net/ethernet/atheros/atl1e/atl1e_main.c |    2 --
 drivers/net/ethernet/atheros/atlx/atl2.c        |    1 -
 3 files changed, 4 deletions(-)

--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -220,7 +220,6 @@ static void atl1c_phy_config(struct time
 
 void atl1c_reinit_locked(struct atl1c_adapter *adapter)
 {
-	WARN_ON(in_interrupt());
 	atl1c_down(adapter);
 	atl1c_up(adapter);
 	clear_bit(__AT_RESETTING, &adapter->flags);
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -127,8 +127,6 @@ static void atl1e_phy_config(struct time
 
 void atl1e_reinit_locked(struct atl1e_adapter *adapter)
 {
-
-	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
 		msleep(1);
 	atl1e_down(adapter);
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1085,7 +1085,6 @@ static int atl2_up(struct atl2_adapter *
 
 static void atl2_reinit_locked(struct atl2_adapter *adapter)
 {
-	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags))
 		msleep(1);
 	atl2_down(adapter);


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 06/35] net: cxgb3: Cleanup in_interrupt() usage
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (4 preceding siblings ...)
  2020-09-27 19:48 ` [patch 05/35] net: atheros: Remove WARN_ON(in_interrupt()) Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 19:48 ` [patch 07/35] net: cxbg4: Remove pointless in_interrupt() check Thomas Gleixner
                   ` (30 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Vishal Kulkarni, David S. Miller, Jakub Kicinski, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Sebastian Andrzej Siewior, Luc Van Oostenryck, Jay Cliburn,
	Chris Snook, Jeff Kirsher, intel-wired-lan, Shannon Nelson,
	Pensando Drivers, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Thomas Gleixner <tglx@linutronix.de>

t3_sge_stop() is called from task context and from error handlers in
interrupt context. It relies on in_interrupt() to differentiate the
contexts.

in_interrupt() is deprecated as it is ill defined and does not provide what
it suggests.

Instead of replacing it with some other construct, simply split the
function into t3_sge_stop_dma(), which can be called from any context, and
t3_sge_stop() which can be only called from task context.

This has the advantage that any bogus invocation of t3_sge_stop() from
wrong contexts can be caught by debug kernels instead of being papered over
by the conditional.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Vishal Kulkarni <vishal@chelsio.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

---
 drivers/net/ethernet/chelsio/cxgb3/adapter.h    |    1 
 drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c |    2 -
 drivers/net/ethernet/chelsio/cxgb3/sge.c        |   44 ++++++++++++++----------
 3 files changed, 29 insertions(+), 18 deletions(-)

--- a/drivers/net/ethernet/chelsio/cxgb3/adapter.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/adapter.h
@@ -313,6 +313,7 @@ void t3_os_link_fault(struct adapter *ad
 void t3_os_link_fault_handler(struct adapter *adapter, int port_id);
 
 void t3_sge_start(struct adapter *adap);
+void t3_sge_stop_dma(struct adapter *adap);
 void t3_sge_stop(struct adapter *adap);
 void t3_start_sge_timers(struct adapter *adap);
 void t3_stop_sge_timers(struct adapter *adap);
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -2996,7 +2996,7 @@ void t3_fatal_err(struct adapter *adapte
 	unsigned int fw_status[4];
 
 	if (adapter->flags & FULL_INIT_DONE) {
-		t3_sge_stop(adapter);
+		t3_sge_stop_dma(adapter);
 		t3_write_reg(adapter, A_XGM_TX_CTRL, 0);
 		t3_write_reg(adapter, A_XGM_RX_CTRL, 0);
 		t3_write_reg(adapter, XGM_REG(A_XGM_TX_CTRL, 1), 0);
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -3271,30 +3271,40 @@ void t3_sge_start(struct adapter *adap)
 }
 
 /**
- *	t3_sge_stop - disable SGE operation
+ *	t3_sge_stop_dma - Disable SGE DMA engine operation
  *	@adap: the adapter
  *
- *	Disables the DMA engine.  This can be called in emeregencies (e.g.,
- *	from error interrupts) or from normal process context.  In the latter
- *	case it also disables any pending queue restart tasklets.  Note that
- *	if it is called in interrupt context it cannot disable the restart
- *	tasklets as it cannot wait, however the tasklets will have no effect
- *	since the doorbells are disabled and the driver will call this again
- *	later from process context, at which time the tasklets will be stopped
- *	if they are still running.
+ *	Can be invoked from interrupt context e.g.  error handler.
+ *
+ *	Note that this function cannot disable the restart of tasklets as
+ *	it cannot wait if called from interrupt context, however the
+ *	tasklets will have no effect since the doorbells are disabled. The
+ *	driver will call tg3_sge_stop() later from process context, at
+ *	which time the tasklets will be stopped if they are still running.
  */
-void t3_sge_stop(struct adapter *adap)
+void t3_sge_stop_dma(struct adapter *adap)
 {
 	t3_set_reg_field(adap, A_SG_CONTROL, F_GLOBALENABLE, 0);
-	if (!in_interrupt()) {
-		int i;
+}
+
+/**
+ *	t3_sge_stop - disable SGE operation completly
+ *	@adap: the adapter
+ *
+ *	Called from process context. Disables the DMA engine and any
+ *	pending queue restart tasklets.
+ */
+void t3_sge_stop(struct adapter *adap)
+{
+	int i;
+
+	t3_sge_stop_dma(adap);
 
-		for (i = 0; i < SGE_QSETS; ++i) {
-			struct sge_qset *qs = &adap->sge.qs[i];
+	for (i = 0; i < SGE_QSETS; ++i) {
+		struct sge_qset *qs = &adap->sge.qs[i];
 
-			tasklet_kill(&qs->txq[TXQ_OFLD].qresume_tsk);
-			tasklet_kill(&qs->txq[TXQ_CTRL].qresume_tsk);
-		}
+		tasklet_kill(&qs->txq[TXQ_OFLD].qresume_tsk);
+		tasklet_kill(&qs->txq[TXQ_CTRL].qresume_tsk);
 	}
 }
 


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 07/35] net: cxbg4: Remove pointless in_interrupt() check
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (5 preceding siblings ...)
  2020-09-27 19:48 ` [patch 06/35] net: cxgb3: Cleanup in_interrupt() usage Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 19:48 ` [patch 08/35] net: e100: Remove in_interrupt() usage and pointless GFP_ATOMIC allocation Thomas Gleixner
                   ` (29 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Vishal Kulkarni, David S. Miller, Jakub Kicinski, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Sebastian Andrzej Siewior, Luc Van Oostenryck, Jay Cliburn,
	Chris Snook, Jeff Kirsher, intel-wired-lan, Shannon Nelson,
	Pensando Drivers, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Thomas Gleixner <tglx@linutronix.de>

t4_sge_stop() is only ever called from task context and the in_interrupt()
check is presumably a leftover from copying t3_sge_stop().

Aside of in_interrupt() being deprecated because it's not providing what it
claims to provide, this check would paper over illegitimate callers.

The functions invoked from t4_sge_stop() contain already warnings to catch
invocations from invalid contexts.

Remove it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Vishal Kulkarni <vishal@chelsio.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org


---
 drivers/net/ethernet/chelsio/cxgb4/sge.c |    3 ---
 1 file changed, 3 deletions(-)

--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -4872,9 +4872,6 @@ void t4_sge_stop(struct adapter *adap)
 	int i;
 	struct sge *s = &adap->sge;
 
-	if (in_interrupt())  /* actions below require waiting */
-		return;
-
 	if (s->rx_timer.function)
 		del_timer_sync(&s->rx_timer);
 	if (s->tx_timer.function)


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 08/35] net: e100: Remove in_interrupt() usage and pointless GFP_ATOMIC allocation
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (6 preceding siblings ...)
  2020-09-27 19:48 ` [patch 07/35] net: cxbg4: Remove pointless in_interrupt() check Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 19:48 ` [patch 09/35] net: fec_mpc52xx: Replace in_interrupt() usage Thomas Gleixner
                   ` (28 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Jeff Kirsher, David S. Miller,
	Jakub Kicinski, intel-wired-lan, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Shannon Nelson,
	Pensando Drivers, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

e100_hw_init() invokes e100_self_test() only if in_interrupt() returns
false as e100_self_test() uses msleep() which requires sleepable task
context. The in_interrupt() check is incomplete because in_interrupt()
cannot catch callers from contexts which have just preemption or interrupts
disabled.

e100_hw_init() is invoked from:

  - e100_loopback_test() which clearly is sleepable task context as the
    function uses msleep() itself.

  - e100_up() which clearly is sleepable task context as well because it
    invokes e100_alloc_cbs() abd request_irq() which both require sleepable
    task context due to GFP_KERNEL allocations and mutex_lock() operations.

Remove the pointless in_interrupt() check.

As a side effect of this analysis it turned out that e100_rx_alloc_list()
which is only invoked from e100_loopback_test() and e100_up() pointlessly
uses a GFP_ATOMIC allocation. The next invoked function e100_alloc_cbs() is
using GFP_KERNEL already.

Change the allocation mode in e100_rx_alloc_list() to GFP_KERNEL as well.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: intel-wired-lan@lists.osuosl.org
Cc: netdev@vger.kernel.org

---
 drivers/net/ethernet/intel/e100.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -1531,7 +1531,7 @@ static int e100_hw_init(struct nic *nic)
 	e100_hw_reset(nic);
 
 	netif_err(nic, hw, nic->netdev, "e100_hw_init\n");
-	if (!in_interrupt() && (err = e100_self_test(nic)))
+	if ((err = e100_self_test(nic)))
 		return err;
 
 	if ((err = e100_phy_init(nic)))
@@ -2155,7 +2155,7 @@ static int e100_rx_alloc_list(struct nic
 	nic->rx_to_use = nic->rx_to_clean = NULL;
 	nic->ru_running = RU_UNINITIALIZED;
 
-	if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
+	if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_KERNEL)))
 		return -ENOMEM;
 
 	for (rx = nic->rxs, i = 0; i < count; rx++, i++) {


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 09/35] net: fec_mpc52xx: Replace in_interrupt() usage
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (7 preceding siblings ...)
  2020-09-27 19:48 ` [patch 08/35] net: e100: Remove in_interrupt() usage and pointless GFP_ATOMIC allocation Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 19:48 ` [patch 10/35] net: intel: Remove in_interrupt() warnings Thomas Gleixner
                   ` (27 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, David S. Miller, Jakub Kicinski,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The usage of in_interrupt() in drivers is phased out and Linus clearly
requested that code which changes behaviour depending on context should
either be seperated or the context be conveyed in an argument passed by the
caller, which usually knows the context.

mpc52xx_fec_stop() uses in_interrupt() to check if it is safe to sleep. All
callers run in well defined contexts.

Pass an argument from the callers indicating whether it is safe to sleep.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org

---
 drivers/net/ethernet/freescale/fec_mpc52xx.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -74,7 +74,7 @@ struct mpc52xx_fec_priv {
 static irqreturn_t mpc52xx_fec_interrupt(int, void *);
 static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *);
 static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *);
-static void mpc52xx_fec_stop(struct net_device *dev);
+static void mpc52xx_fec_stop(struct net_device *dev, bool may_sleep);
 static void mpc52xx_fec_start(struct net_device *dev);
 static void mpc52xx_fec_reset(struct net_device *dev);
 
@@ -283,7 +283,7 @@ static int mpc52xx_fec_close(struct net_
 
 	netif_stop_queue(dev);
 
-	mpc52xx_fec_stop(dev);
+	mpc52xx_fec_stop(dev, true);
 
 	mpc52xx_fec_free_rx_buffers(dev, priv->rx_dmatsk);
 
@@ -693,7 +693,7 @@ static void mpc52xx_fec_start(struct net
  *
  * stop all activity on fec and empty dma buffers
  */
-static void mpc52xx_fec_stop(struct net_device *dev)
+static void mpc52xx_fec_stop(struct net_device *dev, bool may_sleep)
 {
 	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
 	struct mpc52xx_fec __iomem *fec = priv->fec;
@@ -706,7 +706,7 @@ static void mpc52xx_fec_stop(struct net_
 	bcom_disable(priv->rx_dmatsk);
 
 	/* Wait for tx queue to drain, but only if we're in process context */
-	if (!in_interrupt()) {
+	if (may_sleep) {
 		timeout = jiffies + msecs_to_jiffies(2000);
 		while (time_before(jiffies, timeout) &&
 				!bcom_queue_empty(priv->tx_dmatsk))
@@ -738,7 +738,7 @@ static void mpc52xx_fec_reset(struct net
 	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
 	struct mpc52xx_fec __iomem *fec = priv->fec;
 
-	mpc52xx_fec_stop(dev);
+	mpc52xx_fec_stop(dev, false);
 
 	out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status));
 	out_be32(&fec->reset_cntrl, FEC_RESET_CNTRL_RESET_FIFO);


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 10/35] net: intel: Remove in_interrupt() warnings
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (8 preceding siblings ...)
  2020-09-27 19:48 ` [patch 09/35] net: fec_mpc52xx: Replace in_interrupt() usage Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-28 23:04   ` Alexander Duyck
  2020-09-27 19:48 ` [patch 11/35] net: ionic: Replace in_interrupt() usage Thomas Gleixner
                   ` (26 subsequent siblings)
  36 siblings, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Jeff Kirsher, David S. Miller,
	Jakub Kicinski, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, intel-wired-lan,
	Shannon Nelson, Pensando Drivers, Andrew Lunn, Heiner Kallweit,
	Russell King, Thomas Bogendoerfer, Solarflare linux maintainers,
	Edward Cree, Martin Habets, Jon Mason, Daniel Drake,
	Ulrich Kunitz, Kalle Valo, linux-wireless, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

in_interrupt() is ill defined and does not provide what the name
suggests. The usage especially in driver code is deprecated and a tree wide
effort to clean up and consolidate the (ab)usage of in_interrupt() and
related checks is happening.

In this case the checks cover only parts of the contexts in which these
functions cannot be called. They fail to detect preemption or interrupt
disabled invocations.

As the functions which are invoked from the various places contain already
a broad variety of checks (always enabled or debug option dependent) cover
all invalid conditions already, there is no point in having inconsistent
warnings in those drivers.

Just remove them.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org

---
 drivers/net/ethernet/intel/e1000/e1000_main.c     |    1 -
 drivers/net/ethernet/intel/fm10k/fm10k_pci.c      |    2 --
 drivers/net/ethernet/intel/i40e/i40e_main.c       |    4 ----
 drivers/net/ethernet/intel/ice/ice_main.c         |    1 -
 drivers/net/ethernet/intel/igb/igb_main.c         |    1 -
 drivers/net/ethernet/intel/igc/igc_main.c         |    1 -
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |    1 -
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |    2 --
 8 files changed, 13 deletions(-)

--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -534,7 +534,6 @@ void e1000_down(struct e1000_adapter *ad
 
 void e1000_reinit_locked(struct e1000_adapter *adapter)
 {
-	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
 		msleep(1);
 
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -221,8 +221,6 @@ static bool fm10k_prepare_for_reset(stru
 {
 	struct net_device *netdev = interface->netdev;
 
-	WARN_ON(in_interrupt());
-
 	/* put off any impending NetWatchDogTimeout */
 	netif_trans_update(netdev);
 
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -6689,7 +6689,6 @@ static void i40e_vsi_reinit_locked(struc
 {
 	struct i40e_pf *pf = vsi->back;
 
-	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__I40E_CONFIG_BUSY, pf->state))
 		usleep_range(1000, 2000);
 	i40e_down(vsi);
@@ -8462,9 +8461,6 @@ void i40e_do_reset(struct i40e_pf *pf, u
 {
 	u32 val;
 
-	WARN_ON(in_interrupt());
-
-
 	/* do the biggest reset indicated */
 	if (reset_flags & BIT_ULL(__I40E_GLOBAL_RESET_REQUESTED)) {
 
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -486,7 +486,6 @@ static void ice_do_reset(struct ice_pf *
 	struct ice_hw *hw = &pf->hw;
 
 	dev_dbg(dev, "reset_type 0x%x requested\n", reset_type);
-	WARN_ON(in_interrupt());
 
 	ice_prepare_for_reset(pf);
 
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2220,7 +2220,6 @@ void igb_down(struct igb_adapter *adapte
 
 void igb_reinit_locked(struct igb_adapter *adapter)
 {
-	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
 		usleep_range(1000, 2000);
 	igb_down(adapter);
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -3831,7 +3831,6 @@ void igc_down(struct igc_adapter *adapte
 
 void igc_reinit_locked(struct igc_adapter *adapter)
 {
-	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
 		usleep_range(1000, 2000);
 	igc_down(adapter);
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -5677,7 +5677,6 @@ static void ixgbe_up_complete(struct ixg
 
 void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
 {
-	WARN_ON(in_interrupt());
 	/* put off any impending NetWatchDogTimeout */
 	netif_trans_update(adapter->netdev);
 
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -2526,8 +2526,6 @@ void ixgbevf_down(struct ixgbevf_adapter
 
 void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter)
 {
-	WARN_ON(in_interrupt());
-
 	while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state))
 		msleep(1);
 


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 11/35] net: ionic: Replace in_interrupt() usage.
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (9 preceding siblings ...)
  2020-09-27 19:48 ` [patch 10/35] net: intel: Remove in_interrupt() warnings Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-28 17:24   ` Shannon Nelson
  2020-09-27 19:48 ` [patch 12/35] net: ionic: Remove WARN_ON(in_interrupt()) Thomas Gleixner
                   ` (25 subsequent siblings)
  36 siblings, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Shannon Nelson, Pensando Drivers,
	David S. Miller, Jakub Kicinski, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The in_interrupt() usage in this driver tries to figure out which context
may sleep and which context may not sleep. in_interrupt() is not really
suitable as it misses both preemption disabled and interrupt disabled
invocations from task context.

Conditionals like that in driver code are frowned upon in general because
invocations of functions from invalid contexts might not be detected
as the conditional papers over it.

ionic_lif_addr() can be called from:

 1) ->ndo_set_rx_mode() which is under netif_addr_lock_bh()) so it must not
    sleep.

 2) Init and setup functions which are in fully preemptible task context.

_ionic_lif_rx_mode() has only one call path with BH disabled.

ionic_link_status_check_request() has two call paths:

 1) NAPI which obviously cannot sleep

 2) Setup which is again fully preemptible task context

Add 'can_sleep' arguments to the affected functions and let the callers
provide the context instead of letting the functions deduce it.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Shannon Nelson <snelson@pensando.io>
Cc: Pensando Drivers <drivers@pensando.io>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org
---

While reviewing the callpaths, a couple of things were observed which could
be improved:

- ionic_lif_deferred_work() can iterate over the list. There is no need
  to schedule the work item after each iteration

- ionic_link_status_check_request() could have ionic_deferred_work within
  ionic_lif(). This would avoid memory allocation from NAPI. More
  important, once IONIC_LIF_F_LINK_CHECK_REQUESTED is set and that alloc
  fails, the link check never happens.

- ionic_lif_handle_fw_down() sets IONIC_LIF_F_FW_RESET. Invokes then
  ionic_lif_deinit() which only invokes cancel_work_sync() if
  IONIC_LIF_F_FW_RESET is not set. I think the logic is wrong here as
  the work must always be cancled. Also the list with ionic_deferred
  work items needs a clean up.

---
 drivers/net/ethernet/pensando/ionic/ionic_dev.c |    2 -
 drivers/net/ethernet/pensando/ionic/ionic_lif.c |   43 +++++++++++-------------
 drivers/net/ethernet/pensando/ionic/ionic_lif.h |    2 -
 3 files changed, 22 insertions(+), 25 deletions(-)

--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
@@ -22,7 +22,7 @@ static void ionic_watchdog_cb(struct tim
 	hb = ionic_heartbeat_check(ionic);
 
 	if (hb >= 0 && ionic->master_lif)
-		ionic_link_status_check_request(ionic->master_lif);
+		ionic_link_status_check_request(ionic->master_lif, false);
 }
 
 void ionic_init_devinfo(struct ionic *ionic)
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -135,7 +135,7 @@ static void ionic_link_status_check(stru
 	clear_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state);
 }
 
-void ionic_link_status_check_request(struct ionic_lif *lif)
+void ionic_link_status_check_request(struct ionic_lif *lif, bool can_sleep)
 {
 	struct ionic_deferred_work *work;
 
@@ -143,7 +143,7 @@ void ionic_link_status_check_request(str
 	if (test_and_set_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state))
 		return;
 
-	if (in_interrupt()) {
+	if (!can_sleep) {
 		work = kzalloc(sizeof(*work), GFP_ATOMIC);
 		if (!work)
 			return;
@@ -751,7 +751,7 @@ static bool ionic_notifyq_service(struct
 
 	switch (le16_to_cpu(comp->event.ecode)) {
 	case IONIC_EVENT_LINK_CHANGE:
-		ionic_link_status_check_request(lif);
+		ionic_link_status_check_request(lif, false);
 		break;
 	case IONIC_EVENT_RESET:
 		work = kzalloc(sizeof(*work), GFP_ATOMIC);
@@ -928,7 +928,8 @@ static int ionic_lif_addr_del(struct ion
 	return 0;
 }
 
-static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add)
+static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add,
+			  bool can_sleep)
 {
 	struct ionic *ionic = lif->ionic;
 	struct ionic_deferred_work *work;
@@ -957,7 +958,7 @@ static int ionic_lif_addr(struct ionic_l
 			lif->nucast--;
 	}
 
-	if (in_interrupt()) {
+	if (!can_sleep) {
 		work = kzalloc(sizeof(*work), GFP_ATOMIC);
 		if (!work) {
 			netdev_err(lif->netdev, "%s OOM\n", __func__);
@@ -983,12 +984,12 @@ static int ionic_lif_addr(struct ionic_l
 
 static int ionic_addr_add(struct net_device *netdev, const u8 *addr)
 {
-	return ionic_lif_addr(netdev_priv(netdev), addr, true);
+	return ionic_lif_addr(netdev_priv(netdev), addr, true, false);
 }
 
 static int ionic_addr_del(struct net_device *netdev, const u8 *addr)
 {
-	return ionic_lif_addr(netdev_priv(netdev), addr, false);
+	return ionic_lif_addr(netdev_priv(netdev), addr, false, false);
 }
 
 static void ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode)
@@ -1032,19 +1033,15 @@ static void _ionic_lif_rx_mode(struct io
 {
 	struct ionic_deferred_work *work;
 
-	if (in_interrupt()) {
-		work = kzalloc(sizeof(*work), GFP_ATOMIC);
-		if (!work) {
-			netdev_err(lif->netdev, "%s OOM\n", __func__);
-			return;
-		}
-		work->type = IONIC_DW_TYPE_RX_MODE;
-		work->rx_mode = rx_mode;
-		netdev_dbg(lif->netdev, "deferred: rx_mode\n");
-		ionic_lif_deferred_enqueue(&lif->deferred, work);
-	} else {
-		ionic_lif_rx_mode(lif, rx_mode);
+	work = kzalloc(sizeof(*work), GFP_ATOMIC);
+	if (!work) {
+		netdev_err(lif->netdev, "%s OOM\n", __func__);
+		return;
 	}
+	work->type = IONIC_DW_TYPE_RX_MODE;
+	work->rx_mode = rx_mode;
+	netdev_dbg(lif->netdev, "deferred: rx_mode\n");
+	ionic_lif_deferred_enqueue(&lif->deferred, work);
 }
 
 static void ionic_set_rx_mode(struct net_device *netdev)
@@ -1312,7 +1309,7 @@ static int ionic_set_mac_address(struct
 	eth_commit_mac_addr_change(netdev, addr);
 	netdev_info(netdev, "updating mac addr %pM\n", mac);
 
-	return ionic_addr_add(netdev, mac);
+	return ionic_lif_addr(netdev_priv(netdev), mac, true, true);
 }
 
 static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
@@ -2252,7 +2249,7 @@ static void ionic_lif_handle_fw_up(struc
 	}
 
 	clear_bit(IONIC_LIF_F_FW_RESET, lif->state);
-	ionic_link_status_check_request(lif);
+	ionic_link_status_check_request(lif, true);
 	netif_device_attach(lif->netdev);
 	dev_info(ionic->dev, "FW Up: LIFs restarted\n");
 
@@ -2468,7 +2465,7 @@ static int ionic_station_set(struct ioni
 		 */
 		if (!ether_addr_equal(ctx.comp.lif_getattr.mac,
 				      netdev->dev_addr))
-			ionic_lif_addr(lif, netdev->dev_addr, true);
+			ionic_lif_addr(lif, netdev->dev_addr, true, true);
 	} else {
 		/* Update the netdev mac with the device's mac */
 		memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len);
@@ -2485,7 +2482,7 @@ static int ionic_station_set(struct ioni
 
 	netdev_dbg(lif->netdev, "adding station MAC addr %pM\n",
 		   netdev->dev_addr);
-	ionic_lif_addr(lif, netdev->dev_addr, true);
+	ionic_lif_addr(lif, netdev->dev_addr, true, true);
 
 	return 0;
 }
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -237,7 +237,7 @@ static inline u32 ionic_coal_usec_to_hw(
 
 typedef void (*ionic_reset_cb)(struct ionic_lif *lif, void *arg);
 
-void ionic_link_status_check_request(struct ionic_lif *lif);
+void ionic_link_status_check_request(struct ionic_lif *lif, bool can_sleep);
 void ionic_get_stats64(struct net_device *netdev,
 		       struct rtnl_link_stats64 *ns);
 void ionic_lif_deferred_enqueue(struct ionic_deferred *def,


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 12/35] net: ionic: Remove WARN_ON(in_interrupt()).
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (10 preceding siblings ...)
  2020-09-27 19:48 ` [patch 11/35] net: ionic: Replace in_interrupt() usage Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-28 17:26   ` Shannon Nelson
  2020-09-27 19:48 ` [patch 13/35] net: mdiobus: Remove WARN_ON_ONCE(in_interrupt()) Thomas Gleixner
                   ` (24 subsequent siblings)
  36 siblings, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Shannon Nelson, Pensando Drivers,
	David S. Miller, Jakub Kicinski, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

in_interrupt() is ill defined and does not provide what the name
suggests. The usage especially in driver code is deprecated and a tree wide
effort to clean up and consolidate the (ab)usage of in_interrupt() and
related checks is happening.

In this case the check covers only parts of the contexts in which these
functions cannot be called. It fails to detect preemption or interrupt
disabled invocations.

As the functions which are invoked from ionic_adminq_post() and
ionic_dev_cmd_wait() contain a broad variety of checks (always enabled or
debug option dependent) which cover all invalid conditions already, there
is no point in having inconsistent warnings in those drivers.

Just remove them.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Shannon Nelson <snelson@pensando.io>
Cc: Pensando Drivers <drivers@pensando.io>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org

---
 drivers/net/ethernet/pensando/ionic/ionic_main.c |    4 ----
 1 file changed, 4 deletions(-)

--- a/drivers/net/ethernet/pensando/ionic/ionic_main.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c
@@ -248,8 +248,6 @@ static int ionic_adminq_post(struct ioni
 	struct ionic_queue *adminq;
 	int err = 0;
 
-	WARN_ON(in_interrupt());
-
 	if (!lif->adminqcq)
 		return -EIO;
 
@@ -346,8 +344,6 @@ int ionic_dev_cmd_wait(struct ionic *ion
 	int done;
 	int err;
 
-	WARN_ON(in_interrupt());
-
 	/* Wait for dev cmd to complete, retrying if we get EAGAIN,
 	 * but don't wait any longer than max_seconds.
 	 */


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 13/35] net: mdiobus: Remove WARN_ON_ONCE(in_interrupt())
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (11 preceding siblings ...)
  2020-09-27 19:48 ` [patch 12/35] net: ionic: Remove WARN_ON(in_interrupt()) Thomas Gleixner
@ 2020-09-27 19:48 ` Thomas Gleixner
  2020-09-27 23:00   ` Andrew Lunn
  2020-09-27 19:49 ` [patch 14/35] net: natsemi: Replace in_interrupt() usage Thomas Gleixner
                   ` (23 subsequent siblings)
  36 siblings, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:48 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Andrew Lunn, Heiner Kallweit,
	Russell King, David S. Miller, Jakub Kicinski, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

in_interrupt() is ill defined and does not provide what the name
suggests. The usage especially in driver code is deprecated and a tree wide
effort to clean up and consolidate the (ab)usage of in_interrupt() and
related checks is happening.

In this case the check covers only parts of the contexts in which these
functions cannot be called. It fails to detect preemption or interrupt
disabled invocations.

As the functions which contain these warnings invoke mutex_lock() which
contains a broad variety of checks (always enabled or debug option
dependent) and therefore covers all invalid conditions already, there is no
point in having inconsistent warnings in those drivers. The conditional
return is not really valuable in practice either.

Just remove them.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Heiner Kallweit <hkallweit1@gmail.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org

---
 drivers/net/phy/mdio_bus.c |   15 ---------------
 1 file changed, 15 deletions(-)

--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -825,9 +825,6 @@ int mdiobus_read_nested(struct mii_bus *
 {
 	int retval;
 
-	if (WARN_ON_ONCE(in_interrupt()))
-		return -EINVAL;
-
 	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
 	retval = __mdiobus_read(bus, addr, regnum);
 	mutex_unlock(&bus->mdio_lock);
@@ -850,9 +847,6 @@ int mdiobus_read(struct mii_bus *bus, in
 {
 	int retval;
 
-	if (WARN_ON_ONCE(in_interrupt()))
-		return -EINVAL;
-
 	mutex_lock(&bus->mdio_lock);
 	retval = __mdiobus_read(bus, addr, regnum);
 	mutex_unlock(&bus->mdio_lock);
@@ -879,9 +873,6 @@ int mdiobus_write_nested(struct mii_bus
 {
 	int err;
 
-	if (WARN_ON_ONCE(in_interrupt()))
-		return -EINVAL;
-
 	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
 	err = __mdiobus_write(bus, addr, regnum, val);
 	mutex_unlock(&bus->mdio_lock);
@@ -905,9 +896,6 @@ int mdiobus_write(struct mii_bus *bus, i
 {
 	int err;
 
-	if (WARN_ON_ONCE(in_interrupt()))
-		return -EINVAL;
-
 	mutex_lock(&bus->mdio_lock);
 	err = __mdiobus_write(bus, addr, regnum, val);
 	mutex_unlock(&bus->mdio_lock);
@@ -929,9 +917,6 @@ int mdiobus_modify(struct mii_bus *bus,
 {
 	int err;
 
-	if (WARN_ON_ONCE(in_interrupt()))
-		return -EINVAL;
-
 	mutex_lock(&bus->mdio_lock);
 	err = __mdiobus_modify_changed(bus, addr, regnum, mask, set);
 	mutex_unlock(&bus->mdio_lock);


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 14/35] net: natsemi: Replace in_interrupt() usage.
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (12 preceding siblings ...)
  2020-09-27 19:48 ` [patch 13/35] net: mdiobus: Remove WARN_ON_ONCE(in_interrupt()) Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 15/35] net: sfc: " Thomas Gleixner
                   ` (22 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Thomas Bogendoerfer, David S. Miller,
	Jakub Kicinski, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Solarflare linux maintainers,
	Edward Cree, Martin Habets, Jon Mason, Daniel Drake,
	Ulrich Kunitz, Kalle Valo, linux-wireless, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

The usage of in_interrupt() in drivers is phased out and Linus clearly
requested that code which changes behaviour depending on context should
either be seperated or the context be conveyed in an argument passed by the
caller, which usually knows the context.

sonic_quiesce() uses 'in_interrupt() || irqs_disabled()' to chose either
udelay() or usleep_range() in the wait loop.

In all callchains leading to it the context is well defined and known.

Add a 'may_sleep' argument and pass it through the various callchains
leading to this function.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org

---
 drivers/net/ethernet/natsemi/sonic.c |   24 ++++++++++++------------
 drivers/net/ethernet/natsemi/sonic.h |    2 +-
 2 files changed, 13 insertions(+), 13 deletions(-)

--- a/drivers/net/ethernet/natsemi/sonic.c
+++ b/drivers/net/ethernet/natsemi/sonic.c
@@ -143,7 +143,7 @@ static int sonic_open(struct net_device
 	/*
 	 * Initialize the SONIC
 	 */
-	sonic_init(dev);
+	sonic_init(dev, true);
 
 	netif_start_queue(dev);
 
@@ -153,7 +153,7 @@ static int sonic_open(struct net_device
 }
 
 /* Wait for the SONIC to become idle. */
-static void sonic_quiesce(struct net_device *dev, u16 mask)
+static void sonic_quiesce(struct net_device *dev, u16 mask, bool may_sleep)
 {
 	struct sonic_local * __maybe_unused lp = netdev_priv(dev);
 	int i;
@@ -163,7 +163,7 @@ static void sonic_quiesce(struct net_dev
 		bits = SONIC_READ(SONIC_CMD) & mask;
 		if (!bits)
 			return;
-		if (irqs_disabled() || in_interrupt())
+		if (!may_sleep)
 			udelay(20);
 		else
 			usleep_range(100, 200);
@@ -187,7 +187,7 @@ static int sonic_close(struct net_device
 	 * stop the SONIC, disable interrupts
 	 */
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
-	sonic_quiesce(dev, SONIC_CR_ALL);
+	sonic_quiesce(dev, SONIC_CR_ALL, true);
 
 	SONIC_WRITE(SONIC_IMR, 0);
 	SONIC_WRITE(SONIC_ISR, 0x7fff);
@@ -229,7 +229,7 @@ static void sonic_tx_timeout(struct net_
 	 * disable all interrupts before releasing DMA buffers
 	 */
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
-	sonic_quiesce(dev, SONIC_CR_ALL);
+	sonic_quiesce(dev, SONIC_CR_ALL, false);
 
 	SONIC_WRITE(SONIC_IMR, 0);
 	SONIC_WRITE(SONIC_ISR, 0x7fff);
@@ -246,7 +246,7 @@ static void sonic_tx_timeout(struct net_
 		}
 	}
 	/* Try to restart the adaptor. */
-	sonic_init(dev);
+	sonic_init(dev, false);
 	lp->stats.tx_errors++;
 	netif_trans_update(dev); /* prevent tx timeout */
 	netif_wake_queue(dev);
@@ -692,9 +692,9 @@ static void sonic_multicast_list(struct
 
 			/* LCAM and TXP commands can't be used simultaneously */
 			spin_lock_irqsave(&lp->lock, flags);
-			sonic_quiesce(dev, SONIC_CR_TXP);
+			sonic_quiesce(dev, SONIC_CR_TXP, false);
 			SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM);
-			sonic_quiesce(dev, SONIC_CR_LCAM);
+			sonic_quiesce(dev, SONIC_CR_LCAM, false);
 			spin_unlock_irqrestore(&lp->lock, flags);
 		}
 	}
@@ -708,7 +708,7 @@ static void sonic_multicast_list(struct
 /*
  * Initialize the SONIC ethernet controller.
  */
-static int sonic_init(struct net_device *dev)
+static int sonic_init(struct net_device *dev, bool may_sleep)
 {
 	struct sonic_local *lp = netdev_priv(dev);
 	int i;
@@ -730,7 +730,7 @@ static int sonic_init(struct net_device
 	 */
 	SONIC_WRITE(SONIC_CMD, 0);
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS | SONIC_CR_STP);
-	sonic_quiesce(dev, SONIC_CR_ALL);
+	sonic_quiesce(dev, SONIC_CR_ALL, may_sleep);
 
 	/*
 	 * initialize the receive resource area
@@ -759,7 +759,7 @@ static int sonic_init(struct net_device
 	netif_dbg(lp, ifup, dev, "%s: issuing RRRA command\n", __func__);
 
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RRRA);
-	sonic_quiesce(dev, SONIC_CR_RRRA);
+	sonic_quiesce(dev, SONIC_CR_RRRA, may_sleep);
 
 	/*
 	 * Initialize the receive descriptors so that they
@@ -834,7 +834,7 @@ static int sonic_init(struct net_device
 	 * load the CAM
 	 */
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM);
-	sonic_quiesce(dev, SONIC_CR_LCAM);
+	sonic_quiesce(dev, SONIC_CR_LCAM, may_sleep);
 
 	/*
 	 * enable receiver, disable loopback
--- a/drivers/net/ethernet/natsemi/sonic.h
+++ b/drivers/net/ethernet/natsemi/sonic.h
@@ -338,7 +338,7 @@ static void sonic_rx(struct net_device *
 static int sonic_close(struct net_device *dev);
 static struct net_device_stats *sonic_get_stats(struct net_device *dev);
 static void sonic_multicast_list(struct net_device *dev);
-static int sonic_init(struct net_device *dev);
+static int sonic_init(struct net_device *dev, bool may_sleep);
 static void sonic_tx_timeout(struct net_device *dev, unsigned int txqueue);
 static void sonic_msg_init(struct net_device *dev);
 static int sonic_alloc_descriptors(struct net_device *dev);


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 15/35] net: sfc: Replace in_interrupt() usage.
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (13 preceding siblings ...)
  2020-09-27 19:49 ` [patch 14/35] net: natsemi: Replace in_interrupt() usage Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-28 19:03   ` Edward Cree
  2020-09-27 19:49 ` [patch 16/35] net: sunbmac: Replace " Thomas Gleixner
                   ` (21 subsequent siblings)
  36 siblings, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Solarflare linux maintainers,
	Edward Cree, Martin Habets, David S. Miller, Jakub Kicinski,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

efx_ef10_try_update_nic_stats_vf() uses in_interrupt() to figure out
whether it is safe to sleep or not.

The following callers are involved:

- efx_start_all() and efx_stop_all() are fully preemptible because a
  mutex is acquired near by.

- efx_ethtool_get_stats() is ivoked from ethtool_ops->get_ethtool_stats()
  and is fully preemptible.

- efx_net_stats() which can be invoked under dev_base_lock from
  net-sysfs::netstat_show(). dev_base_lock is a rwlock_t which disables
  preemption implicitly. 

  in_interrupt() cannot detect context which has only preemption disabled
  so the check fails to detect that this calling context is not safe to
  sleep.

  Obviously this is a bug and clearly this has never been tested with any
  of the relevant and mandatory debug options enabled, which would have
  caught it.

  Changing the condition to preemptible() is not useful either because on
  CONFIG_PREEMPT_COUNT=n kernels preemptible() is useless.

  Aside of that Linus clearly requested that functions which change their
  behaviour depending on execution context should either be split up or the
  callers provide context information via an argument.

Add a 'can_sleep' argument to efx_ef10_try_update_nic_stats_vf() and let
the callers indicate the context from which this is called.

Another oddity of that code is that it uses GFP_ATOMIC _after_ establishing
that the context is safe to sleep.

Convert it to GFP_KERNEL while at it.

Note, that the fixes tag is empty as it is unclear which of the commits to
blame.

Fixes: ????
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Solarflare linux maintainers <linux-net-drivers@solarflare.com>
Cc: Edward Cree <ecree@solarflare.com>
Cc: Martin Habets <mhabets@solarflare.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/sfc/ef10.c           |   18 +++++++++---------
 drivers/net/ethernet/sfc/ef100_nic.c      |    3 ++-
 drivers/net/ethernet/sfc/efx_common.c     |    6 +++---
 drivers/net/ethernet/sfc/ethtool_common.c |    2 +-
 drivers/net/ethernet/sfc/net_driver.h     |    3 ++-
 drivers/net/ethernet/sfc/siena.c          |    3 ++-
 6 files changed, 19 insertions(+), 16 deletions(-)

--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1797,7 +1797,8 @@ static size_t efx_ef10_update_stats_comm
 }
 
 static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats,
-				       struct rtnl_link_stats64 *core_stats)
+				       struct rtnl_link_stats64 *core_stats,
+				       bool can_sleep)
 {
 	struct efx_ef10_nic_data *nic_data = efx->nic_data;
 	DECLARE_BITMAP(mask, EF10_STAT_COUNT);
@@ -1836,7 +1837,7 @@ static size_t efx_ef10_update_stats_pf(s
 	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
 }
 
-static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx)
+static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx, bool can_sleep)
 	__must_hold(&efx->stats_lock)
 {
 	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
@@ -1849,20 +1850,18 @@ static int efx_ef10_try_update_nic_stats
 	__le64 *dma_stats;
 	int rc;
 
-	spin_unlock_bh(&efx->stats_lock);
-
-	if (in_interrupt()) {
+	if (!can_sleep) {
 		/* If in atomic context, cannot update stats.  Just update the
 		 * software stats and return so the caller can continue.
 		 */
-		spin_lock_bh(&efx->stats_lock);
 		efx_update_sw_stats(efx, stats);
 		return 0;
 	}
 
+	spin_unlock_bh(&efx->stats_lock);
 	efx_ef10_get_stat_mask(efx, mask);
 
-	rc = efx_nic_alloc_buffer(efx, &stats_buf, dma_len, GFP_ATOMIC);
+	rc = efx_nic_alloc_buffer(efx, &stats_buf, dma_len, GFP_KERNEL);
 	if (rc) {
 		spin_lock_bh(&efx->stats_lock);
 		return rc;
@@ -1910,9 +1909,10 @@ static int efx_ef10_try_update_nic_stats
 }
 
 static size_t efx_ef10_update_stats_vf(struct efx_nic *efx, u64 *full_stats,
-				       struct rtnl_link_stats64 *core_stats)
+				       struct rtnl_link_stats64 *core_stats,
+				       bool can_sleep)
 {
-	if (efx_ef10_try_update_nic_stats_vf(efx))
+	if (efx_ef10_try_update_nic_stats_vf(efx, can_sleep))
 		return 0;
 
 	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -599,7 +599,8 @@ static size_t ef100_update_stats_common(
 
 static size_t ef100_update_stats(struct efx_nic *efx,
 				 u64 *full_stats,
-				 struct rtnl_link_stats64 *core_stats)
+				 struct rtnl_link_stats64 *core_stats,
+				 bool can_sleep)
 {
 	__le64 *mc_stats = kmalloc(array_size(efx->num_mac_stats, sizeof(__le64)), GFP_ATOMIC);
 	struct ef100_nic_data *nic_data = efx->nic_data;
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -552,7 +552,7 @@ void efx_start_all(struct efx_nic *efx)
 		efx->type->start_stats(efx);
 		efx->type->pull_stats(efx);
 		spin_lock_bh(&efx->stats_lock);
-		efx->type->update_stats(efx, NULL, NULL);
+		efx->type->update_stats(efx, NULL, NULL, true);
 		spin_unlock_bh(&efx->stats_lock);
 	}
 }
@@ -576,7 +576,7 @@ void efx_stop_all(struct efx_nic *efx)
 		 */
 		efx->type->pull_stats(efx);
 		spin_lock_bh(&efx->stats_lock);
-		efx->type->update_stats(efx, NULL, NULL);
+		efx->type->update_stats(efx, NULL, NULL, true);
 		spin_unlock_bh(&efx->stats_lock);
 		efx->type->stop_stats(efx);
 	}
@@ -600,7 +600,7 @@ void efx_net_stats(struct net_device *ne
 	struct efx_nic *efx = netdev_priv(net_dev);
 
 	spin_lock_bh(&efx->stats_lock);
-	efx->type->update_stats(efx, NULL, stats);
+	efx->type->update_stats(efx, NULL, stats, false);
 	spin_unlock_bh(&efx->stats_lock);
 }
 
--- a/drivers/net/ethernet/sfc/ethtool_common.c
+++ b/drivers/net/ethernet/sfc/ethtool_common.c
@@ -502,7 +502,7 @@ void efx_ethtool_get_stats(struct net_de
 	spin_lock_bh(&efx->stats_lock);
 
 	/* Get NIC statistics */
-	data += efx->type->update_stats(efx, data, NULL);
+	data += efx->type->update_stats(efx, data, NULL, true);
 
 	/* Get software statistics */
 	for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++) {
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1358,7 +1358,8 @@ struct efx_nic_type {
 	void (*finish_flr)(struct efx_nic *efx);
 	size_t (*describe_stats)(struct efx_nic *efx, u8 *names);
 	size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats,
-			       struct rtnl_link_stats64 *core_stats);
+			       struct rtnl_link_stats64 *core_stats,
+			       bool can_sleep);
 	void (*start_stats)(struct efx_nic *efx);
 	void (*pull_stats)(struct efx_nic *efx);
 	void (*stop_stats)(struct efx_nic *efx);
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -587,7 +587,8 @@ static int siena_try_update_nic_stats(st
 }
 
 static size_t siena_update_nic_stats(struct efx_nic *efx, u64 *full_stats,
-				     struct rtnl_link_stats64 *core_stats)
+				     struct rtnl_link_stats64 *core_stats,
+				     bool can_sleep)
 {
 	struct siena_nic_data *nic_data = efx->nic_data;
 	u64 *stats = nic_data->stats;


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 16/35] net: sunbmac: Replace in_interrupt() usage
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (14 preceding siblings ...)
  2020-09-27 19:49 ` [patch 15/35] net: sfc: " Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 17/35] net: sun3lance: Remove redundant checks in interrupt handler Thomas Gleixner
                   ` (20 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, David S. Miller, Jakub Kicinski,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

bigmac_init_rings() has an argument signaling if it is called from the
interrupt handler. This is used to decide between GFP_KERNEL and GFP_ATOMIC
for memory allocations.

But it also checks in_interrupt() to handle invocations which come from the
timer callback bigmac_timer() via bigmac_hw_init(), which is invoked with
'in_irq = 0'. While the timer callback is clearly not in hard interrupt
context it is still not sleepable context.

Rename the argument to `non_blocking' and set it to true if invoked from
the timer callback or the interrupt handler which allows to remove the
in_interrupt() check and makes the code consistent.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org

---
 drivers/net/ethernet/sun/sunbmac.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

--- a/drivers/net/ethernet/sun/sunbmac.c
+++ b/drivers/net/ethernet/sun/sunbmac.c
@@ -209,13 +209,13 @@ static void bigmac_clean_rings(struct bi
 	}
 }
 
-static void bigmac_init_rings(struct bigmac *bp, int from_irq)
+static void bigmac_init_rings(struct bigmac *bp, bool non_blocking)
 {
 	struct bmac_init_block *bb = bp->bmac_block;
 	int i;
 	gfp_t gfp_flags = GFP_KERNEL;
 
-	if (from_irq || in_interrupt())
+	if (non_blocking)
 		gfp_flags = GFP_ATOMIC;
 
 	bp->rx_new = bp->rx_old = bp->tx_new = bp->tx_old = 0;
@@ -489,7 +489,7 @@ static void bigmac_tcvr_init(struct bigm
 	}
 }
 
-static int bigmac_init_hw(struct bigmac *, int);
+static int bigmac_init_hw(struct bigmac *, bool);
 
 static int try_next_permutation(struct bigmac *bp, void __iomem *tregs)
 {
@@ -549,7 +549,7 @@ static void bigmac_timer(struct timer_li
 				if (ret == -1) {
 					printk(KERN_ERR "%s: Link down, cable problem?\n",
 					       bp->dev->name);
-					ret = bigmac_init_hw(bp, 0);
+					ret = bigmac_init_hw(bp, true);
 					if (ret) {
 						printk(KERN_ERR "%s: Error, cannot re-init the "
 						       "BigMAC.\n", bp->dev->name);
@@ -617,7 +617,7 @@ static void bigmac_begin_auto_negotiatio
 	add_timer(&bp->bigmac_timer);
 }
 
-static int bigmac_init_hw(struct bigmac *bp, int from_irq)
+static int bigmac_init_hw(struct bigmac *bp, bool non_blocking)
 {
 	void __iomem *gregs        = bp->gregs;
 	void __iomem *cregs        = bp->creg;
@@ -635,7 +635,7 @@ static int bigmac_init_hw(struct bigmac
 	qec_init(bp);
 
 	/* Alloc and reset the tx/rx descriptor chains. */
-	bigmac_init_rings(bp, from_irq);
+	bigmac_init_rings(bp, non_blocking);
 
 	/* Initialize the PHY. */
 	bigmac_tcvr_init(bp);
@@ -749,7 +749,7 @@ static void bigmac_is_medium_rare(struct
 	}
 
 	printk(" RESET\n");
-	bigmac_init_hw(bp, 1);
+	bigmac_init_hw(bp, true);
 }
 
 /* BigMAC transmit complete service routines. */
@@ -921,7 +921,7 @@ static int bigmac_open(struct net_device
 		return ret;
 	}
 	timer_setup(&bp->bigmac_timer, bigmac_timer, 0);
-	ret = bigmac_init_hw(bp, 0);
+	ret = bigmac_init_hw(bp, false);
 	if (ret)
 		free_irq(dev->irq, bp);
 	return ret;
@@ -945,7 +945,7 @@ static void bigmac_tx_timeout(struct net
 {
 	struct bigmac *bp = netdev_priv(dev);
 
-	bigmac_init_hw(bp, 0);
+	bigmac_init_hw(bp, true);
 	netif_wake_queue(dev);
 }
 


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 17/35] net: sun3lance: Remove redundant checks in interrupt handler
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (15 preceding siblings ...)
  2020-09-27 19:49 ` [patch 16/35] net: sunbmac: Replace " Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 18/35] net: vxge: Remove in_interrupt() conditionals Thomas Gleixner
                   ` (19 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, David S. Miller, Jakub Kicinski,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

lance_interrupt() contains two pointless checks:

 - A check whether the 'dev_id' argument is NULL. 'dev_id' is the pointer
   which was handed in to request_irq() and the interrupt handler will
   always be invoked with that pointer as 'dev_id' argument by the core
   code.

 - A check for interrupt reentrancy. The core code already guarantees
   non-reentrancy of interrupt handlers.

Remove these check.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/amd/sun3lance.c |   11 -----------
 1 file changed, 11 deletions(-)

--- a/drivers/net/ethernet/amd/sun3lance.c
+++ b/drivers/net/ethernet/amd/sun3lance.c
@@ -657,16 +657,6 @@ static irqreturn_t lance_interrupt( int
 	struct net_device *dev = dev_id;
 	struct lance_private *lp = netdev_priv(dev);
 	int csr0;
-	static int in_interrupt;
-
-	if (dev == NULL) {
-		DPRINTK( 1, ( "lance_interrupt(): invalid dev_id\n" ));
-		return IRQ_NONE;
-	}
-
-	if (in_interrupt)
-		DPRINTK( 2, ( "%s: Re-entering the interrupt handler.\n", dev->name ));
-	in_interrupt = 1;
 
  still_more:
 	flush_cache_all();
@@ -774,7 +764,6 @@ static irqreturn_t lance_interrupt( int
 
 	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
 				  dev->name, DREG ));
-	in_interrupt = 0;
 	return IRQ_HANDLED;
 }
 


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 18/35] net: vxge: Remove in_interrupt() conditionals
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (16 preceding siblings ...)
  2020-09-27 19:49 ` [patch 17/35] net: sun3lance: Remove redundant checks in interrupt handler Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 19/35] net: zd1211rw: Remove ZD_ASSERT(in_interrupt()) Thomas Gleixner
                   ` (18 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Jon Mason, David S. Miller,
	Jakub Kicinski, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Daniel Drake, Ulrich Kunitz, Kalle Valo, linux-wireless,
	linux-usb, Greg Kroah-Hartman, Arend van Spriel, Franky Lin,
	Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

vxge_os_dma_malloc() and vxge_os_dma_malloc_async() are both called from
callchains which use GFP_KERNEL allocations unconditionally or have other
requirements to be called from fully preemptible task context..

vxge_os_dma_malloc():
  1)  __vxge_hw_blockpool_create() <- GFP_KERNEL
	
  2)  __vxge_hw_mempool_grow() <- vzalloc()
        __vxge_hw_blockpool_malloc()

vxge_os_dma_malloc_async():
  1  __vxge_hw_mempool_grow() <- vzalloc()
      __vxge_hw_blockpool_malloc()
	__vxge_hw_blockpool_blocks_add()

  2)  vxge_hw_vpath_open()	<- vzalloc()
	__vxge_hw_blockpool_block_allocate()

That means neither of these functions needs a conditional allocation mode.

Remove the in_interrupt() conditional and use GFP_KERNEL.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Jon Mason <jdmason@kudzu.us>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org

---
 drivers/net/ethernet/neterion/vxge/vxge-config.c |    9 +--------
 drivers/net/ethernet/neterion/vxge/vxge-config.h |    7 +------
 2 files changed, 2 insertions(+), 14 deletions(-)

--- a/drivers/net/ethernet/neterion/vxge/vxge-config.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c
@@ -2303,16 +2303,9 @@ static void vxge_hw_blockpool_block_add(
 static inline void
 vxge_os_dma_malloc_async(struct pci_dev *pdev, void *devh, unsigned long size)
 {
-	gfp_t flags;
 	void *vaddr;
 
-	if (in_interrupt())
-		flags = GFP_ATOMIC | GFP_DMA;
-	else
-		flags = GFP_KERNEL | GFP_DMA;
-
-	vaddr = kmalloc((size), flags);
-
+	vaddr = kmalloc(size, GFP_KERNEL | GFP_DMA);
 	vxge_hw_blockpool_block_add(devh, vaddr, size, pdev, pdev);
 }
 
--- a/drivers/net/ethernet/neterion/vxge/vxge-config.h
+++ b/drivers/net/ethernet/neterion/vxge/vxge-config.h
@@ -1899,18 +1899,13 @@ static inline void *vxge_os_dma_malloc(s
 			struct pci_dev **p_dmah,
 			struct pci_dev **p_dma_acch)
 {
-	gfp_t flags;
 	void *vaddr;
 	unsigned long misaligned = 0;
 	int realloc_flag = 0;
 	*p_dma_acch = *p_dmah = NULL;
 
-	if (in_interrupt())
-		flags = GFP_ATOMIC | GFP_DMA;
-	else
-		flags = GFP_KERNEL | GFP_DMA;
 realloc:
-	vaddr = kmalloc((size), flags);
+	vaddr = kmalloc(size, GFP_KERNEL | GFP_DMA);
 	if (vaddr == NULL)
 		return vaddr;
 	misaligned = (unsigned long)VXGE_ALIGN((unsigned long)vaddr,


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 19/35] net: zd1211rw: Remove ZD_ASSERT(in_interrupt())
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (17 preceding siblings ...)
  2020-09-27 19:49 ` [patch 18/35] net: vxge: Remove in_interrupt() conditionals Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 20/35] net: usb: kaweth: Replace kaweth_control() with usb_control_msg() Thomas Gleixner
                   ` (17 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, David S. Miller, Jakub Kicinski, linux-wireless,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

in_interrupt() is ill defined and does not provide what the name
suggests. The usage especially in driver code is deprecated and
a tree wide effort to clean up and consolidate the (ab)usage of
in_interrupt() and related checks is happening.

handle_regs_int() is always invoked as part of URB callback which is either
invoked from hard or soft interrupt context.

Remove the magic assertion.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Daniel Drake <dsd@gentoo.org>
Cc: Ulrich Kunitz <kune@deine-taler.de>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/zydas/zd1211rw/zd_usb.c |    1 -
 1 file changed, 1 deletion(-)

--- a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
@@ -378,7 +378,6 @@ static inline void handle_regs_int(struc
 	int len;
 	u16 int_num;
 
-	ZD_ASSERT(in_interrupt());
 	spin_lock_irqsave(&intr->lock, flags);
 
 	int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2));


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 20/35] net: usb: kaweth: Replace kaweth_control() with usb_control_msg()
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (18 preceding siblings ...)
  2020-09-27 19:49 ` [patch 19/35] net: zd1211rw: Remove ZD_ASSERT(in_interrupt()) Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 21/35] net: usb: kaweth: Remove last user of kaweth_control() Thomas Gleixner
                   ` (16 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, David S. Miller, Jakub Kicinski,
	linux-usb, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, Greg Kroah-Hartman, Arend van Spriel, Franky Lin,
	Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

kaweth_control() is almost the same as usb_control_msg() except for the
memory allocation mode (GFP_ATOMIC vs GFP_NOIO) and the in_interrupt()
check.

All the invocations of kaweth_control() are within the probe function in
fully preemtible context so there is no reason to use atomic allocations,
GFP_NOIO which is used by usb_control_msg() is perfectly fine.

Replace kaweth_control() invocations from probe with usb_control_msg().

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-usb@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/usb/kaweth.c |   93 +++++++++++++++--------------------------------
 1 file changed, 30 insertions(+), 63 deletions(-)

--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -282,19 +282,13 @@ static int kaweth_control(struct kaweth_
  ****************************************************************/
 static int kaweth_read_configuration(struct kaweth_device *kaweth)
 {
-	int retval;
-
-	retval = kaweth_control(kaweth,
-				usb_rcvctrlpipe(kaweth->dev, 0),
+	return usb_control_msg(kaweth->dev, usb_rcvctrlpipe(kaweth->dev, 0),
 				KAWETH_COMMAND_GET_ETHERNET_DESC,
 				USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
-				0,
-				0,
-				(void *)&kaweth->configuration,
+				0, 0,
+				&kaweth->configuration,
 				sizeof(kaweth->configuration),
 				KAWETH_CONTROL_TIMEOUT);
-
-	return retval;
 }
 
 /****************************************************************
@@ -302,21 +296,14 @@ static int kaweth_read_configuration(str
  ****************************************************************/
 static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size)
 {
-	int retval;
-
 	netdev_dbg(kaweth->net, "Setting URB size to %d\n", (unsigned)urb_size);
 
-	retval = kaweth_control(kaweth,
-				usb_sndctrlpipe(kaweth->dev, 0),
-				KAWETH_COMMAND_SET_URB_SIZE,
-				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-				urb_size,
-				0,
-				(void *)&kaweth->scratch,
-				0,
-				KAWETH_CONTROL_TIMEOUT);
-
-	return retval;
+	return usb_control_msg(kaweth->dev, usb_sndctrlpipe(kaweth->dev, 0),
+			       KAWETH_COMMAND_SET_URB_SIZE,
+			       USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+			       urb_size, 0,
+			       &kaweth->scratch, 0,
+			       KAWETH_CONTROL_TIMEOUT);
 }
 
 /****************************************************************
@@ -324,21 +311,14 @@ static int kaweth_set_urb_size(struct ka
  ****************************************************************/
 static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait)
 {
-	int retval;
-
 	netdev_dbg(kaweth->net, "Set SOFS wait to %d\n", (unsigned)sofs_wait);
 
-	retval = kaweth_control(kaweth,
-				usb_sndctrlpipe(kaweth->dev, 0),
-				KAWETH_COMMAND_SET_SOFS_WAIT,
-				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-				sofs_wait,
-				0,
-				(void *)&kaweth->scratch,
-				0,
-				KAWETH_CONTROL_TIMEOUT);
-
-	return retval;
+	return usb_control_msg(kaweth->dev, usb_sndctrlpipe(kaweth->dev, 0),
+			       KAWETH_COMMAND_SET_SOFS_WAIT,
+			       USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+			       sofs_wait, 0,
+			       &kaweth->scratch, 0,
+			       KAWETH_CONTROL_TIMEOUT);
 }
 
 /****************************************************************
@@ -347,22 +327,15 @@ static int kaweth_set_sofs_wait(struct k
 static int kaweth_set_receive_filter(struct kaweth_device *kaweth,
 				     __u16 receive_filter)
 {
-	int retval;
-
 	netdev_dbg(kaweth->net, "Set receive filter to %d\n",
 		   (unsigned)receive_filter);
 
-	retval = kaweth_control(kaweth,
-				usb_sndctrlpipe(kaweth->dev, 0),
-				KAWETH_COMMAND_SET_PACKET_FILTER,
-				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-				receive_filter,
-				0,
-				(void *)&kaweth->scratch,
-				0,
-				KAWETH_CONTROL_TIMEOUT);
-
-	return retval;
+	return usb_control_msg(kaweth->dev, usb_sndctrlpipe(kaweth->dev, 0),
+			       KAWETH_COMMAND_SET_PACKET_FILTER,
+			       USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+			       receive_filter, 0,
+			       &kaweth->scratch, 0,
+			       KAWETH_CONTROL_TIMEOUT);
 }
 
 /****************************************************************
@@ -407,14 +380,11 @@ static int kaweth_download_firmware(stru
 		   kaweth->firmware_buf, kaweth);
 	netdev_dbg(kaweth->net, "Firmware length: %d\n", data_len);
 
-	return kaweth_control(kaweth,
-		              usb_sndctrlpipe(kaweth->dev, 0),
+	return usb_control_msg(kaweth->dev, usb_sndctrlpipe(kaweth->dev, 0),
 			      KAWETH_COMMAND_SCAN,
 			      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-			      0,
-			      0,
-			      (void *)kaweth->firmware_buf,
-			      data_len,
+			      0, 0,
+			      kaweth->firmware_buf, data_len,
 			      KAWETH_CONTROL_TIMEOUT);
 }
 
@@ -433,15 +403,12 @@ static int kaweth_trigger_firmware(struc
 	kaweth->firmware_buf[6] = 0x00;
 	kaweth->firmware_buf[7] = 0x00;
 
-	return kaweth_control(kaweth,
-			      usb_sndctrlpipe(kaweth->dev, 0),
-			      KAWETH_COMMAND_SCAN,
-			      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-			      0,
-			      0,
-			      (void *)kaweth->firmware_buf,
-			      8,
-			      KAWETH_CONTROL_TIMEOUT);
+	return usb_control_msg(kaweth->dev, usb_sndctrlpipe(kaweth->dev, 0),
+			       KAWETH_COMMAND_SCAN,
+			       USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+			       0, 0,
+			       (void *)kaweth->firmware_buf, 8,
+			       KAWETH_CONTROL_TIMEOUT);
 }
 
 /****************************************************************


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 21/35] net: usb: kaweth: Remove last user of kaweth_control()
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (19 preceding siblings ...)
  2020-09-27 19:49 ` [patch 20/35] net: usb: kaweth: Replace kaweth_control() with usb_control_msg() Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-28  6:50   ` Greg Kroah-Hartman
  2020-09-27 19:49 ` [patch 22/35] net: usb: net1080: Remove in_interrupt() comment Thomas Gleixner
                   ` (15 subsequent siblings)
  36 siblings, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, David S. Miller, Jakub Kicinski,
	Greg Kroah-Hartman, linux-usb, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

kaweth_async_set_rx_mode() invokes kaweth_contol() and has two callers:

- kaweth_open() which is invoked from preemptible context
.
- kaweth_start_xmit() which holds a spinlock and has bottom halfs disabled.

If called from kaweth_start_xmit() kaweth_async_set_rx_mode() obviously
cannot block, which means it can't call kaweth_control(). This is detected
with an in_interrupt() check.

Replace the in_interrupt() check in kaweth_async_set_rx_mode() with an
argument which is set true by the caller if the context is safe to sleep,
otherwise false.

Now kaweth_control() is only called from preemptible context which means
there is no need for GFP_ATOMIC allocations anymore. Replace it with
usb_control_msg(). Cleanup the code a bit while at it.

Finally remove kaweth_control() since the last user is gone.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/usb/kaweth.c |  168 ++++-------------------------------------------
 1 file changed, 17 insertions(+), 151 deletions(-)

--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -103,10 +103,6 @@ static int kaweth_probe(
 		const struct usb_device_id *id	/* from id_table */
 	);
 static void kaweth_disconnect(struct usb_interface *intf);
-static int kaweth_internal_control_msg(struct usb_device *usb_dev,
-				       unsigned int pipe,
-				       struct usb_ctrlrequest *cmd, void *data,
-				       int len, int timeout);
 static int kaweth_suspend(struct usb_interface *intf, pm_message_t message);
 static int kaweth_resume(struct usb_interface *intf);
 
@@ -236,48 +232,6 @@ struct kaweth_device
 };
 
 /****************************************************************
- *     kaweth_control
- ****************************************************************/
-static int kaweth_control(struct kaweth_device *kaweth,
-			  unsigned int pipe,
-			  __u8 request,
-			  __u8 requesttype,
-			  __u16 value,
-			  __u16 index,
-			  void *data,
-			  __u16 size,
-			  int timeout)
-{
-	struct usb_ctrlrequest *dr;
-	int retval;
-
-	if(in_interrupt()) {
-		netdev_dbg(kaweth->net, "in_interrupt()\n");
-		return -EBUSY;
-	}
-
-	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
-	if (!dr)
-		return -ENOMEM;
-
-	dr->bRequestType = requesttype;
-	dr->bRequest = request;
-	dr->wValue = cpu_to_le16(value);
-	dr->wIndex = cpu_to_le16(index);
-	dr->wLength = cpu_to_le16(size);
-
-	retval = kaweth_internal_control_msg(kaweth->dev,
-					     pipe,
-					     dr,
-					     data,
-					     size,
-					     timeout);
-
-	kfree(dr);
-	return retval;
-}
-
-/****************************************************************
  *     kaweth_read_configuration
  ****************************************************************/
 static int kaweth_read_configuration(struct kaweth_device *kaweth)
@@ -531,7 +485,8 @@ static int kaweth_resubmit_rx_urb(struct
 	return result;
 }
 
-static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth);
+static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth,
+				     bool may_sleep);
 
 /****************************************************************
  *     kaweth_usb_receive
@@ -661,7 +616,7 @@ static int kaweth_open(struct net_device
 
 	netif_start_queue(net);
 
-	kaweth_async_set_rx_mode(kaweth);
+	kaweth_async_set_rx_mode(kaweth, true);
 	return 0;
 
 err_out:
@@ -749,7 +704,7 @@ static netdev_tx_t kaweth_start_xmit(str
 
 	spin_lock_irq(&kaweth->device_lock);
 
-	kaweth_async_set_rx_mode(kaweth);
+	kaweth_async_set_rx_mode(kaweth, false);
 	netif_stop_queue(net);
 	if (IS_BLOCKED(kaweth->status)) {
 		goto skip;
@@ -826,36 +781,31 @@ static void kaweth_set_rx_mode(struct ne
 /****************************************************************
  *     kaweth_async_set_rx_mode
  ****************************************************************/
-static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
+static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth,
+				     bool may_sleep)
 {
-	int result;
+	int ret;
 	__u16 packet_filter_bitmap = kaweth->packet_filter_bitmap;
 
 	kaweth->packet_filter_bitmap = 0;
 	if (packet_filter_bitmap == 0)
 		return;
 
-	if (in_interrupt())
+	if (!may_sleep)
 		return;
 
-	result = kaweth_control(kaweth,
-				usb_sndctrlpipe(kaweth->dev, 0),
-				KAWETH_COMMAND_SET_PACKET_FILTER,
-				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-				packet_filter_bitmap,
-				0,
-				(void *)&kaweth->scratch,
-				0,
-				KAWETH_CONTROL_TIMEOUT);
-
-	if(result < 0) {
+	ret = usb_control_msg(kaweth->dev, usb_sndctrlpipe(kaweth->dev, 0),
+			      KAWETH_COMMAND_SET_PACKET_FILTER,
+			      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+			      packet_filter_bitmap, 0,
+			      &kaweth->scratch, 0,
+			      KAWETH_CONTROL_TIMEOUT);
+	if (ret < 0)
 		dev_err(&kaweth->intf->dev, "Failed to set Rx mode: %d\n",
-			result);
-	}
-	else {
+			ret);
+	else
 		netdev_dbg(kaweth->net, "Set Rx mode to %d\n",
 			   packet_filter_bitmap);
-	}
 }
 
 /****************************************************************
@@ -1163,88 +1113,4 @@ static void kaweth_disconnect(struct usb
 }
 
 
-// FIXME this completion stuff is a modified clone of
-// an OLD version of some stuff in usb.c ...
-struct usb_api_data {
-	wait_queue_head_t wqh;
-	int done;
-};
-
-/*-------------------------------------------------------------------*
- * completion handler for compatibility wrappers (sync control/bulk) *
- *-------------------------------------------------------------------*/
-static void usb_api_blocking_completion(struct urb *urb)
-{
-        struct usb_api_data *awd = (struct usb_api_data *)urb->context;
-
-	awd->done=1;
-	wake_up(&awd->wqh);
-}
-
-/*-------------------------------------------------------------------*
- *                         COMPATIBILITY STUFF                       *
- *-------------------------------------------------------------------*/
-
-// Starts urb and waits for completion or timeout
-static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
-{
-	struct usb_api_data awd;
-        int status;
-
-        init_waitqueue_head(&awd.wqh);
-        awd.done = 0;
-
-        urb->context = &awd;
-        status = usb_submit_urb(urb, GFP_ATOMIC);
-        if (status) {
-                // something went wrong
-                usb_free_urb(urb);
-                return status;
-        }
-
-	if (!wait_event_timeout(awd.wqh, awd.done, timeout)) {
-                // timeout
-                dev_warn(&urb->dev->dev, "usb_control/bulk_msg: timeout\n");
-                usb_kill_urb(urb);  // remove urb safely
-                status = -ETIMEDOUT;
-        }
-	else {
-                status = urb->status;
-	}
-
-        if (actual_length) {
-                *actual_length = urb->actual_length;
-	}
-
-        usb_free_urb(urb);
-        return status;
-}
-
-/*-------------------------------------------------------------------*/
-// returns status (negative) or length (positive)
-static int kaweth_internal_control_msg(struct usb_device *usb_dev,
-				       unsigned int pipe,
-				       struct usb_ctrlrequest *cmd, void *data,
-				       int len, int timeout)
-{
-        struct urb *urb;
-        int retv;
-        int length = 0; /* shut up GCC */
-
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-        if (!urb)
-                return -ENOMEM;
-
-        usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data,
-			 len, usb_api_blocking_completion, NULL);
-
-        retv = usb_start_wait_urb(urb, timeout, &length);
-        if (retv < 0) {
-                return retv;
-	}
-        else {
-                return length;
-	}
-}
-
 module_usb_driver(kaweth_driver);


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 22/35] net: usb: net1080: Remove in_interrupt() comment
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (20 preceding siblings ...)
  2020-09-27 19:49 ` [patch 21/35] net: usb: kaweth: Remove last user of kaweth_control() Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 23/35] net: wan/lmc: Remove lmc_trace() Thomas Gleixner
                   ` (14 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, David S. Miller, Jakub Kicinski,
	Greg Kroah-Hartman, linux-usb, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The comment above nc_vendor_write() suggests that the function could become
async so that is usable in `in_interrupt()' context or that it already is
safe to be called from such a context.

Eitherway: The function did not become async since v2.4.9.2 (2002) and it
must be not be called from `in_interrupt()' context because it sleeps on
mutltiple occations.

Remove the misleading comment.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/usb/net1080.c |    1 -
 1 file changed, 1 deletion(-)

--- a/drivers/net/usb/net1080.c
+++ b/drivers/net/usb/net1080.c
@@ -113,7 +113,6 @@ nc_register_read(struct usbnet *dev, u8
 	return nc_vendor_read(dev, REQUEST_REGISTER, regnum, retval_ptr);
 }
 
-// no retval ... can become async, usable in_interrupt()
 static void
 nc_vendor_write(struct usbnet *dev, u8 req, u8 regnum, u16 value)
 {


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 23/35] net: wan/lmc: Remove lmc_trace()
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (21 preceding siblings ...)
  2020-09-27 19:49 ` [patch 22/35] net: usb: net1080: Remove in_interrupt() comment Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 24/35] net: brcmfmac: Replace in_interrupt() Thomas Gleixner
                   ` (13 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, David S. Miller, Jakub Kicinski,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

lmc_trace() was first introduced in commit e7a392d5158af ("Import
2.3.99pre6-5") and was not touched ever since.

The reason for looking at this was to get rid of the in_interrupt() usage,
but while looking at it the following observations were made:

 - At least lmc_get_stats() (->ndo_get_stats()) is invoked with disabled
   preemption which is not detected by the in_interrupt() check, which
   would cause schedule() to be called from invalid context.

 - The code is hidden behind #ifdef LMC_TRACE which is not defined within
   the kernel and wasn't at the time it was introduced.

 - Three jiffies don't match 50ms. msleep() would be a better match which
   would also avoid the schedule() invocation. But why have it to begin
   with?

 - Nobody would do something like this today. Either netdev_dbg() or
   trace_printk() or a trace event would be used.  If only the functions
   related to this driver are interesting then ftrace can be used with
   filtering.

As it is obviously broken for years, simply remove it.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org

---
 drivers/net/wan/lmc/lmc_debug.c |   18 ------
 drivers/net/wan/lmc/lmc_debug.h |    1 
 drivers/net/wan/lmc/lmc_main.c  |  105 +++-------------------------------------
 drivers/net/wan/lmc/lmc_media.c |    4 -
 drivers/net/wan/lmc/lmc_proto.c |   16 ------
 5 files changed, 8 insertions(+), 136 deletions(-)

--- a/drivers/net/wan/lmc/lmc_debug.c
+++ b/drivers/net/wan/lmc/lmc_debug.c
@@ -62,22 +62,4 @@ void lmcEventLog(u32 EventNum, u32 arg2,
 }
 #endif  /*  DEBUG  */
 
-void lmc_trace(struct net_device *dev, char *msg){
-#ifdef LMC_TRACE
-    unsigned long j = jiffies + 3; /* Wait for 50 ms */
-
-    if(in_interrupt()){
-        printk("%s: * %s\n", dev->name, msg);
-//        while(time_before(jiffies, j+10))
-//            ;
-    }
-    else {
-        printk("%s: %s\n", dev->name, msg);
-        while(time_before(jiffies, j))
-            schedule();
-    }
-#endif
-}
-
-
 /* --------------------------- end if_lmc_linux.c ------------------------ */
--- a/drivers/net/wan/lmc/lmc_debug.h
+++ b/drivers/net/wan/lmc/lmc_debug.h
@@ -48,6 +48,5 @@ extern u32 lmcEventLogBuf[LMC_EVENTLOGSI
 
 void lmcConsoleLog(char *type, unsigned char *ucData, int iLen);
 void lmcEventLog(u32 EventNum, u32 arg2, u32 arg3);
-void lmc_trace(struct net_device *dev, char *msg);
 
 #endif
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -113,8 +113,6 @@ int lmc_ioctl(struct net_device *dev, st
     u16 regVal;
     unsigned long flags;
 
-    lmc_trace(dev, "lmc_ioctl in");
-
     /*
      * Most functions mess with the structure
      * Disable interrupts while we do the polling
@@ -619,8 +617,6 @@ int lmc_ioctl(struct net_device *dev, st
         break;
     }
 
-    lmc_trace(dev, "lmc_ioctl out");
-
     return ret;
 }
 
@@ -634,8 +630,6 @@ static void lmc_watchdog(struct timer_li
     u32 ticks;
     unsigned long flags;
 
-    lmc_trace(dev, "lmc_watchdog in");
-
     spin_lock_irqsave(&sc->lmc_lock, flags);
 
     if(sc->check != 0xBEAFCAFE){
@@ -782,9 +776,6 @@ static void lmc_watchdog(struct timer_li
     add_timer (&sc->timer);
 
     spin_unlock_irqrestore(&sc->lmc_lock, flags);
-
-    lmc_trace(dev, "lmc_watchdog out");
-
 }
 
 static int lmc_attach(struct net_device *dev, unsigned short encoding,
@@ -813,8 +804,6 @@ static int lmc_init_one(struct pci_dev *
 	int err;
 	static int cards_found;
 
-	/* lmc_trace(dev, "lmc_init_one in"); */
-
 	err = pcim_enable_device(pdev);
 	if (err) {
 		printk(KERN_ERR "lmc: pci enable failed: %d\n", err);
@@ -955,7 +944,6 @@ static int lmc_init_one(struct pci_dev *
     sc->lmc_ok = 0;
     sc->last_link_status = 0;
 
-    lmc_trace(dev, "lmc_init_one out");
     return 0;
 }
 
@@ -981,8 +969,6 @@ static int lmc_open(struct net_device *d
     lmc_softc_t *sc = dev_to_sc(dev);
     int err;
 
-    lmc_trace(dev, "lmc_open in");
-
     lmc_led_on(sc, LMC_DS3_LED0);
 
     lmc_dec_reset(sc);
@@ -992,17 +978,14 @@ static int lmc_open(struct net_device *d
     LMC_EVENT_LOG(LMC_EVENT_RESET2, lmc_mii_readreg(sc, 0, 16),
 		  lmc_mii_readreg(sc, 0, 17));
 
-    if (sc->lmc_ok){
-        lmc_trace(dev, "lmc_open lmc_ok out");
+    if (sc->lmc_ok)
         return 0;
-    }
 
     lmc_softreset (sc);
 
     /* Since we have to use PCI bus, this should work on x86,alpha,ppc */
     if (request_irq (dev->irq, lmc_interrupt, IRQF_SHARED, dev->name, dev)){
         printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq);
-        lmc_trace(dev, "lmc_open irq failed out");
         return -EAGAIN;
     }
     sc->got_irq = 1;
@@ -1078,8 +1061,6 @@ static int lmc_open(struct net_device *d
     sc->timer.expires = jiffies + HZ;
     add_timer (&sc->timer);
 
-    lmc_trace(dev, "lmc_open out");
-
     return 0;
 }
 
@@ -1091,8 +1072,6 @@ static void lmc_running_reset (struct ne
 {
     lmc_softc_t *sc = dev_to_sc(dev);
 
-    lmc_trace(dev, "lmc_running_reset in");
-
     /* stop interrupts */
     /* Clear the interrupt mask */
     LMC_CSR_WRITE (sc, csr_intr, 0x00000000);
@@ -1114,8 +1093,6 @@ static void lmc_running_reset (struct ne
 
     sc->lmc_cmdmode |= (TULIP_CMD_TXRUN | TULIP_CMD_RXRUN);
     LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
-
-    lmc_trace(dev, "lmc_running_reset_out");
 }
 
 
@@ -1128,16 +1105,12 @@ static int lmc_close(struct net_device *
     /* not calling release_region() as we should */
     lmc_softc_t *sc = dev_to_sc(dev);
 
-    lmc_trace(dev, "lmc_close in");
-
     sc->lmc_ok = 0;
     sc->lmc_media->set_link_status (sc, 0);
     del_timer (&sc->timer);
     lmc_proto_close(sc);
     lmc_ifdown (dev);
 
-    lmc_trace(dev, "lmc_close out");
-
     return 0;
 }
 
@@ -1149,8 +1122,6 @@ static int lmc_ifdown (struct net_device
     u32 csr6;
     int i;
 
-    lmc_trace(dev, "lmc_ifdown in");
-
     /* Don't let anything else go on right now */
     //    dev->start = 0;
     netif_stop_queue(dev);
@@ -1200,8 +1171,6 @@ static int lmc_ifdown (struct net_device
     netif_wake_queue(dev);
     sc->extra_stats.tx_tbusy0++;
 
-    lmc_trace(dev, "lmc_ifdown out");
-
     return 0;
 }
 
@@ -1220,8 +1189,6 @@ static irqreturn_t lmc_interrupt (int ir
     int max_work = LMC_RXDESCS;
     int handled = 0;
 
-    lmc_trace(dev, "lmc_interrupt in");
-
     spin_lock(&sc->lmc_lock);
 
     /*
@@ -1264,12 +1231,10 @@ static irqreturn_t lmc_interrupt (int ir
             lmc_running_reset (dev);
             break;
         }
-        
-        if (csr & TULIP_STS_RXINTR){
-            lmc_trace(dev, "rx interrupt");
+
+        if (csr & TULIP_STS_RXINTR)
             lmc_rx (dev);
-            
-        }
+
         if (csr & (TULIP_STS_TXINTR | TULIP_STS_TXNOBUF | TULIP_STS_TXSTOPPED)) {
 
 	    int		n_compl = 0 ;
@@ -1389,7 +1354,6 @@ static irqreturn_t lmc_interrupt (int ir
 
     spin_unlock(&sc->lmc_lock);
 
-    lmc_trace(dev, "lmc_interrupt out");
     return IRQ_RETVAL(handled);
 }
 
@@ -1401,8 +1365,6 @@ static netdev_tx_t lmc_start_xmit(struct
     int entry;
     unsigned long flags;
 
-    lmc_trace(dev, "lmc_start_xmit in");
-
     spin_lock_irqsave(&sc->lmc_lock, flags);
 
     /* normal path, tbusy known to be zero */
@@ -1477,7 +1439,6 @@ static netdev_tx_t lmc_start_xmit(struct
 
     spin_unlock_irqrestore(&sc->lmc_lock, flags);
 
-    lmc_trace(dev, "lmc_start_xmit_out");
     return NETDEV_TX_OK;
 }
 
@@ -1493,8 +1454,6 @@ static int lmc_rx(struct net_device *dev
     struct sk_buff *skb, *nsb;
     u16 len;
 
-    lmc_trace(dev, "lmc_rx in");
-
     lmc_led_on(sc, LMC_DS3_LED3);
 
     rxIntLoopCnt = 0;		/* debug -baz */
@@ -1673,9 +1632,6 @@ static int lmc_rx(struct net_device *dev
     lmc_led_off(sc, LMC_DS3_LED3);
 
 skip_out_of_mem:
-
-    lmc_trace(dev, "lmc_rx out");
-
     return 0;
 }
 
@@ -1684,16 +1640,12 @@ static struct net_device_stats *lmc_get_
     lmc_softc_t *sc = dev_to_sc(dev);
     unsigned long flags;
 
-    lmc_trace(dev, "lmc_get_stats in");
-
     spin_lock_irqsave(&sc->lmc_lock, flags);
 
     sc->lmc_device->stats.rx_missed_errors += LMC_CSR_READ(sc, csr_missed_frames) & 0xffff;
 
     spin_unlock_irqrestore(&sc->lmc_lock, flags);
 
-    lmc_trace(dev, "lmc_get_stats out");
-
     return &sc->lmc_device->stats;
 }
 
@@ -1712,12 +1664,8 @@ unsigned lmc_mii_readreg (lmc_softc_t *
     int command = (0xf6 << 10) | (devaddr << 5) | regno;
     int retval = 0;
 
-    lmc_trace(sc->lmc_device, "lmc_mii_readreg in");
-
     LMC_MII_SYNC (sc);
 
-    lmc_trace(sc->lmc_device, "lmc_mii_readreg: done sync");
-
     for (i = 15; i >= 0; i--)
     {
         int dataval = (command & (1 << i)) ? 0x20000 : 0;
@@ -1730,8 +1678,6 @@ unsigned lmc_mii_readreg (lmc_softc_t *
         /* __SLOW_DOWN_IO; */
     }
 
-    lmc_trace(sc->lmc_device, "lmc_mii_readreg: done1");
-
     for (i = 19; i > 0; i--)
     {
         LMC_CSR_WRITE (sc, csr_9, 0x40000);
@@ -1743,8 +1689,6 @@ unsigned lmc_mii_readreg (lmc_softc_t *
         /* __SLOW_DOWN_IO; */
     }
 
-    lmc_trace(sc->lmc_device, "lmc_mii_readreg out");
-
     return (retval >> 1) & 0xffff;
 }
 
@@ -1753,8 +1697,6 @@ void lmc_mii_writereg (lmc_softc_t * con
     int i = 32;
     int command = (0x5002 << 16) | (devaddr << 23) | (regno << 18) | data;
 
-    lmc_trace(sc->lmc_device, "lmc_mii_writereg in");
-
     LMC_MII_SYNC (sc);
 
     i = 31;
@@ -1787,16 +1729,12 @@ void lmc_mii_writereg (lmc_softc_t * con
         /* __SLOW_DOWN_IO; */
         i--;
     }
-
-    lmc_trace(sc->lmc_device, "lmc_mii_writereg out");
 }
 
 static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/
 {
     int i;
 
-    lmc_trace(sc->lmc_device, "lmc_softreset in");
-
     /* Initialize the receive rings and buffers. */
     sc->lmc_txfull = 0;
     sc->lmc_next_rx = 0;
@@ -1871,55 +1809,40 @@ static void lmc_softreset (lmc_softc_t *
     }
     sc->lmc_txring[i - 1].buffer2 = virt_to_bus (&sc->lmc_txring[0]);
     LMC_CSR_WRITE (sc, csr_txlist, virt_to_bus (sc->lmc_txring));
-
-    lmc_trace(sc->lmc_device, "lmc_softreset out");
 }
 
 void lmc_gpio_mkinput(lmc_softc_t * const sc, u32 bits) /*fold00*/
 {
-    lmc_trace(sc->lmc_device, "lmc_gpio_mkinput in");
     sc->lmc_gpio_io &= ~bits;
     LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
-    lmc_trace(sc->lmc_device, "lmc_gpio_mkinput out");
 }
 
 void lmc_gpio_mkoutput(lmc_softc_t * const sc, u32 bits) /*fold00*/
 {
-    lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput in");
     sc->lmc_gpio_io |= bits;
     LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io));
-    lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput out");
 }
 
 void lmc_led_on(lmc_softc_t * const sc, u32 led) /*fold00*/
 {
-    lmc_trace(sc->lmc_device, "lmc_led_on in");
-    if((~sc->lmc_miireg16) & led){ /* Already on! */
-        lmc_trace(sc->lmc_device, "lmc_led_on aon out");
+    if ((~sc->lmc_miireg16) & led) /* Already on! */
         return;
-    }
-    
+
     sc->lmc_miireg16 &= ~led;
     lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
-    lmc_trace(sc->lmc_device, "lmc_led_on out");
 }
 
 void lmc_led_off(lmc_softc_t * const sc, u32 led) /*fold00*/
 {
-    lmc_trace(sc->lmc_device, "lmc_led_off in");
-    if(sc->lmc_miireg16 & led){ /* Already set don't do anything */
-        lmc_trace(sc->lmc_device, "lmc_led_off aoff out");
+    if (sc->lmc_miireg16 & led) /* Already set don't do anything */
         return;
-    }
-    
+
     sc->lmc_miireg16 |= led;
     lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
-    lmc_trace(sc->lmc_device, "lmc_led_off out");
 }
 
 static void lmc_reset(lmc_softc_t * const sc) /*fold00*/
 {
-    lmc_trace(sc->lmc_device, "lmc_reset in");
     sc->lmc_miireg16 |= LMC_MII16_FIFO_RESET;
     lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
 
@@ -1955,13 +1878,11 @@ static void lmc_reset(lmc_softc_t * cons
     sc->lmc_media->init(sc);
 
     sc->extra_stats.resetCount++;
-    lmc_trace(sc->lmc_device, "lmc_reset out");
 }
 
 static void lmc_dec_reset(lmc_softc_t * const sc) /*fold00*/
 {
     u32 val;
-    lmc_trace(sc->lmc_device, "lmc_dec_reset in");
 
     /*
      * disable all interrupts
@@ -2017,14 +1938,11 @@ static void lmc_dec_reset(lmc_softc_t *
     val = LMC_CSR_READ(sc, csr_sia_general);
     val |= (TULIP_WATCHDOG_TXDISABLE | TULIP_WATCHDOG_RXDISABLE);
     LMC_CSR_WRITE(sc, csr_sia_general, val);
-
-    lmc_trace(sc->lmc_device, "lmc_dec_reset out");
 }
 
 static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, /*fold00*/
                          size_t csr_size)
 {
-    lmc_trace(sc->lmc_device, "lmc_initcsrs in");
     sc->lmc_csrs.csr_busmode	        = csr_base +  0 * csr_size;
     sc->lmc_csrs.csr_txpoll		= csr_base +  1 * csr_size;
     sc->lmc_csrs.csr_rxpoll		= csr_base +  2 * csr_size;
@@ -2041,7 +1959,6 @@ static void lmc_initcsrs(lmc_softc_t * c
     sc->lmc_csrs.csr_13		        = csr_base + 13 * csr_size;
     sc->lmc_csrs.csr_14		        = csr_base + 14 * csr_size;
     sc->lmc_csrs.csr_15		        = csr_base + 15 * csr_size;
-    lmc_trace(sc->lmc_device, "lmc_initcsrs out");
 }
 
 static void lmc_driver_timeout(struct net_device *dev, unsigned int txqueue)
@@ -2050,8 +1967,6 @@ static void lmc_driver_timeout(struct ne
     u32 csr6;
     unsigned long flags;
 
-    lmc_trace(dev, "lmc_driver_timeout in");
-
     spin_lock_irqsave(&sc->lmc_lock, flags);
 
     printk("%s: Xmitter busy|\n", dev->name);
@@ -2094,8 +2009,4 @@ static void lmc_driver_timeout(struct ne
 bug_out:
 
     spin_unlock_irqrestore(&sc->lmc_lock, flags);
-
-    lmc_trace(dev, "lmc_driver_timeout out");
-
-
 }
--- a/drivers/net/wan/lmc/lmc_media.c
+++ b/drivers/net/wan/lmc/lmc_media.c
@@ -1026,7 +1026,6 @@ lmc_t1_get_link_status (lmc_softc_t * co
    * led3 red    = Loss of Signal (LOS) or out of frame (OOF)
    *               conditions detected on T3 receive signal
    */
-    lmc_trace(sc->lmc_device, "lmc_t1_get_link_status in");
     lmc_led_on(sc, LMC_DS3_LED2);
 
     lmc_mii_writereg (sc, 0, 17, T1FRAMER_ALARM1_STATUS);
@@ -1120,9 +1119,6 @@ lmc_t1_get_link_status (lmc_softc_t * co
     lmc_mii_writereg (sc, 0, 17, T1FRAMER_ALARM2_STATUS);
     sc->lmc_xinfo.t1_alarm2_status = lmc_mii_readreg (sc, 0, 18);
 
-    
-    lmc_trace(sc->lmc_device, "lmc_t1_get_link_status out");
-
     return ret;
 }
 
--- a/drivers/net/wan/lmc/lmc_proto.c
+++ b/drivers/net/wan/lmc/lmc_proto.c
@@ -47,7 +47,6 @@
 // attach
 void lmc_proto_attach(lmc_softc_t *sc) /*FOLD00*/
 {
-    lmc_trace(sc->lmc_device, "lmc_proto_attach in");
     if (sc->if_type == LMC_NET) {
             struct net_device *dev = sc->lmc_device;
             /*
@@ -57,12 +56,10 @@ void lmc_proto_attach(lmc_softc_t *sc) /
             dev->hard_header_len = 0;
             dev->addr_len = 0;
         }
-    lmc_trace(sc->lmc_device, "lmc_proto_attach out");
 }
 
 int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd)
 {
-	lmc_trace(sc->lmc_device, "lmc_proto_ioctl");
 	if (sc->if_type == LMC_PPP)
 		return hdlc_ioctl(sc->lmc_device, ifr, cmd);
 	return -EOPNOTSUPP;
@@ -72,32 +69,23 @@ int lmc_proto_open(lmc_softc_t *sc)
 {
 	int ret = 0;
 
-	lmc_trace(sc->lmc_device, "lmc_proto_open in");
-
 	if (sc->if_type == LMC_PPP) {
 		ret = hdlc_open(sc->lmc_device);
 		if (ret < 0)
 			printk(KERN_WARNING "%s: HDLC open failed: %d\n",
 			       sc->name, ret);
 	}
-
-	lmc_trace(sc->lmc_device, "lmc_proto_open out");
 	return ret;
 }
 
 void lmc_proto_close(lmc_softc_t *sc)
 {
-	lmc_trace(sc->lmc_device, "lmc_proto_close in");
-
 	if (sc->if_type == LMC_PPP)
 		hdlc_close(sc->lmc_device);
-
-	lmc_trace(sc->lmc_device, "lmc_proto_close out");
 }
 
 __be16 lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/
 {
-    lmc_trace(sc->lmc_device, "lmc_proto_type in");
     switch(sc->if_type){
     case LMC_PPP:
 	    return hdlc_type_trans(skb, sc->lmc_device);
@@ -113,13 +101,10 @@ void lmc_proto_close(lmc_softc_t *sc)
         return htons(ETH_P_802_2);
         break;
     }
-    lmc_trace(sc->lmc_device, "lmc_proto_tye out");
-
 }
 
 void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/
 {
-    lmc_trace(sc->lmc_device, "lmc_proto_netif in");
     switch(sc->if_type){
     case LMC_PPP:
     case LMC_NET:
@@ -129,5 +114,4 @@ void lmc_proto_netif(lmc_softc_t *sc, st
     case LMC_RAW:
         break;
     }
-    lmc_trace(sc->lmc_device, "lmc_proto_netif out");
 }


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 24/35] net: brcmfmac: Replace in_interrupt()
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (22 preceding siblings ...)
  2020-09-27 19:49 ` [patch 23/35] net: wan/lmc: Remove lmc_trace() Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-28  7:35   ` Arend Van Spriel
  2020-09-28  9:40   ` Arend Van Spriel
  2020-09-27 19:49 ` [patch 25/35] net: brcmfmac: Use netif_rx_any_context() Thomas Gleixner
                   ` (12 subsequent siblings)
  36 siblings, 2 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Arend van Spriel, Franky Lin,
	Hante Meuleman, Chi-Hsien Lin, Wright Feng, Kalle Valo,
	David S. Miller, Jakub Kicinski, linux-wireless,
	brcm80211-dev-list.pdl, brcm80211-dev-list, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

brcmf_sdio_isr() is using in_interrupt() to distinguish if it is called
from a interrupt service routine or from a worker thread.

Passing such information from the calling context is preferred and
requested by Linus, so add an argument `in_isr' to brcmf_sdio_isr() and let
the callers pass the information about the calling context.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
Cc: Franky Lin <franky.lin@broadcom.com>
Cc: Hante Meuleman <hante.meuleman@broadcom.com>
Cc: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
Cc: Wright Feng <wright.feng@cypress.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: brcm80211-dev-list.pdl@broadcom.com
Cc: brcm80211-dev-list@cypress.com
Cc: netdev@vger.kernel.org
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c |    4 ++--
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c   |    4 ++--
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h   |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -73,7 +73,7 @@ static irqreturn_t brcmf_sdiod_oob_irqha
 		sdiodev->irq_en = false;
 	}
 
-	brcmf_sdio_isr(sdiodev->bus);
+	brcmf_sdio_isr(sdiodev->bus, true);
 
 	return IRQ_HANDLED;
 }
@@ -85,7 +85,7 @@ static void brcmf_sdiod_ib_irqhandler(st
 
 	brcmf_dbg(INTR, "IB intr triggered\n");
 
-	brcmf_sdio_isr(sdiodev->bus);
+	brcmf_sdio_isr(sdiodev->bus, false);
 }
 
 /* dummy handler for SDIO function 2 interrupt */
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3625,7 +3625,7 @@ void brcmf_sdio_trigger_dpc(struct brcmf
 	}
 }
 
-void brcmf_sdio_isr(struct brcmf_sdio *bus)
+void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr)
 {
 	brcmf_dbg(TRACE, "Enter\n");
 
@@ -3636,7 +3636,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b
 
 	/* Count the interrupt call */
 	bus->sdcnt.intrcount++;
-	if (in_interrupt())
+	if (in_isr)
 		atomic_set(&bus->ipend, 1);
 	else
 		if (brcmf_sdio_intr_rstatus(bus)) {
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -372,7 +372,7 @@ int brcmf_sdiod_remove(struct brcmf_sdio
 
 struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
 void brcmf_sdio_remove(struct brcmf_sdio *bus);
-void brcmf_sdio_isr(struct brcmf_sdio *bus);
+void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr);
 
 void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, bool active);
 void brcmf_sdio_wowl_config(struct device *dev, bool enabled);


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 25/35] net: brcmfmac: Use netif_rx_any_context().
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (23 preceding siblings ...)
  2020-09-27 19:49 ` [patch 24/35] net: brcmfmac: Replace in_interrupt() Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-28  8:03   ` Arend Van Spriel
  2020-09-27 19:49 ` [patch 26/35] net: brcmfmac: Convey allocation mode as argument Thomas Gleixner
                   ` (11 subsequent siblings)
  36 siblings, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Arend van Spriel, Franky Lin,
	Hante Meuleman, Kalle Valo, David S. Miller, Jakub Kicinski,
	linux-wireless, brcm80211-dev-list.pdl, brcm80211-dev-list,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Chi-Hsien Lin, Wright Feng,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The usage of in_interrupt() in non-core code is phased out. Ideally the
information of the calling context should be passed by the callers or the
functions be split as appropriate.

brcmfmac uses in_interupt() to select the netif_rx*() variant which matches
the calling context. The attempt to consolidate the code by passing an
arguemnt or by distangling it failed due lack of knowledge about this
driver and because the call chains are convoluted and hard to follow.

As a stop gap use netif_rx_any_context() which invokes the correct code
path depending on context which confines the usage of in_interrupt() to
core code.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
Cc: Franky Lin <franky.lin@broadcom.com>
Cc: Hante Meuleman <hante.meuleman@broadcom.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: brcm80211-dev-list.pdl@broadcom.com
Cc: brcm80211-dev-list@cypress.com
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c |    9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -418,14 +418,7 @@ void brcmf_netif_rx(struct brcmf_if *ifp
 	ifp->ndev->stats.rx_packets++;
 
 	brcmf_dbg(DATA, "rx proto=0x%X\n", ntohs(skb->protocol));
-	if (in_interrupt())
-		netif_rx(skb);
-	else
-		/* If the receive is not processed inside an ISR,
-		 * the softirqd must be woken explicitly to service
-		 * the NET_RX_SOFTIRQ.  This is handled by netif_rx_ni().
-		 */
-		netif_rx_ni(skb);
+	netif_rx_any_context(skb);
 }
 
 void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 26/35] net: brcmfmac: Convey allocation mode as argument
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (24 preceding siblings ...)
  2020-09-27 19:49 ` [patch 25/35] net: brcmfmac: Use netif_rx_any_context() Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-28  9:34   ` Arend Van Spriel
  2020-09-27 19:49 ` [patch 27/35] net: ipw2x00,iwlegacy,iwlwifi: Remove in_interrupt() from debug macros Thomas Gleixner
                   ` (10 subsequent siblings)
  36 siblings, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Arend van Spriel, Franky Lin,
	Hante Meuleman, Chi-Hsien Lin, Wright Feng, Kalle Valo,
	David S. Miller, Jakub Kicinski, linux-wireless,
	brcm80211-dev-list.pdl, brcm80211-dev-list, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The usage of in_interrupt() in drivers is phased out and Linus clearly
requested that code which changes behaviour depending on context should
either be seperated or the context be conveyed in an argument passed by the
caller, which usually knows the context.

brcmf_fweh_process_event() uses in_interrupt() to select the allocation
mode GFP_KERNEL/GFP_ATOMIC. Aside of the above reasons this check is
incomplete as it cannot detect contexts which just have preemption or
interrupts disabled.

All callchains leading to brcmf_fweh_process_event() can clearly identify
the calling context. Convey a 'gfp' argument through the callchains and let
the callers hand in the appropriate GFP mode.

This has also the advantage that any change of execution context or
preemption/interrupt state in these callchains will be detected by the
memory allocator for all GFP_KERNEL allocations.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
Cc: Franky Lin <franky.lin@broadcom.com>
Cc: Hante Meuleman <hante.meuleman@broadcom.com>
Cc: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
Cc: Wright Feng <wright.feng@cypress.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: brcm80211-dev-list.pdl@broadcom.com
Cc: brcm80211-dev-list@cypress.com
Cc: netdev@vger.kernel.org
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h    |    5 +++--
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c   |   11 ++++++-----
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c   |    8 ++------
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h   |    7 ++++---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c |    2 +-
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c   |    8 ++++----
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c    |    2 +-
 7 files changed, 21 insertions(+), 22 deletions(-)

--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -249,9 +249,10 @@ int brcmf_bus_reset(struct brcmf_bus *bu
  */
 
 /* Receive frame for delivery to OS.  Callee disposes of rxp. */
-void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_event);
+void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_event,
+		    gfp_t gfp);
 /* Receive async event packet from firmware. Callee disposes of rxp. */
-void brcmf_rx_event(struct device *dev, struct sk_buff *rxp);
+void brcmf_rx_event(struct device *dev, struct sk_buff *rxp, gfp_t gfp);
 
 int brcmf_alloc(struct device *dev, struct brcmf_mp_device *settings);
 /* Indication from bus module regarding presence/insertion of dongle. */
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -489,7 +489,8 @@ static int brcmf_rx_hdrpull(struct brcmf
 	return 0;
 }
 
-void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
+void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event,
+		    gfp_t gfp)
 {
 	struct brcmf_if *ifp;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
@@ -506,13 +507,13 @@ void brcmf_rx_frame(struct device *dev,
 		/* Process special event packets */
 		if (handle_event)
 			brcmf_fweh_process_skb(ifp->drvr, skb,
-					       BCMILCP_SUBTYPE_VENDOR_LONG);
-
+					       BCMILCP_SUBTYPE_VENDOR_LONG,
+					       gfp);
 		brcmf_netif_rx(ifp, skb);
 	}
 }
 
-void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
+void brcmf_rx_event(struct device *dev, struct sk_buff *skb, gfp_t gfp)
 {
 	struct brcmf_if *ifp;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
@@ -523,7 +524,7 @@ void brcmf_rx_event(struct device *dev,
 	if (brcmf_rx_hdrpull(drvr, skb, &ifp))
 		return;
 
-	brcmf_fweh_process_skb(ifp->drvr, skb, 0);
+	brcmf_fweh_process_skb(ifp->drvr, skb, 0, gfp);
 	brcmu_pkt_buf_free_skb(skb);
 }
 
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
@@ -387,12 +387,11 @@ int brcmf_fweh_activate_events(struct br
  */
 void brcmf_fweh_process_event(struct brcmf_pub *drvr,
 			      struct brcmf_event *event_packet,
-			      u32 packet_len)
+			      u32 packet_len, gfp_t gfp)
 {
 	enum brcmf_fweh_event_code code;
 	struct brcmf_fweh_info *fweh = &drvr->fweh;
 	struct brcmf_fweh_queue_item *event;
-	gfp_t alloc_flag = GFP_KERNEL;
 	void *data;
 	u32 datalen;
 
@@ -411,10 +410,7 @@ void brcmf_fweh_process_event(struct brc
 	    datalen + sizeof(*event_packet) > packet_len)
 		return;
 
-	if (in_interrupt())
-		alloc_flag = GFP_ATOMIC;
-
-	event = kzalloc(sizeof(*event) + datalen, alloc_flag);
+	event = kzalloc(sizeof(*event) + datalen, gfp);
 	if (!event)
 		return;
 
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
@@ -319,11 +319,12 @@ void brcmf_fweh_unregister(struct brcmf_
 int brcmf_fweh_activate_events(struct brcmf_if *ifp);
 void brcmf_fweh_process_event(struct brcmf_pub *drvr,
 			      struct brcmf_event *event_packet,
-			      u32 packet_len);
+			      u32 packet_len, gfp_t gfp);
 void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing);
 
 static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
-					  struct sk_buff *skb, u16 stype)
+					  struct sk_buff *skb, u16 stype,
+					  gfp_t gfp)
 {
 	struct brcmf_event *event_packet;
 	u16 subtype, usr_stype;
@@ -354,7 +355,7 @@ static inline void brcmf_fweh_process_sk
 	if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
 		return;
 
-	brcmf_fweh_process_event(drvr, event_packet, skb->len + ETH_HLEN);
+	brcmf_fweh_process_event(drvr, event_packet, skb->len + ETH_HLEN, gfp);
 }
 
 #endif /* FWEH_H_ */
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -1128,7 +1128,7 @@ static void brcmf_msgbuf_process_event(s
 
 	skb->protocol = eth_type_trans(skb, ifp->ndev);
 
-	brcmf_fweh_process_skb(ifp->drvr, skb, 0);
+	brcmf_fweh_process_skb(ifp->drvr, skb, 0, GFP_KERNEL);
 
 exit:
 	brcmu_pkt_buf_free_skb(skb);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -1701,10 +1701,10 @@ static u8 brcmf_sdio_rxglom(struct brcmf
 					   pfirst->prev);
 			skb_unlink(pfirst, &bus->glom);
 			if (brcmf_sdio_fromevntchan(&dptr[SDPCM_HWHDR_LEN]))
-				brcmf_rx_event(bus->sdiodev->dev, pfirst);
+				brcmf_rx_event(bus->sdiodev->dev, pfirst, GFP_KERNEL);
 			else
 				brcmf_rx_frame(bus->sdiodev->dev, pfirst,
-					       false);
+					       false, GFP_KERNEL);
 			bus->sdcnt.rxglompkts++;
 		}
 
@@ -2035,10 +2035,10 @@ static uint brcmf_sdio_readframes(struct
 		if (pkt->len == 0)
 			brcmu_pkt_buf_free_skb(pkt);
 		else if (rd->channel == SDPCM_EVENT_CHANNEL)
-			brcmf_rx_event(bus->sdiodev->dev, pkt);
+			brcmf_rx_event(bus->sdiodev->dev, pkt, GFP_KERNEL);
 		else
 			brcmf_rx_frame(bus->sdiodev->dev, pkt,
-				       false);
+				       false, GFP_KERNEL);
 
 		/* prepare the descriptor for the next read */
 		rd->len = rd->len_nxtfrm << 4;
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -532,7 +532,7 @@ static void brcmf_usb_rx_complete(struct
 	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP ||
 	    devinfo->bus_pub.state == BRCMFMAC_USB_STATE_SLEEP) {
 		skb_put(skb, urb->actual_length);
-		brcmf_rx_frame(devinfo->dev, skb, true);
+		brcmf_rx_frame(devinfo->dev, skb, true, GFP_ATOMIC);
 		brcmf_usb_rx_refill(devinfo, req);
 		usb_mark_last_busy(urb->dev);
 	} else {


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 27/35] net: ipw2x00,iwlegacy,iwlwifi: Remove in_interrupt() from debug macros
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (25 preceding siblings ...)
  2020-09-27 19:49 ` [patch 26/35] net: brcmfmac: Convey allocation mode as argument Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 28/35] net: iwlwifi: Remove in_interrupt() from tracing macro Thomas Gleixner
                   ` (9 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Stanislav Yakovlev, Kalle Valo,
	David S. Miller, Jakub Kicinski, linux-wireless, netdev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The usage of in_interrupt() in non-core code is phased out.

The debugging macros in these drivers use in_interrupt() to print 'I' or
'U' depending on the return value of in_interrupt(). While 'U' is confusing
at best and 'I' is not really describing the actual context (hard interupt,
soft interrupt, bottom half disabled section) these debug macros originate
from the pre ftrace kernel era and their value today is questionable. They
probably should be removed completely.

The macros weere added initially for ipw2100 and then spreaded when the
driver was forked.

Remove the in_interrupt() usage at least..

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Stanislav Yakovlev <stas.yakovlev@gmail.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: Stanislaw Gruszka <stf_xl@wp.pl>
Cc: Johannes Berg <johannes.berg@intel.com>
Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Cc: Luca Coelho <luciano.coelho@intel.com>
Cc: Intel Linux Wireless <linuxwifi@intel.com>

---
 drivers/net/wireless/intel/ipw2x00/ipw2100.c   |    3 +--
 drivers/net/wireless/intel/ipw2x00/ipw2200.h   |    6 ++----
 drivers/net/wireless/intel/ipw2x00/libipw.h    |    3 +--
 drivers/net/wireless/intel/iwlegacy/common.h   |    4 ++--
 drivers/net/wireless/intel/iwlwifi/iwl-debug.c |    3 +--
 5 files changed, 7 insertions(+), 12 deletions(-)

--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -201,8 +201,7 @@ static u32 ipw2100_debug_level = IPW_DL_
 #define IPW_DEBUG(level, message...) \
 do { \
 	if (ipw2100_debug_level & (level)) { \
-		printk(KERN_DEBUG "ipw2100: %c %s ", \
-                       in_interrupt() ? 'I' : 'U',  __func__); \
+		printk(KERN_DEBUG "ipw2100: %s ", __func__); \
 		printk(message); \
 	} \
 } while (0)
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.h
@@ -1382,14 +1382,12 @@ BIT_ARG16(x)
 
 #define IPW_DEBUG(level, fmt, args...) \
 do { if (ipw_debug_level & (level)) \
-  printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \
-         in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
+  printk(KERN_DEBUG DRV_NAME": %s " fmt, __func__ , ## args); } while (0)
 
 #ifdef CONFIG_IPW2200_DEBUG
 #define IPW_LL_DEBUG(level, fmt, args...) \
 do { if (ipw_debug_level & (level)) \
-  printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \
-         in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
+  printk(KERN_DEBUG DRV_NAME": %s " fmt, __func__ , ## args); } while (0)
 #else
 #define IPW_LL_DEBUG(level, fmt, args...) do {} while (0)
 #endif				/* CONFIG_IPW2200_DEBUG */
--- a/drivers/net/wireless/intel/ipw2x00/libipw.h
+++ b/drivers/net/wireless/intel/ipw2x00/libipw.h
@@ -60,8 +60,7 @@
 extern u32 libipw_debug_level;
 #define LIBIPW_DEBUG(level, fmt, args...) \
 do { if (libipw_debug_level & (level)) \
-  printk(KERN_DEBUG "libipw: %c %s " fmt, \
-         in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
+  printk(KERN_DEBUG "libipw: %s " fmt, __func__ , ## args); } while (0)
 #else
 #define LIBIPW_DEBUG(level, fmt, args...) do {} while (0)
 #endif				/* CONFIG_LIBIPW_DEBUG */
--- a/drivers/net/wireless/intel/iwlegacy/common.h
+++ b/drivers/net/wireless/intel/iwlegacy/common.h
@@ -2925,8 +2925,8 @@ do {									\
 #define IL_DBG(level, fmt, args...)					\
 do {									\
 	if (il_get_debug_level(il) & level)				\
-		dev_err(&il->hw->wiphy->dev, "%c %s " fmt,		\
-			in_interrupt() ? 'I' : 'U', __func__ , ##args); \
+		dev_err(&il->hw->wiphy->dev, "%s " fmt, __func__,	\
+			 ##args);					\
 } while (0)
 
 #define il_print_hex_dump(il, level, p, len)				\
--- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c
@@ -121,8 +121,7 @@ void __iwl_dbg(struct device *dev,
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if (iwl_have_debug_level(level) &&
 	    (!limit || net_ratelimit()))
-		dev_printk(KERN_DEBUG, dev, "%c %s %pV",
-			   in_interrupt() ? 'I' : 'U', function, &vaf);
+		dev_printk(KERN_DEBUG, dev, "%s %pV", function, &vaf);
 #endif
 	trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf);
 	va_end(args);


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 28/35] net: iwlwifi: Remove in_interrupt() from tracing macro.
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (26 preceding siblings ...)
  2020-09-27 19:49 ` [patch 27/35] net: ipw2x00,iwlegacy,iwlwifi: Remove in_interrupt() from debug macros Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-28  6:13   ` Coelho, Luciano
  2020-09-27 19:49 ` [patch 29/35] net: hostap: Remove in_interrupt() usage Thomas Gleixner
                   ` (8 subsequent siblings)
  36 siblings, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Johannes Berg, Emmanuel Grumbach,
	Luca Coelho, Intel Linux Wireless, Kalle Valo, David S. Miller,
	Jakub Kicinski, linux-wireless, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The usage of in_interrupt) in driver code is phased out.

The iwlwifi_dbg tracepoint records in_interrupt() seperately, but that's
superfluous because the trace header already records all kind of state and
context information like hardirq status, softirq status, preemption count
etc.

Aside of that the recording of in_interrupt() as boolean does not allow to
distinguish between the possible contexts (hard interrupt, soft interrupt,
bottom half disabled) while the trace header gives precise information.

Remove the duplicate information from the tracepoint and fixup the caller.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Johannes Berg <johannes.berg@intel.com>
Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Cc: Luca Coelho <luciano.coelho@intel.com>
Cc: Intel Linux Wireless <linuxwifi@intel.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/intel/iwlwifi/iwl-debug.c        |    2 +-
 drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h |    6 ++----
 2 files changed, 3 insertions(+), 5 deletions(-)

--- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c
@@ -123,7 +123,7 @@ void __iwl_dbg(struct device *dev,
 	    (!limit || net_ratelimit()))
 		dev_printk(KERN_DEBUG, dev, "%s %pV", function, &vaf);
 #endif
-	trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf);
+	trace_iwlwifi_dbg(level, function, &vaf);
 	va_end(args);
 }
 IWL_EXPORT_SYMBOL(__iwl_dbg);
--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h
@@ -54,18 +54,16 @@ DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_
 );
 
 TRACE_EVENT(iwlwifi_dbg,
-	TP_PROTO(u32 level, bool in_interrupt, const char *function,
+	TP_PROTO(u32 level, const char *function,
 		 struct va_format *vaf),
-	TP_ARGS(level, in_interrupt, function, vaf),
+	TP_ARGS(level, function, vaf),
 	TP_STRUCT__entry(
 		__field(u32, level)
-		__field(u8, in_interrupt)
 		__string(function, function)
 		__dynamic_array(char, msg, MAX_MSG_LEN)
 	),
 	TP_fast_assign(
 		__entry->level = level;
-		__entry->in_interrupt = in_interrupt;
 		__assign_str(function, function);
 		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
 				       MAX_MSG_LEN, vaf->fmt,


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 29/35] net: hostap: Remove in_interrupt() usage
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (27 preceding siblings ...)
  2020-09-27 19:49 ` [patch 28/35] net: iwlwifi: Remove in_interrupt() from tracing macro Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 30/35] net: mwifiex: Use netif_rx_any_context() Thomas Gleixner
                   ` (7 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Jouni Malinen, Kalle Valo,
	David S. Miller, Jakub Kicinski, linux-wireless, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Amitkumar Karwar, Ganapathi Bhat,
	Xinming Hu, libertas-dev, Pascal Terjan, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

in_interrupt() is ill defined and does not provide what the name
suggests. The usage especially in driver code is deprecated and a tree wide
effort to clean up and consolidate the (ab)usage of in_interrupt() and
related checks is happening.

hfa384x_cmd() and prism2_hw_reset() check in_interrupt() at function entry
and if true emit a printk at debug loglevel and return. This is clearly debug
code.

Both functions invoke functions which can sleep. These functions already
have appropriate debug checks which cover all invalid contexts, while
in_interrupt() fails to detect context which just has preemption or
interrupts disabled.

Remove both checks as they are incomplete, debug only and already covered
by the subsequently invoked functions properly. If called from invalid
context the resulting back trace is definitely more helpful to analyze the
problem than a printk at debug loglevel.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Jouni Malinen <j@w1.fi>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/intersil/hostap/hostap_hw.c |   12 ------------
 1 file changed, 12 deletions(-)

--- a/drivers/net/wireless/intersil/hostap/hostap_hw.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_hw.c
@@ -320,12 +320,6 @@ static int hfa384x_cmd(struct net_device
 	iface = netdev_priv(dev);
 	local = iface->local;
 
-	if (in_interrupt()) {
-		printk(KERN_DEBUG "%s: hfa384x_cmd called from interrupt "
-		       "context\n", dev->name);
-		return -1;
-	}
-
 	if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN) {
 		printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n",
 		       dev->name);
@@ -1560,12 +1554,6 @@ static void prism2_hw_reset(struct net_d
 	iface = netdev_priv(dev);
 	local = iface->local;
 
-	if (in_interrupt()) {
-		printk(KERN_DEBUG "%s: driver bug - prism2_hw_reset() called "
-		       "in interrupt context\n", dev->name);
-		return;
-	}
-
 	if (local->hw_downloading)
 		return;
 


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 30/35] net: mwifiex: Use netif_rx_any_context().
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (28 preceding siblings ...)
  2020-09-27 19:49 ` [patch 29/35] net: hostap: Remove in_interrupt() usage Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 31/35] net: libertas libertas_tf: Remove in_interrupt() from debug macro Thomas Gleixner
                   ` (6 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Amitkumar Karwar, Ganapathi Bhat,
	Xinming Hu, Kalle Valo, David S. Miller, Jakub Kicinski,
	linux-wireless, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Dave Miller, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The usage of in_interrupt() in non-core code is phased out. Ideally the
information of the calling context should be passed by the callers or the
functions be split as appropriate.

mwifiex uses in_interupt() to select the netif_rx*() variant which matches
the calling context. The attempt to consolidate the code by passing an
arguemnt or by distangling it failed due lack of knowledge about this
driver and because the call chains are hard to follow.

As a stop gap use netif_rx_any_context() which invokes the correct code
path depending on context and confines the in_interrupt() usage to core
code.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Amitkumar Karwar <amitkarwar@gmail.com>
Cc: Ganapathi Bhat <ganapathi.bhat@nxp.com>
Cc: Xinming Hu <huxinming820@gmail.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/marvell/mwifiex/uap_txrx.c |    6 +-----
 drivers/net/wireless/marvell/mwifiex/util.c     |    6 +-----
 2 files changed, 2 insertions(+), 10 deletions(-)

--- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
@@ -350,11 +350,7 @@ int mwifiex_uap_recv_packet(struct mwifi
 		skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
 
 	/* Forward multicast/broadcast packet to upper layer*/
-	if (in_interrupt())
-		netif_rx(skb);
-	else
-		netif_rx_ni(skb);
-
+	netif_rx_any_context(skb);
 	return 0;
 }
 
--- a/drivers/net/wireless/marvell/mwifiex/util.c
+++ b/drivers/net/wireless/marvell/mwifiex/util.c
@@ -488,11 +488,7 @@ int mwifiex_recv_packet(struct mwifiex_p
 	    (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
 		skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
 
-	if (in_interrupt())
-		netif_rx(skb);
-	else
-		netif_rx_ni(skb);
-
+	netif_rx_any_context(skb);
 	return 0;
 }
 


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 31/35] net: libertas libertas_tf: Remove in_interrupt() from debug macro.
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (29 preceding siblings ...)
  2020-09-27 19:49 ` [patch 30/35] net: mwifiex: Use netif_rx_any_context() Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 32/35] net: libertas: Use netif_rx_any_context() Thomas Gleixner
                   ` (5 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Kalle Valo, David S. Miller,
	Jakub Kicinski, libertas-dev, linux-wireless, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, Pascal Terjan, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The debug macro prints (INT) when in_interrupt() returns true. The value of
this information is dubious as it does not distinguish between the various
contexts which are covered by in_interrupt().

As the usage of in_interrupt() in drivers is phased out and the same
information can be more precisely obtained with tracing, remove the
in_interrupt() conditional from this debug printk.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: libertas-dev@lists.infradead.org
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/marvell/libertas/defs.h        |    3 +--
 drivers/net/wireless/marvell/libertas_tf/deb_defs.h |    3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

--- a/drivers/net/wireless/marvell/libertas/defs.h
+++ b/drivers/net/wireless/marvell/libertas/defs.h
@@ -50,8 +50,7 @@ extern unsigned int lbs_debug;
 #ifdef DEBUG
 #define LBS_DEB_LL(grp, grpnam, fmt, args...) \
 do { if ((lbs_debug & (grp)) == (grp)) \
-  printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
-         in_interrupt() ? " (INT)" : "", ## args); } while (0)
+  printk(KERN_DEBUG DRV_NAME grpnam ": " fmt, ## args); } while (0)
 #else
 #define LBS_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
 #endif
--- a/drivers/net/wireless/marvell/libertas_tf/deb_defs.h
+++ b/drivers/net/wireless/marvell/libertas_tf/deb_defs.h
@@ -48,8 +48,7 @@ extern unsigned int lbtf_debug;
 #ifdef DEBUG
 #define LBTF_DEB_LL(grp, grpnam, fmt, args...) \
 do { if ((lbtf_debug & (grp)) == (grp)) \
-  printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
-         in_interrupt() ? " (INT)" : "", ## args); } while (0)
+  printk(KERN_DEBUG DRV_NAME grpnam ": " fmt, ## args); } while (0)
 #else
 #define LBTF_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
 #endif


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 32/35] net: libertas: Use netif_rx_any_context()
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (30 preceding siblings ...)
  2020-09-27 19:49 ` [patch 31/35] net: libertas libertas_tf: Remove in_interrupt() from debug macro Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 33/35] net: rtlwifi: Remove void* casts related to delayed work Thomas Gleixner
                   ` (4 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Kalle Valo, David S. Miller,
	Jakub Kicinski, Pascal Terjan, libertas-dev, linux-wireless,
	netdev, Christian Benvenuti, Govindarajulu Varadarajan,
	Dave Miller, Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, Ping-Ke Shih

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The usage of in_interrupt() in non-core code is phased out. Ideally the
information of the calling context should be passed by the callers or the
functions be split as appropriate.

libertas uses in_interupt() to select the netif_rx*() variant which matches
the calling context. The attempt to consolidate the code by passing an
arguemnt or by distangling it failed due lack of knowledge about this
driver and because the call chains are hard to follow.

As a stop gap tse netif_rx_any_context() which invokes the correct code
path depending on context and confines the in_interrupt() usage to core
code.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Pascal Terjan <pterjan@google.com>
Cc: libertas-dev@lists.infradead.org
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/marvell/libertas/rx.c |   11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

--- a/drivers/net/wireless/marvell/libertas/rx.c
+++ b/drivers/net/wireless/marvell/libertas/rx.c
@@ -147,10 +147,7 @@ int lbs_process_rxed_packet(struct lbs_p
 	dev->stats.rx_packets++;
 
 	skb->protocol = eth_type_trans(skb, dev);
-	if (in_interrupt())
-		netif_rx(skb);
-	else
-		netif_rx_ni(skb);
+	netif_rx_any_context(skb);
 
 	ret = 0;
 done:
@@ -265,11 +262,7 @@ static int process_rxed_802_11_packet(st
 	dev->stats.rx_packets++;
 
 	skb->protocol = eth_type_trans(skb, priv->dev);
-
-	if (in_interrupt())
-		netif_rx(skb);
-	else
-		netif_rx_ni(skb);
+	netif_rx_any_context(skb);
 
 	ret = 0;
 


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 33/35] net: rtlwifi: Remove void* casts related to delayed work
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (31 preceding siblings ...)
  2020-09-27 19:49 ` [patch 32/35] net: libertas: Use netif_rx_any_context() Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 34/35] net: rtlwifi: Remove in_interrupt() from debug macro Thomas Gleixner
                   ` (3 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Ping-Ke Shih, Kalle Valo,
	David S. Miller, Jakub Kicinski, linux-wireless, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

INIT_DELAYED_WORK() takes two arguments: A pointer to the delayed work and
a function reference for the callback.

The rtl code casts all function references to (void *) because the
callbacks in use are not matching the required function signature. That's
error prone and bad pratice.

Some of the callback functions are also global, but only used in a single
file.

Clean the mess up by:

  - Adding the proper arguments to the callback functions and using them in
    the container_of() constructs correctly which removes the hideous
    container_of_dwork_rtl() macro as well.

  - Removing the type cast at the initializers

  - Making the unnecessary global functions static

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Ping-Ke Shih <pkshih@realtek.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/realtek/rtlwifi/base.c |   39 +++++++++++++---------------
 drivers/net/wireless/realtek/rtlwifi/base.h |    3 --
 drivers/net/wireless/realtek/rtlwifi/ps.c   |   19 ++++++-------
 drivers/net/wireless/realtek/rtlwifi/ps.h   |    6 ++--
 drivers/net/wireless/realtek/rtlwifi/wifi.h |    3 --
 5 files changed, 31 insertions(+), 39 deletions(-)

--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -436,6 +436,10 @@ static void _rtl_init_mac80211(struct ie
 	}
 }
 
+static void rtl_watchdog_wq_callback(struct work_struct *work);
+static void rtl_fwevt_wq_callback(struct work_struct *work);
+static void rtl_c2hcmd_wq_callback(struct work_struct *work);
+
 static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -454,17 +458,14 @@ static void _rtl_init_deferred_work(stru
 	}
 
 	INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
-			  (void *)rtl_watchdog_wq_callback);
+			  rtl_watchdog_wq_callback);
 	INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
-			  (void *)rtl_ips_nic_off_wq_callback);
-	INIT_DELAYED_WORK(&rtlpriv->works.ps_work,
-			  (void *)rtl_swlps_wq_callback);
+			  rtl_ips_nic_off_wq_callback);
+	INIT_DELAYED_WORK(&rtlpriv->works.ps_work, rtl_swlps_wq_callback);
 	INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq,
-			  (void *)rtl_swlps_rfon_wq_callback);
-	INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq,
-			  (void *)rtl_fwevt_wq_callback);
-	INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq,
-			  (void *)rtl_c2hcmd_wq_callback);
+			  rtl_swlps_rfon_wq_callback);
+	INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, rtl_fwevt_wq_callback);
+	INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq, rtl_c2hcmd_wq_callback);
 }
 
 void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq)
@@ -2042,11 +2043,10 @@ void rtl_collect_scan_list(struct ieee80
 }
 EXPORT_SYMBOL(rtl_collect_scan_list);
 
-void rtl_watchdog_wq_callback(void *data)
+static void rtl_watchdog_wq_callback(struct work_struct *work)
 {
-	struct rtl_works *rtlworks = container_of_dwork_rtl(data,
-							    struct rtl_works,
-							    watchdog_wq);
+	struct rtl_works *rtlworks = container_of(work, struct rtl_works,
+						  watchdog_wq.work);
 	struct ieee80211_hw *hw = rtlworks->hw;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -2239,10 +2239,10 @@ void rtl_watch_dog_timer_callback(struct
 		  jiffies + MSECS(RTL_WATCH_DOG_TIME));
 }
 
-void rtl_fwevt_wq_callback(void *data)
+static void rtl_fwevt_wq_callback(struct work_struct *work)
 {
-	struct rtl_works *rtlworks =
-		container_of_dwork_rtl(data, struct rtl_works, fwevt_wq);
+	struct rtl_works *rtlworks = container_of(work, struct rtl_works,
+						  fwevt_wq.work);
 	struct ieee80211_hw *hw = rtlworks->hw;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
@@ -2368,11 +2368,10 @@ void rtl_c2hcmd_launcher(struct ieee8021
 	}
 }
 
-void rtl_c2hcmd_wq_callback(void *data)
+static void rtl_c2hcmd_wq_callback(struct work_struct *work)
 {
-	struct rtl_works *rtlworks = container_of_dwork_rtl(data,
-							    struct rtl_works,
-							    c2hcmd_wq);
+	struct rtl_works *rtlworks = container_of(work, struct rtl_works,
+						  c2hcmd_wq.work);
 	struct ieee80211_hw *hw = rtlworks->hw;
 
 	rtl_c2hcmd_launcher(hw, 1);
--- a/drivers/net/wireless/realtek/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -108,9 +108,6 @@ int rtl_rx_agg_start(struct ieee80211_hw
 int rtl_rx_agg_stop(struct ieee80211_hw *hw,
 		    struct ieee80211_sta *sta, u16 tid);
 void rtl_rx_ampdu_apply(struct rtl_priv *rtlpriv);
-void rtl_watchdog_wq_callback(void *data);
-void rtl_fwevt_wq_callback(void *data);
-void rtl_c2hcmd_wq_callback(void *data);
 void rtl_c2hcmd_launcher(struct ieee80211_hw *hw, int exec);
 void rtl_c2hcmd_enqueue(struct ieee80211_hw *hw, struct sk_buff *skb);
 
--- a/drivers/net/wireless/realtek/rtlwifi/ps.c
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
@@ -179,10 +179,10 @@ static void _rtl_ps_inactive_ps(struct i
 	ppsc->swrf_processing = false;
 }
 
-void rtl_ips_nic_off_wq_callback(void *data)
+void rtl_ips_nic_off_wq_callback(struct work_struct *work)
 {
-	struct rtl_works *rtlworks =
-	    container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq);
+	struct rtl_works *rtlworks = container_of(work, struct rtl_works,
+						  ips_nic_off_wq.work);
 	struct ieee80211_hw *hw = rtlworks->hw;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -562,10 +562,10 @@ void rtl_swlps_rf_awake(struct ieee80211
 	mutex_unlock(&rtlpriv->locks.lps_mutex);
 }
 
-void rtl_swlps_rfon_wq_callback(void *data)
+void rtl_swlps_rfon_wq_callback(struct work_struct *work)
 {
-	struct rtl_works *rtlworks =
-	    container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq);
+	struct rtl_works *rtlworks = container_of(work, struct rtl_works,
+						  ps_rfon_wq.work);
 	struct ieee80211_hw *hw = rtlworks->hw;
 
 	rtl_swlps_rf_awake(hw);
@@ -675,11 +675,10 @@ void rtl_lps_leave(struct ieee80211_hw *
 }
 EXPORT_SYMBOL_GPL(rtl_lps_leave);
 
-void rtl_swlps_wq_callback(void *data)
+void rtl_swlps_wq_callback(struct work_struct *work)
 {
-	struct rtl_works *rtlworks = container_of_dwork_rtl(data,
-				     struct rtl_works,
-				     ps_work);
+	struct rtl_works *rtlworks = container_of(work, struct rtl_works,
+						  ps_work.work);
 	struct ieee80211_hw *hw = rtlworks->hw;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	bool ps = false;
--- a/drivers/net/wireless/realtek/rtlwifi/ps.h
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.h
@@ -10,15 +10,15 @@ bool rtl_ps_enable_nic(struct ieee80211_
 bool rtl_ps_disable_nic(struct ieee80211_hw *hw);
 void rtl_ips_nic_off(struct ieee80211_hw *hw);
 void rtl_ips_nic_on(struct ieee80211_hw *hw);
-void rtl_ips_nic_off_wq_callback(void *data);
+void rtl_ips_nic_off_wq_callback(struct work_struct *work);
 void rtl_lps_enter(struct ieee80211_hw *hw);
 void rtl_lps_leave(struct ieee80211_hw *hw);
 
 void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode);
 
 void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len);
-void rtl_swlps_wq_callback(void *data);
-void rtl_swlps_rfon_wq_callback(void *data);
+void rtl_swlps_wq_callback(struct work_struct *work);
+void rtl_swlps_rfon_wq_callback(struct work_struct *work);
 void rtl_swlps_rf_awake(struct ieee80211_hw *hw);
 void rtl_swlps_rf_sleep(struct ieee80211_hw *hw);
 void rtl_p2p_ps_cmd(struct ieee80211_hw *hw , u8 p2p_ps_state);
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -2936,9 +2936,6 @@ enum bt_radio_shared {
 #define	RT_SET_PS_LEVEL(ppsc, _ps_flg)		\
 	(ppsc->cur_ps_level |= _ps_flg)
 
-#define container_of_dwork_rtl(x, y, z) \
-	container_of(to_delayed_work(x), y, z)
-
 #define FILL_OCTET_STRING(_os, _octet, _len)	\
 		(_os).octet = (u8 *)(_octet);		\
 		(_os).length = (_len);


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 34/35] net: rtlwifi: Remove in_interrupt() from debug macro
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (32 preceding siblings ...)
  2020-09-27 19:49 ` [patch 33/35] net: rtlwifi: Remove void* casts related to delayed work Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 19:49 ` [patch 35/35] net: rtlwifi: Replace in_interrupt() for context detection Thomas Gleixner
                   ` (2 subsequent siblings)
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Ping-Ke Shih, Kalle Valo,
	David S. Miller, Jakub Kicinski, linux-wireless, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

The usage of in_interrupt() in drivers in is phased out.

rtlwifi uses in_interrupt() in the RT_TRACE() debug macro which is
sprinkled all over the driver. RT_TRACE() is almost identical to RTPRINT()
which another hideous debug printk wrapper. The only difference is the
printout of in_interrupt().

The decoding of in_interrupt() as hexvalue is non-trivial and aside of
being phased out for driver use the return value is just by chance the
masked preempt count value and not a boolean.

These home brewn printk debug aids are tedious to work with and provide
only minimal context.  They should be replaced by trace_printk() or a debug
tracepoint which automatically records all context information.

To make progress on the in_interrupt() cleanup, make RT_TRACE() use the
RTPRINT() debug function and remove _rtl_dbg_trace().

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Ping-Ke Shih <pkshih@realtek.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/realtek/rtlwifi/debug.c |   20 --------------------
 drivers/net/wireless/realtek/rtlwifi/debug.h |    6 +-----
 2 files changed, 1 insertion(+), 25 deletions(-)

--- a/drivers/net/wireless/realtek/rtlwifi/debug.c
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.c
@@ -8,26 +8,6 @@
 #include <linux/vmalloc.h>
 
 #ifdef CONFIG_RTLWIFI_DEBUG
-void _rtl_dbg_trace(struct rtl_priv *rtlpriv, u64 comp, int level,
-		    const char *fmt, ...)
-{
-	if (unlikely((comp & rtlpriv->cfg->mod_params->debug_mask) &&
-		     level <= rtlpriv->cfg->mod_params->debug_level)) {
-		struct va_format vaf;
-		va_list args;
-
-		va_start(args, fmt);
-
-		vaf.fmt = fmt;
-		vaf.va = &args;
-
-		pr_info(":<%lx> %pV", in_interrupt(), &vaf);
-
-		va_end(args);
-	}
-}
-EXPORT_SYMBOL_GPL(_rtl_dbg_trace);
-
 void _rtl_dbg_print(struct rtl_priv *rtlpriv, u64 comp, int level,
 		    const char *fmt, ...)
 {
--- a/drivers/net/wireless/realtek/rtlwifi/debug.h
+++ b/drivers/net/wireless/realtek/rtlwifi/debug.h
@@ -149,10 +149,6 @@ enum dbgp_flag_e {
 struct rtl_priv;
 
 __printf(4, 5)
-void _rtl_dbg_trace(struct rtl_priv *rtlpriv, u64 comp, int level,
-		    const char *fmt, ...);
-
-__printf(4, 5)
 void _rtl_dbg_print(struct rtl_priv *rtlpriv, u64 comp, int level,
 		    const char *fmt, ...);
 
@@ -161,7 +157,7 @@ void _rtl_dbg_print_data(struct rtl_priv
 			 const void *hexdata, int hexdatalen);
 
 #define RT_TRACE(rtlpriv, comp, level, fmt, ...)			\
-	_rtl_dbg_trace(rtlpriv, comp, level,				\
+	_rtl_dbg_print(rtlpriv, comp, level,				\
 		       fmt, ##__VA_ARGS__)
 
 #define RTPRINT(rtlpriv, dbgtype, dbgflag, fmt, ...)			\


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [patch 35/35] net: rtlwifi: Replace in_interrupt() for context detection
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (33 preceding siblings ...)
  2020-09-27 19:49 ` [patch 34/35] net: rtlwifi: Remove in_interrupt() from debug macro Thomas Gleixner
@ 2020-09-27 19:49 ` Thomas Gleixner
  2020-09-27 20:22 ` [patch 00/35] net: in_interrupt() cleanup and fixes Joe Perches
  2020-09-27 20:57 ` David Miller
  36 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-27 19:49 UTC (permalink / raw)
  To: LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Ping-Ke Shih, Kalle Valo,
	David S. Miller, Jakub Kicinski, linux-wireless, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jonathan Corbet, Mauro Carvalho Chehab, linux-doc,
	Luc Van Oostenryck, Jay Cliburn, Chris Snook, Vishal Kulkarni,
	Jeff Kirsher, intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Andrew Lunn, Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

rtl_lps_enter() and rtl_lps_leave() are using in_interrupt() to detect
whether it is safe to acquire a mutex or if it is required to defer to a
workqueue.

The usage of in_interrupt() in drivers is phased out and Linus clearly
requested that code which changes behaviour depending on context should
either be seperated or the context be conveyed in an argument passed by the
caller, which usually knows the context.

in_interrupt() also is only partially correct because it fails to chose the
correct code path when just preemption or interrupts are disabled.

Add an argument 'may_block' to both functions and adjust the callers to
pass the context information.

The following call chains were analyzed to be safe to block:

    rtl_watchdog_wq_callback()
      rlf_lps_leave/enter()

    rtl_op_suspend()
      rtl_lps_leave()

    rtl_op_bss_info_changed()
      rtl_lps_leave()

    rtl_op_sw_scan_start()
      rtl_lps_leave()

The following call chains were analyzed to be unsafe to block:

    _rtl_pci_interrupt()
      _rtl_pci_rx_interrupt()
	  rtl_lps_leave()

    _rtl_pci_interrupt()
      _rtl_pci_rx_interrupt()
        rtl_is_special_data()
	  rtl_lps_leave()

    _rtl_pci_interrupt()
      _rtl_pci_rx_interrupt()
        rtl_is_special_data()
	  setup_special_tx()
	    rtl_lps_leave()

    _rtl_pci_interrupt()
      _rtl_pci_tx_isr
        rtl_lps_leave()

      halbtc_leave_lps()
        rtl_lps_leave()

This leaves four callers of rtl_lps_enter/leave() where the analyzis
stopped dead in the maze of several nested pointer based callchains and
lack of rtlwifi hardware to debug this via tracing:

     halbtc_leave_lps(), halbtc_enter_lps(), halbtc_normal_lps(),
     halbtc_pre_normal_lps()

These four have been cautionally marked to be unable to block which is the
safe option, but the rtwifi wizards should be able to clarify that.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Ping-Ke Shih <pkshih@realtek.com>
Cc: Kalle Valo <kvalo@codeaurora.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org

---
 drivers/net/wireless/realtek/rtlwifi/base.c                   |    8 +++---
 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c |   12 ++++++----
 drivers/net/wireless/realtek/rtlwifi/core.c                   |    6 ++---
 drivers/net/wireless/realtek/rtlwifi/pci.c                    |    4 +--
 drivers/net/wireless/realtek/rtlwifi/ps.c                     |    8 +++---
 drivers/net/wireless/realtek/rtlwifi/ps.h                     |    4 +--
 6 files changed, 23 insertions(+), 19 deletions(-)

--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -1456,7 +1456,7 @@ static void setup_special_tx(struct rtl_
 	if (rtlpriv->cfg->ops->get_btc_status())
 		rtlpriv->btcoexist.btc_ops->btc_special_packet_notify(
 					rtlpriv, type);
-	rtl_lps_leave(hw);
+	rtl_lps_leave(hw, false);
 	ppsc->last_delaylps_stamp_jiffies = jiffies;
 }
 
@@ -1546,7 +1546,7 @@ u8 rtl_is_special_data(struct ieee80211_
 
 		if (is_tx) {
 			rtlpriv->ra.is_special_data = true;
-			rtl_lps_leave(hw);
+			rtl_lps_leave(hw, false);
 			ppsc->last_delaylps_stamp_jiffies = jiffies;
 
 			setup_special_tx(rtlpriv, ppsc, PACKET_EAPOL);
@@ -2147,9 +2147,9 @@ static void rtl_watchdog_wq_callback(str
 		if (rtlpriv->link_info.num_rx_inperiod +
 		      rtlpriv->link_info.num_tx_inperiod > 8 ||
 		    rtlpriv->link_info.num_rx_inperiod > 2)
-			rtl_lps_leave(hw);
+			rtl_lps_leave(hw, true);
 		else
-			rtl_lps_enter(hw);
+			rtl_lps_enter(hw, true);
 
 label_lps_done:
 		;
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -285,7 +285,8 @@ static void halbtc_leave_lps(struct btc_
 
 	btcoexist->bt_info.bt_ctrl_lps = true;
 	btcoexist->bt_info.bt_lps_on = false;
-	rtl_lps_leave(rtlpriv->mac80211.hw);
+	/* FIXME: Context is unclear. Is it allowed to block? */
+	rtl_lps_leave(rtlpriv->mac80211.hw, false);
 }
 
 static void halbtc_enter_lps(struct btc_coexist *btcoexist)
@@ -306,7 +307,8 @@ static void halbtc_enter_lps(struct btc_
 
 	btcoexist->bt_info.bt_ctrl_lps = true;
 	btcoexist->bt_info.bt_lps_on = true;
-	rtl_lps_enter(rtlpriv->mac80211.hw);
+	/* FIXME: Context is unclear. Is it allowed to block? */
+	rtl_lps_enter(rtlpriv->mac80211.hw, false);
 }
 
 static void halbtc_normal_lps(struct btc_coexist *btcoexist)
@@ -317,7 +319,8 @@ static void halbtc_normal_lps(struct btc
 
 	if (btcoexist->bt_info.bt_ctrl_lps) {
 		btcoexist->bt_info.bt_lps_on = false;
-		rtl_lps_leave(rtlpriv->mac80211.hw);
+		/* FIXME: Context is unclear. Is it allowed to block? */
+		rtl_lps_leave(rtlpriv->mac80211.hw, false);
 		btcoexist->bt_info.bt_ctrl_lps = false;
 	}
 }
@@ -328,7 +331,8 @@ static void halbtc_pre_normal_lps(struct
 
 	if (btcoexist->bt_info.bt_ctrl_lps) {
 		btcoexist->bt_info.bt_lps_on = false;
-		rtl_lps_leave(rtlpriv->mac80211.hw);
+		/* FIXME: Context is unclear. Is it allowed to block? */
+		rtl_lps_leave(rtlpriv->mac80211.hw, false);
 	}
 }
 
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -544,7 +544,7 @@ static int rtl_op_suspend(struct ieee802
 	rtlhal->driver_is_goingto_unload = true;
 	rtlhal->enter_pnp_sleep = true;
 
-	rtl_lps_leave(hw);
+	rtl_lps_leave(hw, true);
 	rtl_op_stop(hw);
 	device_set_wakeup_enable(wiphy_dev(hw->wiphy), true);
 	return 0;
@@ -1151,7 +1151,7 @@ static void rtl_op_bss_info_changed(stru
 			mstatus = RT_MEDIA_DISCONNECT;
 
 			if (mac->link_state == MAC80211_LINKED)
-				rtl_lps_leave(hw);
+				rtl_lps_leave(hw, true);
 			if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
 				rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
 			mac->link_state = MAC80211_NOLINK;
@@ -1448,7 +1448,7 @@ static void rtl_op_sw_scan_start(struct
 	}
 
 	if (mac->link_state == MAC80211_LINKED) {
-		rtl_lps_leave(hw);
+		rtl_lps_leave(hw, true);
 		mac->link_state = MAC80211_LINKED_SCANNING;
 	} else {
 		rtl_ips_nic_on(hw);
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -622,7 +622,7 @@ static void _rtl_pci_tx_isr(struct ieee8
 	if (((rtlpriv->link_info.num_rx_inperiod +
 	      rtlpriv->link_info.num_tx_inperiod) > 8) ||
 	      rtlpriv->link_info.num_rx_inperiod > 2)
-		rtl_lps_leave(hw);
+		rtl_lps_leave(hw, false);
 }
 
 static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
@@ -875,7 +875,7 @@ static void _rtl_pci_rx_interrupt(struct
 		if (((rtlpriv->link_info.num_rx_inperiod +
 		      rtlpriv->link_info.num_tx_inperiod) > 8) ||
 		      rtlpriv->link_info.num_rx_inperiod > 2)
-			rtl_lps_leave(hw);
+			rtl_lps_leave(hw, false);
 		skb = new_skb;
 no_new:
 		if (rtlpriv->use_new_trx_flow) {
--- a/drivers/net/wireless/realtek/rtlwifi/ps.c
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.c
@@ -653,22 +653,22 @@ void rtl_lps_change_work_callback(struct
 }
 EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback);
 
-void rtl_lps_enter(struct ieee80211_hw *hw)
+void rtl_lps_enter(struct ieee80211_hw *hw, bool may_block)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
-	if (!in_interrupt())
+	if (may_block)
 		return rtl_lps_enter_core(hw);
 	rtlpriv->enter_ps = true;
 	schedule_work(&rtlpriv->works.lps_change_work);
 }
 EXPORT_SYMBOL_GPL(rtl_lps_enter);
 
-void rtl_lps_leave(struct ieee80211_hw *hw)
+void rtl_lps_leave(struct ieee80211_hw *hw, bool may_block)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
-	if (!in_interrupt())
+	if (may_block)
 		return rtl_lps_leave_core(hw);
 	rtlpriv->enter_ps = false;
 	schedule_work(&rtlpriv->works.lps_change_work);
--- a/drivers/net/wireless/realtek/rtlwifi/ps.h
+++ b/drivers/net/wireless/realtek/rtlwifi/ps.h
@@ -11,8 +11,8 @@ bool rtl_ps_disable_nic(struct ieee80211
 void rtl_ips_nic_off(struct ieee80211_hw *hw);
 void rtl_ips_nic_on(struct ieee80211_hw *hw);
 void rtl_ips_nic_off_wq_callback(struct work_struct *work);
-void rtl_lps_enter(struct ieee80211_hw *hw);
-void rtl_lps_leave(struct ieee80211_hw *hw);
+void rtl_lps_enter(struct ieee80211_hw *hw, bool may_block);
+void rtl_lps_leave(struct ieee80211_hw *hw, bool may_block);
 
 void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode);
 


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 00/35] net: in_interrupt() cleanup and fixes
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (34 preceding siblings ...)
  2020-09-27 19:49 ` [patch 35/35] net: rtlwifi: Replace in_interrupt() for context detection Thomas Gleixner
@ 2020-09-27 20:22 ` Joe Perches
  2020-09-27 20:57 ` David Miller
  36 siblings, 0 replies; 59+ messages in thread
From: Joe Perches @ 2020-09-27 20:22 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Christian Benvenuti, Govindarajulu Varadarajan, Dave Miller,
	Jakub Kicinski, netdev, Jonathan Corbet, Mauro Carvalho Chehab,
	linux-doc, Sebastian Andrzej Siewior, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, linux-usb, Greg Kroah-Hartman, Arend van Spriel,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

On Sun, 2020-09-27 at 21:48 +0200, Thomas Gleixner wrote:
> Folks,
> 
> in the discussion about preempt count consistency accross kernel configurations:
> 
>   https://lore.kernel.org/r/20200914204209.256266093@linutronix.de/
> 
> Linus clearly requested that code in drivers and libraries which changes
> behaviour based on execution context should either be split up so that
> e.g. task context invocations and BH invocations have different interfaces
> or if that's not possible the context information has to be provided by the
> caller which knows in which context it is executing.
> 
> This includes conditional locking, allocation mode (GFP_*) decisions and
> avoidance of code paths which might sleep.

Are these patches intended to be applied to Linus'
tree before v5.9 is released?

This patchset will cause conflicts against -next.

For instance, in patch 34, RT_TRACE has already
been removed in -next.



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 00/35] net: in_interrupt() cleanup and fixes
  2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
                   ` (35 preceding siblings ...)
  2020-09-27 20:22 ` [patch 00/35] net: in_interrupt() cleanup and fixes Joe Perches
@ 2020-09-27 20:57 ` David Miller
  2020-09-28 10:25   ` Thomas Gleixner
  36 siblings, 1 reply; 59+ messages in thread
From: David Miller @ 2020-09-27 20:57 UTC (permalink / raw)
  To: tglx
  Cc: linux-kernel, peterz, torvalds, paulmck, willy, benve, _govind,
	kuba, netdev, corbet, mchehab+huawei, linux-doc, bigeasy,
	luc.vanoostenryck, jcliburn, chris.snook, vishal,
	jeffrey.t.kirsher, intel-wired-lan, snelson, drivers, andrew,
	hkallweit1, linux, tsbogend, linux-net-drivers, ecree, mhabets,
	jdmason, dsd, kune, kvalo, linux-wireless, linux-usb, gregkh,
	arend.vanspriel, franky.lin, hante.meuleman, chi-hsien.lin,
	wright.feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	stas.yakovlev, stf_xl, johannes.berg, emmanuel.grumbach,
	luciano.coelho, linuxwifi

From: Thomas Gleixner <tglx@linutronix.de>
Date: Sun, 27 Sep 2020 21:48:46 +0200

> in the discussion about preempt count consistency accross kernel configurations:

Please respin this against net-next, some of the patches in here are already
in net-next (the wireless debug macro one) and even after that the series
doesn't build:

drivers/net/ethernet/cisco/enic/enic_main.c: In function ‘enic_reset’:
drivers/net/ethernet/cisco/enic/enic_main.c:2315:2: error: implicit declaration of function ‘enic_set_api_state’; did you mean ‘enic_set_api_busy’? [-Werror=implicit-function-declaration]
 2315 |  enic_set_api_state(enic, true);
      |  ^~~~~~~~~~~~~~~~~~
      |  enic_set_api_busy
At top level:
drivers/net/ethernet/cisco/enic/enic_main.c:2298:13: warning: ‘enic_set_api_busy’ defined but not used [-Wunused-function]
 2298 | static void enic_set_api_busy(struct enic *enic, bool busy)
      |             ^~~~~~~~~~~~~~~~~

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 13/35] net: mdiobus: Remove WARN_ON_ONCE(in_interrupt())
  2020-09-27 19:48 ` [patch 13/35] net: mdiobus: Remove WARN_ON_ONCE(in_interrupt()) Thomas Gleixner
@ 2020-09-27 23:00   ` Andrew Lunn
  0 siblings, 0 replies; 59+ messages in thread
From: Andrew Lunn @ 2020-09-27 23:00 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Peter Zijlstra, Linus Torvalds, Paul McKenney,
	Matthew Wilcox, Sebastian Andrzej Siewior, Heiner Kallweit,
	Russell King, David S. Miller, Jakub Kicinski, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

On Sun, Sep 27, 2020 at 09:48:59PM +0200, Thomas Gleixner wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> 
> in_interrupt() is ill defined and does not provide what the name
> suggests. The usage especially in driver code is deprecated and a tree wide
> effort to clean up and consolidate the (ab)usage of in_interrupt() and
> related checks is happening.
> 
> In this case the check covers only parts of the contexts in which these
> functions cannot be called. It fails to detect preemption or interrupt
> disabled invocations.
> 
> As the functions which contain these warnings invoke mutex_lock() which
> contains a broad variety of checks (always enabled or debug option
> dependent) and therefore covers all invalid conditions already, there is no
> point in having inconsistent warnings in those drivers. The conditional
> return is not really valuable in practice either.
> 
> Just remove them.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 28/35] net: iwlwifi: Remove in_interrupt() from tracing macro.
  2020-09-27 19:49 ` [patch 28/35] net: iwlwifi: Remove in_interrupt() from tracing macro Thomas Gleixner
@ 2020-09-28  6:13   ` Coelho, Luciano
  0 siblings, 0 replies; 59+ messages in thread
From: Coelho, Luciano @ 2020-09-28  6:13 UTC (permalink / raw)
  To: tglx, linux-kernel
  Cc: stf_xl, torvalds, intel-wired-lan, brcm80211-dev-list.pdl,
	jcliburn, andrew, davem, netdev, linux, hkallweit1,
	linux-net-drivers, libertas-dev, jdmason, dsd, peterz, corbet,
	luc.vanoostenryck, linux-usb, wright.feng, amitkarwar,
	ganapathi.bhat, brcm80211-dev-list, j, tsbogend, kuba, Berg,
	Johannes, mhabets, mchehab+huawei, Kirsher, Jeffrey T, snelson,
	Grumbach, Emmanuel, willy, chris.snook, paulmck, vishal,
	franky.lin, stas.yakovlev, pterjan, _govind, benve, gregkh,
	chi-hsien.lin, huxinming820, linuxwifi, ecree, bigeasy, drivers,
	pkshih, kune, arend.vanspriel, linux-doc, kvalo, linux-wireless,
	hante.meuleman

On Sun, 2020-09-27 at 21:49 +0200, Thomas Gleixner wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> 
> The usage of in_interrupt) in driver code is phased out.
> 
> The iwlwifi_dbg tracepoint records in_interrupt() seperately, but that's
> superfluous because the trace header already records all kind of state and
> context information like hardirq status, softirq status, preemption count
> etc.
> 
> Aside of that the recording of in_interrupt() as boolean does not allow to
> distinguish between the possible contexts (hard interrupt, soft interrupt,
> bottom half disabled) while the trace header gives precise information.
> 
> Remove the duplicate information from the tracepoint and fixup the caller.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Johannes Berg <johannes.berg@intel.com>
> Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> Cc: Luca Coelho <luciano.coelho@intel.com>
> Cc: Intel Linux Wireless <linuxwifi@intel.com>
> Cc: Kalle Valo <kvalo@codeaurora.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: linux-wireless@vger.kernel.org
> Cc: netdev@vger.kernel.org

Acked-by: Luca Coelho <luca@coelho.fi>

--
Luca.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 21/35] net: usb: kaweth: Remove last user of kaweth_control()
  2020-09-27 19:49 ` [patch 21/35] net: usb: kaweth: Remove last user of kaweth_control() Thomas Gleixner
@ 2020-09-28  6:50   ` Greg Kroah-Hartman
  0 siblings, 0 replies; 59+ messages in thread
From: Greg Kroah-Hartman @ 2020-09-28  6:50 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Peter Zijlstra, Linus Torvalds, Paul McKenney,
	Matthew Wilcox, Sebastian Andrzej Siewior, David S. Miller,
	Jakub Kicinski, linux-usb, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Kalle Valo,
	linux-wireless, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

On Sun, Sep 27, 2020 at 09:49:07PM +0200, Thomas Gleixner wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> 
> kaweth_async_set_rx_mode() invokes kaweth_contol() and has two callers:
> 
> - kaweth_open() which is invoked from preemptible context
> .
> - kaweth_start_xmit() which holds a spinlock and has bottom halfs disabled.
> 
> If called from kaweth_start_xmit() kaweth_async_set_rx_mode() obviously
> cannot block, which means it can't call kaweth_control(). This is detected
> with an in_interrupt() check.
> 
> Replace the in_interrupt() check in kaweth_async_set_rx_mode() with an
> argument which is set true by the caller if the context is safe to sleep,
> otherwise false.
> 
> Now kaweth_control() is only called from preemptible context which means
> there is no need for GFP_ATOMIC allocations anymore. Replace it with
> usb_control_msg(). Cleanup the code a bit while at it.
> 
> Finally remove kaweth_control() since the last user is gone.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: linux-usb@vger.kernel.org
> Cc: netdev@vger.kernel.org

Thanks for the cleanup, that driver really needed it!

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 24/35] net: brcmfmac: Replace in_interrupt()
  2020-09-27 19:49 ` [patch 24/35] net: brcmfmac: Replace in_interrupt() Thomas Gleixner
@ 2020-09-28  7:35   ` Arend Van Spriel
  2020-09-28  9:19     ` Ulf Hansson
  2020-09-28  9:40   ` Arend Van Spriel
  1 sibling, 1 reply; 59+ messages in thread
From: Arend Van Spriel @ 2020-09-28  7:35 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, Kalle Valo, David S. Miller,
	Jakub Kicinski, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih, Ulf Hansson

[-- Attachment #1: Type: text/plain, Size: 390 bytes --]

+ Uffe

On 9/27/2020 9:49 PM, Thomas Gleixner wrote:
> @@ -85,7 +85,7 @@ static void brcmf_sdiod_ib_irqhandler(st
>   
>   	brcmf_dbg(INTR, "IB intr triggered\n");
>   
> -	brcmf_sdio_isr(sdiodev->bus);
> +	brcmf_sdio_isr(sdiodev->bus, false);
>   }

Hi Uffe,

I assume the above code is okay, but want to confirm. Is the SDIO 
interrupt guaranteed to be on a worker thread?

Thanks,
Arend

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4176 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 25/35] net: brcmfmac: Use netif_rx_any_context().
  2020-09-27 19:49 ` [patch 25/35] net: brcmfmac: Use netif_rx_any_context() Thomas Gleixner
@ 2020-09-28  8:03   ` Arend Van Spriel
  0 siblings, 0 replies; 59+ messages in thread
From: Arend Van Spriel @ 2020-09-28  8:03 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Franky Lin, Hante Meuleman,
	Kalle Valo, David S. Miller, Jakub Kicinski, linux-wireless,
	brcm80211-dev-list.pdl, brcm80211-dev-list, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Chi-Hsien Lin, Wright Feng,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

[-- Attachment #1: Type: text/plain, Size: 941 bytes --]

On 9/27/2020 9:49 PM, Thomas Gleixner wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>
> The usage of in_interrupt() in non-core code is phased out. Ideally the
> information of the calling context should be passed by the callers or the
> functions be split as appropriate.
>
> brcmfmac uses in_interupt() to select the netif_rx*() variant which matches
> the calling context. The attempt to consolidate the code by passing an
> arguemnt or by distangling it failed due lack of knowledge about this
> driver and because the call chains are convoluted and hard to follow.

I think it is only for USB devices that the function can be called in
"interrupt" context. PCIe devices call it from thread context for sure.
The function brcmf_netif_rx() is (in)directly called by brcmf_rx_frame(), 
which is used by SDIO and USB. Anyway, it will be a bit more work, but 
doable. Let me see what I can come up with.

Regards,
Arend



[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4176 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 24/35] net: brcmfmac: Replace in_interrupt()
  2020-09-28  7:35   ` Arend Van Spriel
@ 2020-09-28  9:19     ` Ulf Hansson
  2020-09-28  9:37       ` Arend Van Spriel
  0 siblings, 1 reply; 59+ messages in thread
From: Ulf Hansson @ 2020-09-28  9:19 UTC (permalink / raw)
  To: Arend Van Spriel
  Cc: Thomas Gleixner, LKML, Peter Zijlstra, Linus Torvalds,
	Paul McKenney, Matthew Wilcox, Sebastian Andrzej Siewior,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	Kalle Valo, David S. Miller, Jakub Kicinski, linux-wireless,
	brcm80211-dev-list.pdl, brcm80211-dev-list, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, Linux Documentation, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Linux USB List,
	Greg Kroah-Hartman, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

On Mon, 28 Sep 2020 at 09:35, Arend Van Spriel
<arend.vanspriel@broadcom.com> wrote:
>
> + Uffe
>
> On 9/27/2020 9:49 PM, Thomas Gleixner wrote:
> > @@ -85,7 +85,7 @@ static void brcmf_sdiod_ib_irqhandler(st
> >
> >       brcmf_dbg(INTR, "IB intr triggered\n");
> >
> > -     brcmf_sdio_isr(sdiodev->bus);
> > +     brcmf_sdio_isr(sdiodev->bus, false);
> >   }
>
> Hi Uffe,
>
> I assume the above code is okay, but want to confirm. Is the SDIO
> interrupt guaranteed to be on a worker thread?

Correct.

As a matter of fact, the sdio irqs can be delivered through a couple
of different paths. The legacy (scheduled for removal), is from a
dedicated kthread. The more "modern" way is either from the context of
a threaded IRQ handler or via a workqueue.

However, there are also so-called out of band SDIO irqs, typically
routed via a separate GPIO line. This isn't managed by the MMC/SDIO
subsystem, but the SDIO functional driver itself.

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 26/35] net: brcmfmac: Convey allocation mode as argument
  2020-09-27 19:49 ` [patch 26/35] net: brcmfmac: Convey allocation mode as argument Thomas Gleixner
@ 2020-09-28  9:34   ` Arend Van Spriel
  0 siblings, 0 replies; 59+ messages in thread
From: Arend Van Spriel @ 2020-09-28  9:34 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, Kalle Valo, David S. Miller,
	Jakub Kicinski, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

[-- Attachment #1: Type: text/plain, Size: 1211 bytes --]

On 9/27/2020 9:49 PM, Thomas Gleixner wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> 
> The usage of in_interrupt() in drivers is phased out and Linus clearly
> requested that code which changes behaviour depending on context should
> either be seperated or the context be conveyed in an argument passed by the
> caller, which usually knows the context.
> 
> brcmf_fweh_process_event() uses in_interrupt() to select the allocation
> mode GFP_KERNEL/GFP_ATOMIC. Aside of the above reasons this check is
> incomplete as it cannot detect contexts which just have preemption or
> interrupts disabled.
> 
> All callchains leading to brcmf_fweh_process_event() can clearly identify
> the calling context. Convey a 'gfp' argument through the callchains and let
> the callers hand in the appropriate GFP mode.
> 
> This has also the advantage that any change of execution context or
> preemption/interrupt state in these callchains will be detected by the
> memory allocator for all GFP_KERNEL allocations.

Looking at the functions changed I see overlap with patch 25/35 so maybe 
change to gfp flag to a 'in_isr' bool. The flag can then be used for 
dealing with netif_rx as well.

Regards,
Arend

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4176 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 24/35] net: brcmfmac: Replace in_interrupt()
  2020-09-28  9:19     ` Ulf Hansson
@ 2020-09-28  9:37       ` Arend Van Spriel
  0 siblings, 0 replies; 59+ messages in thread
From: Arend Van Spriel @ 2020-09-28  9:37 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Thomas Gleixner, LKML, Peter Zijlstra, Linus Torvalds,
	Paul McKenney, Matthew Wilcox, Sebastian Andrzej Siewior,
	Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	Kalle Valo, David S. Miller, Jakub Kicinski, linux-wireless,
	brcm80211-dev-list.pdl, brcm80211-dev-list, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, Linux Documentation, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, Linux USB List,
	Greg Kroah-Hartman, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

[-- Attachment #1: Type: text/plain, Size: 1174 bytes --]

On 9/28/2020 11:19 AM, Ulf Hansson wrote:
> On Mon, 28 Sep 2020 at 09:35, Arend Van Spriel
> <arend.vanspriel@broadcom.com> wrote:
>>
>> + Uffe
>>
>> On 9/27/2020 9:49 PM, Thomas Gleixner wrote:
>>> @@ -85,7 +85,7 @@ static void brcmf_sdiod_ib_irqhandler(st
>>>
>>>        brcmf_dbg(INTR, "IB intr triggered\n");
>>>
>>> -     brcmf_sdio_isr(sdiodev->bus);
>>> +     brcmf_sdio_isr(sdiodev->bus, false);
>>>    }
>>
>> Hi Uffe,
>>
>> I assume the above code is okay, but want to confirm. Is the SDIO
>> interrupt guaranteed to be on a worker thread?
> 
> Correct.
> 
> As a matter of fact, the sdio irqs can be delivered through a couple
> of different paths. The legacy (scheduled for removal), is from a
> dedicated kthread. The more "modern" way is either from the context of
> a threaded IRQ handler or via a workqueue.
> 
> However, there are also so-called out of band SDIO irqs, typically
> routed via a separate GPIO line. This isn't managed by the MMC/SDIO
> subsystem, but the SDIO functional driver itself.

In brcmfmac we indeed support the out-of-band interrupt. That scnenario 
is also taken care of in this patch. Thanks for the confirmation.

Regards,
Arend

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4176 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 24/35] net: brcmfmac: Replace in_interrupt()
  2020-09-27 19:49 ` [patch 24/35] net: brcmfmac: Replace in_interrupt() Thomas Gleixner
  2020-09-28  7:35   ` Arend Van Spriel
@ 2020-09-28  9:40   ` Arend Van Spriel
  1 sibling, 0 replies; 59+ messages in thread
From: Arend Van Spriel @ 2020-09-28  9:40 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, Kalle Valo, David S. Miller,
	Jakub Kicinski, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer,
	Solarflare linux maintainers, Edward Cree, Martin Habets,
	Jon Mason, Daniel Drake, Ulrich Kunitz, linux-usb,
	Greg Kroah-Hartman, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

[-- Attachment #1: Type: text/plain, Size: 1467 bytes --]

On 9/27/2020 9:49 PM, Thomas Gleixner wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> 
> brcmf_sdio_isr() is using in_interrupt() to distinguish if it is called
> from a interrupt service routine or from a worker thread.
> 
> Passing such information from the calling context is preferred and
> requested by Linus, so add an argument `in_isr' to brcmf_sdio_isr() and let
> the callers pass the information about the calling context.

After getting confirmation here is my ...

Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
> Cc: Franky Lin <franky.lin@broadcom.com>
> Cc: Hante Meuleman <hante.meuleman@broadcom.com>
> Cc: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
> Cc: Wright Feng <wright.feng@cypress.com>
> Cc: Kalle Valo <kvalo@codeaurora.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: linux-wireless@vger.kernel.org
> Cc: brcm80211-dev-list.pdl@broadcom.com
> Cc: brcm80211-dev-list@cypress.com
> Cc: netdev@vger.kernel.org
> ---
>   drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c |    4 ++--
>   drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c   |    4 ++--
>   drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h   |    2 +-
>   3 files changed, 5 insertions(+), 5 deletions(-)

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4176 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 00/35] net: in_interrupt() cleanup and fixes
  2020-09-27 20:57 ` David Miller
@ 2020-09-28 10:25   ` Thomas Gleixner
  0 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-28 10:25 UTC (permalink / raw)
  To: David Miller
  Cc: linux-kernel, peterz, torvalds, paulmck, willy, benve, _govind,
	kuba, netdev, corbet, mchehab+huawei, linux-doc, bigeasy,
	luc.vanoostenryck, jcliburn, chris.snook, vishal,
	jeffrey.t.kirsher, intel-wired-lan, snelson, drivers, andrew,
	hkallweit1, linux, tsbogend, linux-net-drivers, ecree, mhabets,
	jdmason, dsd, kune, kvalo, linux-wireless, linux-usb, gregkh,
	arend.vanspriel, franky.lin, hante.meuleman, chi-hsien.lin,
	wright.feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	stas.yakovlev, stf_xl, johannes.berg, emmanuel.grumbach,
	luciano.coelho, linuxwifi

On Sun, Sep 27 2020 at 13:57, David Miller wrote:

> From: Thomas Gleixner <tglx@linutronix.de>
> Date: Sun, 27 Sep 2020 21:48:46 +0200
>
>> in the discussion about preempt count consistency accross kernel configurations:
>
> Please respin this against net-next, some of the patches in here are already
> in net-next (the wireless debug macro one) and even after that the series
> doesn't build:

Will do.

> drivers/net/ethernet/cisco/enic/enic_main.c: In function ‘enic_reset’:
> drivers/net/ethernet/cisco/enic/enic_main.c:2315:2: error: implicit declaration of function ‘enic_set_api_state’; did you mean ‘enic_set_api_busy’? [-Werror=implicit-function-declaration]
>  2315 |  enic_set_api_state(enic, true);
>       |  ^~~~~~~~~~~~~~~~~~
>       |  enic_set_api_busy
> At top level:
> drivers/net/ethernet/cisco/enic/enic_main.c:2298:13: warning: ‘enic_set_api_busy’ defined but not used [-Wunused-function]
>  2298 | static void enic_set_api_busy(struct enic *enic, bool busy)
>       |             ^~~~~~~~~~~~~~~~~

Duh, not sure how I managed that. Sorry. will fix and rebase.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 11/35] net: ionic: Replace in_interrupt() usage.
  2020-09-27 19:48 ` [patch 11/35] net: ionic: Replace in_interrupt() usage Thomas Gleixner
@ 2020-09-28 17:24   ` Shannon Nelson
  2020-09-28 19:51     ` Shannon Nelson
  0 siblings, 1 reply; 59+ messages in thread
From: Shannon Nelson @ 2020-09-28 17:24 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Pensando Drivers, David S. Miller,
	Jakub Kicinski, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

On 9/27/20 12:48 PM, Thomas Gleixner wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>
> The in_interrupt() usage in this driver tries to figure out which context
> may sleep and which context may not sleep. in_interrupt() is not really
> suitable as it misses both preemption disabled and interrupt disabled
> invocations from task context.
>
> Conditionals like that in driver code are frowned upon in general because
> invocations of functions from invalid contexts might not be detected
> as the conditional papers over it.
>
> ionic_lif_addr() can be called from:
>
>   1) ->ndo_set_rx_mode() which is under netif_addr_lock_bh()) so it must not
>      sleep.
>
>   2) Init and setup functions which are in fully preemptible task context.
>
> _ionic_lif_rx_mode() has only one call path with BH disabled.
>
> ionic_link_status_check_request() has two call paths:
>
>   1) NAPI which obviously cannot sleep
>
>   2) Setup which is again fully preemptible task context
>
> Add 'can_sleep' arguments to the affected functions and let the callers
> provide the context instead of letting the functions deduce it.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Shannon Nelson <snelson@pensando.io>
> Cc: Pensando Drivers <drivers@pensando.io>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: netdev@vger.kernel.org

Acked-by: Shannon Nelson <snelson@pensando.io>

> ---
>
> While reviewing the callpaths, a couple of things were observed which could
> be improved:
>
> - ionic_lif_deferred_work() can iterate over the list. There is no need
>    to schedule the work item after each iteration

I think the original writer's intent was to avoid monopolizing the work 
thread for very long on any one cycle, with the thought that we'd be 
making more use of this than we currently are.  I'll address this.

>
> - ionic_link_status_check_request() could have ionic_deferred_work within
>    ionic_lif(). This would avoid memory allocation from NAPI. More
>    important, once IONIC_LIF_F_LINK_CHECK_REQUESTED is set and that alloc
>    fails, the link check never happens.

Thanks, I'll fix up that error condition.

>
> - ionic_lif_handle_fw_down() sets IONIC_LIF_F_FW_RESET. Invokes then
>    ionic_lif_deinit() which only invokes cancel_work_sync() if
>    IONIC_LIF_F_FW_RESET is not set. I think the logic is wrong here as
>    the work must always be cancled. Also the list with ionic_deferred
>    work items needs a clean up.

I'll look at that, thanks.

sln



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 12/35] net: ionic: Remove WARN_ON(in_interrupt()).
  2020-09-27 19:48 ` [patch 12/35] net: ionic: Remove WARN_ON(in_interrupt()) Thomas Gleixner
@ 2020-09-28 17:26   ` Shannon Nelson
  0 siblings, 0 replies; 59+ messages in thread
From: Shannon Nelson @ 2020-09-28 17:26 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Pensando Drivers, David S. Miller,
	Jakub Kicinski, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

On 9/27/20 12:48 PM, Thomas Gleixner wrote:
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>
> in_interrupt() is ill defined and does not provide what the name
> suggests. The usage especially in driver code is deprecated and a tree wide
> effort to clean up and consolidate the (ab)usage of in_interrupt() and
> related checks is happening.
>
> In this case the check covers only parts of the contexts in which these
> functions cannot be called. It fails to detect preemption or interrupt
> disabled invocations.
>
> As the functions which are invoked from ionic_adminq_post() and
> ionic_dev_cmd_wait() contain a broad variety of checks (always enabled or
> debug option dependent) which cover all invalid conditions already, there
> is no point in having inconsistent warnings in those drivers.
>
> Just remove them.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Shannon Nelson <snelson@pensando.io>
> Cc: Pensando Drivers <drivers@pensando.io>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: netdev@vger.kernel.org
Thanks.

Acked-by: Shannon Nelson <snelson@pensando.io>

> ---
>   drivers/net/ethernet/pensando/ionic/ionic_main.c |    4 ----
>   1 file changed, 4 deletions(-)
>
> --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c
> +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c
> @@ -248,8 +248,6 @@ static int ionic_adminq_post(struct ioni
>   	struct ionic_queue *adminq;
>   	int err = 0;
>   
> -	WARN_ON(in_interrupt());
> -
>   	if (!lif->adminqcq)
>   		return -EIO;
>   
> @@ -346,8 +344,6 @@ int ionic_dev_cmd_wait(struct ionic *ion
>   	int done;
>   	int err;
>   
> -	WARN_ON(in_interrupt());
> -
>   	/* Wait for dev cmd to complete, retrying if we get EAGAIN,
>   	 * but don't wait any longer than max_seconds.
>   	 */
>


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 15/35] net: sfc: Replace in_interrupt() usage.
  2020-09-27 19:49 ` [patch 15/35] net: sfc: " Thomas Gleixner
@ 2020-09-28 19:03   ` Edward Cree
  2020-09-28 20:05     ` [RFC PATCH net-next] sfc: replace " Edward Cree
  0 siblings, 1 reply; 59+ messages in thread
From: Edward Cree @ 2020-09-28 19:03 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Solarflare linux maintainers,
	Martin Habets, David S. Miller, Jakub Kicinski, netdev,
	Christian Benvenuti, Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Shannon Nelson, Pensando Drivers, Andrew Lunn,
	Heiner Kallweit, Russell King, Thomas Bogendoerfer, Jon Mason,
	Daniel Drake, Ulrich Kunitz, Kalle Valo, linux-wireless,
	linux-usb, Greg Kroah-Hartman, Arend van Spriel, Franky Lin,
	Hante Meuleman, Chi-Hsien Lin, Wright Feng,
	brcm80211-dev-list.pdl, brcm80211-dev-list, Stanislav Yakovlev,
	Stanislaw Gruszka, Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

On 27/09/2020 20:49, Thomas Gleixner wrote:
> Note, that the fixes tag is empty as it is unclear which of the commits to
> blame.
Seems like it should be
Fixes: f00bf2305cab("sfc: don't update stats on VF when called in atomic context")
 since that adds the in_interrupt() check and the code concerned
 doesn't seemto have changed a great deal since.

Anyway, this fix looks correct, and you can have my
Acked-by: Edward Cree <ecree@solarflare.com>
 but I thinkit might be cleaner to avoid having to have this unused
 can_sleep argument on all the NICs that don't need it, by instead
 adding an update_stats_atomic() member to struct efx_nic_type, which
 could be set to the same as update_stats() for everything except
 EF10 VFs which would just do the call to efx_update_sw_stats().
I'll send an rfc patch embodying the above shortly...

-ed

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 11/35] net: ionic: Replace in_interrupt() usage.
  2020-09-28 17:24   ` Shannon Nelson
@ 2020-09-28 19:51     ` Shannon Nelson
  2020-09-29 14:37       ` Thomas Gleixner
  0 siblings, 1 reply; 59+ messages in thread
From: Shannon Nelson @ 2020-09-28 19:51 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Pensando Drivers, David S. Miller,
	Jakub Kicinski, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

On 9/28/20 10:24 AM, Shannon Nelson wrote:
> On 9/27/20 12:48 PM, Thomas Gleixner wrote:
>> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>>
>> The in_interrupt() usage in this driver tries to figure out which 
>> context
>> may sleep and which context may not sleep. in_interrupt() is not really
>> suitable as it misses both preemption disabled and interrupt disabled
>> invocations from task context.
>>
>> Conditionals like that in driver code are frowned upon in general 
>> because
>> invocations of functions from invalid contexts might not be detected
>> as the conditional papers over it.
>>
>> ionic_lif_addr() can be called from:
>>
>>   1) ->ndo_set_rx_mode() which is under netif_addr_lock_bh()) so it 
>> must not
>>      sleep.
>>
>>   2) Init and setup functions which are in fully preemptible task 
>> context.
>>
>> _ionic_lif_rx_mode() has only one call path with BH disabled.

Now that I've had my coffee, let's look at this again - there are 
multiple paths that get us to _ionic_lif_rx_mode():

.ndo_set_rx_mode
   ionic_set_rx_mode,
     _ionic_lif_rx_mode

{ ionic_open, ionic_lif_handle_fw_up, ionic_start_queues_reconfig }
     ionic_txrx_init
       ionic_set_rx_mode
         _ionic_lif_rx_mode

We may not want to change this one.

sln



>>
>> ionic_link_status_check_request() has two call paths:
>>
>>   1) NAPI which obviously cannot sleep
>>
>>   2) Setup which is again fully preemptible task context
>>
>> Add 'can_sleep' arguments to the affected functions and let the callers
>> provide the context instead of letting the functions deduce it.
>>
>> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Shannon Nelson <snelson@pensando.io>
>> Cc: Pensando Drivers <drivers@pensando.io>
>> Cc: "David S. Miller" <davem@davemloft.net>
>> Cc: Jakub Kicinski <kuba@kernel.org>
>> Cc: netdev@vger.kernel.org
>
> Acked-by: Shannon Nelson <snelson@pensando.io>
>
>> ---
>>
>> While reviewing the callpaths, a couple of things were observed which 
>> could
>> be improved:
>>
>> - ionic_lif_deferred_work() can iterate over the list. There is no need
>>    to schedule the work item after each iteration
>
> I think the original writer's intent was to avoid monopolizing the 
> work thread for very long on any one cycle, with the thought that we'd 
> be making more use of this than we currently are.  I'll address this.
>
>>
>> - ionic_link_status_check_request() could have ionic_deferred_work 
>> within
>>    ionic_lif(). This would avoid memory allocation from NAPI. More
>>    important, once IONIC_LIF_F_LINK_CHECK_REQUESTED is set and that 
>> alloc
>>    fails, the link check never happens.
>
> Thanks, I'll fix up that error condition.
>
>>
>> - ionic_lif_handle_fw_down() sets IONIC_LIF_F_FW_RESET. Invokes then
>>    ionic_lif_deinit() which only invokes cancel_work_sync() if
>>    IONIC_LIF_F_FW_RESET is not set. I think the logic is wrong here as
>>    the work must always be cancled. Also the list with ionic_deferred
>>    work items needs a clean up.
>
> I'll look at that, thanks.
>
> sln
>
>


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [RFC PATCH net-next] sfc: replace in_interrupt() usage
  2020-09-28 19:03   ` Edward Cree
@ 2020-09-28 20:05     ` Edward Cree
  2020-09-28 20:24       ` Thomas Gleixner
  2020-09-29  9:39       ` Martin Habets
  0 siblings, 2 replies; 59+ messages in thread
From: Edward Cree @ 2020-09-28 20:05 UTC (permalink / raw)
  To: linux-net-drivers, tglx; +Cc: linux-kernel, netdev

efx_ef10_try_update_nic_stats_vf() used in_interrupt() to figure out
 whether it is safe to sleep (for MCDI) or not.
The only caller from which it was not is efx_net_stats(), which can be
 invoked under dev_base_lock from net-sysfs::netstat_show().
So add a new update_stats_atomic() method to struct efx_nic_type, and
 call it from efx_net_stats(), removing the need for
 efx_ef10_try_update_nic_stats_vf() to behave differently for this case
 (which it wasn't doing correctly anyway).
For all nic_types other than EF10 VF, this method is NULL and so we
 call the regular update_stats() methods, which are happy with being
 called from atomic contexts.

Fixes: f00bf2305cab ("sfc: don't update stats on VF when called in atomic context")
Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Edward Cree <ecree@solarflare.com>
---
Only compile-tested so far, because I'm waiting for my kernel to
 finish rebuilding with CONFIG_DEBUG_ATOMIC_SLEEP which I'm hoping
 is the right thing to detect the bug in the existing code.
I also wasn't quite sure how to give credit to the thorough analysis
 in the commit message of Sebastian's patch.  I don't think we have
 a Whatever-by: tag to cover that, do we?
And this doesn't include your GFP_KERNEL change, which should
 probably go in separately if you take this.

 drivers/net/ethernet/sfc/ef10.c       | 22 +++++++++++++---------
 drivers/net/ethernet/sfc/efx_common.c |  2 +-
 drivers/net/ethernet/sfc/net_driver.h |  5 +++++
 drivers/net/ethernet/sfc/nic_common.h |  7 +++++++
 4 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index c9df2e96ebe4..b702ba5986dc 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1871,15 +1871,6 @@ static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx)
 
 	spin_unlock_bh(&efx->stats_lock);
 
-	if (in_interrupt()) {
-		/* If in atomic context, cannot update stats.  Just update the
-		 * software stats and return so the caller can continue.
-		 */
-		spin_lock_bh(&efx->stats_lock);
-		efx_update_sw_stats(efx, stats);
-		return 0;
-	}
-
 	efx_ef10_get_stat_mask(efx, mask);
 
 	rc = efx_nic_alloc_buffer(efx, &stats_buf, dma_len, GFP_ATOMIC);
@@ -1938,6 +1929,18 @@ static size_t efx_ef10_update_stats_vf(struct efx_nic *efx, u64 *full_stats,
 	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
 }
 
+static size_t efx_ef10_update_stats_atomic_vf(struct efx_nic *efx, u64 *full_stats,
+					      struct rtnl_link_stats64 *core_stats)
+{
+	struct efx_ef10_nic_data *nic_data = efx->nic_data;
+
+	/* In atomic context, cannot update HW stats.  Just update the
+	 * software stats and return so the caller can continue.
+	 */
+	efx_update_sw_stats(efx, nic_data->stats);
+	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
+}
+
 static void efx_ef10_push_irq_moderation(struct efx_channel *channel)
 {
 	struct efx_nic *efx = channel->efx;
@@ -3998,6 +4001,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
 	.finish_flr = efx_port_dummy_op_void,
 	.describe_stats = efx_ef10_describe_stats,
 	.update_stats = efx_ef10_update_stats_vf,
+	.update_stats_atomic = efx_ef10_update_stats_atomic_vf,
 	.start_stats = efx_port_dummy_op_void,
 	.pull_stats = efx_port_dummy_op_void,
 	.stop_stats = efx_port_dummy_op_void,
diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
index c256db241570..72a3f0e09f52 100644
--- a/drivers/net/ethernet/sfc/efx_common.c
+++ b/drivers/net/ethernet/sfc/efx_common.c
@@ -602,7 +602,7 @@ void efx_net_stats(struct net_device *net_dev, struct rtnl_link_stats64 *stats)
 	struct efx_nic *efx = netdev_priv(net_dev);
 
 	spin_lock_bh(&efx->stats_lock);
-	efx->type->update_stats(efx, NULL, stats);
+	efx_nic_update_stats_atomic(efx, NULL, stats);
 	spin_unlock_bh(&efx->stats_lock);
 }
 
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 47aa753e64bd..9f7dfdf708cf 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1172,6 +1172,9 @@ struct efx_udp_tunnel {
  * @describe_stats: Describe statistics for ethtool
  * @update_stats: Update statistics not provided by event handling.
  *	Either argument may be %NULL.
+ * @update_stats_atomic: Update statistics while in atomic context, if that
+ *	is more limiting than @update_stats.  Otherwise, leave %NULL and
+ *	driver core will call @update_stats.
  * @start_stats: Start the regular fetching of statistics
  * @pull_stats: Pull stats from the NIC and wait until they arrive.
  * @stop_stats: Stop the regular fetching of statistics
@@ -1316,6 +1319,8 @@ struct efx_nic_type {
 	size_t (*describe_stats)(struct efx_nic *efx, u8 *names);
 	size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats,
 			       struct rtnl_link_stats64 *core_stats);
+	size_t (*update_stats_atomic)(struct efx_nic *efx, u64 *full_stats,
+				      struct rtnl_link_stats64 *core_stats);
 	void (*start_stats)(struct efx_nic *efx);
 	void (*pull_stats)(struct efx_nic *efx);
 	void (*stop_stats)(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/nic_common.h b/drivers/net/ethernet/sfc/nic_common.h
index 82271f0b8627..b9cafe9cd568 100644
--- a/drivers/net/ethernet/sfc/nic_common.h
+++ b/drivers/net/ethernet/sfc/nic_common.h
@@ -244,6 +244,13 @@ void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
 			  const unsigned long *mask, u64 *stats,
 			  const void *dma_buf, bool accumulate);
 void efx_nic_fix_nodesc_drop_stat(struct efx_nic *efx, u64 *stat);
+static inline size_t efx_nic_update_stats_atomic(struct efx_nic *efx, u64 *full_stats,
+						 struct rtnl_link_stats64 *core_stats)
+{
+	if (efx->type->update_stats_atomic)
+		return efx->type->update_stats_atomic(efx, full_stats, core_stats);
+	return efx->type->update_stats(efx, full_stats, core_stats);
+}
 
 #define EFX_MAX_FLUSH_TIME 5000
 

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [RFC PATCH net-next] sfc: replace in_interrupt() usage
  2020-09-28 20:05     ` [RFC PATCH net-next] sfc: replace " Edward Cree
@ 2020-09-28 20:24       ` Thomas Gleixner
  2020-09-29 15:15         ` Edward Cree
  2020-09-29  9:39       ` Martin Habets
  1 sibling, 1 reply; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-28 20:24 UTC (permalink / raw)
  To: Edward Cree, linux-net-drivers; +Cc: linux-kernel, netdev

On Mon, Sep 28 2020 at 21:05, Edward Cree wrote:
> efx_ef10_try_update_nic_stats_vf() used in_interrupt() to figure out
>  whether it is safe to sleep (for MCDI) or not.
> The only caller from which it was not is efx_net_stats(), which can be
>  invoked under dev_base_lock from net-sysfs::netstat_show().
> So add a new update_stats_atomic() method to struct efx_nic_type, and
>  call it from efx_net_stats(), removing the need for
>  efx_ef10_try_update_nic_stats_vf() to behave differently for this case
>  (which it wasn't doing correctly anyway).
> For all nic_types other than EF10 VF, this method is NULL and so we
>  call the regular update_stats() methods, which are happy with being
>  called from atomic contexts.
>
> Fixes: f00bf2305cab ("sfc: don't update stats on VF when called in atomic context")
> Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Signed-off-by: Edward Cree <ecree@solarflare.com>

That's much nicer.

> ---
> Only compile-tested so far, because I'm waiting for my kernel to
>  finish rebuilding with CONFIG_DEBUG_ATOMIC_SLEEP which I'm hoping
>  is the right thing to detect the bug in the existing code.
> I also wasn't quite sure how to give credit to the thorough analysis
>  in the commit message of Sebastian's patch.  I don't think we have
>  a Whatever-by: tag to cover that, do we?

Sebastian did the analysis and I did some word polishing, but the credit
surely goes to him.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 10/35] net: intel: Remove in_interrupt() warnings
  2020-09-27 19:48 ` [patch 10/35] net: intel: Remove in_interrupt() warnings Thomas Gleixner
@ 2020-09-28 23:04   ` Alexander Duyck
  0 siblings, 0 replies; 59+ messages in thread
From: Alexander Duyck @ 2020-09-28 23:04 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Peter Zijlstra, Linus Torvalds, Paul McKenney,
	Matthew Wilcox, Sebastian Andrzej Siewior, Jeff Kirsher,
	David S. Miller, Jakub Kicinski, Netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, intel-wired-lan,
	Shannon Nelson, Pensando Drivers, Andrew Lunn, Heiner Kallweit,
	Russell King, Thomas Bogendoerfer, Solarflare linux maintainers,
	Edward Cree, Martin Habets, Jon Mason, Daniel Drake,
	Ulrich Kunitz, Kalle Valo, linux-wireless, USB list,
	Greg Kroah-Hartman, Arend van Spriel, Franky Lin, Hante Meuleman,
	Chi-Hsien Lin, Wright Feng, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Stanislav Yakovlev, Stanislaw Gruszka,
	Johannes Berg, Emmanuel Grumbach, Luca Coelho,
	Intel Linux Wireless, Jouni Malinen, Amitkumar Karwar,
	Ganapathi Bhat, Xinming Hu, libertas-dev, Pascal Terjan,
	Ping-Ke Shih

On Sun, Sep 27, 2020 at 1:00 PM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>
> in_interrupt() is ill defined and does not provide what the name
> suggests. The usage especially in driver code is deprecated and a tree wide
> effort to clean up and consolidate the (ab)usage of in_interrupt() and
> related checks is happening.
>
> In this case the checks cover only parts of the contexts in which these
> functions cannot be called. They fail to detect preemption or interrupt
> disabled invocations.
>
> As the functions which are invoked from the various places contain already
> a broad variety of checks (always enabled or debug option dependent) cover
> all invalid conditions already, there is no point in having inconsistent
> warnings in those drivers.
>
> Just remove them.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: netdev@vger.kernel.org

The patch looks good to me.

Reviewed-by: Alexander Duyck <alexander.h.duyck@linux.intel.com>

> ---
>  drivers/net/ethernet/intel/e1000/e1000_main.c     |    1 -
>  drivers/net/ethernet/intel/fm10k/fm10k_pci.c      |    2 --
>  drivers/net/ethernet/intel/i40e/i40e_main.c       |    4 ----
>  drivers/net/ethernet/intel/ice/ice_main.c         |    1 -
>  drivers/net/ethernet/intel/igb/igb_main.c         |    1 -
>  drivers/net/ethernet/intel/igc/igc_main.c         |    1 -
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |    1 -
>  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |    2 --
>  8 files changed, 13 deletions(-)
>
> --- a/drivers/net/ethernet/intel/e1000/e1000_main.c
> +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
> @@ -534,7 +534,6 @@ void e1000_down(struct e1000_adapter *ad
>
>  void e1000_reinit_locked(struct e1000_adapter *adapter)
>  {
> -       WARN_ON(in_interrupt());
>         while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
>                 msleep(1);
>
> --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
> +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
> @@ -221,8 +221,6 @@ static bool fm10k_prepare_for_reset(stru
>  {
>         struct net_device *netdev = interface->netdev;
>
> -       WARN_ON(in_interrupt());
> -
>         /* put off any impending NetWatchDogTimeout */
>         netif_trans_update(netdev);
>
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -6689,7 +6689,6 @@ static void i40e_vsi_reinit_locked(struc
>  {
>         struct i40e_pf *pf = vsi->back;
>
> -       WARN_ON(in_interrupt());
>         while (test_and_set_bit(__I40E_CONFIG_BUSY, pf->state))
>                 usleep_range(1000, 2000);
>         i40e_down(vsi);
> @@ -8462,9 +8461,6 @@ void i40e_do_reset(struct i40e_pf *pf, u
>  {
>         u32 val;
>
> -       WARN_ON(in_interrupt());
> -
> -
>         /* do the biggest reset indicated */
>         if (reset_flags & BIT_ULL(__I40E_GLOBAL_RESET_REQUESTED)) {
>
> --- a/drivers/net/ethernet/intel/ice/ice_main.c
> +++ b/drivers/net/ethernet/intel/ice/ice_main.c
> @@ -486,7 +486,6 @@ static void ice_do_reset(struct ice_pf *
>         struct ice_hw *hw = &pf->hw;
>
>         dev_dbg(dev, "reset_type 0x%x requested\n", reset_type);
> -       WARN_ON(in_interrupt());
>
>         ice_prepare_for_reset(pf);
>
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -2220,7 +2220,6 @@ void igb_down(struct igb_adapter *adapte
>
>  void igb_reinit_locked(struct igb_adapter *adapter)
>  {
> -       WARN_ON(in_interrupt());
>         while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
>                 usleep_range(1000, 2000);
>         igb_down(adapter);
> --- a/drivers/net/ethernet/intel/igc/igc_main.c
> +++ b/drivers/net/ethernet/intel/igc/igc_main.c
> @@ -3831,7 +3831,6 @@ void igc_down(struct igc_adapter *adapte
>
>  void igc_reinit_locked(struct igc_adapter *adapter)
>  {
> -       WARN_ON(in_interrupt());
>         while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
>                 usleep_range(1000, 2000);
>         igc_down(adapter);
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -5677,7 +5677,6 @@ static void ixgbe_up_complete(struct ixg
>
>  void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
>  {
> -       WARN_ON(in_interrupt());
>         /* put off any impending NetWatchDogTimeout */
>         netif_trans_update(adapter->netdev);
>
> --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> @@ -2526,8 +2526,6 @@ void ixgbevf_down(struct ixgbevf_adapter
>
>  void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter)
>  {
> -       WARN_ON(in_interrupt());
> -
>         while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state))
>                 msleep(1);
>
>

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFC PATCH net-next] sfc: replace in_interrupt() usage
  2020-09-28 20:05     ` [RFC PATCH net-next] sfc: replace " Edward Cree
  2020-09-28 20:24       ` Thomas Gleixner
@ 2020-09-29  9:39       ` Martin Habets
  1 sibling, 0 replies; 59+ messages in thread
From: Martin Habets @ 2020-09-29  9:39 UTC (permalink / raw)
  To: Edward Cree; +Cc: linux-net-drivers, tglx, linux-kernel, netdev

On Mon, Sep 28, 2020 at 09:05:52PM +0100, Edward Cree wrote:
> efx_ef10_try_update_nic_stats_vf() used in_interrupt() to figure out
>  whether it is safe to sleep (for MCDI) or not.
> The only caller from which it was not is efx_net_stats(), which can be
>  invoked under dev_base_lock from net-sysfs::netstat_show().
> So add a new update_stats_atomic() method to struct efx_nic_type, and
>  call it from efx_net_stats(), removing the need for
>  efx_ef10_try_update_nic_stats_vf() to behave differently for this case
>  (which it wasn't doing correctly anyway).
> For all nic_types other than EF10 VF, this method is NULL and so we
>  call the regular update_stats() methods, which are happy with being
>  called from atomic contexts.
> 
> Fixes: f00bf2305cab ("sfc: don't update stats on VF when called in atomic context")
> Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Signed-off-by: Edward Cree <ecree@solarflare.com>

Reviewed-by: Martin Habets <mhabets@solarflare.com>

> ---
> Only compile-tested so far, because I'm waiting for my kernel to
>  finish rebuilding with CONFIG_DEBUG_ATOMIC_SLEEP which I'm hoping
>  is the right thing to detect the bug in the existing code.
> I also wasn't quite sure how to give credit to the thorough analysis
>  in the commit message of Sebastian's patch.  I don't think we have
>  a Whatever-by: tag to cover that, do we?
> And this doesn't include your GFP_KERNEL change, which should
>  probably go in separately if you take this.
> 
>  drivers/net/ethernet/sfc/ef10.c       | 22 +++++++++++++---------
>  drivers/net/ethernet/sfc/efx_common.c |  2 +-
>  drivers/net/ethernet/sfc/net_driver.h |  5 +++++
>  drivers/net/ethernet/sfc/nic_common.h |  7 +++++++
>  4 files changed, 26 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
> index c9df2e96ebe4..b702ba5986dc 100644
> --- a/drivers/net/ethernet/sfc/ef10.c
> +++ b/drivers/net/ethernet/sfc/ef10.c
> @@ -1871,15 +1871,6 @@ static int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx)
>  
>  	spin_unlock_bh(&efx->stats_lock);
>  
> -	if (in_interrupt()) {
> -		/* If in atomic context, cannot update stats.  Just update the
> -		 * software stats and return so the caller can continue.
> -		 */
> -		spin_lock_bh(&efx->stats_lock);
> -		efx_update_sw_stats(efx, stats);
> -		return 0;
> -	}
> -
>  	efx_ef10_get_stat_mask(efx, mask);
>  
>  	rc = efx_nic_alloc_buffer(efx, &stats_buf, dma_len, GFP_ATOMIC);
> @@ -1938,6 +1929,18 @@ static size_t efx_ef10_update_stats_vf(struct efx_nic *efx, u64 *full_stats,
>  	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
>  }
>  
> +static size_t efx_ef10_update_stats_atomic_vf(struct efx_nic *efx, u64 *full_stats,
> +					      struct rtnl_link_stats64 *core_stats)
> +{
> +	struct efx_ef10_nic_data *nic_data = efx->nic_data;
> +
> +	/* In atomic context, cannot update HW stats.  Just update the
> +	 * software stats and return so the caller can continue.
> +	 */
> +	efx_update_sw_stats(efx, nic_data->stats);
> +	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
> +}
> +
>  static void efx_ef10_push_irq_moderation(struct efx_channel *channel)
>  {
>  	struct efx_nic *efx = channel->efx;
> @@ -3998,6 +4001,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
>  	.finish_flr = efx_port_dummy_op_void,
>  	.describe_stats = efx_ef10_describe_stats,
>  	.update_stats = efx_ef10_update_stats_vf,
> +	.update_stats_atomic = efx_ef10_update_stats_atomic_vf,
>  	.start_stats = efx_port_dummy_op_void,
>  	.pull_stats = efx_port_dummy_op_void,
>  	.stop_stats = efx_port_dummy_op_void,
> diff --git a/drivers/net/ethernet/sfc/efx_common.c b/drivers/net/ethernet/sfc/efx_common.c
> index c256db241570..72a3f0e09f52 100644
> --- a/drivers/net/ethernet/sfc/efx_common.c
> +++ b/drivers/net/ethernet/sfc/efx_common.c
> @@ -602,7 +602,7 @@ void efx_net_stats(struct net_device *net_dev, struct rtnl_link_stats64 *stats)
>  	struct efx_nic *efx = netdev_priv(net_dev);
>  
>  	spin_lock_bh(&efx->stats_lock);
> -	efx->type->update_stats(efx, NULL, stats);
> +	efx_nic_update_stats_atomic(efx, NULL, stats);
>  	spin_unlock_bh(&efx->stats_lock);
>  }
>  
> diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
> index 47aa753e64bd..9f7dfdf708cf 100644
> --- a/drivers/net/ethernet/sfc/net_driver.h
> +++ b/drivers/net/ethernet/sfc/net_driver.h
> @@ -1172,6 +1172,9 @@ struct efx_udp_tunnel {
>   * @describe_stats: Describe statistics for ethtool
>   * @update_stats: Update statistics not provided by event handling.
>   *	Either argument may be %NULL.
> + * @update_stats_atomic: Update statistics while in atomic context, if that
> + *	is more limiting than @update_stats.  Otherwise, leave %NULL and
> + *	driver core will call @update_stats.
>   * @start_stats: Start the regular fetching of statistics
>   * @pull_stats: Pull stats from the NIC and wait until they arrive.
>   * @stop_stats: Stop the regular fetching of statistics
> @@ -1316,6 +1319,8 @@ struct efx_nic_type {
>  	size_t (*describe_stats)(struct efx_nic *efx, u8 *names);
>  	size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats,
>  			       struct rtnl_link_stats64 *core_stats);
> +	size_t (*update_stats_atomic)(struct efx_nic *efx, u64 *full_stats,
> +				      struct rtnl_link_stats64 *core_stats);
>  	void (*start_stats)(struct efx_nic *efx);
>  	void (*pull_stats)(struct efx_nic *efx);
>  	void (*stop_stats)(struct efx_nic *efx);
> diff --git a/drivers/net/ethernet/sfc/nic_common.h b/drivers/net/ethernet/sfc/nic_common.h
> index 82271f0b8627..b9cafe9cd568 100644
> --- a/drivers/net/ethernet/sfc/nic_common.h
> +++ b/drivers/net/ethernet/sfc/nic_common.h
> @@ -244,6 +244,13 @@ void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
>  			  const unsigned long *mask, u64 *stats,
>  			  const void *dma_buf, bool accumulate);
>  void efx_nic_fix_nodesc_drop_stat(struct efx_nic *efx, u64 *stat);
> +static inline size_t efx_nic_update_stats_atomic(struct efx_nic *efx, u64 *full_stats,
> +						 struct rtnl_link_stats64 *core_stats)
> +{
> +	if (efx->type->update_stats_atomic)
> +		return efx->type->update_stats_atomic(efx, full_stats, core_stats);
> +	return efx->type->update_stats(efx, full_stats, core_stats);
> +}
>  
>  #define EFX_MAX_FLUSH_TIME 5000
>  

-- 
Martin Habets <mhabets@solarflare.com>

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [patch 11/35] net: ionic: Replace in_interrupt() usage.
  2020-09-28 19:51     ` Shannon Nelson
@ 2020-09-29 14:37       ` Thomas Gleixner
  0 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-29 14:37 UTC (permalink / raw)
  To: Shannon Nelson, LKML
  Cc: Peter Zijlstra, Linus Torvalds, Paul McKenney, Matthew Wilcox,
	Sebastian Andrzej Siewior, Pensando Drivers, David S. Miller,
	Jakub Kicinski, netdev, Christian Benvenuti,
	Govindarajulu Varadarajan, Jonathan Corbet,
	Mauro Carvalho Chehab, linux-doc, Luc Van Oostenryck,
	Jay Cliburn, Chris Snook, Vishal Kulkarni, Jeff Kirsher,
	intel-wired-lan, Andrew Lunn, Heiner Kallweit, Russell King,
	Thomas Bogendoerfer, Solarflare linux maintainers, Edward Cree,
	Martin Habets, Jon Mason, Daniel Drake, Ulrich Kunitz,
	Kalle Valo, linux-wireless, linux-usb, Greg Kroah-Hartman,
	Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, brcm80211-dev-list.pdl, brcm80211-dev-list,
	Stanislav Yakovlev, Stanislaw Gruszka, Johannes Berg,
	Emmanuel Grumbach, Luca Coelho, Intel Linux Wireless,
	Jouni Malinen, Amitkumar Karwar, Ganapathi Bhat, Xinming Hu,
	libertas-dev, Pascal Terjan, Ping-Ke Shih

On Mon, Sep 28 2020 at 12:51, Shannon Nelson wrote:
> On 9/28/20 10:24 AM, Shannon Nelson wrote:
>>> ionic_lif_addr() can be called from:
>>>
>>>   1) ->ndo_set_rx_mode() which is under netif_addr_lock_bh()) so it 
>>> must not
>>>      sleep.
>>>
>>>   2) Init and setup functions which are in fully preemptible task 
>>> context.
>>>
>>> _ionic_lif_rx_mode() has only one call path with BH disabled.
>
> Now that I've had my coffee, let's look at this again - there are 
> multiple paths that get us to _ionic_lif_rx_mode():
>
> .ndo_set_rx_mode
>    ionic_set_rx_mode,
>      _ionic_lif_rx_mode
>
> { ionic_open, ionic_lif_handle_fw_up, ionic_start_queues_reconfig }
>      ionic_txrx_init
>        ionic_set_rx_mode
>          _ionic_lif_rx_mode

Hrm. Let me stare at it again...

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFC PATCH net-next] sfc: replace in_interrupt() usage
  2020-09-28 20:24       ` Thomas Gleixner
@ 2020-09-29 15:15         ` Edward Cree
  2020-09-29 19:27           ` Thomas Gleixner
  0 siblings, 1 reply; 59+ messages in thread
From: Edward Cree @ 2020-09-29 15:15 UTC (permalink / raw)
  To: Thomas Gleixner, linux-net-drivers; +Cc: linux-kernel, netdev

> On Mon, Sep 28 2020 at 21:05, Edward Cree wrote:
>> Only compile-tested so far, because I'm waiting for my kernel to
>>  finish rebuilding with CONFIG_DEBUG_ATOMIC_SLEEP

I've now tested and confirmed that the might_sleep warning goes
 away with this patch.

Thomas, do you want to pull it into v2 of your series, or should
 I submit it separately to David?

-ed

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [RFC PATCH net-next] sfc: replace in_interrupt() usage
  2020-09-29 15:15         ` Edward Cree
@ 2020-09-29 19:27           ` Thomas Gleixner
  0 siblings, 0 replies; 59+ messages in thread
From: Thomas Gleixner @ 2020-09-29 19:27 UTC (permalink / raw)
  To: Edward Cree, linux-net-drivers; +Cc: linux-kernel, netdev

On Tue, Sep 29 2020 at 16:15, Edward Cree wrote:
>> On Mon, Sep 28 2020 at 21:05, Edward Cree wrote:
>>> Only compile-tested so far, because I'm waiting for my kernel to
>>>  finish rebuilding with CONFIG_DEBUG_ATOMIC_SLEEP
>
> I've now tested and confirmed that the might_sleep warning goes
>  away with this patch.
>
> Thomas, do you want to pull it into v2 of your series, or should
>  I submit it separately to David?

I have it already, but if Dave applies it right away, that's fine.

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2020-09-29 19:27 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-27 19:48 [patch 00/35] net: in_interrupt() cleanup and fixes Thomas Gleixner
2020-09-27 19:48 ` [patch 01/35] net: enic: Cure the enic api locking trainwreck Thomas Gleixner
2020-09-27 19:48 ` [patch 02/35] net: caif: Remove unused caif SPI driver Thomas Gleixner
2020-09-27 19:48 ` [patch 03/35] net: Add netif_rx_any_context() Thomas Gleixner
2020-09-27 19:48 ` [patch 04/35] net: caif: Use netif_rx_any_context() Thomas Gleixner
2020-09-27 19:48 ` [patch 05/35] net: atheros: Remove WARN_ON(in_interrupt()) Thomas Gleixner
2020-09-27 19:48 ` [patch 06/35] net: cxgb3: Cleanup in_interrupt() usage Thomas Gleixner
2020-09-27 19:48 ` [patch 07/35] net: cxbg4: Remove pointless in_interrupt() check Thomas Gleixner
2020-09-27 19:48 ` [patch 08/35] net: e100: Remove in_interrupt() usage and pointless GFP_ATOMIC allocation Thomas Gleixner
2020-09-27 19:48 ` [patch 09/35] net: fec_mpc52xx: Replace in_interrupt() usage Thomas Gleixner
2020-09-27 19:48 ` [patch 10/35] net: intel: Remove in_interrupt() warnings Thomas Gleixner
2020-09-28 23:04   ` Alexander Duyck
2020-09-27 19:48 ` [patch 11/35] net: ionic: Replace in_interrupt() usage Thomas Gleixner
2020-09-28 17:24   ` Shannon Nelson
2020-09-28 19:51     ` Shannon Nelson
2020-09-29 14:37       ` Thomas Gleixner
2020-09-27 19:48 ` [patch 12/35] net: ionic: Remove WARN_ON(in_interrupt()) Thomas Gleixner
2020-09-28 17:26   ` Shannon Nelson
2020-09-27 19:48 ` [patch 13/35] net: mdiobus: Remove WARN_ON_ONCE(in_interrupt()) Thomas Gleixner
2020-09-27 23:00   ` Andrew Lunn
2020-09-27 19:49 ` [patch 14/35] net: natsemi: Replace in_interrupt() usage Thomas Gleixner
2020-09-27 19:49 ` [patch 15/35] net: sfc: " Thomas Gleixner
2020-09-28 19:03   ` Edward Cree
2020-09-28 20:05     ` [RFC PATCH net-next] sfc: replace " Edward Cree
2020-09-28 20:24       ` Thomas Gleixner
2020-09-29 15:15         ` Edward Cree
2020-09-29 19:27           ` Thomas Gleixner
2020-09-29  9:39       ` Martin Habets
2020-09-27 19:49 ` [patch 16/35] net: sunbmac: Replace " Thomas Gleixner
2020-09-27 19:49 ` [patch 17/35] net: sun3lance: Remove redundant checks in interrupt handler Thomas Gleixner
2020-09-27 19:49 ` [patch 18/35] net: vxge: Remove in_interrupt() conditionals Thomas Gleixner
2020-09-27 19:49 ` [patch 19/35] net: zd1211rw: Remove ZD_ASSERT(in_interrupt()) Thomas Gleixner
2020-09-27 19:49 ` [patch 20/35] net: usb: kaweth: Replace kaweth_control() with usb_control_msg() Thomas Gleixner
2020-09-27 19:49 ` [patch 21/35] net: usb: kaweth: Remove last user of kaweth_control() Thomas Gleixner
2020-09-28  6:50   ` Greg Kroah-Hartman
2020-09-27 19:49 ` [patch 22/35] net: usb: net1080: Remove in_interrupt() comment Thomas Gleixner
2020-09-27 19:49 ` [patch 23/35] net: wan/lmc: Remove lmc_trace() Thomas Gleixner
2020-09-27 19:49 ` [patch 24/35] net: brcmfmac: Replace in_interrupt() Thomas Gleixner
2020-09-28  7:35   ` Arend Van Spriel
2020-09-28  9:19     ` Ulf Hansson
2020-09-28  9:37       ` Arend Van Spriel
2020-09-28  9:40   ` Arend Van Spriel
2020-09-27 19:49 ` [patch 25/35] net: brcmfmac: Use netif_rx_any_context() Thomas Gleixner
2020-09-28  8:03   ` Arend Van Spriel
2020-09-27 19:49 ` [patch 26/35] net: brcmfmac: Convey allocation mode as argument Thomas Gleixner
2020-09-28  9:34   ` Arend Van Spriel
2020-09-27 19:49 ` [patch 27/35] net: ipw2x00,iwlegacy,iwlwifi: Remove in_interrupt() from debug macros Thomas Gleixner
2020-09-27 19:49 ` [patch 28/35] net: iwlwifi: Remove in_interrupt() from tracing macro Thomas Gleixner
2020-09-28  6:13   ` Coelho, Luciano
2020-09-27 19:49 ` [patch 29/35] net: hostap: Remove in_interrupt() usage Thomas Gleixner
2020-09-27 19:49 ` [patch 30/35] net: mwifiex: Use netif_rx_any_context() Thomas Gleixner
2020-09-27 19:49 ` [patch 31/35] net: libertas libertas_tf: Remove in_interrupt() from debug macro Thomas Gleixner
2020-09-27 19:49 ` [patch 32/35] net: libertas: Use netif_rx_any_context() Thomas Gleixner
2020-09-27 19:49 ` [patch 33/35] net: rtlwifi: Remove void* casts related to delayed work Thomas Gleixner
2020-09-27 19:49 ` [patch 34/35] net: rtlwifi: Remove in_interrupt() from debug macro Thomas Gleixner
2020-09-27 19:49 ` [patch 35/35] net: rtlwifi: Replace in_interrupt() for context detection Thomas Gleixner
2020-09-27 20:22 ` [patch 00/35] net: in_interrupt() cleanup and fixes Joe Perches
2020-09-27 20:57 ` David Miller
2020-09-28 10:25   ` Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).