diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 6ce8f4f0c70e..8179516b819c 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -53,6 +53,7 @@
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc.h>
 #include <linux/usb/cdc_ncm.h>
+#include <linux/acpi.h>
 
 #if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
 static bool prefer_mbim = true;
@@ -814,6 +815,177 @@ static const struct net_device_ops cdc_ncm_netdev_ops = {
 	.ndo_validate_addr   = eth_validate_addr,
 };
 
+int acpi_mac_passthru_invalid(void)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	int ret = -EINVAL;
+
+	/* returns _AUXMAC_#AABBCCDDEEFF# */
+	status = acpi_evaluate_object(NULL, "\\_SB.AMAC", NULL, &buffer);
+	obj = (union acpi_object *)buffer.pointer;
+
+	if (!ACPI_SUCCESS(status))
+		return -ENODEV;
+	if (obj->type != ACPI_TYPE_BUFFER || obj->string.length != 0x17) {
+		acpi_info("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) {
+		acpi_info("Invalid header when reading pass-thru MAC addr\n");
+		goto amacout;
+	}
+	/* return success, otherwise return non-zero if invalid buffer read or
+	 * MAC pass through is disabled in BIOS
+	 */
+	ret = 0;
+
+amacout:
+	kfree(obj);
+	return ret;
+}
+
+int get_acpi_mac_passthru(char *MACAddress)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	int ret = -EINVAL;
+	unsigned char buf[6];
+
+	/* returns _AUXMAC_#AABBCCDDEEFF# */
+	status = acpi_evaluate_object(NULL, "\\_SB.AMAC", NULL, &buffer);
+	obj = (union acpi_object *)buffer.pointer;
+
+	if (!ACPI_SUCCESS(status))
+		return -ENODEV;
+
+	ret = hex2bin(buf, obj->string.pointer + 9, 6);
+	if (!(ret == 0 && is_valid_ether_addr(buf))) {
+		acpi_info("Invalid MAC for pass-thru MAC addr: %d, %pM\n",
+			  ret, buf);
+		ret = -EINVAL;
+		goto amacout;
+	}
+	memcpy(MACAddress, buf, 6);
+	acpi_info("Pass-thru MAC addr %pM\n", MACAddress);
+
+amacout:
+	kfree(obj);
+	return ret;
+}
+
+/* Provide method to get MAC address from the USB device's ethernet controller.
+ * If the device supports CDC_GET_ADDRESS, we should receive just six bytes.
+ * Otherwise, use the prior method by asking for the descriptor.
+ */
+static int cdc_ncm_get_ethernet_address(struct usbnet *dev,
+					struct cdc_ncm_ctx *ctx)
+{
+	int ret;
+	u8 iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
+
+	ret = usbnet_read_cmd(dev, USB_CDC_GET_NET_ADDRESS,
+			      USB_DIR_IN | USB_TYPE_CLASS
+			      | USB_RECIP_INTERFACE, 0,
+			      iface_no, dev->net->dev_addr, ETH_ALEN);
+
+	if (ret == ETH_ALEN) {
+		ret = 0;	/* success */
+	} else {
+		ret = usbnet_get_ethernet_addr(dev,
+				ctx->ether_desc->iMACAddress);
+	}
+
+	return ret;
+}
+
+/* Provide method to push MAC address to the USB device's ethernet controller.
+ * If the device does not support CDC_SET_ADDRESS, there is no harm and we
+ * proceed as before.
+ */
+static int cdc_ncm_set_ethernet_address(struct usbnet *dev,
+					struct sockaddr *addr)
+{
+	int ret;
+	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+	u8 iface_no_data = ctx->data->cur_altsetting->desc.bInterfaceNumber;
+	u8 iface_no_control = ctx->control->cur_altsetting->desc.bInterfaceNumber;
+	int temp;
+
+	/* The host shall only send SET_NET_ADDRESS command while
+	 * the NCM Data Interface is in alternate setting 0.
+	 */
+	temp = usb_set_interface(dev->udev, iface_no_data, 0);
+	if (temp) {
+		dev_dbg(&dev->udev->dev, "set interface failed\n");
+		return -ENODEV;
+		}
+
+	ret = usbnet_write_cmd(dev, USB_CDC_SET_NET_ADDRESS,
+			       USB_DIR_OUT | USB_TYPE_CLASS
+			       | USB_RECIP_INTERFACE, 0,
+			       iface_no_control, addr->sa_data, ETH_ALEN);
+
+	if (ret == ETH_ALEN)
+		ret = 0;	// success
+	else if (ret < 0)
+		dev_dbg(&dev->udev->dev, "bad MAC address put, %d\n", ret);
+
+	/* restore alternate setting.
+	 * The NCM data altsetting is fixed, so we hard-coded it.
+	 */
+	temp = usb_set_interface(dev->udev, iface_no_data,
+			CDC_NCM_DATA_ALTSETTING_NCM);
+	if (temp) {
+		dev_dbg(&dev->udev->dev, "set interface failed\n");
+		return -ENODEV;
+		}
+
+	return ret;
+}
+
+static int cdc_ncm_determine_ethernet_addr(struct usb_interface *intf)
+{
+	struct sockaddr sa;
+	struct usbnet *dev = usb_get_intfdata(intf);
+	struct cdc_ncm_ctx *ctx;
+	int ret = 0;
+
+	if (!dev)
+		return 0;
+
+	/* MAC pass through function only apply to Realtek RTL8153-DD chip */
+	if (!(dev->udev->descriptor.idVendor == 0x0bda
+		&& dev->udev->descriptor.idProduct == 0x8153
+		&& (dev->udev->descriptor.bcdDevice & 0xff00) == 0x3300))
+		return 0;
+
+	ctx = (struct cdc_ncm_ctx *)dev->data[0];
+	if (!ctx->ether_desc)
+		return 0;
+
+	ret = cdc_ncm_get_ethernet_address(dev, ctx);
+	if (ret) {
+		dev_dbg(&intf->dev, "failed to get mac address\n");
+		return ret;
+	}
+
+	if (!get_acpi_mac_passthru(sa.sa_data)) {
+		if (memcmp(dev->net->dev_addr, sa.sa_data, ETH_ALEN) != 0) {
+			if (!cdc_ncm_set_ethernet_address(dev, &sa))
+				memcpy(dev->net->dev_addr, sa.sa_data, ETH_ALEN);
+		}
+	}
+
+	dev_info(&intf->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
+
+	return 0;
+}
+
 int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags)
 {
 	struct cdc_ncm_ctx *ctx;
@@ -945,6 +1117,9 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
 		}
 		dev_info(&intf->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
 	}
+	/* Execute MAC pass thru only if enabled in BIOS */
+	if (acpi_mac_passthru_invalid() == 0)
+		cdc_ncm_determine_ethernet_addr(intf);
 
 	/* finish setting up the device specific data */
 	cdc_ncm_setup(dev);
@@ -1892,6 +2067,25 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
 	}
 }
 
+static int cdc_ncm_resume(struct usb_interface *intf)
+{
+	int ret;
+
+	ret = usbnet_resume(intf);
+	if (ret == 0)
+		cdc_ncm_determine_ethernet_addr(intf);
+
+	return ret;
+}
+
+static int cdc_ncm_post_reset(struct usb_interface *intf)
+{
+	/* reset the MAC address in case of policy change */
+	cdc_ncm_determine_ethernet_addr(intf);
+
+	return 0;
+}
+
 static const struct driver_info cdc_ncm_info = {
 	.description = "CDC NCM (NO ZLP)",
 	.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
@@ -2051,8 +2245,9 @@ static struct usb_driver cdc_ncm_driver = {
 	.probe = usbnet_probe,
 	.disconnect = usbnet_disconnect,
 	.suspend = usbnet_suspend,
-	.resume = usbnet_resume,
-	.reset_resume =	usbnet_resume,
+	.resume = cdc_ncm_resume,
+	.reset_resume =	cdc_ncm_resume,
+	.post_reset = cdc_ncm_post_reset,
 	.supports_autosuspend = 1,
 	.disable_hub_initiated_lpm = 1,
 };
