diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-05-12 13:06:08 +0100 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-05-12 13:06:08 +0100 |
commit | 25061d285747f20aafa4b50df1b0b5665fef29cd (patch) | |
tree | c302ac93e3476788a4671ee556a902fce2592f3a /drivers/net/usb | |
parent | 7a6476143270d947924f5bbbc124accb0e558bf4 (diff) | |
parent | 6560ffd1ccd688152393dc7c35dbdcc33140633b (diff) |
Merge tag 'regmap-3.4' into regmap-stride
regmap: Last minute bug fix for 3.4
This is a last minute bug fix that was only just noticed since the code
path that's being exercised here is one that is fairly rarely used. The
changelog for the change itself is extremely clear and the code itself
is obvious to inspection so should be pretty safe.
Conflicts:
drivers/base/regmap/regmap.c (overlap between the fix and stride code)
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/asix.c | 4 | ||||
-rw-r--r-- | drivers/net/usb/qmi_wwan.c | 30 | ||||
-rw-r--r-- | drivers/net/usb/smsc75xx.c | 36 | ||||
-rw-r--r-- | drivers/net/usb/smsc95xx.c | 3 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 5 |
5 files changed, 63 insertions, 15 deletions
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 5ee032cafad..42b5151aa78 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -355,7 +355,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, u32 packet_len; u32 padbytes = 0xffff0000; - padlen = ((skb->len + 4) % 512) ? 0 : 4; + padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4; if ((!skb_cloned(skb)) && ((headroom + tailroom) >= (4 + padlen))) { @@ -377,7 +377,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, cpu_to_le32s(&packet_len); skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); - if ((skb->len % 512) == 0) { + if (padlen) { cpu_to_le32s(&padbytes); memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); skb_put(skb, sizeof(padbytes)); diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 552d24bf862..d316503b35d 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -365,6 +365,27 @@ static const struct driver_info qmi_wwan_force_int4 = { .data = BIT(4), /* interface whitelist bitmap */ }; +/* Sierra Wireless provide equally useless interface descriptors + * Devices in QMI mode can be switched between two different + * configurations: + * a) USB interface #8 is QMI/wwan + * b) USB interfaces #8, #19 and #20 are QMI/wwan + * + * Both configurations provide a number of other interfaces (serial++), + * some of which have the same endpoint configuration as we expect, so + * a whitelist or blacklist is necessary. + * + * FIXME: The below whitelist should include BIT(20). It does not + * because I cannot get it to work... + */ +static const struct driver_info qmi_wwan_sierra = { + .description = "Sierra Wireless wwan/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_gobi, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, + .data = BIT(8) | BIT(19), /* interface whitelist bitmap */ +}; #define HUAWEI_VENDOR_ID 0x12D1 #define QMI_GOBI_DEVICE(vend, prod) \ @@ -445,6 +466,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* Sierra Wireless MC77xx in QMI mode */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1199, + .idProduct = 0x68a2, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, {QMI_GOBI_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {QMI_GOBI_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 187d01ccb97..00103a8c5e0 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -98,7 +98,7 @@ static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index, if (unlikely(ret < 0)) netdev_warn(dev->net, - "Failed to read register index 0x%08x", index); + "Failed to read reg index 0x%08x: %d", index, ret); le32_to_cpus(buf); *data = *buf; @@ -128,7 +128,7 @@ static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index, if (unlikely(ret < 0)) netdev_warn(dev->net, - "Failed to write register index 0x%08x", index); + "Failed to write reg index 0x%08x: %d", index, ret); kfree(buf); @@ -171,7 +171,7 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx) idx &= dev->mii.reg_num_mask; addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR) | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR) - | MII_ACCESS_READ; + | MII_ACCESS_READ | MII_ACCESS_BUSY; ret = smsc75xx_write_reg(dev, MII_ACCESS, addr); check_warn_goto_done(ret, "Error writing MII_ACCESS"); @@ -210,7 +210,7 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx, idx &= dev->mii.reg_num_mask; addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR) | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR) - | MII_ACCESS_WRITE; + | MII_ACCESS_WRITE | MII_ACCESS_BUSY; ret = smsc75xx_write_reg(dev, MII_ACCESS, addr); check_warn_goto_done(ret, "Error writing MII_ACCESS"); @@ -508,9 +508,10 @@ static int smsc75xx_link_reset(struct usbnet *dev) u16 lcladv, rmtadv; int ret; - /* clear interrupt status */ + /* read and write to clear phy interrupt status */ ret = smsc75xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC); check_warn_return(ret, "Error reading PHY_INT_SRC"); + smsc75xx_mdio_write(dev->net, mii->phy_id, PHY_INT_SRC, 0xffff); ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL); check_warn_return(ret, "Error writing INT_STS"); @@ -643,7 +644,7 @@ static int smsc75xx_set_mac_address(struct usbnet *dev) static int smsc75xx_phy_initialize(struct usbnet *dev) { - int bmcr, timeout = 0; + int bmcr, ret, timeout = 0; /* Initialize MII structure */ dev->mii.dev = dev->net; @@ -651,6 +652,7 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) dev->mii.mdio_write = smsc75xx_mdio_write; dev->mii.phy_id_mask = 0x1f; dev->mii.reg_num_mask = 0x1f; + dev->mii.supports_gmii = 1; dev->mii.phy_id = SMSC75XX_INTERNAL_PHY_ID; /* reset phy and wait for reset to complete */ @@ -661,7 +663,7 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR); check_warn_return(bmcr, "Error reading MII_BMCR"); timeout++; - } while ((bmcr & MII_BMCR) && (timeout < 100)); + } while ((bmcr & BMCR_RESET) && (timeout < 100)); if (timeout >= 100) { netdev_warn(dev->net, "timeout on PHY Reset"); @@ -671,10 +673,13 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000, + ADVERTISE_1000FULL); - /* read to clear */ - smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC); - check_warn_return(bmcr, "Error reading PHY_INT_SRC"); + /* read and write to clear phy interrupt status */ + ret = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC); + check_warn_return(ret, "Error reading PHY_INT_SRC"); + smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_SRC, 0xffff); smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK, PHY_INT_MASK_DEFAULT); @@ -946,6 +951,14 @@ static int smsc75xx_reset(struct usbnet *dev) ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf); check_warn_return(ret, "Failed to write INT_EP_CTL: %d", ret); + /* allow mac to detect speed and duplex from phy */ + ret = smsc75xx_read_reg(dev, MAC_CR, &buf); + check_warn_return(ret, "Failed to read MAC_CR: %d", ret); + + buf |= (MAC_CR_ADD | MAC_CR_ASD); + ret = smsc75xx_write_reg(dev, MAC_CR, buf); + check_warn_return(ret, "Failed to write MAC_CR: %d", ret); + ret = smsc75xx_read_reg(dev, MAC_TX, &buf); check_warn_return(ret, "Failed to read MAC_TX: %d", ret); @@ -1051,6 +1064,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->ethtool_ops = &smsc75xx_ethtool_ops; dev->net->flags |= IFF_MULTICAST; dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD; + dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; return 0; } @@ -1211,7 +1225,7 @@ static const struct driver_info smsc75xx_info = { .rx_fixup = smsc75xx_rx_fixup, .tx_fixup = smsc75xx_tx_fixup, .status = smsc75xx_status, - .flags = FLAG_ETHER | FLAG_SEND_ZLP, + .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR, }; static const struct usb_device_id products[] = { diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 5f19f84d349..94ae66999f5 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1017,6 +1017,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->ethtool_ops = &smsc95xx_ethtool_ops; dev->net->flags |= IFF_MULTICAST; dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM; + dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; return 0; } @@ -1191,7 +1192,7 @@ static const struct driver_info smsc95xx_info = { .rx_fixup = smsc95xx_rx_fixup, .tx_fixup = smsc95xx_tx_fixup, .status = smsc95xx_status, - .flags = FLAG_ETHER | FLAG_SEND_ZLP, + .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR, }; static const struct usb_device_id products[] = { diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index b7b3f5b0d40..2d927fb4adf 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -210,6 +210,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf) } else { usb_fill_int_urb(dev->interrupt, dev->udev, pipe, buf, maxp, intr_complete, dev, period); + dev->interrupt->transfer_flags |= URB_FREE_BUFFER; dev_dbg(&intf->dev, "status ep%din, %d bytes period %d\n", usb_pipeendpoint(pipe), maxp, period); @@ -1443,7 +1444,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) status = register_netdev (net); if (status) - goto out3; + goto out4; netif_info(dev, probe, dev->net, "register '%s' at usb-%s-%s, %s, %pM\n", udev->dev.driver->name, @@ -1461,6 +1462,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) return 0; +out4: + usb_free_urb(dev->interrupt); out3: if (info->unbind) info->unbind (dev, udev); |