diff options
Diffstat (limited to 'drivers/net/usb/r8152.c')
-rw-r--r-- | drivers/net/usb/r8152.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index b9f526ed0d30..ac079395c8d4 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -670,6 +670,7 @@ enum rtl8152_flags { SCHEDULE_TASKLET, GREEN_ETHERNET, DELL_TB_RX_AGG_BUG, + LENOVO_MACPASSTHRU, }; /* Define these values to match your device */ @@ -1408,38 +1409,52 @@ static int vendor_mac_passthru_addr_read(struct r8152 *tp, struct sockaddr *sa) int ret = -EINVAL; u32 ocp_data; unsigned char buf[6]; - - /* test for -AD variant of RTL8153 */ - ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); - if ((ocp_data & AD_MASK) == 0x1000) { - /* test for MAC address pass-through bit */ - ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, EFUSE); - if ((ocp_data & PASS_THRU_MASK) != 1) { - netif_dbg(tp, probe, tp->netdev, - "No efuse for RTL8153-AD MAC pass through\n"); - return -ENODEV; - } + char *mac_obj_name; + acpi_object_type mac_obj_type; + int mac_strlen; + + if (test_bit(LENOVO_MACPASSTHRU, &tp->flags)) { + mac_obj_name = "\\MACA"; + mac_obj_type = ACPI_TYPE_STRING; + mac_strlen = 0x16; } else { - /* test for RTL8153-BND and RTL8153-BD */ - ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1); - if ((ocp_data & BND_MASK) == 0 && (ocp_data & BD_MASK) == 0) { - netif_dbg(tp, probe, tp->netdev, - "Invalid variant for MAC pass through\n"); - return -ENODEV; + /* test for -AD variant of RTL8153 */ + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); + if ((ocp_data & AD_MASK) == 0x1000) { + /* test for MAC address pass-through bit */ + ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, EFUSE); + if ((ocp_data & PASS_THRU_MASK) != 1) { + netif_dbg(tp, probe, tp->netdev, + "No efuse for RTL8153-AD MAC pass through\n"); + return -ENODEV; + } + } else { + /* test for RTL8153-BND and RTL8153-BD */ + ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1); + if ((ocp_data & BND_MASK) == 0 && (ocp_data & BD_MASK) == 0) { + netif_dbg(tp, probe, tp->netdev, + "Invalid variant for MAC pass through\n"); + return -ENODEV; + } } + + mac_obj_name = "\\_SB.AMAC"; + mac_obj_type = ACPI_TYPE_BUFFER; + mac_strlen = 0x17; } /* returns _AUXMAC_#AABBCCDDEEFF# */ - status = acpi_evaluate_object(NULL, "\\_SB.AMAC", NULL, &buffer); + status = acpi_evaluate_object(NULL, mac_obj_name, NULL, &buffer); obj = (union acpi_object *)buffer.pointer; if (!ACPI_SUCCESS(status)) return -ENODEV; - if (obj->type != ACPI_TYPE_BUFFER || obj->string.length != 0x17) { + if (obj->type != mac_obj_type || obj->string.length != mac_strlen) { netif_warn(tp, probe, tp->netdev, "Invalid buffer for pass-thru MAC addr: (%d, %d)\n", obj->type, obj->string.length); goto amacout; } + if (strncmp(obj->string.pointer, "_AUXMAC_#", 9) != 0 || strncmp(obj->string.pointer + 0x15, "#", 1) != 0) { netif_warn(tp, probe, tp->netdev, @@ -6629,6 +6644,10 @@ static int rtl8152_probe(struct usb_interface *intf, netdev->hw_features &= ~NETIF_F_RXCSUM; } + if (le16_to_cpu(udev->descriptor.idVendor) == VENDOR_ID_LENOVO && + le16_to_cpu(udev->descriptor.idProduct) == 0x3082) + set_bit(LENOVO_MACPASSTHRU, &tp->flags); + if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 && udev->serial && (!strcmp(udev->serial, "000001000000") || !strcmp(udev->serial, "000002000000"))) { @@ -6755,6 +6774,7 @@ static const struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3069)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3082)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)}, |