platform/x86: thinkpad_acpi: sysfs interface to auxmac

Newer Thinkpads have a feature called MAC Address Pass-through.
This patch provides a sysfs interface that userspace can use
to get this auxiliary mac address.

Signed-off-by: Fernando Eckhardt Valle <fevalle@ipt.br>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20230926202144.5906-1-fevalle@ipt.br
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
Fernando Eckhardt Valle 2023-09-26 17:21:44 -03:00 committed by Ilpo Järvinen
parent 9cf63f3a33
commit 18801efed7
No known key found for this signature in database
GPG key ID: 59AC4F6153E5CE31
2 changed files with 108 additions and 0 deletions

View file

@ -53,6 +53,7 @@ detailed description):
- Lap mode sensor
- Setting keyboard language
- WWAN Antenna type
- Auxmac
A compatibility table by model and feature is maintained on the web
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
@ -1511,6 +1512,25 @@ Currently 2 antenna types are supported as mentioned below:
The property is read-only. If the platform doesn't have support the sysfs
class is not created.
Auxmac
------
sysfs: auxmac
Some newer Thinkpads have a feature called MAC Address Pass-through. This
feature is implemented by the system firmware to provide a system unique MAC,
that can override a dock or USB ethernet dongle MAC, when connected to a
network. This property enables user-space to easily determine the MAC address
if the feature is enabled.
The values of this auxiliary MAC are:
cat /sys/devices/platform/thinkpad_acpi/auxmac
If the feature is disabled, the value will be 'disabled'.
This property is read-only.
Adaptive keyboard
-----------------

View file

@ -10785,6 +10785,89 @@ static struct ibm_struct dprc_driver_data = {
.name = "dprc",
};
/*
* Auxmac
*
* This auxiliary mac address is enabled in the bios through the
* MAC Address Pass-through feature. In most cases, there are three
* possibilities: Internal Mac, Second Mac, and disabled.
*
*/
#define AUXMAC_LEN 12
#define AUXMAC_START 9
#define AUXMAC_STRLEN 22
#define AUXMAC_BEGIN_MARKER 8
#define AUXMAC_END_MARKER 21
static char auxmac[AUXMAC_LEN + 1];
static int auxmac_init(struct ibm_init_struct *iibm)
{
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
status = acpi_evaluate_object(NULL, "\\MACA", NULL, &buffer);
if (ACPI_FAILURE(status))
return -ENODEV;
obj = buffer.pointer;
if (obj->type != ACPI_TYPE_STRING || obj->string.length != AUXMAC_STRLEN) {
pr_info("Invalid buffer for MAC address pass-through.\n");
goto auxmacinvalid;
}
if (obj->string.pointer[AUXMAC_BEGIN_MARKER] != '#' ||
obj->string.pointer[AUXMAC_END_MARKER] != '#') {
pr_info("Invalid header for MAC address pass-through.\n");
goto auxmacinvalid;
}
if (strncmp(obj->string.pointer + AUXMAC_START, "XXXXXXXXXXXX", AUXMAC_LEN) != 0)
strscpy(auxmac, obj->string.pointer + AUXMAC_START, sizeof(auxmac));
else
strscpy(auxmac, "disabled", sizeof(auxmac));
free:
kfree(obj);
return 0;
auxmacinvalid:
strscpy(auxmac, "unavailable", sizeof(auxmac));
goto free;
}
static struct ibm_struct auxmac_data = {
.name = "auxmac",
};
static ssize_t auxmac_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sysfs_emit(buf, "%s\n", auxmac);
}
static DEVICE_ATTR_RO(auxmac);
static umode_t auxmac_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
return auxmac[0] == 0 ? 0 : attr->mode;
}
static struct attribute *auxmac_attributes[] = {
&dev_attr_auxmac.attr,
NULL
};
static const struct attribute_group auxmac_attr_group = {
.is_visible = auxmac_attr_is_visible,
.attrs = auxmac_attributes,
};
/* --------------------------------------------------------------------- */
static struct attribute *tpacpi_driver_attributes[] = {
@ -10843,6 +10926,7 @@ static const struct attribute_group *tpacpi_groups[] = {
&proxsensor_attr_group,
&kbdlang_attr_group,
&dprc_attr_group,
&auxmac_attr_group,
NULL,
};
@ -11414,6 +11498,10 @@ static struct ibm_init_struct ibms_init[] __initdata = {
.init = tpacpi_dprc_init,
.data = &dprc_driver_data,
},
{
.init = auxmac_init,
.data = &auxmac_data,
},
};
static int __init set_ibm_param(const char *val, const struct kernel_param *kp)