Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Driver for USB ethernet port of Conexant CX82310-based ADSL routers
0004  * Copyright (C) 2010 by Ondrej Zary
0005  * some parts inspired by the cxacru driver
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/netdevice.h>
0010 #include <linux/etherdevice.h>
0011 #include <linux/ethtool.h>
0012 #include <linux/workqueue.h>
0013 #include <linux/mii.h>
0014 #include <linux/usb.h>
0015 #include <linux/usb/usbnet.h>
0016 
0017 enum cx82310_cmd {
0018     CMD_START       = 0x84, /* no effect? */
0019     CMD_STOP        = 0x85, /* no effect? */
0020     CMD_GET_STATUS      = 0x90, /* returns nothing? */
0021     CMD_GET_MAC_ADDR    = 0x91, /* read MAC address */
0022     CMD_GET_LINK_STATUS = 0x92, /* not useful, link is always up */
0023     CMD_ETHERNET_MODE   = 0x99, /* unknown, needed during init */
0024 };
0025 
0026 enum cx82310_status {
0027     STATUS_UNDEFINED,
0028     STATUS_SUCCESS,
0029     STATUS_ERROR,
0030     STATUS_UNSUPPORTED,
0031     STATUS_UNIMPLEMENTED,
0032     STATUS_PARAMETER_ERROR,
0033     STATUS_DBG_LOOPBACK,
0034 };
0035 
0036 #define CMD_PACKET_SIZE 64
0037 #define CMD_TIMEOUT 100
0038 #define CMD_REPLY_RETRY 5
0039 
0040 #define CX82310_MTU 1514
0041 #define CMD_EP      0x01
0042 
0043 struct cx82310_priv {
0044     struct work_struct reenable_work;
0045     struct usbnet *dev;
0046 };
0047 
0048 /*
0049  * execute control command
0050  *  - optionally send some data (command parameters)
0051  *  - optionally wait for the reply
0052  *  - optionally read some data from the reply
0053  */
0054 static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
0055                u8 *wdata, int wlen, u8 *rdata, int rlen)
0056 {
0057     int actual_len, retries, ret;
0058     struct usb_device *udev = dev->udev;
0059     u8 *buf = kzalloc(CMD_PACKET_SIZE, GFP_KERNEL);
0060 
0061     if (!buf)
0062         return -ENOMEM;
0063 
0064     /* create command packet */
0065     buf[0] = cmd;
0066     if (wdata)
0067         memcpy(buf + 4, wdata, min_t(int, wlen, CMD_PACKET_SIZE - 4));
0068 
0069     /* send command packet */
0070     ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf,
0071                CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT);
0072     if (ret < 0) {
0073         if (cmd != CMD_GET_LINK_STATUS)
0074             netdev_err(dev->net, "send command %#x: error %d\n",
0075                    cmd, ret);
0076         goto end;
0077     }
0078 
0079     if (reply) {
0080         /* wait for reply, retry if it's empty */
0081         for (retries = 0; retries < CMD_REPLY_RETRY; retries++) {
0082             ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, CMD_EP),
0083                        buf, CMD_PACKET_SIZE, &actual_len,
0084                        CMD_TIMEOUT);
0085             if (ret < 0) {
0086                 if (cmd != CMD_GET_LINK_STATUS)
0087                     netdev_err(dev->net, "reply receive error %d\n",
0088                            ret);
0089                 goto end;
0090             }
0091             if (actual_len > 0)
0092                 break;
0093         }
0094         if (actual_len == 0) {
0095             netdev_err(dev->net, "no reply to command %#x\n", cmd);
0096             ret = -EIO;
0097             goto end;
0098         }
0099         if (buf[0] != cmd) {
0100             netdev_err(dev->net, "got reply to command %#x, expected: %#x\n",
0101                    buf[0], cmd);
0102             ret = -EIO;
0103             goto end;
0104         }
0105         if (buf[1] != STATUS_SUCCESS) {
0106             netdev_err(dev->net, "command %#x failed: %#x\n", cmd,
0107                    buf[1]);
0108             ret = -EIO;
0109             goto end;
0110         }
0111         if (rdata)
0112             memcpy(rdata, buf + 4,
0113                    min_t(int, rlen, CMD_PACKET_SIZE - 4));
0114     }
0115 end:
0116     kfree(buf);
0117     return ret;
0118 }
0119 
0120 static int cx82310_enable_ethernet(struct usbnet *dev)
0121 {
0122     int ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
0123 
0124     if (ret)
0125         netdev_err(dev->net, "unable to enable ethernet mode: %d\n",
0126                ret);
0127     return ret;
0128 }
0129 
0130 static void cx82310_reenable_work(struct work_struct *work)
0131 {
0132     struct cx82310_priv *priv = container_of(work, struct cx82310_priv,
0133                          reenable_work);
0134     cx82310_enable_ethernet(priv->dev);
0135 }
0136 
0137 #define partial_len data[0]     /* length of partial packet data */
0138 #define partial_rem data[1]     /* remaining (missing) data length */
0139 #define partial_data    data[2]     /* partial packet data */
0140 
0141 static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
0142 {
0143     int ret;
0144     char buf[15];
0145     struct usb_device *udev = dev->udev;
0146     u8 link[3];
0147     int timeout = 50;
0148     struct cx82310_priv *priv;
0149     u8 addr[ETH_ALEN];
0150 
0151     /* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */
0152     if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0
0153         && strcmp(buf, "USB NET CARD")) {
0154         dev_info(&udev->dev, "ignoring: probably an ADSL modem\n");
0155         return -ENODEV;
0156     }
0157 
0158     ret = usbnet_get_endpoints(dev, intf);
0159     if (ret)
0160         return ret;
0161 
0162     /*
0163      * this must not include ethernet header as the device can send partial
0164      * packets with no header (and sometimes even empty URBs)
0165      */
0166     dev->net->hard_header_len = 0;
0167     /* we can send at most 1514 bytes of data (+ 2-byte header) per URB */
0168     dev->hard_mtu = CX82310_MTU + 2;
0169     /* we can receive URBs up to 4KB from the device */
0170     dev->rx_urb_size = 4096;
0171 
0172     dev->partial_data = (unsigned long) kmalloc(dev->hard_mtu, GFP_KERNEL);
0173     if (!dev->partial_data)
0174         return -ENOMEM;
0175 
0176     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0177     if (!priv) {
0178         ret = -ENOMEM;
0179         goto err_partial;
0180     }
0181     dev->driver_priv = priv;
0182     INIT_WORK(&priv->reenable_work, cx82310_reenable_work);
0183     priv->dev = dev;
0184 
0185     /* wait for firmware to become ready (indicated by the link being up) */
0186     while (--timeout) {
0187         ret = cx82310_cmd(dev, CMD_GET_LINK_STATUS, true, NULL, 0,
0188                   link, sizeof(link));
0189         /* the command can time out during boot - it's not an error */
0190         if (!ret && link[0] == 1 && link[2] == 1)
0191             break;
0192         msleep(500);
0193     }
0194     if (!timeout) {
0195         netdev_err(dev->net, "firmware not ready in time\n");
0196         ret = -ETIMEDOUT;
0197         goto err;
0198     }
0199 
0200     /* enable ethernet mode (?) */
0201     ret = cx82310_enable_ethernet(dev);
0202     if (ret)
0203         goto err;
0204 
0205     /* get the MAC address */
0206     ret = cx82310_cmd(dev, CMD_GET_MAC_ADDR, true, NULL, 0, addr, ETH_ALEN);
0207     if (ret) {
0208         netdev_err(dev->net, "unable to read MAC address: %d\n", ret);
0209         goto err;
0210     }
0211     eth_hw_addr_set(dev->net, addr);
0212 
0213     /* start (does not seem to have any effect?) */
0214     ret = cx82310_cmd(dev, CMD_START, false, NULL, 0, NULL, 0);
0215     if (ret)
0216         goto err;
0217 
0218     return 0;
0219 err:
0220     kfree(dev->driver_priv);
0221 err_partial:
0222     kfree((void *)dev->partial_data);
0223     return ret;
0224 }
0225 
0226 static void cx82310_unbind(struct usbnet *dev, struct usb_interface *intf)
0227 {
0228     struct cx82310_priv *priv = dev->driver_priv;
0229 
0230     kfree((void *)dev->partial_data);
0231     cancel_work_sync(&priv->reenable_work);
0232     kfree(dev->driver_priv);
0233 }
0234 
0235 /*
0236  * RX is NOT easy - we can receive multiple packets per skb, each having 2-byte
0237  * packet length at the beginning.
0238  * The last packet might be incomplete (when it crosses the 4KB URB size),
0239  * continuing in the next skb (without any headers).
0240  * If a packet has odd length, there is one extra byte at the end (before next
0241  * packet or at the end of the URB).
0242  */
0243 static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
0244 {
0245     int len;
0246     struct sk_buff *skb2;
0247     struct cx82310_priv *priv = dev->driver_priv;
0248 
0249     /*
0250      * If the last skb ended with an incomplete packet, this skb contains
0251      * end of that packet at the beginning.
0252      */
0253     if (dev->partial_rem) {
0254         len = dev->partial_len + dev->partial_rem;
0255         skb2 = alloc_skb(len, GFP_ATOMIC);
0256         if (!skb2)
0257             return 0;
0258         skb_put(skb2, len);
0259         memcpy(skb2->data, (void *)dev->partial_data,
0260                dev->partial_len);
0261         memcpy(skb2->data + dev->partial_len, skb->data,
0262                dev->partial_rem);
0263         usbnet_skb_return(dev, skb2);
0264         skb_pull(skb, (dev->partial_rem + 1) & ~1);
0265         dev->partial_rem = 0;
0266         if (skb->len < 2)
0267             return 1;
0268     }
0269 
0270     /* a skb can contain multiple packets */
0271     while (skb->len > 1) {
0272         /* first two bytes are packet length */
0273         len = skb->data[0] | (skb->data[1] << 8);
0274         skb_pull(skb, 2);
0275 
0276         /* if last packet in the skb, let usbnet to process it */
0277         if (len == skb->len || len + 1 == skb->len) {
0278             skb_trim(skb, len);
0279             break;
0280         }
0281 
0282         if (len == 0xffff) {
0283             netdev_info(dev->net, "router was rebooted, re-enabling ethernet mode");
0284             schedule_work(&priv->reenable_work);
0285         } else if (len > CX82310_MTU) {
0286             netdev_err(dev->net, "RX packet too long: %d B\n", len);
0287             return 0;
0288         }
0289 
0290         /* incomplete packet, save it for the next skb */
0291         if (len > skb->len) {
0292             dev->partial_len = skb->len;
0293             dev->partial_rem = len - skb->len;
0294             memcpy((void *)dev->partial_data, skb->data,
0295                    dev->partial_len);
0296             skb_pull(skb, skb->len);
0297             break;
0298         }
0299 
0300         skb2 = alloc_skb(len, GFP_ATOMIC);
0301         if (!skb2)
0302             return 0;
0303         skb_put(skb2, len);
0304         memcpy(skb2->data, skb->data, len);
0305         /* process the packet */
0306         usbnet_skb_return(dev, skb2);
0307 
0308         skb_pull(skb, (len + 1) & ~1);
0309     }
0310 
0311     /* let usbnet process the last packet */
0312     return 1;
0313 }
0314 
0315 /* TX is easy, just add 2 bytes of length at the beginning */
0316 static struct sk_buff *cx82310_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
0317                        gfp_t flags)
0318 {
0319     int len = skb->len;
0320 
0321     if (skb_cow_head(skb, 2)) {
0322         dev_kfree_skb_any(skb);
0323         return NULL;
0324     }
0325     skb_push(skb, 2);
0326 
0327     skb->data[0] = len;
0328     skb->data[1] = len >> 8;
0329 
0330     return skb;
0331 }
0332 
0333 
0334 static const struct driver_info cx82310_info = {
0335     .description    = "Conexant CX82310 USB ethernet",
0336     .flags      = FLAG_ETHER,
0337     .bind       = cx82310_bind,
0338     .unbind     = cx82310_unbind,
0339     .rx_fixup   = cx82310_rx_fixup,
0340     .tx_fixup   = cx82310_tx_fixup,
0341 };
0342 
0343 #define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \
0344     .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
0345                USB_DEVICE_ID_MATCH_DEV_INFO, \
0346     .idVendor = (vend), \
0347     .idProduct = (prod), \
0348     .bDeviceClass = (cl), \
0349     .bDeviceSubClass = (sc), \
0350     .bDeviceProtocol = (pr)
0351 
0352 static const struct usb_device_id products[] = {
0353     {
0354         USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0),
0355         .driver_info = (unsigned long) &cx82310_info
0356     },
0357     { },
0358 };
0359 MODULE_DEVICE_TABLE(usb, products);
0360 
0361 static struct usb_driver cx82310_driver = {
0362     .name       = "cx82310_eth",
0363     .id_table   = products,
0364     .probe      = usbnet_probe,
0365     .disconnect = usbnet_disconnect,
0366     .suspend    = usbnet_suspend,
0367     .resume     = usbnet_resume,
0368     .disable_hub_initiated_lpm = 1,
0369 };
0370 
0371 module_usb_driver(cx82310_driver);
0372 
0373 MODULE_AUTHOR("Ondrej Zary");
0374 MODULE_DESCRIPTION("Conexant CX82310-based ADSL router USB ethernet driver");
0375 MODULE_LICENSE("GPL");