* [PATCH] drivers/net/ns83820.c: add paramter to disable auto negotiation
@ 2006-02-10 4:03 Steve Briggs
2006-02-10 4:17 ` Andrew Morton
0 siblings, 1 reply; 4+ messages in thread
From: Steve Briggs @ 2006-02-10 4:03 UTC (permalink / raw)
To: linux-ns83820; +Cc: linux-kernel
From: Steve Briggs <zzybaloobah@yahoo.com>
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 <zzybaloobah@yahoo.com>
---
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);
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] drivers/net/ns83820.c: add paramter to disable auto negotiation
2006-02-10 4:03 [PATCH] drivers/net/ns83820.c: add paramter to disable auto negotiation Steve Briggs
@ 2006-02-10 4:17 ` Andrew Morton
2006-02-10 9:49 ` Dan Faerch
0 siblings, 1 reply; 4+ messages in thread
From: Andrew Morton @ 2006-02-10 4:17 UTC (permalink / raw)
To: Steve Briggs; +Cc: linux-ns83820, linux-kernel
Steve Briggs <s-briggs@cecer.army.mil> 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'.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] drivers/net/ns83820.c: add paramter to disable auto negotiation
2006-02-10 4:17 ` Andrew Morton
@ 2006-02-10 9:49 ` Dan Faerch
2006-02-10 10:38 ` Andrew Morton
0 siblings, 1 reply; 4+ messages in thread
From: Dan Faerch @ 2006-02-10 9:49 UTC (permalink / raw)
To: Andrew Morton; +Cc: Steve Briggs, linux-ns83820, linux-kernel
On Thu, 2006-02-09 at 20:17 -0800, Andrew Morton wrote:
> Steve Briggs <s-briggs@cecer.army.mil> 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 linux-ns83820@kvack.org.
@@ -66,6 +66,9 @@
*
* 20040828 0.21 - add hardware vlan accleration
* by Neil Horman <nhorman@redhat.com>
+ * 20050321 0.22 - Ethtool cmd support functions.
+ * - set autoneg&duplex via ethtool
+ * by Dan Faerch <dan@hacker.dk>
* 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);
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] drivers/net/ns83820.c: add paramter to disable auto negotiation
2006-02-10 9:49 ` Dan Faerch
@ 2006-02-10 10:38 ` Andrew Morton
0 siblings, 0 replies; 4+ messages in thread
From: Andrew Morton @ 2006-02-10 10:38 UTC (permalink / raw)
To: Dan Faerch; +Cc: s-briggs, linux-ns83820, linux-kernel
Dan Faerch <dan@scannet.dk> wrote:
>
> On Thu, 2006-02-09 at 20:17 -0800, Andrew Morton wrote:
> > Steve Briggs <s-briggs@cecer.army.mil> 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 :)).
Well, sometimes one needs to persist. Or copy me on the patch and I persist
for you ;)
> 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).
>
The patch you have here has all its tabs replaced with spaces and apart
from that doesn't apply to the current development tree. And it seems
to have some very random whitespace usage as well, although I usually
fix those things up if the patch isn't enormous.
Could you fix all this up, generate a nice changelog, add a Signed-off-by:
as per section 11 of Documentation/SubmittingPatches and resend?
Thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2006-02-10 10:38 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-10 4:03 [PATCH] drivers/net/ns83820.c: add paramter to disable auto negotiation Steve Briggs
2006-02-10 4:17 ` Andrew Morton
2006-02-10 9:49 ` Dan Faerch
2006-02-10 10:38 ` Andrew Morton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox