0001
0002
0003
0004
0005
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,
0019 CMD_STOP = 0x85,
0020 CMD_GET_STATUS = 0x90,
0021 CMD_GET_MAC_ADDR = 0x91,
0022 CMD_GET_LINK_STATUS = 0x92,
0023 CMD_ETHERNET_MODE = 0x99,
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
0050
0051
0052
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
0065 buf[0] = cmd;
0066 if (wdata)
0067 memcpy(buf + 4, wdata, min_t(int, wlen, CMD_PACKET_SIZE - 4));
0068
0069
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
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]
0138 #define partial_rem data[1]
0139 #define partial_data data[2]
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
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
0164
0165
0166 dev->net->hard_header_len = 0;
0167
0168 dev->hard_mtu = CX82310_MTU + 2;
0169
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
0186 while (--timeout) {
0187 ret = cx82310_cmd(dev, CMD_GET_LINK_STATUS, true, NULL, 0,
0188 link, sizeof(link));
0189
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
0201 ret = cx82310_enable_ethernet(dev);
0202 if (ret)
0203 goto err;
0204
0205
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
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
0237
0238
0239
0240
0241
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
0251
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
0271 while (skb->len > 1) {
0272
0273 len = skb->data[0] | (skb->data[1] << 8);
0274 skb_pull(skb, 2);
0275
0276
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
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
0306 usbnet_skb_return(dev, skb2);
0307
0308 skb_pull(skb, (len + 1) & ~1);
0309 }
0310
0311
0312 return 1;
0313 }
0314
0315
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");