diff options
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/usb/cdc_ether.c | 13 | ||||
-rw-r--r-- | drivers/net/usb/cdc_ncm.c | 35 | ||||
-rw-r--r-- | drivers/net/usb/hso.c | 13 | ||||
-rw-r--r-- | drivers/net/usb/lan78xx.c | 6 | ||||
-rw-r--r-- | drivers/net/usb/pegasus.c | 7 | ||||
-rw-r--r-- | drivers/net/usb/qmi_wwan.c | 89 | ||||
-rw-r--r-- | drivers/net/usb/r8152.c | 226 | ||||
-rw-r--r-- | drivers/net/usb/r8153_ecm.c | 8 | ||||
-rw-r--r-- | drivers/net/usb/rndis_host.c | 2 | ||||
-rw-r--r-- | drivers/net/usb/rtl8150.c | 6 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 21 |
12 files changed, 298 insertions, 129 deletions
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 1e3719028780..fbbe78643631 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -631,7 +631,6 @@ config USB_NET_AQC111 config USB_RTL8153_ECM tristate "RTL8153 ECM support" depends on USB_NET_CDCETHER && (USB_RTL8152 || USB_RTL8152=n) - default y help This option supports ECM mode for RTL8153 ethernet adapter, when CONFIG_USB_RTL8152 is not set, or the RTL8153 device is not diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 8c1d61c2cbac..a9b551028659 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -793,6 +793,13 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM, @@ -962,6 +969,12 @@ static const struct usb_device_id products[] = { USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&wwan_info, }, { + /* Cinterion PLS83/PLS63 modem by GEMALTO/THALES */ + USB_DEVICE_AND_INTERFACE_INFO(0x1e2d, 0x0069, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_info, +}, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 2bac57d5e8d5..4087c9e33781 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -61,7 +61,7 @@ static bool prefer_mbim; module_param(prefer_mbim, bool, 0644); MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM functions"); -static void cdc_ncm_txpath_bh(unsigned long param); +static void cdc_ncm_txpath_bh(struct tasklet_struct *t); 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; @@ -813,9 +813,11 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ if (!ctx) return -ENOMEM; + ctx->dev = dev; + hrtimer_init(&ctx->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ctx->tx_timer.function = &cdc_ncm_tx_timer_cb; - tasklet_init(&ctx->bh, cdc_ncm_txpath_bh, (unsigned long)dev); + tasklet_setup(&ctx->bh, cdc_ncm_txpath_bh); atomic_set(&ctx->stop, 0); spin_lock_init(&ctx->mtx); @@ -1199,7 +1201,10 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) * accordingly. Otherwise, we should check here. */ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) - delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus); + delayed_ndp_size = ctx->max_ndp_size + + max_t(u32, + ctx->tx_ndp_modulus, + ctx->tx_modulus + ctx->tx_remainder) - 1; else delayed_ndp_size = 0; @@ -1410,7 +1415,8 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) if (!(dev->driver_info->flags & FLAG_SEND_ZLP) && skb_out->len > ctx->min_tx_pkt) { padding_count = ctx->tx_curr_size - skb_out->len; - skb_put_zero(skb_out, padding_count); + if (!WARN_ON(padding_count > ctx->tx_curr_size)) + skb_put_zero(skb_out, padding_count); } else if (skb_out->len < ctx->tx_curr_size && (skb_out->len % dev->maxpacket) == 0) { skb_put_u8(skb_out, 0); /* force short packet */ @@ -1468,10 +1474,10 @@ static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *timer) return HRTIMER_NORESTART; } -static void cdc_ncm_txpath_bh(unsigned long param) +static void cdc_ncm_txpath_bh(struct tasklet_struct *t) { - struct usbnet *dev = (struct usbnet *)param; - struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; + struct cdc_ncm_ctx *ctx = from_tasklet(ctx, t, bh); + struct usbnet *dev = ctx->dev; spin_lock_bh(&ctx->mtx); if (ctx->tx_timer_pending != 0) { @@ -1823,6 +1829,15 @@ cdc_ncm_speed_change(struct usbnet *dev, uint32_t rx_speed = le32_to_cpu(data->DLBitRRate); uint32_t tx_speed = le32_to_cpu(data->ULBitRate); + /* if the speed hasn't changed, don't report it. + * RTL8156 shipped before 2021 sends notification about every 32ms. + */ + if (dev->rx_speed == rx_speed && dev->tx_speed == tx_speed) + return; + + dev->rx_speed = rx_speed; + dev->tx_speed = tx_speed; + /* * Currently the USB-NET API does not support reporting the actual * device speed. Do print it instead. @@ -1863,10 +1878,8 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb) * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE. */ - netif_info(dev, link, dev->net, - "network connection: %sconnected\n", - !!event->wValue ? "" : "dis"); - usbnet_link_change(dev, !!event->wValue, 0); + if (netif_carrier_ok(dev->net) != !!event->wValue) + usbnet_link_change(dev, !!event->wValue, 0); break; case USB_CDC_NOTIFY_SPEED_CHANGE: diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 2bb28db89432..31d51346786a 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -370,7 +370,7 @@ static struct usb_driver hso_driver; static struct tty_driver *tty_drv; static struct hso_device *serial_table[HSO_SERIAL_TTY_MINORS]; static struct hso_device *network_table[HSO_MAX_NET_DEVICES]; -static spinlock_t serial_table_lock; +static DEFINE_SPINLOCK(serial_table_lock); static const s32 default_port_spec[] = { HSO_INTF_MUX | HSO_PORT_NETWORK, @@ -1213,9 +1213,10 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb) * This needs to be a tasklet otherwise we will * end up recursively calling this function. */ -static void hso_unthrottle_tasklet(unsigned long data) +static void hso_unthrottle_tasklet(struct tasklet_struct *t) { - struct hso_serial *serial = (struct hso_serial *)data; + struct hso_serial *serial = from_tasklet(serial, t, + unthrottle_tasklet); unsigned long flags; spin_lock_irqsave(&serial->serial_lock, flags); @@ -1264,9 +1265,8 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) serial->rx_state = RX_IDLE; /* Force default termio settings */ _hso_serial_set_termios(tty, NULL); - tasklet_init(&serial->unthrottle_tasklet, - hso_unthrottle_tasklet, - (unsigned long)serial); + tasklet_setup(&serial->unthrottle_tasklet, + hso_unthrottle_tasklet); result = hso_start_serial_device(serial->parent, GFP_KERNEL); if (result) { hso_stop_serial_device(serial->parent); @@ -3236,7 +3236,6 @@ static int __init hso_init(void) pr_info("%s\n", version); /* Initialise the serial table semaphore and table */ - spin_lock_init(&serial_table_lock); for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) serial_table[i] = NULL; diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index bf243edeb064..e81c5699c952 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -3375,9 +3375,9 @@ static void lan78xx_rx_bh(struct lan78xx_net *dev) netif_wake_queue(dev->net); } -static void lan78xx_bh(unsigned long param) +static void lan78xx_bh(struct tasklet_struct *t) { - struct lan78xx_net *dev = (struct lan78xx_net *)param; + struct lan78xx_net *dev = from_tasklet(dev, t, bh); struct sk_buff *skb; struct skb_data *entry; @@ -3655,7 +3655,7 @@ static int lan78xx_probe(struct usb_interface *intf, skb_queue_head_init(&dev->txq_pend); mutex_init(&dev->phy_mutex); - tasklet_init(&dev->bh, lan78xx_bh, (unsigned long)dev); + tasklet_setup(&dev->bh, lan78xx_bh); INIT_DELAYED_WORK(&dev->wq, lan78xx_delayedwork); init_usb_anchor(&dev->deferred); diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 32e1335c94ad..9a907182569c 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -553,12 +553,11 @@ tl_sched: tasklet_schedule(&pegasus->rx_tl); } -static void rx_fixup(unsigned long data) +static void rx_fixup(struct tasklet_struct *t) { - pegasus_t *pegasus; + pegasus_t *pegasus = from_tasklet(pegasus, t, rx_tl); int status; - pegasus = (pegasus_t *) data; if (pegasus->flags & PEGASUS_UNPLUG) return; @@ -1129,7 +1128,7 @@ static int pegasus_probe(struct usb_interface *intf, goto out1; } - tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); + tasklet_setup(&pegasus->rx_tl, rx_fixup); INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier); diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index d166c321ee9b..17a050521b86 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -57,6 +57,7 @@ struct qmi_wwan_state { enum qmi_wwan_flags { QMI_WWAN_FLAG_RAWIP = 1 << 0, QMI_WWAN_FLAG_MUX = 1 << 1, + QMI_WWAN_FLAG_PASS_THROUGH = 1 << 2, }; enum qmi_wwan_quirks { @@ -186,7 +187,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb) net = qmimux_find_dev(dev, hdr->mux_id); if (!net) goto skip; - skbn = netdev_alloc_skb(net, pkt_len); + skbn = netdev_alloc_skb(net, pkt_len + LL_MAX_HEADER); if (!skbn) return 0; skbn->dev = net; @@ -203,6 +204,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb) goto skip; } + skb_reserve(skbn, LL_MAX_HEADER); skb_put_data(skbn, skb->data + offset + qmimux_hdr_sz, pkt_len); if (netif_rx(skbn) != NET_RX_SUCCESS) { net->stats.rx_errors++; @@ -217,6 +219,28 @@ skip: return 1; } +static ssize_t mux_id_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct net_device *dev = to_net_dev(d); + struct qmimux_priv *priv; + + priv = netdev_priv(dev); + + return sysfs_emit(buf, "0x%02x\n", priv->mux_id); +} + +static DEVICE_ATTR_RO(mux_id); + +static struct attribute *qmi_wwan_sysfs_qmimux_attrs[] = { + &dev_attr_mux_id.attr, + NULL, +}; + +static struct attribute_group qmi_wwan_sysfs_qmimux_attr_group = { + .name = "qmap", + .attrs = qmi_wwan_sysfs_qmimux_attrs, +}; + static int qmimux_register_device(struct net_device *real_dev, u8 mux_id) { struct net_device *new_dev; @@ -239,6 +263,8 @@ static int qmimux_register_device(struct net_device *real_dev, u8 mux_id) goto out_free_newdev; } + new_dev->sysfs_groups[0] = &qmi_wwan_sysfs_qmimux_attr_group; + err = register_netdevice(new_dev); if (err < 0) goto out_free_newdev; @@ -325,6 +351,13 @@ static ssize_t raw_ip_store(struct device *d, struct device_attribute *attr, co if (enable == (info->flags & QMI_WWAN_FLAG_RAWIP)) return len; + /* ip mode cannot be cleared when pass through mode is set */ + if (!enable && (info->flags & QMI_WWAN_FLAG_PASS_THROUGH)) { + netdev_err(dev->net, + "Cannot clear ip mode on pass through device\n"); + return -EINVAL; + } + if (!rtnl_trylock()) return restart_syscall(); @@ -455,14 +488,59 @@ err: return ret; } +static ssize_t pass_through_show(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct usbnet *dev = netdev_priv(to_net_dev(d)); + struct qmi_wwan_state *info; + + info = (void *)&dev->data; + return sprintf(buf, "%c\n", + info->flags & QMI_WWAN_FLAG_PASS_THROUGH ? 'Y' : 'N'); +} + +static ssize_t pass_through_store(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct usbnet *dev = netdev_priv(to_net_dev(d)); + struct qmi_wwan_state *info; + bool enable; + + if (strtobool(buf, &enable)) + return -EINVAL; + + info = (void *)&dev->data; + + /* no change? */ + if (enable == (info->flags & QMI_WWAN_FLAG_PASS_THROUGH)) + return len; + + /* pass through mode can be set for raw ip devices only */ + if (!(info->flags & QMI_WWAN_FLAG_RAWIP)) { + netdev_err(dev->net, + "Cannot set pass through mode on non ip device\n"); + return -EINVAL; + } + + if (enable) + info->flags |= QMI_WWAN_FLAG_PASS_THROUGH; + else + info->flags &= ~QMI_WWAN_FLAG_PASS_THROUGH; + + return len; +} + static DEVICE_ATTR_RW(raw_ip); static DEVICE_ATTR_RW(add_mux); static DEVICE_ATTR_RW(del_mux); +static DEVICE_ATTR_RW(pass_through); static struct attribute *qmi_wwan_sysfs_attrs[] = { &dev_attr_raw_ip.attr, &dev_attr_add_mux.attr, &dev_attr_del_mux.attr, + &dev_attr_pass_through.attr, NULL, }; @@ -509,6 +587,11 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (info->flags & QMI_WWAN_FLAG_MUX) return qmimux_rx_fixup(dev, skb); + if (info->flags & QMI_WWAN_FLAG_PASS_THROUGH) { + skb->protocol = htons(ETH_P_MAP); + return (netif_rx(skb) == NET_RX_SUCCESS); + } + switch (skb->data[0] & 0xf0) { case 0x40: proto = htons(ETH_P_IP); @@ -1013,6 +1096,7 @@ static const struct usb_device_id products[] = { {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ /* 3. Combined interface devices matching on interface number */ @@ -1234,6 +1318,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, {QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, {QMI_FIXED_INTF(0x19d2, 0x1270, 5)}, /* ZTE MF667 */ + {QMI_FIXED_INTF(0x19d2, 0x1275, 3)}, /* ZTE P685M */ {QMI_FIXED_INTF(0x19d2, 0x1401, 2)}, {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ {QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, @@ -1301,12 +1386,14 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x0b3c, 0xc00a, 6)}, /* Olivetti Olicard 160 */ {QMI_FIXED_INTF(0x0b3c, 0xc00b, 4)}, /* Olivetti Olicard 500 */ {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)}, /* Cinterion PLxx */ + {QMI_QUIRK_SET_DTR(0x1e2d, 0x006f, 8)}, /* Cinterion PLS83/PLS63 */ {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)}, /* Cinterion PHxx,PXxx */ {QMI_FIXED_INTF(0x1e2d, 0x0063, 10)}, /* Cinterion ALASxx (1 RmNet) */ {QMI_FIXED_INTF(0x1e2d, 0x0082, 4)}, /* Cinterion PHxx,PXxx (2 RmNet) */ {QMI_FIXED_INTF(0x1e2d, 0x0082, 5)}, /* Cinterion PHxx,PXxx (2 RmNet) */ {QMI_FIXED_INTF(0x1e2d, 0x0083, 4)}, /* Cinterion PHxx,PXxx (1 RmNet + USB Audio)*/ {QMI_QUIRK_SET_DTR(0x1e2d, 0x00b0, 4)}, /* Cinterion CLS8 */ + {QMI_FIXED_INTF(0x1e2d, 0x00b7, 0)}, /* Cinterion MV31 RmNet */ {QMI_FIXED_INTF(0x413c, 0x81a2, 8)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x413c, 0x81a3, 8)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ {QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index c448d6089821..b246817f3405 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -1371,6 +1371,10 @@ void write_mii_word(struct net_device *netdev, int phy_id, int reg, int val) static int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags); +static int +rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, + u32 advertising); + static int rtl8152_set_mac_address(struct net_device *netdev, void *p) { struct r8152 *tp = netdev_priv(netdev); @@ -2393,11 +2397,9 @@ static void tx_bottom(struct r8152 *tp) } while (res == 0); } -static void bottom_half(unsigned long data) +static void bottom_half(struct tasklet_struct *t) { - struct r8152 *tp; - - tp = (struct r8152 *)data; + struct r8152 *tp = from_tasklet(tp, t, tx_tl); if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; @@ -2630,21 +2632,24 @@ static inline u8 rtl8152_get_speed(struct r8152 *tp) return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); } -static void rtl_set_eee_plus(struct r8152 *tp) +static void rtl_eee_plus_en(struct r8152 *tp, bool enable) { u32 ocp_data; - u8 speed; - speed = rtl8152_get_speed(tp); - if (speed & _10bps) { - ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); + ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); + if (enable) ocp_data |= EEEP_CR_EEEP_TX; - ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); - } else { - ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); + else ocp_data &= ~EEEP_CR_EEEP_TX; - ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); - } + ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); +} + +static void rtl_set_eee_plus(struct r8152 *tp) +{ + if (rtl8152_get_speed(tp) & _10bps) + rtl_eee_plus_en(tp, true); + else + rtl_eee_plus_en(tp, false); } static void rxdy_gated_en(struct r8152 *tp, bool enable) @@ -3148,10 +3153,22 @@ static void r8153b_ups_flags(struct r8152 *tp) ocp_write_dword(tp, MCU_TYPE_USB, USB_UPS_FLAGS, ups_flags); } -static void r8153b_green_en(struct r8152 *tp, bool enable) +static void rtl_green_en(struct r8152 *tp, bool enable) { u16 data; + data = sram_read(tp, SRAM_GREEN_CFG); + if (enable) + data |= GREEN_ETH_EN; + else + data &= ~GREEN_ETH_EN; + sram_write(tp, SRAM_GREEN_CFG, data); + + tp->ups_info.green = enable; +} + +static void r8153b_green_en(struct r8152 *tp, bool enable) +{ if (enable) { sram_write(tp, 0x8045, 0); /* 10M abiq&ldvbias */ sram_write(tp, 0x804d, 0x1222); /* 100M short abiq&ldvbias */ @@ -3162,11 +3179,7 @@ static void r8153b_green_en(struct r8152 *tp, bool enable) sram_write(tp, 0x805d, 0x2444); /* 1000M short abiq&ldvbias */ } - data = sram_read(tp, SRAM_GREEN_CFG); - data |= GREEN_ETH_EN; - sram_write(tp, SRAM_GREEN_CFG, data); - - tp->ups_info.green = enable; + rtl_green_en(tp, true); } static u16 r8153_phy_status(struct r8152 *tp, u16 desired) @@ -3207,8 +3220,6 @@ static void r8153b_ups_en(struct r8152 *tp, bool enable) ocp_data |= BIT(0); ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); } else { - u16 data; - ocp_data &= ~(UPS_EN | USP_PREWAKE); ocp_write_byte(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); @@ -3216,31 +3227,20 @@ static void r8153b_ups_en(struct r8152 *tp, bool enable) ocp_data &= ~BIT(0); ocp_write_byte(tp, MCU_TYPE_USB, 0xcfff, ocp_data); - ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); - ocp_data &= ~PCUT_STATUS; - ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); - - data = r8153_phy_status(tp, 0); + if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) { + int i; - switch (data) { - case PHY_STAT_PWRDN: - case PHY_STAT_EXT_INIT: - r8153b_green_en(tp, - test_bit(GREEN_ETHERNET, &tp->flags)); - - data = r8152_mdio_read(tp, MII_BMCR); - data &= ~BMCR_PDOWN; - data |= BMCR_RESET; - r8152_mdio_write(tp, MII_BMCR, data); + for (i = 0; i < 500; i++) { + if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & + AUTOLOAD_DONE) + break; + msleep(20); + } - data = r8153_phy_status(tp, PHY_STAT_LAN_ON); - fallthrough; + tp->rtl_ops.hw_phy_cfg(tp); - default: - if (data != PHY_STAT_LAN_ON) - netif_warn(tp, link, tp->netdev, - "PHY not ready"); - break; + rtl8152_set_speed(tp, tp->autoneg, tp->speed, + tp->duplex, tp->advertising); } } } @@ -3371,7 +3371,7 @@ static void rtl8153b_runtime_enable(struct r8152 *tp, bool enable) r8153b_ups_en(tp, false); r8153_queue_wake(tp, false); rtl_runtime_suspend_enable(tp, false); - if (tp->udev->speed != USB_SPEED_HIGH) + if (tp->udev->speed >= USB_SPEED_SUPER) r8153b_u1u2en(tp, true); } } @@ -3470,59 +3470,76 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type) ocp_write_word(tp, type, PLA_BP_BA, 0); } -static int r8153_patch_request(struct r8152 *tp, bool request) +static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait) { - u16 data; + u16 data, check; int i; data = ocp_reg_read(tp, OCP_PHY_PATCH_CMD); - if (request) + if (request) { data |= PATCH_REQUEST; - else + check = 0; + } else { data &= ~PATCH_REQUEST; + check = PATCH_READY; + } ocp_reg_write(tp, OCP_PHY_PATCH_CMD, data); - for (i = 0; request && i < 5000; i++) { + for (i = 0; wait && i < 5000; i++) { + u32 ocp_data; + usleep_range(1000, 2000); - if (ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY) + ocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT); + if ((ocp_data & PATCH_READY) ^ check) break; } - if (request && !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) { - netif_err(tp, drv, tp->netdev, "patch request fail\n"); - r8153_patch_request(tp, false); + if (request && wait && + !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) { + dev_err(&tp->intf->dev, "PHY patch request fail\n"); + rtl_phy_patch_request(tp, false, false); return -ETIME; } else { return 0; } } -static int r8153_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key) +static void rtl_patch_key_set(struct r8152 *tp, u16 key_addr, u16 patch_key) { - if (r8153_patch_request(tp, true)) { - dev_err(&tp->intf->dev, "patch request fail\n"); - return -ETIME; - } + if (patch_key && key_addr) { + sram_write(tp, key_addr, patch_key); + sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK); + } else if (key_addr) { + u16 data; - sram_write(tp, key_addr, patch_key); - sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK); + sram_write(tp, 0x0000, 0x0000); - return 0; + data = ocp_reg_read(tp, OCP_PHY_LOCK); + data &= ~PATCH_LOCK; + ocp_reg_write(tp, OCP_PHY_LOCK, data); + + sram_write(tp, key_addr, 0x0000); + } else { + WARN_ON_ONCE(1); + } } -static int r8153_post_ram_code(struct r8152 *tp, u16 key_addr) +static int +rtl_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key, bool wait) { - u16 data; + if (rtl_phy_patch_request(tp, true, wait)) + return -ETIME; - sram_write(tp, 0x0000, 0x0000); + rtl_patch_key_set(tp, key_addr, patch_key); - data = ocp_reg_read(tp, OCP_PHY_LOCK); - data &= ~PATCH_LOCK; - ocp_reg_write(tp, OCP_PHY_LOCK, data); + return 0; +} - sram_write(tp, key_addr, 0x0000); +static int rtl_post_ram_code(struct r8152 *tp, u16 key_addr, bool wait) +{ + rtl_patch_key_set(tp, key_addr, 0); - r8153_patch_request(tp, false); + rtl_phy_patch_request(tp, false, wait); ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base); @@ -4007,7 +4024,7 @@ static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac) dev_dbg(&tp->intf->dev, "successfully applied %s\n", mac->info); } -static void rtl8152_apply_firmware(struct r8152 *tp) +static void rtl8152_apply_firmware(struct r8152 *tp, bool power_cut) { struct rtl_fw *rtl_fw = &tp->rtl_fw; const struct firmware *fw; @@ -4038,12 +4055,11 @@ static void rtl8152_apply_firmware(struct r8152 *tp) case RTL_FW_PHY_START: key = (struct fw_phy_patch_key *)block; key_addr = __le16_to_cpu(key->key_reg); - r8153_pre_ram_code(tp, key_addr, - __le16_to_cpu(key->key_data)); + rtl_pre_ram_code(tp, key_addr, __le16_to_cpu(key->key_data), !power_cut); break; case RTL_FW_PHY_STOP: WARN_ON(!key_addr); - r8153_post_ram_code(tp, key_addr); + rtl_post_ram_code(tp, key_addr, !power_cut); break; case RTL_FW_PHY_NC: rtl8152_fw_phy_nc_apply(tp, (struct fw_phy_nc *)block); @@ -4248,7 +4264,7 @@ static void rtl8152_disable(struct r8152 *tp) static void r8152b_hw_phy_cfg(struct r8152 *tp) { - rtl8152_apply_firmware(tp); + rtl8152_apply_firmware(tp, false); rtl_eee_enable(tp, tp->eee_en); r8152_aldps_en(tp, true); r8152b_enable_fc(tp); @@ -4530,7 +4546,7 @@ static void r8153_hw_phy_cfg(struct r8152 *tp) /* disable EEE before updating the PHY parameters */ rtl_eee_enable(tp, false); - rtl8152_apply_firmware(tp); + rtl8152_apply_firmware(tp, false); if (tp->version == RTL_VER_03) { data = ocp_reg_read(tp, OCP_EEE_CFG); @@ -4598,13 +4614,37 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) u32 ocp_data; u16 data; + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); + if (ocp_data & PCUT_STATUS) { + ocp_data &= ~PCUT_STATUS; + ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); + } + /* disable ALDPS before updating the PHY parameters */ r8153_aldps_en(tp, false); /* disable EEE before updating the PHY parameters */ rtl_eee_enable(tp, false); - rtl8152_apply_firmware(tp); + /* U1/U2/L1 idle timer. 500 us */ + ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); + + data = r8153_phy_status(tp, 0); + + switch (data) { + case PHY_STAT_PWRDN: + case PHY_STAT_EXT_INIT: + rtl8152_apply_firmware(tp, true); + + data = r8152_mdio_read(tp, MII_BMCR); + data &= ~BMCR_PDOWN; + r8152_mdio_write(tp, MII_BMCR, data); + break; + case PHY_STAT_LAN_ON: + default: + rtl8152_apply_firmware(tp, false); + break; + } r8153b_green_en(tp, test_bit(GREEN_ETHERNET, &tp->flags)); @@ -4645,7 +4685,7 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); /* Advnace EEE */ - if (!r8153_patch_request(tp, true)) { + if (!rtl_phy_patch_request(tp, true, true)) { data = ocp_reg_read(tp, OCP_POWER_CFG); data |= EEE_CLKDIV_EN; ocp_reg_write(tp, OCP_POWER_CFG, data); @@ -4662,7 +4702,7 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) ocp_reg_write(tp, OCP_SYSCLK_CFG, clk_div_expo(5)); tp->ups_info._250m_ckdiv = true; - r8153_patch_request(tp, false); + rtl_phy_patch_request(tp, false, true); } if (tp->eee_en) @@ -5027,7 +5067,7 @@ static void rtl8153b_up(struct r8152 *tp) r8153_aldps_en(tp, true); - if (tp->udev->speed != USB_SPEED_HIGH) + if (tp->udev->speed >= USB_SPEED_SUPER) r8153b_u1u2en(tp, true); } @@ -5530,9 +5570,6 @@ static void r8153b_init(struct r8152 *tp) /* MSC timer = 0xfff * 8ms = 32760 ms */ ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); - /* U1/U2/L1 idle timer. 500 us */ - ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); - r8153b_power_cut_en(tp, false); r8153b_ups_en(tp, false); r8153_queue_wake(tp, false); @@ -5546,8 +5583,9 @@ static void r8153b_init(struct r8152 *tp) ocp_data |= POLL_LINK_CHG; ocp_write_word(tp, MCU_TYPE_PLA, PLA_EXTRA_STATUS, ocp_data); - if (tp->udev->speed != USB_SPEED_HIGH) + if (tp->udev->speed >= USB_SPEED_SUPER) r8153b_u1u2en(tp, true); + usb_enable_lpm(tp->udev); /* MAC clock speed down */ @@ -5730,6 +5768,9 @@ static int rtl8152_runtime_suspend(struct r8152 *tp) struct net_device *netdev = tp->netdev; int ret = 0; + if (!tp->rtl_ops.autosuspend_en) + return -EBUSY; + set_bit(SELECTIVE_SUSPEND, &tp->flags); smp_mb__after_atomic(); @@ -6129,6 +6170,11 @@ rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) struct r8152 *tp = netdev_priv(net); int ret; + if (!tp->rtl_ops.eee_get) { + ret = -EOPNOTSUPP; + goto out; + } + ret = usb_autopm_get_interface(tp->intf); if (ret < 0) goto out; @@ -6151,6 +6197,11 @@ rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata) struct r8152 *tp = netdev_priv(net); int ret; + if (!tp->rtl_ops.eee_set) { + ret = -EOPNOTSUPP; + goto out; + } + ret = usb_autopm_get_interface(tp->intf); if (ret < 0) goto out; @@ -6550,7 +6601,7 @@ static int rtl_ops_init(struct r8152 *tp) default: ret = -ENODEV; - netif_err(tp, probe, tp->netdev, "Unknown Device\n"); + dev_err(&tp->intf->dev, "Unknown Device\n"); break; } @@ -6714,7 +6765,7 @@ static int rtl8152_probe(struct usb_interface *intf, mutex_init(&tp->control); INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t); INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t); - tasklet_init(&tp->tx_tl, bottom_half, (unsigned long)tp); + tasklet_setup(&tp->tx_tl, bottom_half); tasklet_disable(&tp->tx_tl); netdev->netdev_ops = &rtl8152_netdev_ops; @@ -6807,7 +6858,7 @@ static int rtl8152_probe(struct usb_interface *intf, ret = register_netdev(netdev); if (ret != 0) { - netif_err(tp, probe, netdev, "couldn't register the device\n"); + dev_err(&intf->dev, "couldn't register the device\n"); goto out1; } @@ -6877,6 +6928,7 @@ static const struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x721e)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0xa387)}, {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)}, {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, diff --git a/drivers/net/usb/r8153_ecm.c b/drivers/net/usb/r8153_ecm.c index 2c3fabd38b16..20b2df8d74ae 100644 --- a/drivers/net/usb/r8153_ecm.c +++ b/drivers/net/usb/r8153_ecm.c @@ -122,12 +122,20 @@ static const struct driver_info r8153_info = { }; static const struct usb_device_id products[] = { +/* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */ { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_REALTEK, 0x8153, USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&r8153_info, }, +/* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_LENOVO, 0x721e, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&r8153_info, +}, + { }, /* END */ }; MODULE_DEVICE_TABLE(usb, products); diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 6609d21ef894..f813ca9dec53 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -387,7 +387,7 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) reply_len = sizeof *phym; retval = rndis_query(dev, intf, u.buf, RNDIS_OID_GEN_PHYSICAL_MEDIUM, - 0, (void **) &phym, &reply_len); + reply_len, (void **)&phym, &reply_len); if (retval != 0 || !phym) { /* OID is optional so don't fail here. */ phym_unspec = cpu_to_le32(RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED); diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index bf8a60533f3e..7656f2a3afd9 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -577,9 +577,9 @@ static void free_skb_pool(rtl8150_t *dev) dev_kfree_skb(dev->rx_skb_pool[i]); } -static void rx_fixup(unsigned long data) +static void rx_fixup(struct tasklet_struct *t) { - struct rtl8150 *dev = (struct rtl8150 *)data; + struct rtl8150 *dev = from_tasklet(dev, t, tl); struct sk_buff *skb; int status; @@ -878,7 +878,7 @@ static int rtl8150_probe(struct usb_interface *intf, return -ENOMEM; } - tasklet_init(&dev->tl, rx_fixup, (unsigned long)dev); + tasklet_setup(&dev->tl, rx_fixup); spin_lock_init(&dev->rx_pool_lock); dev->udev = udev; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 1447da1d5729..b4c8080e6f87 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1539,11 +1539,11 @@ static void usbnet_bh (struct timer_list *t) } } -static void usbnet_bh_tasklet(unsigned long data) +static void usbnet_bh_tasklet(struct tasklet_struct *t) { - struct timer_list *t = (struct timer_list *)data; + struct usbnet *dev = from_tasklet(dev, t, bh); - usbnet_bh(t); + usbnet_bh(&dev->delay); } @@ -1673,8 +1673,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) skb_queue_head_init (&dev->txq); skb_queue_head_init (&dev->done); skb_queue_head_init(&dev->rxq_pause); - dev->bh.func = usbnet_bh_tasklet; - dev->bh.data = (unsigned long)&dev->delay; + tasklet_setup(&dev->bh, usbnet_bh_tasklet); INIT_WORK (&dev->kevent, usbnet_deferred_kevent); init_usb_anchor(&dev->deferred); timer_setup(&dev->delay, usbnet_bh, 0); @@ -1964,12 +1963,12 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, cmd, reqtype, value, index, buf, size, USB_CTRL_GET_TIMEOUT); if (err > 0 && err <= size) { - if (data) - memcpy(data, buf, err); - else - netdev_dbg(dev->net, - "Huh? Data requested but thrown away.\n"); - } + if (data) + memcpy(data, buf, err); + else + netdev_dbg(dev->net, + "Huh? Data requested but thrown away.\n"); + } kfree(buf); out: return err; |