diff options
author | David S. Miller <davem@davemloft.net> | 2020-09-30 00:02:55 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-09-30 00:02:55 +0300 |
commit | e6b6be53ec91461c5ecf41a66f54f5869fd989b9 (patch) | |
tree | a733dac12348cbbce4a851dfc1e8ce8916f39b17 | |
parent | 2ec13cbcfadbbeac499f3b63de0f7db490d45a7e (diff) | |
parent | 920872e08391a8efb83077a3b3d9b1097682ca80 (diff) | |
download | linux-e6b6be53ec91461c5ecf41a66f54f5869fd989b9.tar.xz |
Merge branch 'net-in_interrupt-cleanup-and-fixes'
Thomas Gleixner says:
====================
net: in_interrupt() cleanup and fixes
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.
This is the second version of the first batch of related changes. V1 can be
found here:
https://lore.kernel.org/r/20200927194846.045411263@linutronix.de
Changes vs. V1:
- Rebased to net-next
- Fixed the half done rename sillyness in the ENIC patch.
- Fixed the IONIC driver fallout.
- Picked up the SFC fix from Edward and adjusted the GFP_KERNEL change
accordingly.
- Addressed the review comments vs. BCRFMAC.
- Collected Reviewed/Acked-by tags as appropriate.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
89 files changed, 354 insertions, 2234 deletions
diff --git a/Documentation/networking/caif/index.rst b/Documentation/networking/caif/index.rst index 86e5b7832ec3..ec29b6f4bdb4 100644 --- a/Documentation/networking/caif/index.rst +++ b/Documentation/networking/caif/index.rst @@ -10,4 +10,3 @@ Contents: linux_caif caif - spi_porting diff --git a/Documentation/networking/caif/spi_porting.rst b/Documentation/networking/caif/spi_porting.rst deleted file mode 100644 index d49f874b20ac..000000000000 --- 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); diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig index c245edddb48b..a77124bc1f4b 100644 --- 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 diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile index 54ae1165d60a..b1918c8c126c 100644 --- 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 diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c index 4a33ec4fc089..3d63b15bbaa1 100644 --- 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_desc *desc, struct cfhsi *cfhsi) 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_desc *desc, struct cfhsi *cfhsi) 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++; diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c deleted file mode 100644 index 7d5899626130..000000000000 --- 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); diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c deleted file mode 100644 index bb776d33dd8f..000000000000 --- 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, - }, -}; diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c index e1fde585fd0d..00ae1081254d 100644 --- a/drivers/net/ethernet/amd/sun3lance.c +++ b/drivers/net/ethernet/amd/sun3lance.c @@ -657,16 +657,6 @@ static irqreturn_t lance_interrupt( int irq, void *dev_id) 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 irq, void *dev_id) DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n", dev->name, DREG )); - in_interrupt = 0; return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 00de463268a8..0c12cf7bda50 100644 --- 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 timer_list *t) void atl1c_reinit_locked(struct atl1c_adapter *adapter) { - WARN_ON(in_interrupt()); atl1c_down(adapter); atl1c_up(adapter); clear_bit(__AT_RESETTING, &adapter->flags); diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index e43f71849daf..098b0328e3cb 100644 --- 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 timer_list *t) 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); diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index 021fb0e6417a..7b80d924632a 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -1086,7 +1086,6 @@ err_up: 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); diff --git a/drivers/net/ethernet/chelsio/cxgb3/adapter.h b/drivers/net/ethernet/chelsio/cxgb3/adapter.h index 087ff0ffb597..f80fbd81b609 100644 --- 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 *adapter, int port_id, int state); 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); diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 6ed58bc12020..84ad7261e243 100644 --- 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 *adapter) 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); diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 5bb3f0cb36ed..e18e9ce27f94 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -3270,30 +3270,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; - for (i = 0; i < SGE_QSETS; ++i) { - struct sge_qset *qs = &adap->sge.qs[i]; + t3_sge_stop_dma(adap); - tasklet_kill(&qs->txq[TXQ_OFLD].qresume_tsk); - tasklet_kill(&qs->txq[TXQ_CTRL].qresume_tsk); - } + 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); } } diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 2b942b4825d4..54e22f17af3d 100644 --- 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) diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index 18f3aeb88f22..c67a16a48d62 100644 --- 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 */ diff --git a/drivers/net/ethernet/cisco/enic/enic_api.c b/drivers/net/ethernet/cisco/enic/enic_api.c index 89915681473c..3bdc74fba1e3 100644 --- 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(struct net_device *netdev, int vf, 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); diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 4f0329d8778f..fb269d587b74 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -2107,8 +2107,6 @@ static int enic_dev_wait(struct vnic_dev *vdev, int done; int err; - BUG_ON(in_interrupt()); - err = start(vdev, arg); if (err) return err; @@ -2297,6 +2295,13 @@ static int enic_set_rss_nic_cfg(struct enic *enic) 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); @@ -2306,7 +2311,9 @@ static void enic_reset(struct work_struct *work) rtnl_lock(); - spin_lock(&enic->enic_api_lock); + /* Stop any activity from infiniband */ + enic_set_api_busy(enic, true); + enic_stop(enic->netdev); enic_dev_soft_reset(enic); enic_reset_addr_lists(enic); @@ -2314,7 +2321,10 @@ static void enic_reset(struct work_struct *work) 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_busy(enic, false); + call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev); rtnl_unlock(); @@ -2326,7 +2336,9 @@ static void enic_tx_hang_reset(struct work_struct *work) rtnl_lock(); - spin_lock(&enic->enic_api_lock); + /* Stop any activity from infiniband */ + enic_set_api_busy(enic, true); + enic_dev_hang_notify(enic); enic_stop(enic->netdev); enic_dev_hang_reset(enic); @@ -2335,7 +2347,10 @@ static void enic_tx_hang_reset(struct work_struct *work) 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_busy(enic, false); + call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev); rtnl_unlock(); diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index 7a3f066e611d..b3bad429e03b 100644 --- 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_device *dev) 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_device *dev) * * 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_device *dev) 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_device *dev) 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); diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 76bb77b4607a..8cc651d37a7f 100644 --- 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) 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++) { diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 906591614553..5e28cf4fa2cd 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -536,7 +536,6 @@ void e1000_down(struct e1000_adapter *adapter) void e1000_reinit_locked(struct e1000_adapter *adapter) { - WARN_ON(in_interrupt()); while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) msleep(1); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 140212bfe08b..9e3103fae723 100644 --- 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(struct fm10k_intfc *interface) { struct net_device *netdev = interface->netdev; - WARN_ON(in_interrupt()); - /* put off any impending NetWatchDogTimeout */ netif_trans_update(netdev); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 70bd3f47e43a..929c64789119 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6691,7 +6691,6 @@ static void i40e_vsi_reinit_locked(struct i40e_vsi *vsi) { 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); @@ -8464,9 +8463,6 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired) { u32 val; - WARN_ON(in_interrupt()); - - /* do the biggest reset indicated */ if (reset_flags & BIT_ULL(__I40E_GLOBAL_RESET_REQUESTED)) { diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index ffef4c901ea2..1d74466ce77f 100644 --- 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 *pf, enum ice_reset_req reset_type) 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); diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 368f950f68b1..5fc2c381da55 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2221,7 +2221,6 @@ void igb_down(struct igb_adapter *adapter) 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); diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 569747bbefd8..9112dff075cf 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -3833,7 +3833,6 @@ void igc_down(struct igc_adapter *adapter) 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); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 02899f79f0ff..a190d5c616fc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -5672,7 +5672,6 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter) void ixgbe_reinit_locked(struct ixgbe_adapter *adapter) { - WARN_ON(in_interrupt()); /* put off any impending NetWatchDogTimeout */ netif_trans_update(adapter->netdev); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index ba54c728aef2..82fce27f682b 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -2522,8 +2522,6 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter) void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter) { - WARN_ON(in_interrupt()); - while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) msleep(1); diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index dd3605aa5f23..d17d1b4f2585 100644 --- 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 *dev) /* * 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 *dev) } /* 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_device *dev, u16 mask) 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 *dev) * 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_device *dev, unsigned int txqueue) * 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_device *dev, unsigned int txqueue) } } /* 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 net_device *dev) /* 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 net_device *dev) /* * 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 *dev) */ 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 *dev) 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 *dev) * 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 diff --git a/drivers/net/ethernet/natsemi/sonic.h b/drivers/net/ethernet/natsemi/sonic.h index 3cbb62c860c8..a5b803eb8c8a 100644 --- 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 *dev); 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); diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c index 6aba267036dd..f5d48d7c4ce2 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-config.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c @@ -2306,16 +2306,9 @@ exit: 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); } diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.h b/drivers/net/ethernet/neterion/vxge/vxge-config.h index 373165119850..0cd0750484ae 100644 --- 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(struct pci_dev *pdev, 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, diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c index 6068f51a11d9..a02f710200da 100644 --- 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 timer_list *t) hb = ionic_heartbeat_check(ionic); if (hb >= 0 && ionic->lif) - ionic_link_status_check_request(ionic->lif); + ionic_link_status_check_request(ionic->lif, false); } void ionic_init_devinfo(struct ionic *ionic) diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index eb6fe37c0df6..1b4d5eb9bbc9 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -151,7 +151,7 @@ static void ionic_link_status_check(struct ionic_lif *lif) 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; @@ -159,7 +159,7 @@ void ionic_link_status_check_request(struct ionic_lif *lif) 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; @@ -798,7 +798,7 @@ static bool ionic_notifyq_service(struct ionic_cq *cq, 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); @@ -981,7 +981,8 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr) 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; @@ -1010,7 +1011,7 @@ static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add) lif->nucast--; } - if (in_interrupt()) { + if (!can_sleep) { work = kzalloc(sizeof(*work), GFP_ATOMIC); if (!work) { netdev_err(lif->netdev, "%s OOM\n", __func__); @@ -1036,12 +1037,22 @@ static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add) 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, true); +} + +static int ionic_ndo_addr_add(struct net_device *netdev, const u8 *addr) +{ + 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, true); +} + +static int ionic_ndo_addr_del(struct net_device *netdev, const u8 *addr) +{ + return ionic_lif_addr(netdev_priv(netdev), addr, false, false); } static void ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode) @@ -1081,11 +1092,12 @@ static void ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode) lif->rx_mode = rx_mode; } -static void _ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode) +static void _ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode, + bool from_ndo) { struct ionic_deferred_work *work; - if (in_interrupt()) { + if (from_ndo) { work = kzalloc(sizeof(*work), GFP_ATOMIC); if (!work) { netdev_err(lif->netdev, "%s OOM\n", __func__); @@ -1100,7 +1112,16 @@ static void _ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode) } } -static void ionic_set_rx_mode(struct net_device *netdev) +static void ionic_dev_uc_sync(struct net_device *netdev, bool from_ndo) +{ + if (from_ndo) + __dev_uc_sync(netdev, ionic_ndo_addr_add, ionic_ndo_addr_del); + else + __dev_uc_sync(netdev, ionic_addr_add, ionic_addr_del); + +} + +static void ionic_set_rx_mode(struct net_device *netdev, bool from_ndo) { struct ionic_lif *lif = netdev_priv(netdev); struct ionic_identity *ident; @@ -1122,7 +1143,7 @@ static void ionic_set_rx_mode(struct net_device *netdev) * we remove our overflow flag and check the netdev flags * to see if we can disable NIC PROMISC */ - __dev_uc_sync(netdev, ionic_addr_add, ionic_addr_del); + ionic_dev_uc_sync(netdev, from_ndo); nfilters = le32_to_cpu(ident->lif.eth.max_ucast_filters); if (netdev_uc_count(netdev) + 1 > nfilters) { rx_mode |= IONIC_RX_MODE_F_PROMISC; @@ -1134,7 +1155,7 @@ static void ionic_set_rx_mode(struct net_device *netdev) } /* same for multicast */ - __dev_mc_sync(netdev, ionic_addr_add, ionic_addr_del); + ionic_dev_uc_sync(netdev, from_ndo); nfilters = le32_to_cpu(ident->lif.eth.max_mcast_filters); if (netdev_mc_count(netdev) > nfilters) { rx_mode |= IONIC_RX_MODE_F_ALLMULTI; @@ -1146,7 +1167,12 @@ static void ionic_set_rx_mode(struct net_device *netdev) } if (lif->rx_mode != rx_mode) - _ionic_lif_rx_mode(lif, rx_mode); + _ionic_lif_rx_mode(lif, rx_mode, from_ndo); +} + +static void ionic_ndo_set_rx_mode(struct net_device *netdev) +{ + ionic_set_rx_mode(netdev, true); } static __le64 ionic_netdev_features_to_nic(netdev_features_t features) @@ -1391,7 +1417,7 @@ static int ionic_start_queues_reconfig(struct ionic_lif *lif) */ err = ionic_txrx_init(lif); mutex_unlock(&lif->queue_lock); - ionic_link_status_check_request(lif); + ionic_link_status_check_request(lif, true); netif_device_attach(lif->netdev); return err; @@ -1720,7 +1746,7 @@ static int ionic_txrx_init(struct ionic_lif *lif) if (lif->netdev->features & NETIF_F_RXHASH) ionic_lif_rss_init(lif); - ionic_set_rx_mode(lif->netdev); + ionic_set_rx_mode(lif->netdev, false); return 0; @@ -2093,7 +2119,7 @@ static const struct net_device_ops ionic_netdev_ops = { .ndo_stop = ionic_stop, .ndo_start_xmit = ionic_start_xmit, .ndo_get_stats64 = ionic_get_stats64, - .ndo_set_rx_mode = ionic_set_rx_mode, + .ndo_set_rx_mode = ionic_ndo_set_rx_mode, .ndo_set_features = ionic_set_features, .ndo_set_mac_address = ionic_set_mac_address, .ndo_validate_addr = eth_validate_addr, @@ -2521,7 +2547,7 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif) } 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"); @@ -2713,7 +2739,7 @@ static int ionic_station_set(struct ionic_lif *lif) */ 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); @@ -2730,7 +2756,7 @@ static int ionic_station_set(struct ionic_lif *lif) 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; } diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h index c65a5e6c26f4..0224dfd24b8a 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h @@ -245,7 +245,7 @@ static inline u32 ionic_coal_usec_to_hw(struct ionic *ionic, u32 usecs) 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, diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c index e339216949a6..c7a67c5cda42 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c @@ -255,8 +255,6 @@ static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) struct ionic_queue *q; int err = 0; - WARN_ON(in_interrupt()); - if (!lif->adminqcq) return -EIO; @@ -328,8 +326,6 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds) 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. */ diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index c9df2e96ebe4..da6886dcac37 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1871,18 +1871,9 @@ 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); + rc = efx_nic_alloc_buffer(efx, &stats_buf, dma_len, GFP_KERNEL); if (rc) { spin_lock_bh(&efx->stats_lock); return rc; @@ -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 diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index 34fdbc6d6031..c646575e79d5 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c @@ -209,13 +209,13 @@ static void bigmac_clean_rings(struct bigmac *bp) } } -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 bigmac *bp) } } -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_list *t) 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_negotiation(struct bigmac *bp) 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 *bp, int from_irq) 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 bigmac *bp, u32 qec_status, u32 bmac_st } 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 *dev) 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_device *dev, unsigned int txqueue) { struct bigmac *bp = netdev_priv(dev); - bigmac_init_hw(bp, 0); + bigmac_init_hw(bp, true); netif_wake_queue(dev); } diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 0af20faad69d..757e950fb745 100644 --- 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 *bus, int addr, u32 regnum) { 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, int addr, u32 regnum) { 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 *bus, int addr, u32 regnum, u16 val) { 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, int addr, u32 regnum, u16 val) { 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 addr, u32 regnum, u16 mask, u16 set) { 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); diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index ed01dc964c99..144c686b4333 100644 --- 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,65 +232,17 @@ 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) { - 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 +250,14 @@ static int kaweth_read_configuration(struct kaweth_device *kaweth) ****************************************************************/ 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 +265,14 @@ static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size) ****************************************************************/ 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 +281,15 @@ static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait) 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 +334,11 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth, 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 +357,12 @@ static int kaweth_trigger_firmware(struct kaweth_device *kaweth, 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); } /**************************************************************** @@ -564,7 +485,8 @@ static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, 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 @@ -694,7 +616,7 @@ static int kaweth_open(struct net_device *net) netif_start_queue(net); - kaweth_async_set_rx_mode(kaweth); + kaweth_async_set_rx_mode(kaweth, true); return 0; err_out: @@ -782,7 +704,7 @@ static netdev_tx_t kaweth_start_xmit(struct sk_buff *skb, 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; @@ -859,36 +781,31 @@ static void kaweth_set_rx_mode(struct net_device *net) /**************************************************************** * 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); - } } /**************************************************************** @@ -1196,88 +1113,4 @@ static void kaweth_disconnect(struct usb_interface *intf) } -// 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); diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index 1f04f1720426..b0c0c9dd6a02 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -113,7 +113,6 @@ nc_register_read(struct usbnet *dev, u8 regnum, u16 *retval_ptr) 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) { diff --git a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c index f999db788506..2b6051bda3fb 100644 --- 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, u32 arg3) } #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 ------------------------ */ diff --git a/drivers/net/wan/lmc/lmc_debug.h b/drivers/net/wan/lmc/lmc_debug.h index 820adcae5d67..cfae9eddf003 100644 --- a/drivers/net/wan/lmc/lmc_debug.h +++ b/drivers/net/wan/lmc/lmc_debug.h @@ -48,6 +48,5 @@ extern u32 lmcEventLogBuf[LMC_EVENTLOGSIZE * LMC_EVENTLOGARGS]; 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 diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 842def21e089..36600b0a0ab0 100644 --- 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, struct ifreq *ifr, int cmd) /*fold00*/ 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, struct ifreq *ifr, int cmd) /*fold00*/ break; } - lmc_trace(dev, "lmc_ioctl out"); - return ret; } @@ -634,8 +630,6 @@ static void lmc_watchdog(struct timer_list *t) /*fold00*/ 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 @@ kick_timer: 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 *pdev, const struct pci_device_id *ent) 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 *pdev, const struct pci_device_id *ent) 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 *dev) 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 *dev) 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 *dev) 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 net_device *dev) /*fold00*/ { 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 net_device *dev) /*fold00*/ 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 *dev) /* 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 *dev) /*fold00*/ 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 *dev) /*fold00*/ 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 irq, void *dev_instance) /*fold00*/ 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 irq, void *dev_instance) /*fold00*/ 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 @@ lmc_int_fail_out: 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 sk_buff *skb, 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 sk_buff *skb, 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_stats(struct net_device *dev) 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 * const sc, unsigned devaddr, unsigned reg 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 * const sc, unsigned devaddr, unsigned reg /* __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 * const sc, unsigned devaddr, unsigned reg /* __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 * const sc, unsigned devaddr, unsigned regno, 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 * const sc, unsigned devaddr, unsigned regno, /* __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 * const sc) /*fold00*/ } 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 * const sc) /*fold00*/ 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 * const sc) /*fold00*/ 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 * const sc, lmc_csrptr_t csr_base, /*fold00 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 net_device *dev, unsigned int txqueue) 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 net_device *dev, unsigned int txqueue) bug_out: spin_unlock_irqrestore(&sc->lmc_lock, flags); - - lmc_trace(dev, "lmc_driver_timeout out"); - - } diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c index 23ca4a62d6f5..ec1ac7b1f3fd 100644 --- 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 * const sc) * 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 * const sc) 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; } diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c index a58301dd0c1f..e8b0b902b424 100644 --- 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) /*FOLD00*/ 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 @@ __be16 lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/ 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, struct sk_buff *skb) /*FOLD00*/ case LMC_RAW: break; } - lmc_trace(sc->lmc_device, "lmc_proto_netif out"); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 2c95a08a5871..3984fd7d918e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -397,9 +397,9 @@ brcmf_proto_bcdc_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, } static void brcmf_proto_bcdc_rxreorder(struct brcmf_if *ifp, - struct sk_buff *skb) + struct sk_buff *skb, bool inirq) { - brcmf_fws_rxreorder(ifp, skb); + brcmf_fws_rxreorder(ifp, skb, inirq); } static void diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 318bd00bf94f..f9ebb98b0e3c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -74,7 +74,7 @@ static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id) sdiodev->irq_en = false; } - brcmf_sdio_isr(sdiodev->bus); + brcmf_sdio_isr(sdiodev->bus, true); return IRQ_HANDLED; } @@ -86,7 +86,7 @@ static void brcmf_sdiod_ib_irqhandler(struct sdio_func *func) 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 */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 623c0168da79..08f9d47f2e5c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -249,7 +249,8 @@ int brcmf_bus_reset(struct brcmf_bus *bus) */ /* 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, + bool inirq); /* Receive async event packet from firmware. Callee disposes of rxp. */ void brcmf_rx_event(struct device *dev, struct sk_buff *rxp); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index aa9ced3c86fb..4ac1e4fb7812 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -395,7 +395,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, spin_unlock_irqrestore(&ifp->netif_stop_lock, flags); } -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, bool inirq) { /* Most of Broadcom's firmwares send 802.11f ADD frame every time a new * STA connects to the AP interface. This is an obsoleted standard most @@ -418,14 +418,15 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) ifp->ndev->stats.rx_packets++; brcmf_dbg(DATA, "rx proto=0x%X\n", ntohs(skb->protocol)); - if (in_interrupt()) + if (inirq) { netif_rx(skb); - else + } 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); + } } void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb) @@ -474,7 +475,7 @@ void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb) skb->pkt_type = PACKET_OTHERHOST; skb->protocol = htons(ETH_P_802_2); - brcmf_netif_rx(ifp, skb); + brcmf_netif_rx(ifp, skb, false); } static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb, @@ -496,7 +497,8 @@ static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb, 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, + bool inirq) { struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -508,14 +510,16 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event) return; if (brcmf_proto_is_reorder_skb(skb)) { - brcmf_proto_rxreorder(ifp, skb); + brcmf_proto_rxreorder(ifp, skb, inirq); } else { /* Process special event packets */ - if (handle_event) - brcmf_fweh_process_skb(ifp->drvr, skb, - BCMILCP_SUBTYPE_VENDOR_LONG); + if (handle_event) { + gfp_t gfp = inirq ? GFP_ATOMIC : GFP_KERNEL; - brcmf_netif_rx(ifp, skb); + brcmf_fweh_process_skb(ifp->drvr, skb, + BCMILCP_SUBTYPE_VENDOR_LONG, gfp); + } + brcmf_netif_rx(ifp, skb, inirq); } } @@ -530,7 +534,7 @@ void brcmf_rx_event(struct device *dev, struct sk_buff *skb) 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_KERNEL); brcmu_pkt_buf_free_skb(skb); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 33b2ab3b54b0..5767d665cee5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -208,7 +208,7 @@ void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked); void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state); void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); -void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); +void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, bool inirq); void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb); void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked); int brcmf_net_mon_attach(struct brcmf_if *ifp); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index 3bdbb285b3aa..c847062dd393 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c @@ -388,12 +388,11 @@ 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) { 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; @@ -412,10 +411,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, 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; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h index a82f51bc1e69..48414e8b9389 100644 --- 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_pub *drvr, 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_skb(struct brcmf_pub *drvr, 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_ */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index 775e0612fa17..437e83ea8902 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -1664,7 +1664,7 @@ static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi, rfi->pend_pkts -= skb_queue_len(skb_list); } -void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) +void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt, bool inirq) { struct brcmf_pub *drvr = ifp->drvr; u8 *reorder_data; @@ -1682,7 +1682,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) /* validate flags and flow id */ if (flags == 0xFF) { bphy_err(drvr, "invalid flags...so ignore this packet\n"); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, inirq); return; } @@ -1694,7 +1694,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) if (rfi == NULL) { brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n", flow_id); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, inirq); return; } @@ -1719,7 +1719,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) rfi = kzalloc(buf_size, GFP_ATOMIC); if (rfi == NULL) { bphy_err(drvr, "failed to alloc buffer\n"); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, inirq); return; } @@ -1833,7 +1833,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) netif_rx: skb_queue_walk_safe(&reorder_list, pkt, pnext) { __skb_unlink(pkt, &reorder_list); - brcmf_netif_rx(ifp, pkt); + brcmf_netif_rx(ifp, pkt, inirq); } } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h index b16a9d1c0508..50e424b5880d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h @@ -42,6 +42,6 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp); void brcmf_fws_del_interface(struct brcmf_if *ifp); void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb); void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked); -void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb); +void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb, bool inirq); #endif /* FWSIGNAL_H_ */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index bfddb851e386..7c8e08ee8f0f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -536,7 +536,8 @@ static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws, return -ENODEV; } -static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb) +static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb, + bool inirq) { } @@ -1128,7 +1129,7 @@ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf) 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); @@ -1190,7 +1191,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) } skb->protocol = eth_type_trans(skb, ifp->ndev); - brcmf_netif_rx(ifp, skb); + brcmf_netif_rx(ifp, skb, false); } static void brcmf_msgbuf_process_gen_status(struct brcmf_msgbuf *msgbuf, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h index bd08d3aaa8f4..f4a79e217da5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h @@ -32,7 +32,7 @@ struct brcmf_proto { u8 peer[ETH_ALEN]); void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN]); - void (*rxreorder)(struct brcmf_if *ifp, struct sk_buff *skb); + void (*rxreorder)(struct brcmf_if *ifp, struct sk_buff *skb, bool inirq); void (*add_if)(struct brcmf_if *ifp); void (*del_if)(struct brcmf_if *ifp); void (*reset_if)(struct brcmf_if *ifp); @@ -109,9 +109,9 @@ static inline bool brcmf_proto_is_reorder_skb(struct sk_buff *skb) } static inline void -brcmf_proto_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb) +brcmf_proto_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb, bool inirq) { - ifp->drvr->proto->rxreorder(ifp, skb); + ifp->drvr->proto->rxreorder(ifp, skb, inirq); } static inline void diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index d4989e0cd7be..99987a789e7e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1704,7 +1704,7 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq) brcmf_rx_event(bus->sdiodev->dev, pfirst); else brcmf_rx_frame(bus->sdiodev->dev, pfirst, - false); + false, false); bus->sdcnt.rxglompkts++; } @@ -2038,7 +2038,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) brcmf_rx_event(bus->sdiodev->dev, pkt); else brcmf_rx_frame(bus->sdiodev->dev, pkt, - false); + false, false); /* prepare the descriptor for the next read */ rd->len = rd->len_nxtfrm << 4; @@ -3625,7 +3625,7 @@ void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus) } } -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 *bus) /* 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)) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h index 12108927fb50..15d2c02fa3ec 100644 --- 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_dev *sdiodev); 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); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 6f67fefe4b58..586f4dfc638b 100644 --- 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 urb *urb) 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, true); brcmf_usb_rx_refill(devinfo, req); usb_mark_last_busy(urb->dev); } else { diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index b7fbfc77b612..23fbddd0c1f8 100644 --- 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_NONE; #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) diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.h b/drivers/net/wireless/intel/ipw2x00/ipw2200.h index e1ec1c96dcd8..98fe62737888 100644 --- 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 */ diff --git a/drivers/net/wireless/intel/ipw2x00/libipw.h b/drivers/net/wireless/intel/ipw2x00/libipw.h index e87538a8b88b..7964ef7d15f0 100644 --- 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 */ diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h index bc9cd7e5ccb8..ea1b1bb7ddcb 100644 --- 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) \ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c index e1a41fd503a8..7df173cc9ddc 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.c @@ -121,10 +121,9 @@ 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); + trace_iwlwifi_dbg(level, function, &vaf); va_end(args); } IWL_EXPORT_SYMBOL(__iwl_dbg); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h index 9ad93ef60890..d0467da5af03 100644 --- 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_crit, ); 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, diff --git a/drivers/net/wireless/intersil/hostap/hostap_hw.c b/drivers/net/wireless/intersil/hostap/hostap_hw.c index 01a2dd0edd71..22cfb6452644 100644 --- 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 *dev, u16 cmd, u16 param0, 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_device *dev) 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; diff --git a/drivers/net/wireless/marvell/libertas/defs.h b/drivers/net/wireless/marvell/libertas/defs.h index 58e2ead7b0cc..f7e7bf56f924 100644 --- 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 diff --git a/drivers/net/wireless/marvell/libertas/rx.c b/drivers/net/wireless/marvell/libertas/rx.c index f28aa09d1f9e..9f24b0760e1f 100644 --- 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_private *priv, struct sk_buff *skb) 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(struct lbs_private *priv, 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; diff --git a/drivers/net/wireless/marvell/libertas_tf/deb_defs.h b/drivers/net/wireless/marvell/libertas_tf/deb_defs.h index 37a98e228b46..0b520df62f1f 100644 --- 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 diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index 77c8595f84f8..9bbdb8dfce62 100644 --- 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 mwifiex_private *priv, 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; } diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c index de89a1e710b1..d583fa600a29 100644 --- 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_private *priv, struct sk_buff *skb) (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; } diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 8e6f07b3c87e..6e8bd99e8911 100644 --- 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 ieee80211_hw *hw) } } +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(struct ieee80211_hw *hw) } 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) @@ -1455,7 +1456,7 @@ static void setup_special_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc, 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; } @@ -1545,7 +1546,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, 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); @@ -2042,11 +2043,10 @@ label_err: } 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)); @@ -2147,9 +2147,9 @@ void rtl_watchdog_wq_callback(void *data) 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: ; @@ -2239,10 +2239,10 @@ void rtl_watch_dog_timer_callback(struct timer_list *t) 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 ieee80211_hw *hw, int exec) } } -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); diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h index fa92e29fffda..0e4f8a8ae3a5 100644 --- 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 *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); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c index fa4486669d9a..2c05369b79e4 100644 --- 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_coexist *btcoexist) 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_coexist *btcoexist) 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_coexist *btcoexist) 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 btc_coexist *btcoexist) 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); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 2529b6e0fd76..a7259dbc953d 100644 --- 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 ieee80211_hw *hw, 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(struct ieee80211_hw *hw, 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 ieee80211_hw *hw, } 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); diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c index 455b87e7548b..901cdfe3723c 100644 --- 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_out(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_out); - void _rtl_dbg_print(struct rtl_priv *rtlpriv, u64 comp, int level, const char *fmt, ...) { diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h index 6028f1ffa5da..1c0bcf8ec1a9 100644 --- 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_out(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, ...); @@ -160,8 +156,8 @@ void _rtl_dbg_print_data(struct rtl_priv *rtlpriv, u64 comp, int level, const char *titlestring, const void *hexdata, int hexdatalen); -#define rtl_dbg(rtlpriv, comp, level, fmt, ...) \ - _rtl_dbg_out(rtlpriv, comp, level, \ +#define rtl_dbg(rtlpriv, comp, level, fmt, ...) \ + _rtl_dbg_print(rtlpriv, comp, level, \ fmt, ##__VA_ARGS__) #define RTPRINT(rtlpriv, dbgtype, dbgflag, fmt, ...) \ diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index d9f901111e58..3776495fd9d0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -621,7 +621,7 @@ tx_status_ok: 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, @@ -874,7 +874,7 @@ new_trx_end: 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) { diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c index 38442a36f599..f99882255d48 100644 --- 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 ieee80211_hw *hw) 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_hw *hw) 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); @@ -653,33 +653,32 @@ void rtl_lps_change_work_callback(struct work_struct *work) } 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); } 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; diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.h b/drivers/net/wireless/realtek/rtlwifi/ps.h index aaa2ed2bbe16..b37a929def82 100644 --- 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_hw *hw); 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_lps_enter(struct ieee80211_hw *hw); -void rtl_lps_leave(struct ieee80211_hw *hw); +void rtl_ips_nic_off_wq_callback(struct work_struct *work); +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); 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); diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 13421cf2d201..7e80fd829014 100644 --- 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); diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c index 71ec3d4231ef..66367ab7e4c1 100644 --- 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(struct urb *urb) 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)); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a431c3229cbf..28cfa53daf72 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3785,6 +3785,7 @@ void generic_xdp_tx(struct sk_buff *skb, struct bpf_prog *xdp_prog); 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); diff --git a/include/net/caif/caif_spi.h b/include/net/caif/caif_spi.h deleted file mode 100644 index a0bf4cbce71b..000000000000 --- 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_ */ diff --git a/net/core/dev.c b/net/core/dev.c index 873b50ac9668..9d55bf5d1a65 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4841,6 +4841,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); |