lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 26 Apr 2012 21:55:17 +0200
From:	Stephane Fillod <fillods@...rs.sf.net>
To:	netdev@...r.kernel.org
Cc:	steve.glendinning@...well.net
Subject: [PATCH] net: smsc75xx: fix MDIO access

* make MDIO read/write to work, the MII_ACCESS_BUSY bit was missing
  to actually trigger the I/O. Rem: the smsc75xx is different from
  the smsc95xx in that regard.
* fix PHY interrupt acknowledge, which needs a mdio_write
  to clear PHY_INT_SRC instead of a usual read like in smsc95xx.
* fix bug in phy_init loop that was ignoring BMCR reset bit,
  akin to smsc95xx's d946092000698fd204d82a9d239103c656fb63bf
* mark link down on startup and let PHY interrupt deal with carrier
  changes, akin to 07d69d4238418746a7b85c5d05ec17c658a2a390
* declare the smsc75xx's MII as GMII capable

Tested on ARM/Omap3 with LAN7500-CEB.

Signed-off-by: Stephane Fillod <fillods@...rs.sf.net>
Cc: Steve Glendinning <steve.glendinning@...well.net>
---

--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -32,7 +32,7 @@
 #include "smsc75xx.h"
 
 #define SMSC_CHIPNAME			"smsc75xx"
-#define SMSC_DRIVER_VERSION		"1.0.0"
+#define SMSC_DRIVER_VERSION		"1.1.0"
 #define HS_USB_PKT_SIZE			(512)
 #define FS_USB_PKT_SIZE			(64)
 #define DEFAULT_HS_BURST_CAP_SIZE	(16 * 1024 + 5 * HS_USB_PKT_SIZE)
@@ -98,7 +98,7 @@ static int __must_check smsc75xx_read_re
 
 	if (unlikely(ret < 0))
 		netdev_warn(dev->net,
-			"Failed to read register index 0x%08x", index);
+			"Failed to read register index 0x%08x: %d", index, ret);
 
 	le32_to_cpus(buf);
 	*data = *buf;
@@ -128,7 +128,7 @@ static int __must_check smsc75xx_write_r
 
 	if (unlikely(ret < 0))
 		netdev_warn(dev->net,
-			"Failed to write register index 0x%08x", index);
+			"Failed to write register index 0x%08x: %d", index, ret);
 
 	kfree(buf);
 
@@ -171,7 +171,7 @@ static int smsc75xx_mdio_read(struct net
 	idx &= dev->mii.reg_num_mask;
 	addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
 		| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
-		| MII_ACCESS_READ;
+		| MII_ACCESS_READ | MII_ACCESS_BUSY;
 	ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
 	check_warn_goto_done(ret, "Error writing MII_ACCESS");
 
@@ -185,6 +185,8 @@ static int smsc75xx_mdio_read(struct net
 
 done:
 	mutex_unlock(&dev->phy_mutex);
+	netif_dbg(dev, drv, dev->net, "%s: id %x, idx %d, val=%04x",
+					__func__, phy_id, idx, ret);
 	return ret;
 }
 
@@ -195,6 +197,9 @@ static void smsc75xx_mdio_write(struct n
 	u32 val, addr;
 	int ret;
 
+	netif_dbg(dev, drv, dev->net, "%s: id %x, idx %d, val=%04x",
+					__func__, phy_id, idx, regval);
+
 	mutex_lock(&dev->phy_mutex);
 
 	/* confirm MII not busy */
@@ -210,7 +215,7 @@ static void smsc75xx_mdio_write(struct n
 	idx &= dev->mii.reg_num_mask;
 	addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
 		| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
-		| MII_ACCESS_WRITE;
+		| MII_ACCESS_WRITE | MII_ACCESS_BUSY;
 	ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
 	check_warn_goto_done(ret, "Error writing MII_ACCESS");
 
@@ -511,7 +516,11 @@ static int smsc75xx_link_reset(struct us
 	/* clear interrupt status */
 	ret = smsc75xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
 	check_warn_return(ret, "Error reading PHY_INT_SRC");
+	smsc75xx_mdio_write(dev->net, mii->phy_id, PHY_INT_SRC, 0xffff);
 
+	if (!ret)
+		netif_dbg(dev, link, dev->net, "%s: spurious interrupt", __func__);
+
 	ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
 	check_warn_return(ret, "Error writing INT_STS");
 
@@ -643,7 +643,8 @@ static int smsc75xx_phy_initialize(struc
 
 static int smsc75xx_phy_initialize(struct usbnet *dev)
 {
-	int bmcr, timeout = 0;
+	int bmcr, ret, timeout = 0;
+	u32 buf;
 
 	/* Initialize MII structure */
 	dev->mii.dev = dev->net;
@@ -651,17 +662,19 @@ static int smsc75xx_phy_initialize(struc
 	dev->mii.mdio_write = smsc75xx_mdio_write;
 	dev->mii.phy_id_mask = 0x1f;
 	dev->mii.reg_num_mask = 0x1f;
+	dev->mii.supports_gmii = 1;
 	dev->mii.phy_id = SMSC75XX_INTERNAL_PHY_ID;
 
 	/* reset phy and wait for reset to complete */
-	smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+	smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
+		BMCR_RESET | BMCR_ANENABLE);
 
 	do {
 		msleep(10);
 		bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
 		check_warn_return(bmcr, "Error reading MII_BMCR");
 		timeout++;
-	} while ((bmcr & MII_BMCR) && (timeout < 100));
+	} while ((bmcr & BMCR_RESET) && (timeout < 100));
 
 	if (timeout >= 100) {
 		netdev_warn(dev->net, "timeout on PHY Reset");
@@ -671,10 +684,17 @@ static int smsc75xx_phy_initialize(struc
 	smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
 		ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
 		ADVERTISE_PAUSE_ASYM);
+	smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
+		ADVERTISE_1000FULL);
+	/* write to clear */
+	smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_SRC, 0xffff);
 
+	ret = smsc75xx_read_reg(dev, MAC_CR, &buf);
+	check_warn_return(ret, "Failed to read MAC_CR: %d", ret);
+
+	buf |= (MAC_CR_ADD | MAC_CR_ASD);
+	ret = smsc75xx_write_reg(dev, MAC_CR, buf);
+	check_warn_return(ret, "Failed to write MAC_CR: %d", ret);
-	/* read to clear */
-	smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
-	check_warn_return(bmcr, "Error reading PHY_INT_SRC");

 	smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
 		PHY_INT_MASK_DEFAULT);
@@ -1211,7 +1211,7 @@ static const struct driver_info smsc75xx
 	.rx_fixup	= smsc75xx_rx_fixup,
 	.tx_fixup	= smsc75xx_tx_fixup,
 	.status		= smsc75xx_status,
-	.flags		= FLAG_ETHER | FLAG_SEND_ZLP,
+	.flags		= FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
 };
 
 static const struct usb_device_id products[] = {
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ