net: cdc_ncm: cleanup a type issue in cdc_ncm_setup()
[linux-2.6-microblaze.git] / drivers / net / usb / cdc_ncm.c
index d49e4c5..e15ec2b 100644 (file)
@@ -66,7 +66,7 @@ static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
 static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
 static struct usb_driver cdc_ncm_driver;
 
-static u8 cdc_ncm_setup(struct usbnet *dev)
+static int cdc_ncm_setup(struct usbnet *dev)
 {
        struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
        struct usb_cdc_ncm_ntb_parameters ncm_parm;
@@ -76,8 +76,7 @@ static u8 cdc_ncm_setup(struct usbnet *dev)
        int err;
        int eth_hlen;
        u16 ntb_fmt_supported;
-       u32 min_dgram_size;
-       u32 min_hdr_size;
+       __le16 max_datagram_size;
 
        iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
 
@@ -87,8 +86,8 @@ static u8 cdc_ncm_setup(struct usbnet *dev)
                              0, iface_no, &ncm_parm,
                              sizeof(ncm_parm));
        if (err < 0) {
-               dev_dbg(&dev->intf->dev, "failed GET_NTB_PARAMETERS\n");
-               return 1;
+               dev_err(&dev->intf->dev, "failed GET_NTB_PARAMETERS\n");
+               return err; /* GET_NTB_PARAMETERS is required */
        }
 
        /* read correct set of parameters according to device mode */
@@ -101,20 +100,29 @@ static u8 cdc_ncm_setup(struct usbnet *dev)
        ctx->tx_max_datagrams = le16_to_cpu(ncm_parm.wNtbOutMaxDatagrams);
        ntb_fmt_supported = le16_to_cpu(ncm_parm.bmNtbFormatsSupported);
 
-       eth_hlen = ETH_HLEN;
-       min_dgram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
-       min_hdr_size = CDC_NCM_MIN_HDR_SIZE;
-       if (ctx->mbim_desc != NULL) {
-               flags = ctx->mbim_desc->bmNetworkCapabilities;
+       /* there are some minor differences in NCM and MBIM defaults */
+       if (cdc_ncm_comm_intf_is_mbim(ctx->control->cur_altsetting)) {
+               if (!ctx->mbim_desc)
+                       return -EINVAL;
                eth_hlen = 0;
-               min_dgram_size = CDC_MBIM_MIN_DATAGRAM_SIZE;
-               min_hdr_size = 0;
-       } else if (ctx->func_desc != NULL) {
-               flags = ctx->func_desc->bmNetworkCapabilities;
+               flags = ctx->mbim_desc->bmNetworkCapabilities;
+               ctx->max_datagram_size = le16_to_cpu(ctx->mbim_desc->wMaxSegmentSize);
+               if (ctx->max_datagram_size < CDC_MBIM_MIN_DATAGRAM_SIZE)
+                       ctx->max_datagram_size = CDC_MBIM_MIN_DATAGRAM_SIZE;
        } else {
-               flags = 0;
+               if (!ctx->func_desc)
+                       return -EINVAL;
+               eth_hlen = ETH_HLEN;
+               flags = ctx->func_desc->bmNetworkCapabilities;
+               ctx->max_datagram_size = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+               if (ctx->max_datagram_size < CDC_NCM_MIN_DATAGRAM_SIZE)
+                       ctx->max_datagram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
        }
 
+       /* common absolute max for NCM and MBIM */
+       if (ctx->max_datagram_size > CDC_NCM_MAX_DATAGRAM_SIZE)
+               ctx->max_datagram_size = CDC_NCM_MAX_DATAGRAM_SIZE;
+
        dev_dbg(&dev->intf->dev,
                "dwNtbInMaxSize=%u dwNtbOutMaxSize=%u wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u wNdpOutAlignment=%u wNtbOutMaxDatagrams=%u flags=0x%x\n",
                ctx->rx_max, ctx->tx_max, ctx->tx_remainder, ctx->tx_modulus,
@@ -151,9 +159,7 @@ static u8 cdc_ncm_setup(struct usbnet *dev)
        }
 
        /* verify maximum size of transmitted NTB in bytes */
-       if ((ctx->tx_max <
-           (min_hdr_size + min_dgram_size)) ||
-           (ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX)) {
+       if (ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX) {
                dev_dbg(&dev->intf->dev, "Using default maximum transmit length=%d\n",
                        CDC_NCM_NTB_MAX_SIZE_TX);
                ctx->tx_max = CDC_NCM_NTB_MAX_SIZE_TX;
@@ -229,60 +235,33 @@ static u8 cdc_ncm_setup(struct usbnet *dev)
                        dev_dbg(&dev->intf->dev, "Setting NTB format to 16-bit failed\n");
        }
 
-       ctx->max_datagram_size = min_dgram_size;
+       /* inform the device about the selected Max Datagram Size */
+       if (!(flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE))
+               goto out;
 
-       /* set Max Datagram Size (MTU) */
-       if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
-               __le16 max_datagram_size;
-               u16 eth_max_sz;
-               if (ctx->ether_desc != NULL)
-                       eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
-               else if (ctx->mbim_desc != NULL)
-                       eth_max_sz = le16_to_cpu(ctx->mbim_desc->wMaxSegmentSize);
-               else
-                       goto max_dgram_err;
-
-               err = usbnet_read_cmd(dev, USB_CDC_GET_MAX_DATAGRAM_SIZE,
-                                     USB_TYPE_CLASS | USB_DIR_IN
-                                     | USB_RECIP_INTERFACE,
-                                     0, iface_no, &max_datagram_size, 2);
-               if (err < 0) {
-                       dev_dbg(&dev->intf->dev, "GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
-                               min_dgram_size);
-               } else {
-                       ctx->max_datagram_size =
-                               le16_to_cpu(max_datagram_size);
-                       /* Check Eth descriptor value */
-                       if (ctx->max_datagram_size > eth_max_sz)
-                                       ctx->max_datagram_size = eth_max_sz;
-
-                       if (ctx->max_datagram_size > CDC_NCM_MAX_DATAGRAM_SIZE)
-                               ctx->max_datagram_size = CDC_NCM_MAX_DATAGRAM_SIZE;
-
-                       if (ctx->max_datagram_size < min_dgram_size)
-                               ctx->max_datagram_size = min_dgram_size;
-
-                       /* if value changed, update device */
-                       if (ctx->max_datagram_size !=
-                                       le16_to_cpu(max_datagram_size)) {
-                               max_datagram_size = cpu_to_le16(ctx->max_datagram_size);
-                               err = usbnet_write_cmd(dev,
-                                               USB_CDC_SET_MAX_DATAGRAM_SIZE,
-                                               USB_TYPE_CLASS | USB_DIR_OUT
-                                                | USB_RECIP_INTERFACE,
-                                               0,
-                                               iface_no, &max_datagram_size,
-                                               2);
-                               if (err < 0)
-                                       dev_dbg(&dev->intf->dev, "SET_MAX_DGRAM_SIZE failed\n");
-                       }
-               }
+       /* read current mtu value from device */
+       err = usbnet_read_cmd(dev, USB_CDC_GET_MAX_DATAGRAM_SIZE,
+                             USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
+                             0, iface_no, &max_datagram_size, 2);
+       if (err < 0) {
+               dev_dbg(&dev->intf->dev, "GET_MAX_DATAGRAM_SIZE failed\n");
+               goto out;
        }
 
-max_dgram_err:
-       if (dev->net->mtu != (ctx->max_datagram_size - eth_hlen))
-               dev->net->mtu = ctx->max_datagram_size - eth_hlen;
+       if (le16_to_cpu(max_datagram_size) == ctx->max_datagram_size)
+               goto out;
+
+       max_datagram_size = cpu_to_le16(ctx->max_datagram_size);
+       err = usbnet_write_cmd(dev, USB_CDC_SET_MAX_DATAGRAM_SIZE,
+                              USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE,
+                              0, iface_no, &max_datagram_size, 2);
+       if (err < 0)
+               dev_dbg(&dev->intf->dev, "SET_MAX_DATAGRAM_SIZE failed\n");
 
+out:
+       /* set MTU to max supported by the device if necessary */
+       if (dev->net->mtu > ctx->max_datagram_size - eth_hlen)
+               dev->net->mtu = ctx->max_datagram_size - eth_hlen;
        return 0;
 }
 
@@ -391,8 +370,10 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
                        union_desc = (const struct usb_cdc_union_desc *)buf;
                        /* the master must be the interface we are probing */
                        if (intf->cur_altsetting->desc.bInterfaceNumber !=
-                           union_desc->bMasterInterface0)
+                           union_desc->bMasterInterface0) {
+                               dev_dbg(&intf->dev, "bogus CDC Union\n");
                                goto error;
+                       }
                        ctx->data = usb_ifnum_to_if(dev->udev,
                                                    union_desc->bSlaveInterface0);
                        break;
@@ -436,45 +417,59 @@ advance:
        }
 
        /* check if we got everything */
-       if (!ctx->data || (!ctx->mbim_desc && !ctx->ether_desc))
+       if (!ctx->data || (!ctx->mbim_desc && !ctx->ether_desc)) {
+               dev_dbg(&intf->dev, "CDC descriptors missing\n");
                goto error;
+       }
 
        /* claim data interface, if different from control */
        if (ctx->data != ctx->control) {
                temp = usb_driver_claim_interface(driver, ctx->data, dev);
-               if (temp)
+               if (temp) {
+                       dev_dbg(&intf->dev, "failed to claim data intf\n");
                        goto error;
+               }
        }
 
        iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;
 
        /* reset data interface */
        temp = usb_set_interface(dev->udev, iface_no, 0);
-       if (temp)
+       if (temp) {
+               dev_dbg(&intf->dev, "set interface failed\n");
                goto error2;
+       }
 
        /* configure data interface */
        temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
-       if (temp)
+       if (temp) {
+               dev_dbg(&intf->dev, "set interface failed\n");
                goto error2;
+       }
 
        cdc_ncm_find_endpoints(dev, ctx->data);
        cdc_ncm_find_endpoints(dev, ctx->control);
-       if (!dev->in || !dev->out || !dev->status)
+       if (!dev->in || !dev->out || !dev->status) {
+               dev_dbg(&intf->dev, "failed to collect endpoints\n");
                goto error2;
+       }
 
        /* initialize data interface */
-       if (cdc_ncm_setup(dev))
+       if (cdc_ncm_setup(dev)) {
+               dev_dbg(&intf->dev, "cdc_ncm_setup() failed\n");
                goto error2;
+       }
 
        usb_set_intfdata(ctx->data, dev);
        usb_set_intfdata(ctx->control, dev);
 
        if (ctx->ether_desc) {
                temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
-               if (temp)
+               if (temp) {
+                       dev_dbg(&intf->dev, "failed to get mac address\n");
                        goto error2;
-               dev_info(&dev->udev->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
+               }
+               dev_info(&intf->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
        }
 
        /* usbnet use these values for sizing tx/rx queues */
@@ -491,7 +486,7 @@ error2:
 error:
        cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]);
        dev->data[0] = 0;
-       dev_info(&dev->udev->dev, "bind() failure\n");
+       dev_info(&intf->dev, "bind() failure\n");
        return -ENODEV;
 }
 EXPORT_SYMBOL_GPL(cdc_ncm_bind_common);
@@ -835,7 +830,7 @@ static void cdc_ncm_txpath_bh(unsigned long param)
        }
 }
 
-static struct sk_buff *
+struct sk_buff *
 cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
        struct sk_buff *skb_out;
@@ -862,6 +857,7 @@ error:
 
        return NULL;
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_tx_fixup);
 
 /* verify NTB header and return offset of first NDP, or negative error */
 int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
@@ -882,7 +878,7 @@ int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
 
        nth16 = (struct usb_cdc_ncm_nth16 *)skb_in->data;
 
-       if (le32_to_cpu(nth16->dwSignature) != USB_CDC_NCM_NTH16_SIGN) {
+       if (nth16->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN)) {
                netif_dbg(dev, rx_err, dev->net,
                          "invalid NTH16 signature <%#010x>\n",
                          le32_to_cpu(nth16->dwSignature));
@@ -948,7 +944,7 @@ error:
 }
 EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16);
 
-static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
 {
        struct sk_buff *skb;
        struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
@@ -972,7 +968,7 @@ next_ndp:
 
        ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
 
-       if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
+       if (ndp16->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) {
                netif_dbg(dev, rx_err, dev->net,
                          "invalid DPT16 signature <%#010x>\n",
                          le32_to_cpu(ndp16->dwSignature));
@@ -1024,6 +1020,7 @@ err_ndp:
 error:
        return 0;
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_fixup);
 
 static void
 cdc_ncm_speed_change(struct usbnet *dev,
@@ -1189,17 +1186,6 @@ static const struct usb_device_id cdc_devs[] = {
          .driver_info = (unsigned long)&wwan_info,
        },
 
-       /* Huawei NCM devices disguised as vendor specific */
-       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),
-         .driver_info = (unsigned long)&wwan_info,
-       },
-       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
-         .driver_info = (unsigned long)&wwan_info,
-       },
-       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x76),
-         .driver_info = (unsigned long)&wwan_info,
-       },
-
        /* Infineon(now Intel) HSPA Modem platform */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443,
                USB_CLASS_COMM,