Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1767076AbXEBVl4 (ORCPT ); Wed, 2 May 2007 17:41:56 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1767051AbXEBVlz (ORCPT ); Wed, 2 May 2007 17:41:55 -0400 Received: from cassiel.sirena.org.uk ([80.68.93.111]:3440 "EHLO cassiel.sirena.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1767060AbXEBVlp (ORCPT ); Wed, 2 May 2007 17:41:45 -0400 Date: Wed, 2 May 2007 22:41:29 +0100 From: Mark Brown To: =?utf-8?B?UmFmYcWC?= Bilski Cc: Tim Hockin , Andrew Morton , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Message-ID: <20070502214128.GA4814@sirena.org.uk> Mail-Followup-To: =?utf-8?B?UmFmYcWC?= Bilski , Tim Hockin , Andrew Morton , linux-kernel@vger.kernel.org, netdev@vger.kernel.org References: <46379A7E.3000109@interia.pl> <20070501212750.GC31630@sirena.org.uk> <46382798.2090709@interia.pl> <463830E1.8080107@interia.pl> <20070502082211.GD31630@sirena.org.uk> <4638EF0B.9050701@interia.pl> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="IJpNTDwzlM2Ie8A6" Content-Disposition: inline In-Reply-To: <4638EF0B.9050701@interia.pl> X-Cookie: Excellent day to have a rotten day. User-Agent: Mutt/1.5.13 (2006-08-11) X-SA-Exim-Connect-IP: 82.32.140.119 X-SA-Exim-Mail-From: broonie@sirena.org.uk Subject: Re: Natsemi DP83815 driver spaming X-SA-Exim-Version: 4.2.1 (built Tue, 09 Jan 2007 17:23:22 +0000) X-SA-Exim-Scanned: Yes (on cassiel.sirena.org.uk) Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6720 Lines: 198 --IJpNTDwzlM2Ie8A6 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Wed, May 02, 2007 at 10:05:31PM +0200, Rafa=C5=82 Bilski wrote: > What about module option? That would work, though you crossed in the post with me writing a patch adding a sysfs file; I merged the two for overkill (below). I also have a patch which changes the log message for the workaround so that it is displayed by default in order to make this easier to diagnose. diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 109e802..b9f3ab3 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -81,6 +81,8 @@ static const int multicast_filter_limit =3D 100; Setting to > 1518 effectively disables this feature. */ static int rx_copybreak; =20 +static int dspcfg_workaround =3D 1; + /* Used to pass the media type, etc. Both 'options[]' and 'full_duplex[]' should exist for driver interoperability. @@ -139,12 +141,14 @@ MODULE_LICENSE("GPL"); module_param(mtu, int, 0); module_param(debug, int, 0); module_param(rx_copybreak, int, 0); +module_param(dspcfg_workaround, int, 1); module_param_array(options, int, NULL, 0); module_param_array(full_duplex, int, NULL, 0); MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)"); MODULE_PARM_DESC(debug, "DP8381x default debug level"); MODULE_PARM_DESC(rx_copybreak, "DP8381x copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(dspcfg_workaround, "DP8381x: control DspCfg workaround"); MODULE_PARM_DESC(options, "DP8381x: Bits 0-3: media type, bit 17: full duplex"); MODULE_PARM_DESC(full_duplex, "DP8381x full duplex setting(s) (1)"); @@ -590,6 +594,7 @@ struct netdev_private { u32 srr; /* expected DSPCFG value */ u16 dspcfg; + int dspcfg_workaround; /* parms saved in ethtool format */ u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ u8 duplex; /* Duplex, half or full */ @@ -656,6 +661,56 @@ static int netdev_get_regs(struct net_device *dev, u8 = *buf); static int netdev_get_eeprom(struct net_device *dev, u8 *buf); static const struct ethtool_ops ethtool_ops; =20 +#define NATSEMI_ATTR(_name) \ +static ssize_t natsemi_show_##_name(struct device *dev, \ + struct device_attribute *attr, char *buf); \ + static ssize_t natsemi_set_##_name(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count); \ + static DEVICE_ATTR(_name, 0644, natsemi_show_##_name, natsemi_set_##_nam= e) + +#define NATSEMI_CREATE_FILE(_dev, _name) \ + device_create_file(&_dev->dev, &dev_attr_##_name) +#define NATSEMI_REMOVE_FILE(_dev, _name) \ + device_create_file(&_dev->dev, &dev_attr_##_name) + +NATSEMI_ATTR(dspcfg_workaround); + +static ssize_t natsemi_show_dspcfg_workaround(struct device *dev, + struct device_attribute *attr,=20 + char *buf) +{ + struct netdev_private *np =3D netdev_priv(to_net_dev(dev)); + + return sprintf(buf, "%s\n", np->dspcfg_workaround ? "on" : "off"); +} + +static ssize_t natsemi_set_dspcfg_workaround(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct netdev_private *np =3D netdev_priv(to_net_dev(dev)); + int new_setting; + u32 flags; + + /* Find out the new setting */ + if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1= )) + new_setting =3D 1; + else if (!strncmp("off", buf, count - 1) + || !strncmp("0", buf, count - 1)) + new_setting =3D 0; + else + return count;=20 + + spin_lock_irqsave(&np->lock, flags); + + np->dspcfg_workaround =3D new_setting; + + spin_unlock_irqrestore(&np->lock, flags); + + return count; +} + static inline void __iomem *ns_ioaddr(struct net_device *dev) { return (void __iomem *) dev->base_addr; @@ -820,6 +875,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pd= ev, np->ignore_phy =3D 1; else np->ignore_phy =3D 0; + np->dspcfg_workaround =3D dspcfg_workaround; =20 /* Initial port: * - If configured to ignore the PHY set up for external. @@ -899,6 +955,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pd= ev, if (i) goto err_register_netdev; =20 + if (!NATSEMI_CREATE_FILE(pdev, dspcfg_workaround)) + goto err_create_file; + if (netif_msg_drv(np)) { printk(KERN_INFO "natsemi %s: %s at %#08lx (%s), ", dev->name, natsemi_pci_info[chip_idx].name, iostart, @@ -915,6 +974,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pd= ev, } return 0; =20 + err_create_file: + unregister_netdev(dev); + err_register_netdev: iounmap(ioaddr); =20 @@ -1727,7 +1789,8 @@ static void init_registers(struct net_device *dev) * It seems that a reference set for this chip went out with incorrect = info, * and there exist boards that aren't quite right. An unexpected volta= ge * drop can cause the PHY to get itself in a weird state (basically res= et). - * NOTE: this only seems to affect revC chips. + * NOTE: this only seems to affect revC chips. The user can disable + * this check via dspcfg_workaround sysfs option. * 3) check of death of the RX path due to OOM */ static void netdev_timer(unsigned long data) @@ -1753,7 +1816,7 @@ static void netdev_timer(unsigned long data) writew(1, ioaddr+PGSEL); dspcfg =3D readw(ioaddr+DSPCFG); writew(0, ioaddr+PGSEL); - if (dspcfg !=3D np->dspcfg) { + if (np->dspcfg_workaround && dspcfg !=3D np->dspcfg) { if (!netif_queue_stopped(dev)) { spin_unlock_irq(&np->lock); if (netif_msg_hw(np)) @@ -3157,6 +3220,7 @@ static void __devexit natsemi_remove1 (struct pci_dev= *pdev) struct net_device *dev =3D pci_get_drvdata(pdev); void __iomem * ioaddr =3D ns_ioaddr(dev); =20 + NATSEMI_REMOVE_FILE(pdev, dspcfg_workaround); unregister_netdev (dev); pci_release_regions (pdev); iounmap(ioaddr); --=20 "You grabbed my hand and we fell into it, like a daydream - or a fever." --IJpNTDwzlM2Ie8A6 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iQCVAwUBRjkFgw2erOLNe+68AQITagP+PgPIu2ZNHjLmrzT6MLrMxqJ0eGxLFwXO TAf87lPeEI85L96dxDN0UqOwOVf//VlSFxnsN6v/9SYDIDJcU6qJm2yBPAaoSkhI /khY9WG7jIxlZVFSi7D7UK9DpI+EJYiNq8/v2uIIf4vC+pKdRxuQ3k0j7UB3dUg/ FWrZJyCU2/U= =qOvG -----END PGP SIGNATURE----- --IJpNTDwzlM2Ie8A6-- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/