Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Davicom DM96xx USB 10/100Mbps ethernet devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Peter Korsgaard <jacmet@sunsite.dk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * This file is licensed under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * version 2.  This program is licensed "as is" without any warranty of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) //#define DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/ethtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/crc32.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/usb/usbnet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) /* datasheet:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  http://ptm2.cc.utu.fi/ftp/network/cards/DM9601/From_NET/DM9601-DS-P01-930914.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) /* control requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define DM_READ_REGS	0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define DM_WRITE_REGS	0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define DM_READ_MEMS	0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define DM_WRITE_REG	0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define DM_WRITE_MEMS	0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define DM_WRITE_MEM	0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) /* registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define DM_NET_CTRL	0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define DM_RX_CTRL	0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define DM_SHARED_CTRL	0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define DM_SHARED_ADDR	0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define DM_SHARED_DATA	0x0d	/* low + high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define DM_PHY_ADDR	0x10	/* 6 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define DM_MCAST_ADDR	0x16	/* 8 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define DM_GPR_CTRL	0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define DM_GPR_DATA	0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define DM_CHIP_ID	0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define DM_MODE_CTRL	0x91	/* only on dm9620 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) /* chip id values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define ID_DM9601	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define ID_DM9620	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define DM_MAX_MCAST	64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define DM_MCAST_SIZE	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define DM_EEPROM_LEN	256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define DM_TX_OVERHEAD	2	/* 2 byte header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) #define DM_RX_OVERHEAD	7	/* 3 byte header + 4 byte crc tail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) #define DM_TIMEOUT	1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	err = usbnet_read_cmd(dev, DM_READ_REGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 			       0, reg, data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if(err != length && err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	return dm_read(dev, reg, 1, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	err = usbnet_write_cmd(dev, DM_WRITE_REGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 				0, reg, data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	if (err >= 0 && err < length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	return usbnet_write_cmd(dev, DM_WRITE_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 				value, reg, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	usbnet_write_cmd_async(dev, DM_WRITE_REGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 			       0, reg, data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	usbnet_write_cmd_async(dev, DM_WRITE_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			       value, reg, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	mutex_lock(&dev->phy_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	for (i = 0; i < DM_TIMEOUT; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		u8 tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		/* ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		if ((tmp & 1) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	if (i == DM_TIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		netdev_err(dev->net, "%s read timed out!\n", phy ? "phy" : "eeprom");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	ret = dm_read(dev, DM_SHARED_DATA, 2, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		   phy, reg, *value, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	mutex_unlock(&dev->phy_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	mutex_lock(&dev->phy_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	ret = dm_write(dev, DM_SHARED_DATA, 2, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	for (i = 0; i < DM_TIMEOUT; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		u8 tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		/* ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		if ((tmp & 1) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (i == DM_TIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	mutex_unlock(&dev->phy_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int dm_read_eeprom_word(struct usbnet *dev, u8 offset, void *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	return dm_read_shared_word(dev, 0, offset, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static int dm9601_get_eeprom_len(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	return DM_EEPROM_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static int dm9601_get_eeprom(struct net_device *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 			     struct ethtool_eeprom *eeprom, u8 * data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	struct usbnet *dev = netdev_priv(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	__le16 *ebuf = (__le16 *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	/* access is 16bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	if ((eeprom->offset % 2) || (eeprom->len % 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	for (i = 0; i < eeprom->len / 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		if (dm_read_eeprom_word(dev, eeprom->offset / 2 + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 					&ebuf[i]) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	struct usbnet *dev = netdev_priv(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	__le16 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	if (phy_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		netdev_dbg(dev->net, "Only internal phy supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	dm_read_shared_word(dev, 1, loc, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	netdev_dbg(dev->net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		   "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		   phy_id, loc, le16_to_cpu(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	return le16_to_cpu(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 			      int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	struct usbnet *dev = netdev_priv(netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	__le16 res = cpu_to_le16(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	if (phy_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		netdev_dbg(dev->net, "Only internal phy supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	netdev_dbg(dev->net, "dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		   phy_id, loc, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	dm_write_shared_word(dev, 1, loc, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static void dm9601_get_drvinfo(struct net_device *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			       struct ethtool_drvinfo *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	/* Inherit standard device info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	usbnet_get_drvinfo(net, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static u32 dm9601_get_link(struct net_device *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	struct usbnet *dev = netdev_priv(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	return mii_link_ok(&dev->mii);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static int dm9601_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	struct usbnet *dev = netdev_priv(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static const struct ethtool_ops dm9601_ethtool_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	.get_drvinfo	= dm9601_get_drvinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	.get_link	= dm9601_get_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	.get_msglevel	= usbnet_get_msglevel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	.set_msglevel	= usbnet_set_msglevel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	.get_eeprom_len	= dm9601_get_eeprom_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	.get_eeprom	= dm9601_get_eeprom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	.nway_reset	= usbnet_nway_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	.get_link_ksettings	= usbnet_get_link_ksettings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	.set_link_ksettings	= usbnet_set_link_ksettings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static void dm9601_set_multicast(struct net_device *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	struct usbnet *dev = netdev_priv(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	/* We use the 20 byte dev->data for our 8 byte filter buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	 * to avoid allocating memory that is tricky to free later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	u8 *hashes = (u8 *) & dev->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	u8 rx_ctl = 0x31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	memset(hashes, 0x00, DM_MCAST_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	hashes[DM_MCAST_SIZE - 1] |= 0x80;	/* broadcast address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	if (net->flags & IFF_PROMISC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		rx_ctl |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	} else if (net->flags & IFF_ALLMULTI ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		   netdev_mc_count(net) > DM_MAX_MCAST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		rx_ctl |= 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	} else if (!netdev_mc_empty(net)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		struct netdev_hw_addr *ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		netdev_for_each_mc_addr(ha, net) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 			u32 crc = ether_crc(ETH_ALEN, ha->addr) >> 26;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			hashes[crc >> 3] |= 1 << (crc & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	dm_write_async(dev, DM_MCAST_ADDR, DM_MCAST_SIZE, hashes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static void __dm9601_set_mac_address(struct usbnet *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	dm_write_async(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static int dm9601_set_mac_address(struct net_device *net, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	struct sockaddr *addr = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	struct usbnet *dev = netdev_priv(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	if (!is_valid_ether_addr(addr->sa_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		dev_err(&net->dev, "not setting invalid mac address %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 								addr->sa_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	memcpy(net->dev_addr, addr->sa_data, net->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	__dm9601_set_mac_address(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static const struct net_device_ops dm9601_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	.ndo_open		= usbnet_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	.ndo_stop		= usbnet_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	.ndo_start_xmit		= usbnet_start_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	.ndo_tx_timeout		= usbnet_tx_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	.ndo_change_mtu		= usbnet_change_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	.ndo_get_stats64	= usbnet_get_stats64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	.ndo_validate_addr	= eth_validate_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	.ndo_do_ioctl 		= dm9601_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	.ndo_set_rx_mode	= dm9601_set_multicast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	.ndo_set_mac_address	= dm9601_set_mac_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	u8 mac[ETH_ALEN], id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	ret = usbnet_get_endpoints(dev, intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	dev->net->netdev_ops = &dm9601_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	dev->net->ethtool_ops = &dm9601_ethtool_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	dev->net->hard_header_len += DM_TX_OVERHEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	/* dm9620/21a require room for 4 byte padding, even in dm9601
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	 * mode, so we need +1 to be able to receive full size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	 * ethernet frames.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	dev->mii.dev = dev->net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	dev->mii.mdio_read = dm9601_mdio_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	dev->mii.mdio_write = dm9601_mdio_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	dev->mii.phy_id_mask = 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	dev->mii.reg_num_mask = 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	/* reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	dm_write_reg(dev, DM_NET_CTRL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	udelay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	/* read MAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, mac) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		printk(KERN_ERR "Error reading MAC address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	 * Overwrite the auto-generated address only with good ones.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	if (is_valid_ether_addr(mac))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		memcpy(dev->net->dev_addr, mac, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 			"dm9601: No valid MAC address in EEPROM, using %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 			dev->net->dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		__dm9601_set_mac_address(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	if (dm_read_reg(dev, DM_CHIP_ID, &id) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		netdev_err(dev->net, "Error reading chip ID\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	/* put dm9620 devices in dm9601 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	if (id == ID_DM9620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		u8 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		if (dm_read_reg(dev, DM_MODE_CTRL, &mode) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			netdev_err(dev->net, "Error reading MODE_CTRL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 			ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		dm_write_reg(dev, DM_MODE_CTRL, mode & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	/* power up phy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	dm_write_reg(dev, DM_GPR_CTRL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	dm_write_reg(dev, DM_GPR_DATA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	/* receive broadcast packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	dm9601_set_multicast(dev->net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	dm9601_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 			  ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	mii_nway_restart(&dev->mii);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	/* format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	   b1: rx status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	   b2: packet length (incl crc) low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	   b3: packet length (incl crc) high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	   b4..n-4: packet data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	   bn-3..bn: ethernet crc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	if (unlikely(skb->len < DM_RX_OVERHEAD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	status = skb->data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	len = (skb->data[1] | (skb->data[2] << 8)) - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	if (unlikely(status & 0xbf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		if (status & 0x01) dev->net->stats.rx_fifo_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		if (status & 0x02) dev->net->stats.rx_crc_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		if (status & 0x04) dev->net->stats.rx_frame_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		if (status & 0x20) dev->net->stats.rx_missed_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		if (status & 0x90) dev->net->stats.rx_length_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	skb_pull(skb, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	skb_trim(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 				       gfp_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	int len, pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	/* format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	   b1: packet length low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	   b2: packet length high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	   b3..n: packet data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	len = skb->len + DM_TX_OVERHEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	/* workaround for dm962x errata with tx fifo getting out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	 * sync if a USB bulk transfer retry happens right after a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	 * packet with odd / maxpacket length by adding up to 3 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	 * padding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	while ((len & 1) || !(len % dev->maxpacket))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	pad = len - skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		struct sk_buff *skb2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		skb = skb2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	__skb_push(skb, DM_TX_OVERHEAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	if (pad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		memset(skb->data + skb->len, 0, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		__skb_put(skb, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	skb->data[0] = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	skb->data[1] = len >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static void dm9601_status(struct usbnet *dev, struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	int link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	/* format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	   b0: net status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	   b1: tx status 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	   b2: tx status 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	   b3: rx status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	   b4: rx overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	   b5: rx count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	   b6: tx count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	   b7: gpr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	if (urb->actual_length < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	buf = urb->transfer_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	link = !!(buf[0] & 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	if (netif_carrier_ok(dev->net) != link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		usbnet_link_change(dev, link, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		netdev_dbg(dev->net, "Link Status is: %d\n", link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static int dm9601_link_reset(struct usbnet *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	mii_check_media(&dev->mii, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	mii_ethtool_gset(&dev->mii, &ecmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	netdev_dbg(dev->net, "link_reset() speed: %u duplex: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		   ethtool_cmd_speed(&ecmd), ecmd.duplex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static const struct driver_info dm9601_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	.description	= "Davicom DM96xx USB 10/100 Ethernet",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	.flags		= FLAG_ETHER | FLAG_LINK_INTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	.bind		= dm9601_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	.rx_fixup	= dm9601_rx_fixup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	.tx_fixup	= dm9601_tx_fixup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	.status		= dm9601_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	.link_reset	= dm9601_link_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	.reset		= dm9601_link_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static const struct usb_device_id products[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	 USB_DEVICE(0x07aa, 0x9601),	/* Corega FEther USB-TXC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	 USB_DEVICE(0x0a46, 0x9601),	/* Davicom USB-100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	 USB_DEVICE(0x0a46, 0x6688),	/* ZT6688 USB NIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	 USB_DEVICE(0x0a46, 0x0268),	/* ShanTou ST268 USB NIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	 USB_DEVICE(0x0a46, 0x8515),	/* ADMtek ADM8515 USB NIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	USB_DEVICE(0x0a47, 0x9601),	/* Hirose USB-100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	.driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	USB_DEVICE(0x0fe6, 0x8101),	/* DM9601 USB to Fast Ethernet Adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	.driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	 USB_DEVICE(0x0fe6, 0x9700),	/* DM9601 USB to Fast Ethernet Adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	 USB_DEVICE(0x0a46, 0x9000),	/* DM9000E */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	 USB_DEVICE(0x0a46, 0x9620),	/* DM9620 USB to Fast Ethernet Adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	 USB_DEVICE(0x0a46, 0x9621),	/* DM9621A USB to Fast Ethernet Adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	 USB_DEVICE(0x0a46, 0x9622),	/* DM9622 USB to Fast Ethernet Adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	 USB_DEVICE(0x0a46, 0x0269),	/* DM962OA USB to Fast Ethernet Adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	 USB_DEVICE(0x0a46, 0x1269),	/* DM9621A USB to Fast Ethernet Adapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	 USB_DEVICE(0x0586, 0x3427),	/* ZyXEL Keenetic Plus DSL xDSL modem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	 .driver_info = (unsigned long)&dm9601_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	{},			// END
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) MODULE_DEVICE_TABLE(usb, products);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static struct usb_driver dm9601_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	.name = "dm9601",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	.id_table = products,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	.probe = usbnet_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	.disconnect = usbnet_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	.suspend = usbnet_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	.resume = usbnet_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	.disable_hub_initiated_lpm = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) module_usb_driver(dm9601_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) MODULE_DESCRIPTION("Davicom DM96xx USB 10/100 ethernet devices");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) MODULE_LICENSE("GPL");