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

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

 



On Thu, 2006-02-09 at 20:17 -0800, Andrew Morton wrote: 
> Steve Briggs <[email protected]> wrote:
> >
> > 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.
> 
> Better to do this via `ethtool autoneg off'.

Actually I did somewhat the same patch about a year ago and got the same
response:

"This functionality should likelz be done via ethtool..." - Benjamin
LaHaise[1]

So i went back and spend about a week redoing the whole thing to enable
ethtool support and reposted a patch[2], but didnt receive any response
to this whatsoever. I even wrote the maintainer later on personally to
ask if something was wrong with the patch, bad coding, anything, since
there was no reply or reaction. I never received a reply.

So. There IS an ethtool patch and it works for me, though i dont know
how well its made (there must be SOME reason i didnt get a response :)).
It supports autoneg, duplex and speed if i recall correctly.
If you try it out, id love to hear comments (since this was/is the first
time i messed around in kernel stuff).


[1] http://www.kvack.org/~ftp/archives/linux-ns83820/linux-ns83820.0503
    search for "Subject: Autoneg patch"

[2] http://www.kvack.org/~ftp/archives/linux-ns83820/linux-ns83820.0504
    search for "Subject: Re: Autoneg patch"

- Dan Faerch

----------------------------------------------------

diff -Nru ../linux-2.6.11.4/drivers/net/ns83820.c drivers/net/ns83820.c
--- ../linux-2.6.11.4/drivers/net/ns83820.c     Tue Mar 29 13:46:10 2005
+++ drivers/net/ns83820.c       Tue Apr 19 11:47:34 2005
@@ -1,4 +1,4 @@
-#define _VERSION "0.20"
+#define _VERSION "0.22"
 /* ns83820.c by Benjamin LaHaise with contributions.
  *
  * Questions/comments/discussion to [email protected].
@@ -66,6 +66,9 @@
  *
  *     20040828        0.21 -  add hardware vlan accleration
  *                             by Neil Horman <[email protected]>
+ *     20050321        0.22 -  Ethtool cmd support functions.
+ *                          -  set autoneg&duplex via ethtool
+ *                             by Dan Faerch <[email protected]>
  * Driver Overview
  * ===============
  *
@@ -124,6 +127,7 @@
 static int ihr = 2;
 static int reset_phy = 0;
 static int lnksts = 0;         /* CFG_LNKSTS bit polarity */
+static int disable_autoneg  = 0;
 
 /* Dprintk is used for more interesting debug events */
 #undef Dprintk
@@ -1273,6 +1277,177 @@
        return &dev->stats;
 }
 
+/*  Dan Faerch: ethtool get/set support.
+ *  This isnt perfect, but it does the job for me. I only own fiber, so copper support is "less-than-not-perfect". 
+ *  ive NEVER worked with drivers or hardware before (or programmed c for that matter), so please feel free to double check anything!! 
+*/
+
+/* Let ethtool retrieve info */
+static int ns83820_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{        struct ns83820 *dev = PRIV(ndev);  
+         u32 cfg,tanar, tbicr;
+        int have_optical = 0;
+        int fullduplex   = 0;           
+/*
+    Heres what other drivers show:
+        cmd->advertising = 
+        cmd->speed = 
+        cmd->duplex = 
+        cmd->port = 0;
+        cmd->phy_address = 
+        cmd->transceiver = 0;
+        cmd->autoneg = 
+        cmd->maxtxpkt = 0;
+        cmd->maxrxpkt = 0;
+
+   Feel free to implement any of theese that are missing.
+*/
+
+        /*read current configuration*/
+        cfg   = readl(dev->base + CFG) ^ SPDSTS_POLARITY;
+        tanar = readl(dev->base + TANAR);
+        tbicr = readl(dev->base + TBICR);
+
+       /*we have optical thingie-majiggy*/
+        if (dev->CFG_cache & CFG_TBI_EN) {
+               have_optical = 1;
+               //fullduplex   = (tanar & TANAR_FULL_DUP);
+               fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
+
+
+       } else { /*We have a copper wire (or a couple of copperwires at least.... hopefully)*/
+               fullduplex = (cfg & CFG_DUPSTS) ? 1 : 0;
+        }
+
+
+                   printk(KERN_INFO "%s: T:%d-%d-%d -  \n",
+                                       ndev->name,
+                                       (tanar & TANAR_FULL_DUP),
+                                       (cfg & CFG_DUPSTS),
+                                       tanar
+                                       );
+
+
+
+        cmd->supported = (SUPPORTED_Autoneg);
+
+        /*we have optical thingie-majiggy*/
+        if (dev->CFG_cache & CFG_TBI_EN) {
+           cmd->supported |= (SUPPORTED_1000baseT_Half |
+                              SUPPORTED_1000baseT_Full);
+           cmd->supported |= SUPPORTED_FIBRE;
+           cmd->port       = PORT_FIBRE; 
+        } /*TODO: else show copper related thingies*/
+
+        cmd->duplex    = ((fullduplex) ? DUPLEX_FULL : DUPLEX_HALF);
+        cmd->speed      = (
+                              ((cfg / CFG_SPDSTS0) & 3) >= 2 ? SPEED_1000 : 
+                             (((cfg / CFG_SPDSTS0) & 3) == 1 ? SPEED_100  : SPEED_10 )
+                          );
+        //cmd->autoneg    = !disable_autoneg;
+        cmd->autoneg      = (tbicr & TBICR_MR_AN_ENABLE) ? 1: 0;
+        
+        return 0;
+}
+
+/* Let ethool change settings*/
+static int ns83820_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{       struct ns83820 *dev = PRIV(ndev);
+        u32 cfg,tanar;
+       int have_optical = 0;
+       int fullduplex   = 0;
+
+       /*read current configuration*/
+        cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY;
+       tanar = readl(dev->base + TANAR); 
+
+       /*we have optical*/
+        if (dev->CFG_cache & CFG_TBI_EN) {
+               have_optical = 1;
+               fullduplex   = (tanar & TANAR_FULL_DUP);
+       //      fullduplex   = (cfg & CFG_DUPSTS);
+
+       } else { /*We have a copper*/
+               fullduplex = (cfg & CFG_DUPSTS);
+       }
+
+        spin_lock_irq(&dev->misc_lock);
+        spin_lock(&dev->tx_lock);
+      
+        //Set Duplex
+        if ( cmd->duplex != fullduplex) {       //If ethtool-setting is different than current setting
+              /*we have optical*/
+              if (have_optical) {
+                     /*set full duplex*/
+                  if (cmd->duplex==DUPLEX_FULL) {
+                         ndev->name,
+                         RXCFG,
+                         RXCFG | RXCFG_RX_FD,
+                         DUPLEX_FULL,
+                         readl(dev->base + RXCFG),
+                         readl(dev->base + RXCFG) | RXCFG_RX_FD,
+                         readl(dev->base + RXCFG) | ~RXCFG_RX_FD
+                         
+                         );                  
+                       /* force full duplex */
+                       writel(readl(dev->base + TXCFG)
+                              | TXCFG_CSI | TXCFG_HBI | TXCFG_ATP,
+                              dev->base + TXCFG);
+                       writel(readl(dev->base + RXCFG) | RXCFG_RX_FD,
+                              dev->base + RXCFG);
+                       /* Light up full duplex LED */
+                       writel(readl(dev->base + GPIOR) | GPIOR_GP1_OUT,
+                              dev->base + GPIOR);                           
+                           //writel(readl(dev->base + TANAR) | TANAR_FULL_DUP, dev->base + TANAR);
+                      } else {
+                      
+                      
+                      }
+ 
+              } else {
+                  /*we have copper*/
+                  
+              }
+                         printk(KERN_INFO "%s: Duplex set via ethtool\n",
+                         ndev->name);
+        }
+
+        //Set Autoneg
+        if (cmd->autoneg != ((disable_autoneg) ? AUTONEG_DISABLE : AUTONEG_ENABLE )) { //If ethtool-setting is different than current setting
+            if (cmd->autoneg == AUTONEG_ENABLE) {
+                   disable_autoneg=0;
+                   
+                   /* restart 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;
+                   
+                   printk(KERN_INFO "%s: autoneg enabled via ethtool\n",
+                                       ndev->name);
+            } else {
+                   disable_autoneg=1;
+                   
+                   /* disable auto negotiation */
+                   writel(0x00000000,
+                          dev->base + TBICR);              
+                   //dev->linkstate = LINK_UP;
+            }
+            printk(KERN_INFO "%s: autoneg %s via ethtool\n",
+                            ndev->name,
+                            (cmd->autoneg) ? "ENABLED" : "DISABLED"
+                            );            
+        }
+
+         phy_intr(ndev);
+   
+          spin_unlock(&dev->tx_lock);
+          spin_unlock_irq(&dev->misc_lock);
+  
+        return 0;
+}
+/* end ethtool get/set support -df */
+
 static void ns83820_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
 {
        struct ns83820 *dev = PRIV(ndev);
@@ -1289,8 +1464,10 @@
 }
 
 static struct ethtool_ops ops = {
-       .get_drvinfo = ns83820_get_drvinfo,
-       .get_link = ns83820_get_link
+        .get_settings    = ns83820_get_settings, 
+        .set_settings    = ns83820_set_settings,
+       .get_drvinfo     = ns83820_get_drvinfo,
+       .get_link        = ns83820_get_link
 };
 
 static void ns83820_mib_isr(struct ns83820 *dev)
@@ -1983,23 +2160,28 @@
 
        /* setup optical transceiver if we have one */
        if (dev->CFG_cache & CFG_TBI_EN) {
-               printk(KERN_INFO "%s: enabling optical transceiver\n",
+               printk(KERqN_INFO "%s: enabling optical transceiver\n",
                        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,
-                      | TANAR_FULL_DUP,
+               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;
-               */
+               /* Dan Faerch : Allow disabling of autonegotiation on module param*/
+               if (!disable_autoneg) {
+                       /* 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;
+               }
+               else
+               printk(KERN_INFO "%s: Skipping autonegotiation\n",
+                       ndev->name);
+               
+               
                dev->CFG_cache |= CFG_MODE_1000;
        }
 
@@ -2220,6 +2402,9 @@
 
 module_param(reset_phy, int, 0);
 MODULE_PARM_DESC(reset_phy, "Set to 1 to reset the PHY on startup");
+
+module_param(disable_autoneg, int, 0); 
+MODULE_PARM_DESC(autoneg, "Set to 1 to disable autoneg");
 
 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