From patchwork Tue Dec 4 13:19:27 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Turczak X-Patchwork-Id: 203626 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 139672C008F for ; Wed, 5 Dec 2012 00:19:49 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753571Ab2LDNTa (ORCPT ); Tue, 4 Dec 2012 08:19:30 -0500 Received: from netconsequence.de ([85.214.40.104]:36341 "EHLO mx.netconsequence.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752369Ab2LDNT2 convert rfc822-to-8bit (ORCPT ); Tue, 4 Dec 2012 08:19:28 -0500 Received: from [192.168.0.210] (p5B17F37D.dip.t-dialin.net [91.23.243.125]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by mx.netconsequence.de (Postfix) with ESMTPSA id E7E6D11E802E; Tue, 4 Dec 2012 14:19:25 +0100 (CET) Mime-Version: 1.0 (Mac OS X Mail 6.2 \(1499\)) Subject: Re: [PATCH] smsc: RFC: Workaround for problems with lan8710 phy auto MDI-X From: Peter Turczak In-Reply-To: Date: Tue, 4 Dec 2012 14:19:27 +0100 Cc: David Miller , Otavio Salvador , Javier Martinez Canillas , Christian Hohnstaedt , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Message-Id: <8DC2CA71-8F4C-4C92-BEF8-7B881414B7B1@netconsequence.de> References: <8D7E9026-6276-452B-9E0C-AEB8CF38C9FD@netconsequence.de> To: Jiri Kosina X-Mailer: Apple Mail (2.1499) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On Nov 30, 2012, at 4:23 PM, Jiri Kosina wrote: > I am not sure whether compile-time option for something like this is > appropriate. Kernel module parameter, perhaps? > > Of course it'd be far better if faulty hardware can be autodetected in > runtime. Thanks for the input. Currently only the symbol error counter seems to give a good indication that there might be a problem. So I suggest monitoring the symbol error counter. When a certain amount of symbol errors per poll interval is exceeded the auto MDI-X will be disabled. Signed-off-by: Peter Turczak --- drivers/net/phy/smsc.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++- include/linux/smscphy.h | 7 +++++ 2 files changed, 64 insertions(+), 1 deletions(-) diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 88e3991..0748266 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -24,6 +24,16 @@ #include #include +/* Maximum number of symbol errors between two lan8720_read_status calls. */ +#define LAN8720_MAX_SYM_ERR_CNT 100 + +static struct phy_driver lan8710_driver; + +struct smsc_phy_private { + /* Keeps track of the number of the broken received packets */ + int sym_err_count; +}; + static int smsc_phy_config_intr(struct phy_device *phydev) { int rc = phy_write (phydev, MII_LAN83C185_IM, @@ -58,6 +68,7 @@ static int smsc_phy_config_init(struct phy_device *phydev) static int lan87xx_config_init(struct phy_device *phydev) { + struct smsc_phy_private *privdata; /* * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due @@ -79,6 +90,12 @@ static int lan87xx_config_init(struct phy_device *phydev) if (rc < 0) return rc; + privdata = kzalloc(sizeof(*privdata), GFP_KERNEL); + if (!privdata) + return -ENOMEM; + + phydev->priv = privdata; + return smsc_phy_ack_interrupt(phydev); } @@ -87,6 +104,44 @@ static int lan911x_config_init(struct phy_device *phydev) return smsc_phy_ack_interrupt(phydev); } +int lan8720_read_status(struct phy_device *phydev) +{ + int err_count, err_since_last, rc; + struct smsc_phy_private *priv = phydev->priv; + + if (priv != NULL) { + + err_count = phy_read(phydev, MII_LAN8710_SYM_ERR_CNT); + err_since_last = err_count - priv->sym_err_count; + + if (err_since_last < 0) + err_since_last += 65535; + + priv->sym_err_count = err_count; + if (err_since_last > LAN8720_MAX_SYM_ERR_CNT) { + rc = phy_read(phydev, MII_LAN8710_SCSI); + + if (rc < 0) + return rc; + + if (!(rc & MII_LAN8710_SCSI_AMDIXCTRL)) { + + pr_warn("%s: Too may RX errors.", + phydev->bus->name); + pr_warn("Disabling MDI-X\n"); + + rc = phy_write(phydev, MII_LAN8710_SCSI, + rc | MII_LAN8710_SCSI_AMDIXCTRL); + } + + if (rc < 0) + return rc; + } + } + + return genphy_read_status(phydev); +} + static struct phy_driver smsc_phy_driver[] = { { .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ @@ -187,7 +242,7 @@ static struct phy_driver smsc_phy_driver[] = { /* basic functions */ .config_aneg = genphy_config_aneg, - .read_status = genphy_read_status, + .read_status = lan8720_read_status, .config_init = lan87xx_config_init, /* IRQ related */ diff --git a/include/linux/smscphy.h b/include/linux/smscphy.h index ce718cb..a0d3893 100644 --- a/include/linux/smscphy.h +++ b/include/linux/smscphy.h @@ -22,4 +22,11 @@ #define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */ #define MII_LAN83C185_ENERGYON (1 << 1) /* ENERGYON */ +#define MII_LAN8710_SCSI 27 /* Special Control/Status register */ + +#define MII_LAN8710_SCSI_AMDIXCTRL (1<<15) /* Flag to disable Auto-MDIX */ + +#define MII_LAN8710_SYM_ERR_CNT 26 /* Amount of invalid code symbols received */ + + #endif /* __LINUX_SMSCPHY_H__ */