summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0134-net-arcnet-Fix-RESET-flag-handling.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0134-net-arcnet-Fix-RESET-flag-handling.patch')
-rw-r--r--debian/patches-rt/0134-net-arcnet-Fix-RESET-flag-handling.patch311
1 files changed, 0 insertions, 311 deletions
diff --git a/debian/patches-rt/0134-net-arcnet-Fix-RESET-flag-handling.patch b/debian/patches-rt/0134-net-arcnet-Fix-RESET-flag-handling.patch
deleted file mode 100644
index 40b434c29..000000000
--- a/debian/patches-rt/0134-net-arcnet-Fix-RESET-flag-handling.patch
+++ /dev/null
@@ -1,311 +0,0 @@
-From c2f66dc3c8f543d063d97b003766809857f320c2 Mon Sep 17 00:00:00 2001
-From: "Ahmed S. Darwish" <a.darwish@linutronix.de>
-Date: Thu, 28 Jan 2021 20:48:02 +0100
-Subject: [PATCH 134/296] net: arcnet: Fix RESET flag handling
-Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.10/older/patches-5.10.35-rt39.tar.xz
-
-The main arcnet interrupt handler calls arcnet_close() then
-arcnet_open(), if the RESET status flag is encountered.
-
-This is invalid:
-
- 1) In general, interrupt handlers should never call ->ndo_stop() and
- ->ndo_open() functions. They are usually full of blocking calls and
- other methods that are expected to be called only from drivers
- init and exit code paths.
-
- 2) arcnet_close() contains a del_timer_sync(). If the irq handler
- interrupts the to-be-deleted timer, del_timer_sync() will just loop
- forever.
-
- 3) arcnet_close() also calls tasklet_kill(), which has a warning if
- called from irq context.
-
- 4) For device reset, the sequence "arcnet_close(); arcnet_open();" is
- not complete. Some children arcnet drivers have special init/exit
- code sequences, which then embed a call to arcnet_open() and
- arcnet_close() accordingly. Check drivers/net/arcnet/com20020.c.
-
-Run the device RESET sequence from a scheduled workqueue instead.
-
-Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lore.kernel.org/r/20210128194802.727770-1-a.darwish@linutronix.de
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/net/arcnet/arc-rimi.c | 4 +-
- drivers/net/arcnet/arcdevice.h | 6 +++
- drivers/net/arcnet/arcnet.c | 66 +++++++++++++++++++++++++++++--
- drivers/net/arcnet/com20020-isa.c | 4 +-
- drivers/net/arcnet/com20020-pci.c | 2 +-
- drivers/net/arcnet/com20020_cs.c | 2 +-
- drivers/net/arcnet/com90io.c | 4 +-
- drivers/net/arcnet/com90xx.c | 4 +-
- 8 files changed, 78 insertions(+), 14 deletions(-)
-
-diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
-index 98df38fe553c..12d085405bd0 100644
---- a/drivers/net/arcnet/arc-rimi.c
-+++ b/drivers/net/arcnet/arc-rimi.c
-@@ -332,7 +332,7 @@ static int __init arc_rimi_init(void)
- dev->irq = 9;
-
- if (arcrimi_probe(dev)) {
-- free_netdev(dev);
-+ free_arcdev(dev);
- return -EIO;
- }
-
-@@ -349,7 +349,7 @@ static void __exit arc_rimi_exit(void)
- iounmap(lp->mem_start);
- release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
- free_irq(dev->irq, dev);
-- free_netdev(dev);
-+ free_arcdev(dev);
- }
-
- #ifndef MODULE
-diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h
-index 22a49c6d7ae6..5d4a4c7efbbf 100644
---- a/drivers/net/arcnet/arcdevice.h
-+++ b/drivers/net/arcnet/arcdevice.h
-@@ -298,6 +298,10 @@ struct arcnet_local {
-
- int excnak_pending; /* We just got an excesive nak interrupt */
-
-+ /* RESET flag handling */
-+ int reset_in_progress;
-+ struct work_struct reset_work;
-+
- struct {
- uint16_t sequence; /* sequence number (incs with each packet) */
- __be16 aborted_seq;
-@@ -350,7 +354,9 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc)
-
- void arcnet_unregister_proto(struct ArcProto *proto);
- irqreturn_t arcnet_interrupt(int irq, void *dev_id);
-+
- struct net_device *alloc_arcdev(const char *name);
-+void free_arcdev(struct net_device *dev);
-
- int arcnet_open(struct net_device *dev);
- int arcnet_close(struct net_device *dev);
-diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
-index e04efc0a5c97..d76dd7d14299 100644
---- a/drivers/net/arcnet/arcnet.c
-+++ b/drivers/net/arcnet/arcnet.c
-@@ -387,10 +387,44 @@ static void arcnet_timer(struct timer_list *t)
- struct arcnet_local *lp = from_timer(lp, t, timer);
- struct net_device *dev = lp->dev;
-
-- if (!netif_carrier_ok(dev)) {
-+ spin_lock_irq(&lp->lock);
-+
-+ if (!lp->reset_in_progress && !netif_carrier_ok(dev)) {
- netif_carrier_on(dev);
- netdev_info(dev, "link up\n");
- }
-+
-+ spin_unlock_irq(&lp->lock);
-+}
-+
-+static void reset_device_work(struct work_struct *work)
-+{
-+ struct arcnet_local *lp;
-+ struct net_device *dev;
-+
-+ lp = container_of(work, struct arcnet_local, reset_work);
-+ dev = lp->dev;
-+
-+ /* Do not bring the network interface back up if an ifdown
-+ * was already done.
-+ */
-+ if (!netif_running(dev) || !lp->reset_in_progress)
-+ return;
-+
-+ rtnl_lock();
-+
-+ /* Do another check, in case of an ifdown that was triggered in
-+ * the small race window between the exit condition above and
-+ * acquiring RTNL.
-+ */
-+ if (!netif_running(dev) || !lp->reset_in_progress)
-+ goto out;
-+
-+ dev_close(dev);
-+ dev_open(dev, NULL);
-+
-+out:
-+ rtnl_unlock();
- }
-
- static void arcnet_reply_tasklet(unsigned long data)
-@@ -452,12 +486,25 @@ struct net_device *alloc_arcdev(const char *name)
- lp->dev = dev;
- spin_lock_init(&lp->lock);
- timer_setup(&lp->timer, arcnet_timer, 0);
-+ INIT_WORK(&lp->reset_work, reset_device_work);
- }
-
- return dev;
- }
- EXPORT_SYMBOL(alloc_arcdev);
-
-+void free_arcdev(struct net_device *dev)
-+{
-+ struct arcnet_local *lp = netdev_priv(dev);
-+
-+ /* Do not cancel this at ->ndo_close(), as the workqueue itself
-+ * indirectly calls the ifdown path through dev_close().
-+ */
-+ cancel_work_sync(&lp->reset_work);
-+ free_netdev(dev);
-+}
-+EXPORT_SYMBOL(free_arcdev);
-+
- /* Open/initialize the board. This is called sometime after booting when
- * the 'ifconfig' program is run.
- *
-@@ -587,6 +634,10 @@ int arcnet_close(struct net_device *dev)
-
- /* shut down the card */
- lp->hw.close(dev);
-+
-+ /* reset counters */
-+ lp->reset_in_progress = 0;
-+
- module_put(lp->hw.owner);
- return 0;
- }
-@@ -820,6 +871,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
-
- spin_lock_irqsave(&lp->lock, flags);
-
-+ if (lp->reset_in_progress)
-+ goto out;
-+
- /* RESET flag was enabled - if device is not running, we must
- * clear it right away (but nothing else).
- */
-@@ -852,11 +906,14 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
- if (status & RESETflag) {
- arc_printk(D_NORMAL, dev, "spurious reset (status=%Xh)\n",
- status);
-- arcnet_close(dev);
-- arcnet_open(dev);
-+
-+ lp->reset_in_progress = 1;
-+ netif_stop_queue(dev);
-+ netif_carrier_off(dev);
-+ schedule_work(&lp->reset_work);
-
- /* get out of the interrupt handler! */
-- break;
-+ goto out;
- }
- /* RX is inhibited - we must have received something.
- * Prepare to receive into the next buffer.
-@@ -1052,6 +1109,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
- udelay(1);
- lp->hw.intmask(dev, lp->intmask);
-
-+out:
- spin_unlock_irqrestore(&lp->lock, flags);
- return retval;
- }
-diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
-index f983c4ce6b07..be618e4b9ed5 100644
---- a/drivers/net/arcnet/com20020-isa.c
-+++ b/drivers/net/arcnet/com20020-isa.c
-@@ -169,7 +169,7 @@ static int __init com20020_init(void)
- dev->irq = 9;
-
- if (com20020isa_probe(dev)) {
-- free_netdev(dev);
-+ free_arcdev(dev);
- return -EIO;
- }
-
-@@ -182,7 +182,7 @@ static void __exit com20020_exit(void)
- unregister_netdev(my_dev);
- free_irq(my_dev->irq, my_dev);
- release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE);
-- free_netdev(my_dev);
-+ free_arcdev(my_dev);
- }
-
- #ifndef MODULE
-diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
-index eb7f76753c9c..8bdc44b7e09a 100644
---- a/drivers/net/arcnet/com20020-pci.c
-+++ b/drivers/net/arcnet/com20020-pci.c
-@@ -291,7 +291,7 @@ static void com20020pci_remove(struct pci_dev *pdev)
-
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
-- free_netdev(dev);
-+ free_arcdev(dev);
- }
- }
-
-diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c
-index cf607ffcf358..9cc5eb6a8e90 100644
---- a/drivers/net/arcnet/com20020_cs.c
-+++ b/drivers/net/arcnet/com20020_cs.c
-@@ -177,7 +177,7 @@ static void com20020_detach(struct pcmcia_device *link)
- dev = info->dev;
- if (dev) {
- dev_dbg(&link->dev, "kfree...\n");
-- free_netdev(dev);
-+ free_arcdev(dev);
- }
- dev_dbg(&link->dev, "kfree2...\n");
- kfree(info);
-diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
-index cf214b730671..3856b447d38e 100644
---- a/drivers/net/arcnet/com90io.c
-+++ b/drivers/net/arcnet/com90io.c
-@@ -396,7 +396,7 @@ static int __init com90io_init(void)
- err = com90io_probe(dev);
-
- if (err) {
-- free_netdev(dev);
-+ free_arcdev(dev);
- return err;
- }
-
-@@ -419,7 +419,7 @@ static void __exit com90io_exit(void)
-
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
-- free_netdev(dev);
-+ free_arcdev(dev);
- }
-
- module_init(com90io_init)
-diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
-index 3dc3d533cb19..d8dfb9ea0de8 100644
---- a/drivers/net/arcnet/com90xx.c
-+++ b/drivers/net/arcnet/com90xx.c
-@@ -554,7 +554,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem,
- err_release_mem:
- release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
- err_free_dev:
-- free_netdev(dev);
-+ free_arcdev(dev);
- return -EIO;
- }
-
-@@ -672,7 +672,7 @@ static void __exit com90xx_exit(void)
- release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
- release_mem_region(dev->mem_start,
- dev->mem_end - dev->mem_start + 1);
-- free_netdev(dev);
-+ free_arcdev(dev);
- }
- }
-
---
-2.30.2
-