#include <linux/usb.h>
#include <linux/crc32.h>
#include <linux/usb/usbnet.h>
+#include <linux/slab.h>
/* datasheet:
http://ptm2.cc.utu.fi/ftp/network/cards/DM9601/From_NET/DM9601-DS-P01-930914.pdf
void *buf;
int err = -ENOMEM;
- devdbg(dev, "dm_read() reg=0x%02x length=%d", reg, length);
+ netdev_dbg(dev->net, "dm_read() reg=0x%02x length=%d\n", reg, length);
buf = kmalloc(length, GFP_KERNEL);
if (!buf)
void *buf = NULL;
int err = -ENOMEM;
- devdbg(dev, "dm_write() reg=0x%02x, length=%d", reg, length);
+ netdev_dbg(dev->net, "dm_write() reg=0x%02x, length=%d\n", reg, length);
if (data) {
buf = kmalloc(length, GFP_KERNEL);
static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
{
- devdbg(dev, "dm_write_reg() reg=0x%02x, value=0x%02x", reg, value);
+ netdev_dbg(dev->net, "dm_write_reg() reg=0x%02x, value=0x%02x\n",
+ reg, value);
return usb_control_msg(dev->udev,
usb_sndctrlpipe(dev->udev, 0),
DM_WRITE_REG,
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
- deverr(dev, "Error allocating URB in dm_write_async_helper!");
+ netdev_err(dev->net, "Error allocating URB in dm_write_async_helper!\n");
return;
}
req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
if (!req) {
- deverr(dev, "Failed to allocate memory for control request");
+ netdev_err(dev->net, "Failed to allocate memory for control request\n");
usb_free_urb(urb);
return;
}
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status < 0) {
- deverr(dev, "Error submitting the control message: status=%d",
- status);
+ netdev_err(dev->net, "Error submitting the control message: status=%d\n",
+ status);
kfree(req);
usb_free_urb(urb);
}
static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
{
- devdbg(dev, "dm_write_async() reg=0x%02x length=%d", reg, length);
+ netdev_dbg(dev->net, "dm_write_async() reg=0x%02x length=%d\n", reg, length);
dm_write_async_helper(dev, reg, 0, length, data);
}
static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
{
- devdbg(dev, "dm_write_reg_async() reg=0x%02x value=0x%02x",
- reg, value);
+ netdev_dbg(dev->net, "dm_write_reg_async() reg=0x%02x value=0x%02x\n",
+ reg, value);
dm_write_async_helper(dev, reg, value, 0, NULL);
}
}
if (i == DM_TIMEOUT) {
- deverr(dev, "%s read timed out!", phy ? "phy" : "eeprom");
+ netdev_err(dev->net, "%s read timed out!\n", phy ? "phy" : "eeprom");
ret = -EIO;
goto out;
}
dm_write_reg(dev, DM_SHARED_CTRL, 0x0);
ret = dm_read(dev, DM_SHARED_DATA, 2, value);
- devdbg(dev, "read shared %d 0x%02x returned 0x%04x, %d",
- phy, reg, *value, ret);
+ netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n",
+ phy, reg, *value, ret);
out:
mutex_unlock(&dev->phy_mutex);
}
if (i == DM_TIMEOUT) {
- deverr(dev, "%s write timed out!", phy ? "phy" : "eeprom");
+ netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom");
ret = -EIO;
goto out;
}
__le16 res;
if (phy_id) {
- devdbg(dev, "Only internal phy supported");
+ netdev_dbg(dev->net, "Only internal phy supported\n");
return 0;
}
dm_read_shared_word(dev, 1, loc, &res);
- devdbg(dev,
- "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x",
- phy_id, loc, le16_to_cpu(res));
+ netdev_dbg(dev->net,
+ "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
+ phy_id, loc, le16_to_cpu(res));
return le16_to_cpu(res);
}
__le16 res = cpu_to_le16(val);
if (phy_id) {
- devdbg(dev, "Only internal phy supported");
+ netdev_dbg(dev->net, "Only internal phy supported\n");
return;
}
- devdbg(dev,"dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x",
- phy_id, loc, val);
+ netdev_dbg(dev->net, "dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
+ phy_id, loc, val);
dm_write_shared_word(dev, 1, loc, res);
}
return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
}
-static struct ethtool_ops dm9601_ethtool_ops = {
+static const struct ethtool_ops dm9601_ethtool_ops = {
.get_drvinfo = dm9601_get_drvinfo,
.get_link = dm9601_get_link,
.get_msglevel = usbnet_get_msglevel,
if (net->flags & IFF_PROMISC) {
rx_ctl |= 0x02;
- } else if (net->flags & IFF_ALLMULTI || net->mc_count > DM_MAX_MCAST) {
+ } else if (net->flags & IFF_ALLMULTI ||
+ netdev_mc_count(net) > DM_MAX_MCAST) {
rx_ctl |= 0x04;
- } else if (net->mc_count) {
- struct dev_mc_list *mc_list = net->mc_list;
- int i;
+ } else if (!netdev_mc_empty(net)) {
+ struct dev_mc_list *mc_list;
- for (i = 0; i < net->mc_count; i++, mc_list = mc_list->next) {
+ netdev_for_each_mc_addr(mc_list, net) {
u32 crc = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26;
hashes[crc >> 3] |= 1 << (crc & 0x7);
}
dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl);
}
+static void __dm9601_set_mac_address(struct usbnet *dev)
+{
+ dm_write_async(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
+}
+
static int dm9601_set_mac_address(struct net_device *net, void *p)
{
struct sockaddr *addr = p;
struct usbnet *dev = netdev_priv(net);
- if (!is_valid_ether_addr(addr->sa_data))
+ if (!is_valid_ether_addr(addr->sa_data)) {
+ dev_err(&net->dev, "not setting invalid mac address %pM\n",
+ addr->sa_data);
return -EINVAL;
+ }
memcpy(net->dev_addr, addr->sa_data, net->addr_len);
- dm_write_async(dev, DM_PHY_ADDR, net->addr_len, net->dev_addr);
+ __dm9601_set_mac_address(dev);
return 0;
}
+static const struct net_device_ops dm9601_netdev_ops = {
+ .ndo_open = usbnet_open,
+ .ndo_stop = usbnet_stop,
+ .ndo_start_xmit = usbnet_start_xmit,
+ .ndo_tx_timeout = usbnet_tx_timeout,
+ .ndo_change_mtu = usbnet_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = dm9601_ioctl,
+ .ndo_set_multicast_list = dm9601_set_multicast,
+ .ndo_set_mac_address = dm9601_set_mac_address,
+};
+
static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
{
int ret;
if (ret)
goto out;
- dev->net->do_ioctl = dm9601_ioctl;
- dev->net->set_multicast_list = dm9601_set_multicast;
- dev->net->set_mac_address = dm9601_set_mac_address;
+ dev->net->netdev_ops = &dm9601_netdev_ops;
dev->net->ethtool_ops = &dm9601_ethtool_ops;
dev->net->hard_header_len += DM_TX_OVERHEAD;
dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
*/
if (is_valid_ether_addr(mac))
memcpy(dev->net->dev_addr, mac, ETH_ALEN);
+ else {
+ printk(KERN_WARNING
+ "dm9601: No valid MAC address in EEPROM, using %pM\n",
+ dev->net->dev_addr);
+ __dm9601_set_mac_address(dev);
+ }
/* power up phy */
dm_write_reg(dev, DM_GPR_CTRL, 1);
int len;
/* format:
- b0: rx status
- b1: packet length (incl crc) low
- b2: packet length (incl crc) high
- b3..n-4: packet data
+ b1: rx status
+ b2: packet length (incl crc) low
+ b3: packet length (incl crc) high
+ b4..n-4: packet data
bn-3..bn: ethernet crc
*/
len = (skb->data[1] | (skb->data[2] << 8)) - 4;
if (unlikely(status & 0xbf)) {
- if (status & 0x01) dev->stats.rx_fifo_errors++;
- if (status & 0x02) dev->stats.rx_crc_errors++;
- if (status & 0x04) dev->stats.rx_frame_errors++;
- if (status & 0x20) dev->stats.rx_missed_errors++;
- if (status & 0x90) dev->stats.rx_length_errors++;
+ if (status & 0x01) dev->net->stats.rx_fifo_errors++;
+ if (status & 0x02) dev->net->stats.rx_crc_errors++;
+ if (status & 0x04) dev->net->stats.rx_frame_errors++;
+ if (status & 0x20) dev->net->stats.rx_missed_errors++;
+ if (status & 0x90) dev->net->stats.rx_length_errors++;
return 0;
}
int len;
/* format:
- b0: packet length low
- b1: packet length high
+ b1: packet length low
+ b2: packet length high
b3..n: packet data
*/
}
else
netif_carrier_off(dev->net);
- devdbg(dev, "Link Status is: %d", link);
+ netdev_dbg(dev->net, "Link Status is: %d\n", link);
}
}
mii_check_media(&dev->mii, 1, 1);
mii_ethtool_gset(&dev->mii, &ecmd);
- devdbg(dev, "link_reset() speed: %d duplex: %d",
- ecmd.speed, ecmd.duplex);
+ netdev_dbg(dev->net, "link_reset() speed: %d duplex: %d\n",
+ ecmd.speed, ecmd.duplex);
return 0;
}
static const struct driver_info dm9601_info = {
.description = "Davicom DM9601 USB Ethernet",
- .flags = FLAG_ETHER,
+ .flags = FLAG_ETHER | FLAG_LINK_INTR,
.bind = dm9601_bind,
.rx_fixup = dm9601_rx_fixup,
.tx_fixup = dm9601_tx_fixup,
USB_DEVICE(0x0a47, 0x9601), /* Hirose USB-100 */
.driver_info = (unsigned long)&dm9601_info,
},
+ {
+ USB_DEVICE(0x0fe6, 0x8101), /* DM9601 USB to Fast Ethernet Adapter */
+ .driver_info = (unsigned long)&dm9601_info,
+ },
+ {
+ USB_DEVICE(0x0a46, 0x9000), /* DM9000E */
+ .driver_info = (unsigned long)&dm9601_info,
+ },
{}, // END
};