mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 04:04:43 +01:00
platform/x86: thinkpad_acpi: Add sysfs to display details of damaged device.
Add new sysfs interface to identify the impacted component with location of device. Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca> Signed-off-by: Nitin Joshi <nitjoshi@gmail.com> Link: https://patch.msgid.link/20260106174519.6402-2-nitjoshi@gmail.com 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:
parent
28c43bddd0
commit
a85503d541
2 changed files with 118 additions and 3 deletions
|
|
@ -1580,7 +1580,7 @@ Documentation/ABI/testing/sysfs-class-power.
|
|||
Hardware damage detection capability
|
||||
------------------------------------
|
||||
|
||||
sysfs attributes: hwdd_status
|
||||
sysfs attributes: hwdd_status, hwdd_detail
|
||||
|
||||
Thinkpads are adding the ability to detect and report hardware damage.
|
||||
Add new sysfs interface to identify the damaged device status.
|
||||
|
|
@ -1595,6 +1595,21 @@ This value displays status of device damaged.
|
|||
- 0 = Not Damaged
|
||||
- 1 = Damaged
|
||||
|
||||
The command to check location of damaged device is::
|
||||
|
||||
cat /sys/devices/platform/thinkpad_acpi/hwdd_detail
|
||||
|
||||
This value displays location of damaged device having 1 line per damaged "item".
|
||||
For example:
|
||||
|
||||
if no damage is detected:
|
||||
|
||||
- No damage detected
|
||||
|
||||
if damage detected:
|
||||
|
||||
- TYPE-C: Base, Right side, Center port
|
||||
|
||||
The property is read-only. If feature is not supported then sysfs
|
||||
attribute is not created.
|
||||
|
||||
|
|
|
|||
|
|
@ -11090,8 +11090,24 @@ static const struct attribute_group auxmac_attr_group = {
|
|||
#define HWDD_NOT_SUPPORTED BIT(31)
|
||||
#define HWDD_SUPPORT_USBC BIT(0)
|
||||
|
||||
#define PORT_STATUS GENMASK(7, 4)
|
||||
#define NUM_PORTS 4
|
||||
#define PORT_STATUS GENMASK(7, 4)
|
||||
#define LID_STATUS GENMASK(11, 8)
|
||||
#define BASE_STATUS GENMASK(15, 12)
|
||||
#define POS_STATUS GENMASK(3, 2)
|
||||
#define PANEL_STATUS GENMASK(1, 0)
|
||||
|
||||
#define PORT_DETAIL_OFFSET 16
|
||||
|
||||
#define PANEL_TOP 0
|
||||
#define PANEL_BASE 1
|
||||
#define PANEL_LEFT 2
|
||||
#define PANEL_RIGHT 3
|
||||
|
||||
#define POS_LEFT 0
|
||||
#define POS_CENTER 1
|
||||
#define POS_RIGHT 2
|
||||
|
||||
#define NUM_PORTS 4
|
||||
|
||||
static bool hwdd_support_available;
|
||||
static bool ucdd_supported;
|
||||
|
|
@ -11109,6 +11125,88 @@ static int hwdd_command(int command, int *output)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool display_damage(char *buf, int *count, char *type, unsigned int dmg_status)
|
||||
{
|
||||
unsigned char lid_status, base_status, port_status;
|
||||
unsigned char loc_status, pos_status, panel_status;
|
||||
bool damage_detected = false;
|
||||
int i;
|
||||
|
||||
port_status = FIELD_GET(PORT_STATUS, dmg_status);
|
||||
lid_status = FIELD_GET(LID_STATUS, dmg_status);
|
||||
base_status = FIELD_GET(BASE_STATUS, dmg_status);
|
||||
for (i = 0; i < NUM_PORTS; i++) {
|
||||
if (!(dmg_status & BIT(i)) || !(port_status & BIT(i)))
|
||||
continue;
|
||||
|
||||
*count += sysfs_emit_at(buf, *count, "%s: ", type);
|
||||
loc_status = (dmg_status >> (PORT_DETAIL_OFFSET + (4 * i))) & 0xF;
|
||||
pos_status = FIELD_GET(POS_STATUS, loc_status);
|
||||
panel_status = FIELD_GET(PANEL_STATUS, loc_status);
|
||||
|
||||
if (lid_status & BIT(i))
|
||||
*count += sysfs_emit_at(buf, *count, "Lid, ");
|
||||
if (base_status & BIT(i))
|
||||
*count += sysfs_emit_at(buf, *count, "Base, ");
|
||||
|
||||
switch (pos_status) {
|
||||
case PANEL_TOP:
|
||||
*count += sysfs_emit_at(buf, *count, "Top, ");
|
||||
break;
|
||||
case PANEL_BASE:
|
||||
*count += sysfs_emit_at(buf, *count, "Bottom, ");
|
||||
break;
|
||||
case PANEL_LEFT:
|
||||
*count += sysfs_emit_at(buf, *count, "Left, ");
|
||||
break;
|
||||
case PANEL_RIGHT:
|
||||
*count += sysfs_emit_at(buf, *count, "Right, ");
|
||||
break;
|
||||
default:
|
||||
pr_err("Unexpected value %d in switch statement\n", pos_status);
|
||||
}
|
||||
|
||||
switch (panel_status) {
|
||||
case POS_LEFT:
|
||||
*count += sysfs_emit_at(buf, *count, "Left port\n");
|
||||
break;
|
||||
case POS_CENTER:
|
||||
*count += sysfs_emit_at(buf, *count, "Center port\n");
|
||||
break;
|
||||
case POS_RIGHT:
|
||||
*count += sysfs_emit_at(buf, *count, "Right port\n");
|
||||
break;
|
||||
default:
|
||||
*count += sysfs_emit_at(buf, *count, "Undefined\n");
|
||||
break;
|
||||
}
|
||||
damage_detected = true;
|
||||
}
|
||||
return damage_detected;
|
||||
}
|
||||
|
||||
/* sysfs type-c damage detection detail */
|
||||
static ssize_t hwdd_detail_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
unsigned int damage_status;
|
||||
int err, count = 0;
|
||||
|
||||
if (!ucdd_supported)
|
||||
return -ENODEV;
|
||||
|
||||
/* Get USB TYPE-C damage status */
|
||||
err = hwdd_command(HWDD_GET_DMG_USBC, &damage_status);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!display_damage(buf, &count, "Type-C", damage_status))
|
||||
count += sysfs_emit_at(buf, count, "No damage detected\n");
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* sysfs type-c damage detection capability */
|
||||
static ssize_t hwdd_status_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
|
@ -11136,9 +11234,11 @@ static ssize_t hwdd_status_show(struct device *dev,
|
|||
return sysfs_emit(buf, "0\n");
|
||||
}
|
||||
static DEVICE_ATTR_RO(hwdd_status);
|
||||
static DEVICE_ATTR_RO(hwdd_detail);
|
||||
|
||||
static struct attribute *hwdd_attributes[] = {
|
||||
&dev_attr_hwdd_status.attr,
|
||||
&dev_attr_hwdd_detail.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue