diff mbox

[v2] r8152: Add support for setting MAC to system's Auxiliary MAC address

Message ID 1464886687-16284-2-git-send-email-mario_limonciello@dell.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Mario Limonciello June 2, 2016, 4:58 p.m. UTC
Dell systems with Type-C ports have support for a persistent system
specific MAC address when used with Dell Type-C docks and dongles.
This means a dock plugged into two different systems will show different
(but persistent) MAC addresses.  Dell Type-C docks and dongles use the
r8152 driver.

This information for the system's persistent MAC address is burned in when
the HW is built and available under _SB\AMAC in the DSDT at runtime.

More information about the technology is available here:
http://www.dell.com/support/article/us/en/04/SLN301147

Signed-off-by: Mario Limonciello <mario_limonciello@dell.com>
---
 drivers/net/usb/r8152.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

Comments

gregkh@linuxfoundation.org June 2, 2016, 5:48 p.m. UTC | #1
On Thu, Jun 02, 2016 at 11:58:07AM -0500, Mario Limonciello wrote:
> Dell systems with Type-C ports have support for a persistent system
> specific MAC address when used with Dell Type-C docks and dongles.
> This means a dock plugged into two different systems will show different
> (but persistent) MAC addresses.  Dell Type-C docks and dongles use the
> r8152 driver.
> 
> This information for the system's persistent MAC address is burned in when
> the HW is built and available under _SB\AMAC in the DSDT at runtime.
> 
> More information about the technology is available here:
> http://www.dell.com/support/article/us/en/04/SLN301147
> 
> Signed-off-by: Mario Limonciello <mario_limonciello@dell.com>
> ---
>  drivers/net/usb/r8152.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
> index 3f9f6ed..6dea542 100644
> --- a/drivers/net/usb/r8152.c
> +++ b/drivers/net/usb/r8152.c
> @@ -26,6 +26,8 @@
>  #include <linux/mdio.h>
>  #include <linux/usb/cdc.h>
>  #include <linux/suspend.h>
> +#include <linux/acpi.h>
> +#include <linux/dmi.h>
>  
>  /* Information for net-next */
>  #define NETNEXT_VERSION		"08"
> @@ -500,6 +502,7 @@ enum rtl8152_flags {
>  	SELECTIVE_SUSPEND,
>  	PHY_RESET,
>  	SCHEDULE_NAPI,
> +	MAC_PASSTHRU = 0,

Does setting that to 0 really work?  You just did this for two enum
values, what is the compiler supposed to do?

>  };
>  
>  /* Define these values to match your device */
> @@ -653,6 +656,7 @@ enum tx_csum_stat {
>   */
>  static const int multicast_filter_limit = 32;
>  static unsigned int agg_buf_sz = 16384;
> +static bool mac_passthru_active;

very generic name for a platform-specific feature :(


>  
>  #define RTL_LIMITED_TSO_SIZE	(agg_buf_sz - sizeof(struct tx_desc) - \
>  				 VLAN_ETH_HLEN - VLAN_HLEN)
> @@ -1030,6 +1034,49 @@ out1:
>  	return ret;
>  }
>  
> +static int get_auxiliary_addr(struct r8152 *tp, struct sockaddr *sa)

What about the platform mac address api that was pointed out?

> +{
> +	acpi_status status;
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object *obj;
> +	int ret = -1;
> +	unsigned char buf[6];
> +
> +	if (!dmi_name_in_vendors("Dell Inc.") || mac_passthru_active)
> +		return -1;

Don't make up random error values, please use "real" ones.

And you want to check this for all Dell devices?  Please be model
specific, I doubt a bunch of Dell servers wants to run this code...

> +
> +	/* returns _AUXMAC_#AABBCCDDEEFF# */
> +	status = acpi_evaluate_object(NULL, "\\_SB.AMAC", NULL, &buffer);
> +	obj = (union acpi_object *)buffer.pointer;
> +	if (ACPI_SUCCESS(status)) {
> +		if (obj->type != ACPI_TYPE_BUFFER ||
> +		    obj->string.length != 0x17) {
> +			pr_warn("r8152: get_auxiliary_addr: Invalid buffer");
> +			goto amacout;
> +		}
> +		if (strncmp(obj->string.pointer, "_AUXMAC_#", 9) != 0) {
> +			pr_warn("r8152: get_auxiliary_addr: Invalid header");
> +			goto amacout;
> +		}
> +		ret = hex2bin(buf, obj->string.pointer + 9, 6);
> +		if (ret < 0) {
> +			pr_warn("r8152: get_auxiliary_addr: Invalid MAC");
> +			goto amacout;
> +		}
> +		memcpy(sa->sa_data, buf, 6);
> +		ether_addr_copy(tp->netdev->dev_addr, sa->sa_data);
> +		netdev_info(tp->netdev, "Using system MAC address %pM\n",
> +			    sa->sa_data);
> +		set_bit(MAC_PASSTHRU, &tp->flags);
> +		mac_passthru_active = true;
> +		ret = 1;

1 is not a "all is good" return value.

> +	}
> +
> +amacout:
> +	kfree(obj);
> +	return ret;
> +}
> +
>  static int set_ethernet_addr(struct r8152 *tp)
>  {
>  	struct net_device *dev = tp->netdev;
> @@ -1041,6 +1088,10 @@ static int set_ethernet_addr(struct r8152 *tp)
>  	else
>  		ret = pla_ocp_read(tp, PLA_BACKUP, 8, sa.sa_data);
>  
> +	/* if system provides auxiliary MAC address */
> +	if (get_auxiliary_addr(tp, &sa))
> +		ret = 0;

	ret = my_dell_specific_function();

But again, I don't like this, but I'm not the network subsystem
maintainer, I'll defer to them as to if this is something they want in
individual drivers...

thanks,

greg k-h
Mario Limonciello June 2, 2016, 6:32 p.m. UTC | #2
> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Thursday, June 2, 2016 12:48 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: hayeswang@realtek.com; LKML <linux-kernel@vger.kernel.org>; Netdev
> <netdev@vger.kernel.org>; Linux USB <linux-usb@vger.kernel.org>;
> pali.rohar@gmail.com; anthony.wong@canonical.com
> Subject: Re: [PATCH v2] r8152: Add support for setting MAC to system's
> Auxiliary MAC address
> 
> On Thu, Jun 02, 2016 at 11:58:07AM -0500, Mario Limonciello wrote:
> > Dell systems with Type-C ports have support for a persistent system
> > specific MAC address when used with Dell Type-C docks and dongles.
> > This means a dock plugged into two different systems will show different
> > (but persistent) MAC addresses.  Dell Type-C docks and dongles use the
> > r8152 driver.
> >
> > This information for the system's persistent MAC address is burned in
> when
> > the HW is built and available under _SB\AMAC in the DSDT at runtime.
> >
> > More information about the technology is available here:
> > http://www.dell.com/support/article/us/en/04/SLN301147
> >
> > Signed-off-by: Mario Limonciello <mario_limonciello@dell.com>
> > ---
> >  drivers/net/usb/r8152.c | 53
> +++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 53 insertions(+)
> >
> > diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
> > index 3f9f6ed..6dea542 100644
> > --- a/drivers/net/usb/r8152.c
> > +++ b/drivers/net/usb/r8152.c
> > @@ -26,6 +26,8 @@
> >  #include <linux/mdio.h>
> >  #include <linux/usb/cdc.h>
> >  #include <linux/suspend.h>
> > +#include <linux/acpi.h>
> > +#include <linux/dmi.h>
> >
> >  /* Information for net-next */
> >  #define NETNEXT_VERSION		"08"
> > @@ -500,6 +502,7 @@ enum rtl8152_flags {
> >  	SELECTIVE_SUSPEND,
> >  	PHY_RESET,
> >  	SCHEDULE_NAPI,
> > +	MAC_PASSTHRU = 0,
> 
> Does setting that to 0 really work?  You just did this for two enum
> values, what is the compiler supposed to do?

Very silly of me.  I was rushing to send a v2.  
I'm surprised this worked.  Shouldn't be assigned to anything.

> 
> >  };
> >
> >  /* Define these values to match your device */
> > @@ -653,6 +656,7 @@ enum tx_csum_stat {
> >   */
> >  static const int multicast_filter_limit = 32;
> >  static unsigned int agg_buf_sz = 16384;
> > +static bool mac_passthru_active;
> 
> very generic name for a platform-specific feature :(

Once this is broken up into an x86 platform provided method I'll rename this 
to platform_mac_active (or something similar).

> 
> 
> >
> >  #define RTL_LIMITED_TSO_SIZE	(agg_buf_sz - sizeof(struct tx_desc) -
> \
> >  				 VLAN_ETH_HLEN - VLAN_HLEN)
> > @@ -1030,6 +1034,49 @@ out1:
> >  	return ret;
> >  }
> >
> > +static int get_auxiliary_addr(struct r8152 *tp, struct sockaddr *sa)
> 
> What about the platform mac address api that was pointed out?

I mentioned this in the cover letter - I haven't gotten a chance to move it over there yet.
I sent v2 before I did so that you can see what I've been doing as it was relevant to your
other comments.

> 
> > +{
> > +	acpi_status status;
> > +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> > +	union acpi_object *obj;
> > +	int ret = -1;
> > +	unsigned char buf[6];
> > +
> > +	if (!dmi_name_in_vendors("Dell Inc.") || mac_passthru_active)
> > +		return -1;
> 
> Don't make up random error values, please use "real" ones.

OK.

> 
> And you want to check this for all Dell devices?  Please be model
> specific, I doubt a bunch of Dell servers wants to run this code...
> 

Tracking model specific is really going to turn into a giant list never ending list.
To drill down more specifically, I can match on chassis too.

> > +
> > +	/* returns _AUXMAC_#AABBCCDDEEFF# */
> > +	status = acpi_evaluate_object(NULL, "\\_SB.AMAC", NULL, &buffer);
> > +	obj = (union acpi_object *)buffer.pointer;
> > +	if (ACPI_SUCCESS(status)) {
> > +		if (obj->type != ACPI_TYPE_BUFFER ||
> > +		    obj->string.length != 0x17) {
> > +			pr_warn("r8152: get_auxiliary_addr: Invalid buffer");
> > +			goto amacout;
> > +		}
> > +		if (strncmp(obj->string.pointer, "_AUXMAC_#", 9) != 0) {
> > +			pr_warn("r8152: get_auxiliary_addr: Invalid header");
> > +			goto amacout;
> > +		}
> > +		ret = hex2bin(buf, obj->string.pointer + 9, 6);
> > +		if (ret < 0) {
> > +			pr_warn("r8152: get_auxiliary_addr: Invalid MAC");
> > +			goto amacout;
> > +		}
> > +		memcpy(sa->sa_data, buf, 6);
> > +		ether_addr_copy(tp->netdev->dev_addr, sa->sa_data);
> > +		netdev_info(tp->netdev, "Using system MAC address
> %pM\n",
> > +			    sa->sa_data);
> > +		set_bit(MAC_PASSTHRU, &tp->flags);
> > +		mac_passthru_active = true;
> > +		ret = 1;
> 
> 1 is not a "all is good" return value.

OK will switch to 0.
Andrew Lunn June 2, 2016, 7:02 p.m. UTC | #3
> > And you want to check this for all Dell devices?  Please be model
> > specific, I doubt a bunch of Dell servers wants to run this code...
> > 
> 
> Tracking model specific is really going to turn into a giant list never ending list.
> To drill down more specifically, I can match on chassis too.

Does Dell happen to use its own USB Vendor ID for the USB device in
the dock? You could go at this problem from the other direction if it
does have a unique vendor ID.

     Andrew
Mario Limonciello June 2, 2016, 7:04 p.m. UTC | #4
> -----Original Message-----
> From: Andrew Lunn [mailto:andrew@lunn.ch]
> Sent: Thursday, June 2, 2016 2:03 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: gregkh@linuxfoundation.org; hayeswang@realtek.com; linux-
> kernel@vger.kernel.org; netdev@vger.kernel.org; linux-
> usb@vger.kernel.org; pali.rohar@gmail.com; anthony.wong@canonical.com
> Subject: Re: [PATCH v2] r8152: Add support for setting MAC to system's
> Auxiliary MAC address
> 
> > > And you want to check this for all Dell devices?  Please be model
> > > specific, I doubt a bunch of Dell servers wants to run this code...
> > >
> >
> > Tracking model specific is really going to turn into a giant list never ending
> list.
> > To drill down more specifically, I can match on chassis too.
> 
> Does Dell happen to use its own USB Vendor ID for the USB device in
> the dock? You could go at this problem from the other direction if it
> does have a unique vendor ID.
> 
>      Andrew

Unfortunately it's not a Dell specific VID/PID.  I'm asking around to find out
if there is something else identifiable about this dock's NIC (maybe that r8152 
can query).
Andrew Lunn June 2, 2016, 7:09 p.m. UTC | #5
On Thu, Jun 02, 2016 at 07:04:32PM +0000, Mario_Limonciello@Dell.com wrote:
> > -----Original Message-----
> > From: Andrew Lunn [mailto:andrew@lunn.ch]
> > Sent: Thursday, June 2, 2016 2:03 PM
> > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: gregkh@linuxfoundation.org; hayeswang@realtek.com; linux-
> > kernel@vger.kernel.org; netdev@vger.kernel.org; linux-
> > usb@vger.kernel.org; pali.rohar@gmail.com; anthony.wong@canonical.com
> > Subject: Re: [PATCH v2] r8152: Add support for setting MAC to system's
> > Auxiliary MAC address
> > 
> > > > And you want to check this for all Dell devices?  Please be model
> > > > specific, I doubt a bunch of Dell servers wants to run this code...
> > > >
> > >
> > > Tracking model specific is really going to turn into a giant list never ending
> > list.
> > > To drill down more specifically, I can match on chassis too.
> > 
> > Does Dell happen to use its own USB Vendor ID for the USB device in
> > the dock? You could go at this problem from the other direction if it
> > does have a unique vendor ID.
> > 
> >      Andrew
> 
> Unfortunately it's not a Dell specific VID/PID.  I'm asking around to find out
> if there is something else identifiable about this dock's NIC (maybe that r8152 
> can query).

lsusb -v

I assume there is a USB hub in the dock, maybe that has a Dell VID?
Going one level up the USB tree hierarchy should not be too hard.

      Andrew
gregkh@linuxfoundation.org June 3, 2016, 2:01 a.m. UTC | #6
On Thu, Jun 02, 2016 at 06:32:42PM +0000, Mario_Limonciello@Dell.com wrote:
> > And you want to check this for all Dell devices?  Please be model
> > specific, I doubt a bunch of Dell servers wants to run this code...
> > 
> 
> Tracking model specific is really going to turn into a giant list never ending list.
> To drill down more specifically, I can match on chassis too.

Yes, as this is a vendor/platform-specific "quirk", you will have to
update it for each and every individual device you want it enabled as it
is so different from what all other drivers do.

thanks,

greg k-h
Hayes Wang June 3, 2016, 9:43 a.m. UTC | #7
Mario Limonciello [mailto:mario_limonciello@dell.com]
> Sent: Friday, June 03, 2016 12:58 AM
[...]
> @@ -500,6 +502,7 @@ enum rtl8152_flags {
>  	SELECTIVE_SUSPEND,
>  	PHY_RESET,
>  	SCHEDULE_NAPI,
> +	MAC_PASSTHRU = 0,

I don't think you have to give this a value.

>  };
> 
[...]
>  static int set_ethernet_addr(struct r8152 *tp)
>  {
>  	struct net_device *dev = tp->netdev;
> @@ -1041,6 +1088,10 @@ static int set_ethernet_addr(struct r8152 *tp)
>  	else
>  		ret = pla_ocp_read(tp, PLA_BACKUP, 8, sa.sa_data);
> 
> +	/* if system provides auxiliary MAC address */
> +	if (get_auxiliary_addr(tp, &sa))
> +		ret = 0;

It still has problem when tp->version == RTL_VER_01.
First, you would read the current MAC address (MAC1) to sa.sa_data.
Then sa.sa_data may be modified by MAC2 after get_auxiliary_addr().
However, the MAC2 wouldn't be set to the device, because

		if (tp->version == RTL_VER_01)
			ether_addr_copy(dev->dev_addr, sa.sa_data);

Therefore, you would find that dev_addr is MAC2, and the device
uses MAC1.

Best Regards,
Hayes
Mario Limonciello June 3, 2016, 2:44 p.m. UTC | #8
> -----Original Message-----
> From: Andrew Lunn [mailto:andrew@lunn.ch]
> Sent: Thursday, June 2, 2016 2:10 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: gregkh@linuxfoundation.org; hayeswang@realtek.com; linux-
> kernel@vger.kernel.org; netdev@vger.kernel.org; linux-
> usb@vger.kernel.org; pali.rohar@gmail.com; anthony.wong@canonical.com
> Subject: Re: [PATCH v2] r8152: Add support for setting MAC to system's
> Auxiliary MAC address
> 
> On Thu, Jun 02, 2016 at 07:04:32PM +0000, Mario_Limonciello@Dell.com
> wrote:
> > > -----Original Message-----
> > > From: Andrew Lunn [mailto:andrew@lunn.ch]
> > > Sent: Thursday, June 2, 2016 2:03 PM
> > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > Cc: gregkh@linuxfoundation.org; hayeswang@realtek.com; linux-
> > > kernel@vger.kernel.org; netdev@vger.kernel.org; linux-
> > > usb@vger.kernel.org; pali.rohar@gmail.com;
> anthony.wong@canonical.com
> > > Subject: Re: [PATCH v2] r8152: Add support for setting MAC to system's
> > > Auxiliary MAC address
> > >
> > > > > And you want to check this for all Dell devices?  Please be model
> > > > > specific, I doubt a bunch of Dell servers wants to run this code...
> > > > >
> > > >
> > > > Tracking model specific is really going to turn into a giant list never
> ending
> > > list.
> > > > To drill down more specifically, I can match on chassis too.
> > >
> > > Does Dell happen to use its own USB Vendor ID for the USB device in
> > > the dock? You could go at this problem from the other direction if it
> > > does have a unique vendor ID.
> > >
> > >      Andrew
> >
> > Unfortunately it's not a Dell specific VID/PID.  I'm asking around to find out
> > if there is something else identifiable about this dock's NIC (maybe that
> r8152
> > can query).
> 
> lsusb -v
> 
> I assume there is a USB hub in the dock, maybe that has a Dell VID?
> Going one level up the USB tree hierarchy should not be too hard.
> 
>       Andrew

I confirmed with some internal contacts a few extra bits about questions 
about this from throughout the conversation.

1) This feature IS in the general Realtek driver for Windows, not a special Dell driver.
2) The feature only offered to the Realtek 8153-AD, no other Realtek chip will do it 
(even Realtek 8153-VB won't).
3) The feature is activated when a special "Docking" bit is set on the 8153-AD.
4) The feature is activated on all Realtek 8153-AD's on the host system with the
docking bit set.  So on Windows if two Dell docks were hooked up they would both 
have the same AUX MAC. 

So considering that I think it would make sense to only activate in those same
special circumstances (RTL8153-AD, docking bit set, system has \\_SB.AMAC).  
I also feel this should stay in the Realtek driver as this as this implementation is
very Realtek specific.
Mario Limonciello June 3, 2016, 3:08 p.m. UTC | #9
> -----Original Message-----
> From: Hayes Wang [mailto:hayeswang@realtek.com]
> Sent: Friday, June 3, 2016 4:44 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: LKML <linux-kernel@vger.kernel.org>; Netdev
> <netdev@vger.kernel.org>; Linux USB <linux-usb@vger.kernel.org>;
> pali.rohar@gmail.com; anthony.wong@canonical.com; Greg KH
> <gregkh@linuxfoundation.org>
> Subject: RE: [PATCH v2] r8152: Add support for setting MAC to system's
> Auxiliary MAC address
> 
> Mario Limonciello [mailto:mario_limonciello@dell.com]
> > Sent: Friday, June 03, 2016 12:58 AM
> [...]
> > @@ -500,6 +502,7 @@ enum rtl8152_flags {
> >  	SELECTIVE_SUSPEND,
> >  	PHY_RESET,
> >  	SCHEDULE_NAPI,
> > +	MAC_PASSTHRU = 0,
> 
> I don't think you have to give this a value.
> 
> >  };
> >
> [...]
> >  static int set_ethernet_addr(struct r8152 *tp)
> >  {
> >  	struct net_device *dev = tp->netdev;
> > @@ -1041,6 +1088,10 @@ static int set_ethernet_addr(struct r8152 *tp)
> >  	else
> >  		ret = pla_ocp_read(tp, PLA_BACKUP, 8, sa.sa_data);
> >
> > +	/* if system provides auxiliary MAC address */
> > +	if (get_auxiliary_addr(tp, &sa))
> > +		ret = 0;
> 
> It still has problem when tp->version == RTL_VER_01.
> First, you would read the current MAC address (MAC1) to sa.sa_data.
> Then sa.sa_data may be modified by MAC2 after get_auxiliary_addr().
> However, the MAC2 wouldn't be set to the device, because
> 
> 		if (tp->version == RTL_VER_01)
> 			ether_addr_copy(dev->dev_addr, sa.sa_data);
> 
> Therefore, you would find that dev_addr is MAC2, and the device
> uses MAC1.
> 
> Best Regards,
> Hayes
> 

Hayes,

From the information that I got that this is only a valid thing to do on
RTL-8153-AD (when dock bit set), should this only match with 
tp->version  >= RTL_VER_03? 

How can I confirm that the chip is 8153-AD specifically?  I didn't see
something obvious in driver to tell this.

Thanks,
Mario Limonciello June 3, 2016, 3:10 p.m. UTC | #10
> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Thursday, June 2, 2016 9:02 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: hayeswang@realtek.com; linux-kernel@vger.kernel.org;
> netdev@vger.kernel.org; linux-usb@vger.kernel.org; pali.rohar@gmail.com;
> anthony.wong@canonical.com
> Subject: Re: [PATCH v2] r8152: Add support for setting MAC to system's
> Auxiliary MAC address
> 
> On Thu, Jun 02, 2016 at 06:32:42PM +0000, Mario_Limonciello@Dell.com
> wrote:
> > > And you want to check this for all Dell devices?  Please be model
> > > specific, I doubt a bunch of Dell servers wants to run this code...
> > >
> >
> > Tracking model specific is really going to turn into a giant list never ending
> list.
> > To drill down more specifically, I can match on chassis too.
> 
> Yes, as this is a vendor/platform-specific "quirk", you will have to
> update it for each and every individual device you want it enabled as it
> is so different from what all other drivers do.
> 
> thanks,
> 
> greg k-h

After finding out that there is a characteristic specific to Realtek chip in this USB
device, I think it would be best to only run the \\_SB.AMAC lookup when this 
specific USB device is connected.  

Realtek is not maintaining a whitelist of systems in their driver for the other OS,
they approach it from the other end and only lookup auxiliary MAC if the right
device is plugged in.
diff mbox

Patch

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 3f9f6ed..6dea542 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -26,6 +26,8 @@ 
 #include <linux/mdio.h>
 #include <linux/usb/cdc.h>
 #include <linux/suspend.h>
+#include <linux/acpi.h>
+#include <linux/dmi.h>
 
 /* Information for net-next */
 #define NETNEXT_VERSION		"08"
@@ -500,6 +502,7 @@  enum rtl8152_flags {
 	SELECTIVE_SUSPEND,
 	PHY_RESET,
 	SCHEDULE_NAPI,
+	MAC_PASSTHRU = 0,
 };
 
 /* Define these values to match your device */
@@ -653,6 +656,7 @@  enum tx_csum_stat {
  */
 static const int multicast_filter_limit = 32;
 static unsigned int agg_buf_sz = 16384;
+static bool mac_passthru_active;
 
 #define RTL_LIMITED_TSO_SIZE	(agg_buf_sz - sizeof(struct tx_desc) - \
 				 VLAN_ETH_HLEN - VLAN_HLEN)
@@ -1030,6 +1034,49 @@  out1:
 	return ret;
 }
 
+static int get_auxiliary_addr(struct r8152 *tp, struct sockaddr *sa)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	int ret = -1;
+	unsigned char buf[6];
+
+	if (!dmi_name_in_vendors("Dell Inc.") || mac_passthru_active)
+		return -1;
+
+	/* returns _AUXMAC_#AABBCCDDEEFF# */
+	status = acpi_evaluate_object(NULL, "\\_SB.AMAC", NULL, &buffer);
+	obj = (union acpi_object *)buffer.pointer;
+	if (ACPI_SUCCESS(status)) {
+		if (obj->type != ACPI_TYPE_BUFFER ||
+		    obj->string.length != 0x17) {
+			pr_warn("r8152: get_auxiliary_addr: Invalid buffer");
+			goto amacout;
+		}
+		if (strncmp(obj->string.pointer, "_AUXMAC_#", 9) != 0) {
+			pr_warn("r8152: get_auxiliary_addr: Invalid header");
+			goto amacout;
+		}
+		ret = hex2bin(buf, obj->string.pointer + 9, 6);
+		if (ret < 0) {
+			pr_warn("r8152: get_auxiliary_addr: Invalid MAC");
+			goto amacout;
+		}
+		memcpy(sa->sa_data, buf, 6);
+		ether_addr_copy(tp->netdev->dev_addr, sa->sa_data);
+		netdev_info(tp->netdev, "Using system MAC address %pM\n",
+			    sa->sa_data);
+		set_bit(MAC_PASSTHRU, &tp->flags);
+		mac_passthru_active = true;
+		ret = 1;
+	}
+
+amacout:
+	kfree(obj);
+	return ret;
+}
+
 static int set_ethernet_addr(struct r8152 *tp)
 {
 	struct net_device *dev = tp->netdev;
@@ -1041,6 +1088,10 @@  static int set_ethernet_addr(struct r8152 *tp)
 	else
 		ret = pla_ocp_read(tp, PLA_BACKUP, 8, sa.sa_data);
 
+	/* if system provides auxiliary MAC address */
+	if (get_auxiliary_addr(tp, &sa))
+		ret = 0;
+
 	if (ret < 0) {
 		netif_err(tp, probe, dev, "Get ether addr fail\n");
 	} else if (!is_valid_ether_addr(sa.sa_data)) {
@@ -4268,6 +4319,8 @@  static void rtl8152_disconnect(struct usb_interface *intf)
 		if (udev->state == USB_STATE_NOTATTACHED)
 			set_bit(RTL8152_UNPLUG, &tp->flags);
 
+		if (test_bit(MAC_PASSTHRU, &tp->flags))
+			mac_passthru_active = false;
 		netif_napi_del(&tp->napi);
 		unregister_netdev(tp->netdev);
 		tp->rtl_ops.unload(tp);