[PATCH] drivers/net/ns83820.c: add paramter to disable auto negotiation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Steve Briggs <[email protected]>

This patch adds a module paramter, "auto_neg" which is
by default =1.  If it's set to zero, the auto negotiation
code in ns83820_init_one() is skipped and the interface is
set to 1000F.  This only applies to optical transceivers.

This is to allow this driver to work with partners that
don't support auto negotiation (the DGS-3204, for example).

This is for ns83820.c ver 0.22, kernel ver 2.6.15.3

Signed-off-by: Steve Briggs <[email protected]>

---

I use the the Netgear GA621 cards (with optical Xcvrs) and
have always had problems with autonegotiation.  Specifically,
if I have 2 cards connected together and the link goes down
(either one machine goes down or the fiber gets disconnected),
the link doesn't come back up until I reboot both machines.

I've also got a Dlink DGS-3204 fiber switch that doesn't
support autonegotiation, it's 1000F only.  In the
autonegotiation code in the current ns83820.c, it shows
up as
   tanlpar & (TANAR_FULL_DUP | TANAR_HALF_DUP) = 0
so the determination of full/half duplex in phy_intr()
falls through entirely.

I haven't done testing beyond with the Netgear GA621 cards;
on the other hand, if you do nothing, auto_neg = 1 and the
code works as before.


--- linux-2.6.15.3/drivers/net/ns83820.c.orig   2006-02-06 17:36:47.000000000 -0600
+++ linux-2.6.15.3/drivers/net/ns83820.c        2006-02-09 21:46:57.000000000 -0600
@@ -126,6 +126,7 @@
 static int ihr = 2;
 static int reset_phy = 0;
 static int lnksts = 0;         /* CFG_LNKSTS bit polarity */
+static int auto_neg = 1;       /* with an optical Xcvr, set = 0 to force to 1000F */

 /* Dprintk is used for more interesting debug events */
 #undef Dprintk
@@ -695,6 +696,8 @@ static void fastcall phy_intr(struct net
                        writel(readl(dev->base + GPIOR) & ~GPIOR_GP1_OUT,
                               dev->base + GPIOR);
                }
+               else /* partner doesn't autonegotiate, assume 1000F */
+                       fullduplex=1;

                speed = 4; /* 1000F */

@@ -1967,18 +1970,28 @@ static int __devinit ns83820_init_one(st
                        ndev->name);
                writel(readl(dev->base + GPIOR) | 0x3e8, dev->base + GPIOR);

-               /* setup auto negotiation feature advertisement */
-               writel(readl(dev->base + TANAR)
-                      | TANAR_HALF_DUP | TANAR_FULL_DUP,
-                      dev->base + TANAR);
-
-               /* start auto negotiation */
-               writel(TBICR_MR_AN_ENABLE | TBICR_MR_RESTART_AN,
-                      dev->base + TBICR);
-               writel(TBICR_MR_AN_ENABLE, dev->base + TBICR);
-               dev->linkstate = LINK_AUTONEGOTIATE;
-
-               dev->CFG_cache |= CFG_MODE_1000;
+               if (auto_neg == 0) {    /* don't advertise it, and set 1000F */
+                       writel(readl(dev->base + TANAR) & !TANAR_HALF_DUP &
+                              !TANAR_FULL_DUP, dev->base + TANAR);
+                       writel(readl(dev->base + TXCFG) | TXCFG_CSI | TXCFG_HBI,
+                              dev->base + TXCFG);
+                       writel(readl(dev->base + RXCFG) | RXCFG_RX_FD,
+                              dev->base + RXCFG);
+                       dev->linkstate = LINK_UP;
+               } else {
+                       /* setup auto negotiation feature advertisement */
+                       writel(readl(dev->base + TANAR)
+                              | TANAR_HALF_DUP | TANAR_FULL_DUP,
+                              dev->base + TANAR);
+
+                       /* start auto negotiation */
+                       writel(TBICR_MR_AN_ENABLE | TBICR_MR_RESTART_AN,
+                              dev->base + TBICR);
+                       writel(TBICR_MR_AN_ENABLE, dev->base + TBICR);
+                       dev->linkstate = LINK_AUTONEGOTIATE;
+               }
+
+                       dev->CFG_cache |= CFG_MODE_1000;
        }

        writel(dev->CFG_cache, dev->base + CFG);
@@ -2198,5 +2211,8 @@ MODULE_PARM_DESC(ihr, "Time in 100 us in
 module_param(reset_phy, int, 0);
 MODULE_PARM_DESC(reset_phy, "Set to 1 to reset the PHY on startup");

+module_param(auto_neg, int, 1);
+MODULE_PARM_DESC(auto_neg, "Set = 0 to disable auto negotiate and force 1000F (Optical only)");
+
 module_init(ns83820_init);
 module_exit(ns83820_exit);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux