+++ /dev/null
-From 772f66421d5aa0b9f256056f513bbc38ac132271 Mon Sep 17 00:00:00 2001
-From: Finn Thain <fthain@telegraphics.com.au>
-Date: Thu, 23 Jan 2020 09:07:26 +1100
-Subject: net/sonic: Fix CAM initialization
-
-From: Finn Thain <fthain@telegraphics.com.au>
-
-commit 772f66421d5aa0b9f256056f513bbc38ac132271 upstream.
-
-Section 4.3.1 of the datasheet says,
-
- This bit [TXP] must not be set if a Load CAM operation is in
- progress (LCAM is set). The SONIC will lock up if both bits are
- set simultaneously.
-
-Testing has shown that the driver sometimes attempts to set LCAM
-while TXP is set. Avoid this by waiting for command completion
-before and after giving the LCAM command.
-
-After issuing the Load CAM command, poll for !SONIC_CR_LCAM rather than
-SONIC_INT_LCD, because the SONIC_CR_TXP bit can't be used until
-!SONIC_CR_LCAM.
-
-When in reset mode, take the opportunity to reset the CAM Enable
-register.
-
-Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
-Tested-by: Stan Johnson <userm57@yahoo.com>
-Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- drivers/net/ethernet/natsemi/sonic.c | 21 ++++++++++++---------
- 1 file changed, 12 insertions(+), 9 deletions(-)
-
---- a/drivers/net/ethernet/natsemi/sonic.c
-+++ b/drivers/net/ethernet/natsemi/sonic.c
-@@ -550,6 +550,8 @@ static void sonic_multicast_list(struct
- (netdev_mc_count(dev) > 15)) {
- rcr |= SONIC_RCR_AMC;
- } else {
-+ unsigned long flags;
-+
- netif_dbg(lp, ifup, dev, "%s: mc_count %d\n", __func__,
- netdev_mc_count(dev));
- sonic_set_cam_enable(dev, 1); /* always enable our own address */
-@@ -563,9 +565,14 @@ static void sonic_multicast_list(struct
- i++;
- }
- SONIC_WRITE(SONIC_CDC, 16);
-- /* issue Load CAM command */
- SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff);
-+
-+ /* LCAM and TXP commands can't be used simultaneously */
-+ spin_lock_irqsave(&lp->lock, flags);
-+ sonic_quiesce(dev, SONIC_CR_TXP);
- SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM);
-+ sonic_quiesce(dev, SONIC_CR_LCAM);
-+ spin_unlock_irqrestore(&lp->lock, flags);
- }
- }
-
-@@ -592,6 +599,9 @@ static int sonic_init(struct net_device
- SONIC_WRITE(SONIC_ISR, 0x7fff);
- SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
-
-+ /* While in reset mode, clear CAM Enable register */
-+ SONIC_WRITE(SONIC_CE, 0);
-+
- /*
- * clear software reset flag, disable receiver, clear and
- * enable interrupts, then completely initialize the SONIC
-@@ -713,14 +723,7 @@ static int sonic_init(struct net_device
- * load the CAM
- */
- SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM);
--
-- i = 0;
-- while (i++ < 100) {
-- if (SONIC_READ(SONIC_ISR) & SONIC_INT_LCD)
-- break;
-- }
-- netif_dbg(lp, ifup, dev, "%s: CMD=%x, ISR=%x, i=%d\n", __func__,
-- SONIC_READ(SONIC_CMD), SONIC_READ(SONIC_ISR), i);
-+ sonic_quiesce(dev, SONIC_CR_LCAM);
-
- /*
- * enable receiver, disable loopback