ChangeSet 1.1595.7.20, 2003/07/30 13:47:44-07:00, dhollis@davehollis.com

[PATCH] USB: AX8817x mii/ethtool fixes among others

This patch:
Adds the Intellinet device IDs
Adds msg_level support (to be utilized in the future)
Fixes ethtool/mii support so link checking actually works
Changed timeout on usb_fill_int_urb to support High Speed (mru@users.sf.net)
Added devdbg/err/info defines borrowed from usbnet
Changed strlcpy to strncpy

Key issue not currently resolved (as brought up by mru@users.sf.net) is
that the receive performance is terrible on OHCI.  I ran a set of tests
with ttcp and transmit performance achieved 6146.16 KB/sec  but receive
only yielded 466.26 KB/sec which really sucks (sorry for the technical
jargon).  In porting the driver to 2.5 I had to pull the transmit
queueing that Tivo had originally used for the driver to even function.
My initial attempts at pulling the receive queueing met with many
Ooopses thus I backed off.  Looks like I will need to dig in again on
that one.


 drivers/usb/net/ax8817x.c |  123 +++++++++++++++++++++-------------------------
 1 files changed, 58 insertions(+), 65 deletions(-)


diff -Nru a/drivers/usb/net/ax8817x.c b/drivers/usb/net/ax8817x.c
--- a/drivers/usb/net/ax8817x.c	Fri Aug  1 10:54:47 2003
+++ b/drivers/usb/net/ax8817x.c	Fri Aug  1 10:54:47 2003
@@ -1,7 +1,7 @@
 /*
  * ASIX AX8817x USB 2.0 10/100/HomePNA Ethernet controller driver
  *
- * $Id: ax8817x.c,v 1.11 2003/06/15 19:00:02 dhollis Exp $
+ * $Id: ax8817x.c,v 1.17 2003/07/23 20:46:13 dhollis Exp $
  *
  * Copyright (c) 2002-2003 TiVo Inc.
  *
@@ -10,6 +10,12 @@
  *
  * History 
  *
+ *	2003-07-22 - Dave Hollis <dhollis@davehollis.com>  2.0.1
+ *		* Add Intellinet USB ids
+ *		* Fix mii/ethtool support - link check works!
+ *		* Add msglevel support
+ *		* Shamelessly 'borrowed' devdbg/err/info macros from usbnet
+ *		* Change strlcpy to strncpy
  *	2003-06-15 - Dave Hollis <dhollis@davehollis.com>  2.0.0
  *		* Remove crc32 inline function, use core kernel instead
  *		* Set sane defaults for rx_buffers
@@ -50,7 +56,7 @@
  * Known Issues
  *
  * Todo
- *	Fix mii/ethtool output
+ *	Fix receive performance on OHCI
 */
 
 #include <linux/slab.h>
@@ -69,7 +75,7 @@
 #include <linux/version.h>
 
 /* Version Information */
-#define DRIVER_VERSION "v2.0.0"
+#define DRIVER_VERSION "v2.0.1"
 #define DRIVER_AUTHOR "TiVo, Inc."
 #define DRIVER_DESC "ASIX AX8817x USB Ethernet driver"
 #define DRIVER_NAME "ax8817x"
@@ -95,6 +101,7 @@
 #define AX_RX_MAX                   ETH_FRAME_LEN
 #define AX_TIMEOUT_CMD              ( HZ / 10 )
 #define AX_TIMEOUT_TX               ( HZ * 2 )
+#define AX_MCAST_FILTER_SIZE        8
 #define AX_MAX_MCAST                64
 
 #define AX_DRV_STATE_INITIALIZING   0x00
@@ -155,6 +162,7 @@
 	u8 phy_id;
 	u8 phy_state;
 	u8 drv_state;
+	int msg_level;
 };
 
 
@@ -167,12 +175,27 @@
       {USB_DEVICE(0x0846, 0x1040), driver_info:0x00130103},
 	/* D-Link DUB-E100 */
       {USB_DEVICE(0x2001, 0x1a00), driver_info:0x009f9d9f},
-
+        /* Intellinet USB Ethernet */
+      {USB_DEVICE(0x0b95, 0x1720), driver_info:0x00130103},
 	{}
 };
 
 MODULE_DEVICE_TABLE(usb, ax8817x_id_table);
 
+#ifdef DEBUG
+#define devdbg(ax_info, fmt, arg...) \
+	printk(KERN_DEBUG "%s: " fmt "\n" , (ax_info)->net->name, ## arg)
+#else
+#define devdbg(ax_info, fmt, arg...) do {} while(0)
+#endif
+
+#define deverr(ax_info, fmt, arg...) \
+	printk(KERN_ERR "%s: " fmt "\n", (ax_info)->net->name, ## arg)
+	
+#define devinfo(ax_info, fmt, arg...) \
+	do { if ((ax_info)->msg_level >= 1) \
+		printk(KERN_INFO "%s: " fmt "\n", (ax_info)->net->name, ## arg); \
+	} while (0)
 
 static void ax_run_ctl_queue(struct ax8817x_info *, struct ax_cmd_req *,
 			     int);
@@ -880,14 +903,14 @@
 		u32 crc_bits;
 		int i;
 
-		multi_filter = kmalloc(8, GFP_ATOMIC);
+		multi_filter = kmalloc(AX_MCAST_FILTER_SIZE, GFP_ATOMIC);
 		if (multi_filter == NULL) {
 			/* Oops, couldn't allocate a DMA buffer for setting the multicast
 			   filter. Try all multi mode, although the ax_write_cmd_async
 			   will almost certainly fail, too... (but it will printk). */
 			rx_ctl |= 0x02;
 		} else {
-			memset(multi_filter, 0, 8);
+			memset(multi_filter, 0, AX_MCAST_FILTER_SIZE);
 
 			/* Build the multicast hash filter. */
 			for (i = 0; i < net->mc_count; i++) {
@@ -901,7 +924,7 @@
 
 			ax_write_cmd_async(ax_info,
 					   AX_CMD_WRITE_MULTI_FILTER, 0, 0,
-					   8, multi_filter);
+					   AX_MCAST_FILTER_SIZE, multi_filter);
 
 			rx_ctl |= 0x10;
 		}
@@ -915,19 +938,24 @@
 			 __u16 * regd)
 {
 	int ret;
+	u8 buf[4];
 
-	ax_write_cmd(ax_info, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
-	ret =
-	    ax_read_cmd(ax_info, AX_CMD_READ_MII_REG, phy, indx, 2, regd);
-	ax_write_cmd(ax_info, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
-
-	return 0;
+	devdbg(ax_info,"read_mii_word: phy=%02x, indx=%02x, regd=%04x", phy, indx, *regd);
+	
+	ax_write_cmd(ax_info, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
+	
+	ret = ax_read_cmd(ax_info, AX_CMD_READ_MII_REG, ax_info->phy_id, (__u16)indx, 2, regd);
+	devdbg(ax_info,"read_mii_word: AX_CMD_READ_MII_REG ret=%02x, regd=%04x", ret, *regd);
+	
+	ax_write_cmd(ax_info, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+	
+	return ret;
 }
 
 static int write_mii_word(struct ax8817x_info *ax_info, __u8 phy,
 			  __u8 indx, __u16 regd)
 {
-	warn("write_mii_word - not implemented!");
+	deverr(ax_info, "write_mii_word - not implemented!");
 	return 0;
 }
 
@@ -936,6 +964,8 @@
 	struct ax8817x_info *ax_info = dev->priv;
 	int res;
 
+	devdbg(ax_info, "mdio_read: phy_id=%02x, loc=%02x", phy_id, loc);
+	
 	read_mii_word(ax_info, phy_id, loc, (u16 *) & res);
 	return res & 0xffff;
 }
@@ -945,6 +975,7 @@
 {
 	struct ax8817x_info *ax_info = dev->priv;
 
+	devdbg(ax_info, "mdio_write: phy_id=%02x, loc=%02x", phy_id, loc);
 	write_mii_word(ax_info, phy_id, loc, val);
 }
 
@@ -961,10 +992,10 @@
 	case ETHTOOL_GDRVINFO:{
 			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
 
-			strlcpy(info.driver, DRIVER_NAME,
-				ETHTOOL_BUSINFO_LEN);
-			strlcpy(info.version, DRIVER_VERSION,
-				ETHTOOL_BUSINFO_LEN);
+			strncpy(info.driver, DRIVER_NAME,
+				sizeof(info.driver) - 1);
+			strncpy(info.version, DRIVER_VERSION,
+				sizeof(info.version) - 1);
 			usb_make_path(ax_info->usb, info.bus_info,sizeof info.bus_info);
 			if (copy_to_user(uaddr, &info, sizeof(info)))
 				return -EFAULT;
@@ -993,15 +1024,14 @@
 	case ETHTOOL_GLINK:{
 			struct ethtool_value edata = { ETHTOOL_GLINK };
 
-			edata.data =
-			    ax_info->phy_state == AX_PHY_STATE_LINK;
+			edata.data = mii_link_ok(&ax_info->mii);
 			if (copy_to_user(uaddr, &edata, sizeof(edata)))
 				return -EFAULT;
 			return 0;
 		}
 	case ETHTOOL_GMSGLVL:{
 			struct ethtool_value edata = { ETHTOOL_GMSGLVL };
-			/* edata.data = ax_info->msg_enable; FIXME */
+			edata.data = ax_info->msg_level;
 			if (copy_to_user(uaddr, &edata, sizeof(edata)))
 				return -EFAULT;
 			return 0;
@@ -1011,62 +1041,24 @@
 
 			if (copy_from_user(&edata, uaddr, sizeof(edata)))
 				return -EFAULT;
-			/* sp->msg_enable = edata.data;  FIXME */
+			ax_info->msg_level = edata.data;
 			return 0;
 		}
 	}
 	return -EOPNOTSUPP;
 }
 
-static int ax8817x_mii_ioctl(struct net_device *net, struct ifreq *ifr,
-			     int cmd)
-{
-	struct ax8817x_info *ax_info;
-	struct mii_ioctl_data *data_ptr =
-	    (struct mii_ioctl_data *) &(ifr->ifr_data);
-
-	ax_info = net->priv;
-
-	switch (cmd) {
-	case SIOCGMIIPHY:
-		data_ptr->phy_id = ax_info->phy_id;
-		break;
-	case SIOCGMIIREG:
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-
-		ax_read_cmd(ax_info, AX_CMD_READ_MII_REG, 0,
-			    data_ptr->reg_num & 0x1f, 2,
-			    &(data_ptr->val_out));
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-	return 0;
-}
-
 static int ax8817x_ioctl(struct net_device *net, struct ifreq *ifr,
 			 int cmd)
 {
 	struct ax8817x_info *ax_info;
-	int res;
 
 	ax_info = net->priv;
-	res = 0;
-
-	switch (cmd) {
-	case SIOCETHTOOL:
-		res = ax8817x_ethtool_ioctl(net, (void __user *)ifr->ifr_data);
-		break;
-	case SIOCGMIIPHY:	/* Get address of PHY in use */
-	case SIOCGMIIREG:	/* Read from MII PHY register */
-	case SIOCSMIIREG:	/* Write to MII PHY register */
-		return ax8817x_mii_ioctl(net, ifr, cmd);
-	default:
-		res = -EOPNOTSUPP;
-	}
 
-	return res;
+	if (cmd == SIOCETHTOOL)
+		return ax8817x_ethtool_ioctl(net, (void __user *) ifr->ifr_data);
+	
+	return generic_mii_ioctl(&ax_info->mii, (struct mii_ioctl_data *) &ifr->ifr_data, cmd, NULL);
 }
 
 static int ax8817x_net_init(struct net_device *net)
@@ -1219,7 +1211,8 @@
 	ax_info->mii.dev = net;
 	ax_info->mii.mdio_read = mdio_read;
 	ax_info->mii.mdio_write = mdio_write;
-	ax_info->mii.phy_id_mask = 0x1f;
+	ax_info->mii.phy_id = ax_info->phy_id;
+	ax_info->mii.phy_id_mask = 0x3f;
 	ax_info->mii.reg_num_mask = 0x1f;
 
 	/* Set up the interrupt URB, and start PHY state monitoring */
