platform-drivers-x86 for v6.7-1

Highlights:
  - asus-wmi:		Support for screenpad and solve brightness key
 			press duplication
  - int3472:		Eliminate the last use of deprecated GPIO functions
  - mlxbf-pmc:		New HW support
  - msi-ec:		Support new EC configurations
  - thinkpad_acpi:	Support reading aux MAC address during passthrough
  - wmi: 		Fixes & improvements
  - x86-android-tablets:	Detection fix and avoid use of GPIO private APIs
  - Debug & metrics interface improvements
  - Miscellaneous cleanups / fixes / improvements
 
 The following is an automated shortlog grouped by driver:
 
 acer-wmi:
  -  Remove void function return
 
 amd/hsmp:
  -  add support for metrics tbl
  -  create plat specific struct
  -  Fix iomem handling
  -  improve the error log
 
 amd/pmc:
  -  Add dump_custom_stb module parameter
  -  Add PMFW command id to support S2D force flush
  -  Handle overflow cases where the num_samples range is higher
  -  Use flex array when calling amd_pmc_stb_debugfs_open_v2()
 
 asus-wireless:
  -  Replace open coded acpi_match_acpi_device()
 
 asus-wmi:
  -  add support for ASUS screenpad
  -  Do not report brightness up/down keys when also reported by acpi_video
 
 gpiolib: acpi:
  -  Add a ignore interrupt quirk for Peaq C1010
  -  Check if a GPIO is listed in ignore_interrupt earlier
 
 hp-bioscfg:
  -  Annotate struct bios_args with __counted_by
 
 inspur-platform-profile:
  -  Add platform profile support
 
 int3472:
  -  Add new skl_int3472_fill_gpiod_lookup() helper
  -  Add new skl_int3472_gpiod_get_from_temp_lookup() helper
  -  Stop using gpiod_toggle_active_low()
  -  Switch to devm_get_gpiod()
 
 intel: bytcrc_pwrsrc:
  -  Convert to platform remove callback returning void
 
 intel/ifs:
  -  Add new CPU support
  -  Add new error code
  -  ARRAY BIST for Sierra Forest
  -  Gen2 scan image loading
  -  Gen2 Scan test support
  -  Metadata validation for start_chunk
  -  Refactor image loading code
  -  Store IFS generation number
  -  Validate image size
 
 intel_speed_select_if:
  -  Remove hardcoded map size
  -  Use devm_ioremap_resource
 
 intel/tpmi:
  -  Add debugfs support for read/write blocked
  -  Add defines to get version information
 
 intel-uncore-freq:
  -  Ignore minor version change
 
 ISST:
  -  Allow level 0 to be not present
  -  Ignore minor version change
  -  Use fuse enabled mask instead of allowed levels
 
 mellanox:
  -  Fix misspelling error in routine name
  -  Rename some init()/exit() functions for consistent naming
 
 mlxbf-bootctl:
  -  Convert to platform remove callback returning void
 
 mlxbf-pmc:
  -  Add support for BlueField-3
 
 mlxbf-tmfifo:
  -  Convert to platform remove callback returning void
 
 mlx-Convert to platform remove callback returning void:
  - mlx-Convert to platform remove callback returning void
 
 mlxreg-hotplug:
  -  Convert to platform remove callback returning void
 
 mlxreg-io:
  -  Convert to platform remove callback returning void
 
 mlxreg-lc:
  -  Convert to platform remove callback returning void
 
 msi-ec:
  -  Add more EC configs
  -  rename fn_super_swap
 
 nvsw-sn2201:
  -  Convert to platform remove callback returning void
 
 sel3350-Convert to platform remove callback returning void:
  - sel3350-Convert to platform remove callback returning void
 
 siemens: simatic-ipc-batt-apollolake:
  -  Convert to platform remove callback returning void
 
 siemens: simatic-ipc-batt:
  -  Convert to platform remove callback returning void
 
 siemens: simatic-ipc-batt-elkhartlake:
  -  Convert to platform remove callback returning void
 
 siemens: simatic-ipc-batt-f7188x:
  -  Convert to platform remove callback returning void
 
 siemens: simatic-ipc-batt:
  -  Simplify simatic_ipc_batt_remove()
 
 surface: acpi-notify:
  -  Convert to platform remove callback returning void
 
 surface: aggregator:
  -  Annotate struct ssam_event with __counted_by
 
 surface: aggregator-cdev:
  -  Convert to platform remove callback returning void
 
 surface: aggregator-registry:
  -  Convert to platform remove callback returning void
 
 surface: dtx:
  -  Convert to platform remove callback returning void
 
 surface: gpe:
  -  Convert to platform remove callback returning void
 
 surface: hotplug:
  -  Convert to platform remove callback returning void
 
 surface: surface3-wmi:
  -  Convert to platform remove callback returning void
 
 think-lmi:
  -  Add bulk save feature
  -  Replace kstrdup() + strreplace() with kstrdup_and_replace()
  -  Use strreplace() to replace a character by nul
 
 thinkpad_acpi:
  -  Add battery quirk for Thinkpad X120e
  -  replace deprecated strncpy with memcpy
  -  sysfs interface to auxmac
 
 tools/power/x86/intel-speed-select:
  -  Display error for core-power support
  -  Increase max CPUs in one request
  -  No TRL for non compute domains
  -  Sanitize integer arguments
  -  turbo-mode enable disable swapped
  -  Update help for TRL
  -  Use cgroup isolate for CPU 0
  -  v1.18 release
 
 wmi:
  -  Decouple probe deferring from wmi_block_list
  -  Decouple WMI device removal from wmi_block_list
  -  Fix opening of char device
  -  Fix probe failure when failing to register WMI devices
  -  Fix refcounting of WMI devices in legacy functions
 
 x86-android-tablets:
  -  Add a comment about x86_android_tablet_get_gpiod()
  -  Create a platform_device from module_init()
  -  Drop "linux,power-supply-name" from lenovo_yt3_bq25892_0_props[]
  -  Fix Lenovo Yoga Tablet 2 830F/L vs 1050F/L detection
  -  Remove invalid_aei_gpiochip from Peaq C1010
  -  Remove invalid_aei_gpiochip support
  -  Stop using gpiolib private APIs
  -  Use platform-device as gpio-keys parent
 
 xo15-ebook:
  -  Replace open coded acpi_match_acpi_device()
 
 Merges:
  -  Merge branch 'pdx86/platform-drivers-x86-int3472' into review-ilpo
  -  Merge branch 'pdx86/platform-drivers-x86-mellanox-init' into review-ilpo
  -  Merge remote-tracking branch 'intel-speed-select/intel-sst' into review-ilpo
  -  Merge remote-tracking branch 'pdx86/platform-drivers-x86-android-tablets' into review-hans
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQSCSUwRdwTNL2MhaBlZrE9hU+XOMQUCZT+lBwAKCRBZrE9hU+XO
 Mck0AQCFU7dYLCF4d1CXtHf1eZhSXLpYdhcO+C08JGGoM+MqSgD+Jyb9KJHk4pxE
 FvKG51I9neyAne9lvNrLodHRzxCYgAo=
 =duM8
 -----END PGP SIGNATURE-----

Merge tag 'platform-drivers-x86-v6.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform driver updates from Ilpo Järvinen:

 - asus-wmi: Support for screenpad and solve brightness key press
   duplication

 - int3472: Eliminate the last use of deprecated GPIO functions

 - mlxbf-pmc: New HW support

 - msi-ec: Support new EC configurations

 - thinkpad_acpi: Support reading aux MAC address during passthrough

 - wmi: Fixes & improvements

 - x86-android-tablets: Detection fix and avoid use of GPIO private APIs

 - Debug & metrics interface improvements

 - Miscellaneous cleanups / fixes / improvements

* tag 'platform-drivers-x86-v6.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (80 commits)
  platform/x86: inspur-platform-profile: Add platform profile support
  platform/x86: thinkpad_acpi: Add battery quirk for Thinkpad X120e
  platform/x86: wmi: Decouple WMI device removal from wmi_block_list
  platform/x86: wmi: Fix opening of char device
  platform/x86: wmi: Fix probe failure when failing to register WMI devices
  platform/x86: wmi: Fix refcounting of WMI devices in legacy functions
  platform/x86: wmi: Decouple probe deferring from wmi_block_list
  platform/x86/amd/hsmp: Fix iomem handling
  platform/x86: asus-wmi: Do not report brightness up/down keys when also reported by acpi_video
  platform/x86: thinkpad_acpi: replace deprecated strncpy with memcpy
  tools/power/x86/intel-speed-select: v1.18 release
  tools/power/x86/intel-speed-select: Use cgroup isolate for CPU 0
  tools/power/x86/intel-speed-select: Increase max CPUs in one request
  tools/power/x86/intel-speed-select: Display error for core-power support
  tools/power/x86/intel-speed-select: No TRL for non compute domains
  tools/power/x86/intel-speed-select: turbo-mode enable disable swapped
  tools/power/x86/intel-speed-select: Update help for TRL
  tools/power/x86/intel-speed-select: Sanitize integer arguments
  platform/x86: acer-wmi: Remove void function return
  platform/x86/amd/pmc: Add dump_custom_stb module parameter
  ...
This commit is contained in:
Linus Torvalds 2023-10-31 17:53:00 -10:00
commit 59fff63cc2
62 changed files with 3044 additions and 497 deletions

View File

@ -383,6 +383,36 @@ Description:
Note that any changes to this attribute requires a reboot
for changes to take effect.
What: /sys/class/firmware-attributes/*/attributes/save_settings
Date: August 2023
KernelVersion: 6.6
Contact: Mark Pearson <mpearson-lenovo@squebb.ca>
Description:
On Lenovo platforms there is a limitation in the number of times an attribute can be
saved. This is an architectural limitation and it limits the number of attributes
that can be modified to 48.
A solution for this is instead of the attribute being saved after every modification,
to allow a user to bulk set the attributes, and then trigger a final save. This allows
unlimited attributes.
Read the attribute to check what save mode is enabled (single or bulk).
E.g:
# cat /sys/class/firmware-attributes/thinklmi/attributes/save_settings
single
Write the attribute with 'bulk' to enable bulk save mode.
Write the attribute with 'single' to enable saving, after every attribute set.
The default setting is single mode.
E.g:
# echo bulk > /sys/class/firmware-attributes/thinklmi/attributes/save_settings
When in bulk mode write 'save' to trigger a save of all currently modified attributes.
Note, once a save has been triggered, in bulk mode, attributes can no longer be set and
will return a permissions error. This is to prevent users hitting the 48+ save limitation
(which requires entering the BIOS to clear the error condition)
E.g:
# echo save > /sys/class/firmware-attributes/thinklmi/attributes/save_settings
What: /sys/class/firmware-attributes/*/attributes/debug_cmd
Date: July 2021
KernelVersion: 5.14

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

@ -41,6 +41,24 @@ In-kernel integration:
* Locking across callers is taken care by the driver.
HSMP sysfs interface
====================
1. Metrics table binary sysfs
AMD MI300A MCM provides GET_METRICS_TABLE message to retrieve
most of the system management information from SMU in one go.
The metrics table is made available as hexadecimal sysfs binary file
under per socket sysfs directory created at
/sys/devices/platform/amd_hsmp/socket%d/metrics_bin
Note: lseek() is not supported as entire metrics table is read.
Metrics table definitions will be documented as part of Public PPR.
The same is defined in the amd_hsmp.h header.
An example
==========

View File

@ -222,6 +222,7 @@
#define MSR_INTEGRITY_CAPS_ARRAY_BIST BIT(MSR_INTEGRITY_CAPS_ARRAY_BIST_BIT)
#define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT 4
#define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT)
#define MSR_INTEGRITY_CAPS_SAF_GEN_MASK GENMASK_ULL(10, 9)
#define MSR_LBR_NHM_FROM 0x00000680
#define MSR_LBR_NHM_TO 0x000006c0

View File

@ -47,6 +47,9 @@ enum hsmp_message_ids {
HSMP_SET_PCI_RATE, /* 20h Control link rate on PCIe devices */
HSMP_SET_POWER_MODE, /* 21h Select power efficiency profile policy */
HSMP_SET_PSTATE_MAX_MIN, /* 22h Set the max and min DF P-State */
HSMP_GET_METRIC_TABLE_VER, /* 23h Get metrics table version */
HSMP_GET_METRIC_TABLE, /* 24h Get metrics table */
HSMP_GET_METRIC_TABLE_DRAM_ADDR,/* 25h Get metrics table dram address */
HSMP_MSG_ID_MAX,
};
@ -64,6 +67,14 @@ enum hsmp_msg_type {
HSMP_GET = 1,
};
enum hsmp_proto_versions {
HSMP_PROTO_VER2 = 2,
HSMP_PROTO_VER3,
HSMP_PROTO_VER4,
HSMP_PROTO_VER5,
HSMP_PROTO_VER6
};
struct hsmp_msg_desc {
int num_args;
int response_sz;
@ -295,6 +306,104 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[] = {
* input: args[0] = min df pstate[15:8] + max df pstate[7:0]
*/
{1, 0, HSMP_SET},
/*
* HSMP_GET_METRIC_TABLE_VER, num_args = 0, response_sz = 1
* output: args[0] = metrics table version
*/
{0, 1, HSMP_GET},
/*
* HSMP_GET_METRIC_TABLE, num_args = 0, response_sz = 0
*/
{0, 0, HSMP_GET},
/*
* HSMP_GET_METRIC_TABLE_DRAM_ADDR, num_args = 0, response_sz = 2
* output: args[0] = lower 32 bits of the address
* output: args[1] = upper 32 bits of the address
*/
{0, 2, HSMP_GET},
};
/* Metrics table (supported only with proto version 6) */
struct hsmp_metric_table {
__u32 accumulation_counter;
/* TEMPERATURE */
__u32 max_socket_temperature;
__u32 max_vr_temperature;
__u32 max_hbm_temperature;
__u64 max_socket_temperature_acc;
__u64 max_vr_temperature_acc;
__u64 max_hbm_temperature_acc;
/* POWER */
__u32 socket_power_limit;
__u32 max_socket_power_limit;
__u32 socket_power;
/* ENERGY */
__u64 timestamp;
__u64 socket_energy_acc;
__u64 ccd_energy_acc;
__u64 xcd_energy_acc;
__u64 aid_energy_acc;
__u64 hbm_energy_acc;
/* FREQUENCY */
__u32 cclk_frequency_limit;
__u32 gfxclk_frequency_limit;
__u32 fclk_frequency;
__u32 uclk_frequency;
__u32 socclk_frequency[4];
__u32 vclk_frequency[4];
__u32 dclk_frequency[4];
__u32 lclk_frequency[4];
__u64 gfxclk_frequency_acc[8];
__u64 cclk_frequency_acc[96];
/* FREQUENCY RANGE */
__u32 max_cclk_frequency;
__u32 min_cclk_frequency;
__u32 max_gfxclk_frequency;
__u32 min_gfxclk_frequency;
__u32 fclk_frequency_table[4];
__u32 uclk_frequency_table[4];
__u32 socclk_frequency_table[4];
__u32 vclk_frequency_table[4];
__u32 dclk_frequency_table[4];
__u32 lclk_frequency_table[4];
__u32 max_lclk_dpm_range;
__u32 min_lclk_dpm_range;
/* XGMI */
__u32 xgmi_width;
__u32 xgmi_bitrate;
__u64 xgmi_read_bandwidth_acc[8];
__u64 xgmi_write_bandwidth_acc[8];
/* ACTIVITY */
__u32 socket_c0_residency;
__u32 socket_gfx_busy;
__u32 dram_bandwidth_utilization;
__u64 socket_c0_residency_acc;
__u64 socket_gfx_busy_acc;
__u64 dram_bandwidth_acc;
__u32 max_dram_bandwidth;
__u64 dram_bandwidth_utilization_acc;
__u64 pcie_bandwidth_acc[4];
/* THROTTLERS */
__u32 prochot_residency_acc;
__u32 ppt_residency_acc;
__u32 socket_thm_residency_acc;
__u32 vr_thm_residency_acc;
__u32 hbm_thm_residency_acc;
__u32 spare;
/* New items at the end to maintain driver compatibility */
__u32 gfxclk_frequency[8];
};
/* Reset to default packing */

View File

@ -1028,17 +1028,15 @@ static int mlxbf_bootctl_probe(struct platform_device *pdev)
return ret;
}
static int mlxbf_bootctl_remove(struct platform_device *pdev)
static void mlxbf_bootctl_remove(struct platform_device *pdev)
{
sysfs_remove_bin_file(&pdev->dev.kobj,
&mlxbf_bootctl_bootfifo_sysfs_attr);
return 0;
}
static struct platform_driver mlxbf_bootctl_driver = {
.probe = mlxbf_bootctl_probe,
.remove = mlxbf_bootctl_remove,
.remove_new = mlxbf_bootctl_remove,
.driver = {
.name = "mlxbf-bootctl",
.dev_groups = mlxbf_bootctl_groups,

View File

@ -30,14 +30,16 @@
#define MLXBF_PMC_EVENT_SET_BF1 0
#define MLXBF_PMC_EVENT_SET_BF2 1
#define MLXBF_PMC_EVENT_SET_BF3 2
#define MLXBF_PMC_EVENT_INFO_LEN 100
#define MLXBF_PMC_MAX_BLOCKS 30
#define MLXBF_PMC_MAX_ATTRS 30
#define MLXBF_PMC_MAX_ATTRS 70
#define MLXBF_PMC_INFO_SZ 4
#define MLXBF_PMC_REG_SIZE 8
#define MLXBF_PMC_L3C_REG_SIZE 4
#define MLXBF_PMC_TYPE_CRSPACE 2
#define MLXBF_PMC_TYPE_COUNTER 1
#define MLXBF_PMC_TYPE_REGISTER 0
@ -78,6 +80,16 @@
#define MLXBF_PMC_L3C_PERF_CNT_LOW_VAL GENMASK(31, 0)
#define MLXBF_PMC_L3C_PERF_CNT_HIGH_VAL GENMASK(24, 0)
#define MLXBF_PMC_CRSPACE_PERFMON_REG0 0x0
#define MLXBF_PMC_CRSPACE_PERFSEL_SZ 4
#define MLXBF_PMC_CRSPACE_PERFSEL0 GENMASK(23, 16)
#define MLXBF_PMC_CRSPACE_PERFSEL1 GENMASK(7, 0)
#define MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ 0x2
#define MLXBF_PMC_CRSPACE_PERFMON_CTL(n) (n * MLXBF_PMC_CRSPACE_PERFMON_REG0_SZ)
#define MLXBF_PMC_CRSPACE_PERFMON_EN BIT(30)
#define MLXBF_PMC_CRSPACE_PERFMON_CLR BIT(28)
#define MLXBF_PMC_CRSPACE_PERFMON_VAL0(n) (MLXBF_PMC_CRSPACE_PERFMON_CTL(n) + 0xc)
/**
* struct mlxbf_pmc_attribute - Structure to hold attribute and block info
* for each sysfs entry
@ -124,6 +136,9 @@ struct mlxbf_pmc_block_info {
* @pdev: The kernel structure representing the device
* @total_blocks: Total number of blocks
* @tile_count: Number of tiles in the system
* @llt_enable: Info on enabled LLTs
* @mss_enable: Info on enabled MSSs
* @group_num: Group number assigned to each valid block
* @hwmon_dev: Hwmon device for bfperf
* @block_name: Block name
* @block: Block info
@ -136,6 +151,9 @@ struct mlxbf_pmc_context {
struct platform_device *pdev;
uint32_t total_blocks;
uint32_t tile_count;
uint8_t llt_enable;
uint8_t mss_enable;
uint32_t group_num;
struct device *hwmon_dev;
const char *block_name[MLXBF_PMC_MAX_BLOCKS];
struct mlxbf_pmc_block_info block[MLXBF_PMC_MAX_BLOCKS];
@ -260,7 +278,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_ecc_events[] = {
{ 0x348, "DRAM_ECC_ERROR" },
};
static const struct mlxbf_pmc_events mlxbf_pmc_mss_events[] = {
static const struct mlxbf_pmc_events mlxbf_pmc_mss_events_1[] = {
{ 0x0, "DISABLE" },
{ 0xc0, "RXREQ_MSS" },
{ 0xc1, "RXDAT_MSS" },
@ -268,6 +286,164 @@ static const struct mlxbf_pmc_events mlxbf_pmc_mss_events[] = {
{ 0xc3, "TXDAT_MSS" },
};
static const struct mlxbf_pmc_events mlxbf_pmc_mss_events_3[] = {
{0, "SKYLIB_CDN_TX_FLITS"},
{1, "SKYLIB_DDN_TX_FLITS"},
{2, "SKYLIB_NDN_TX_FLITS"},
{3, "SKYLIB_SDN_TX_FLITS"},
{4, "SKYLIB_UDN_TX_FLITS"},
{5, "SKYLIB_CDN_RX_FLITS"},
{6, "SKYLIB_DDN_RX_FLITS"},
{7, "SKYLIB_NDN_RX_FLITS"},
{8, "SKYLIB_SDN_RX_FLITS"},
{9, "SKYLIB_UDN_RX_FLITS"},
{10, "SKYLIB_CDN_TX_STALL"},
{11, "SKYLIB_DDN_TX_STALL"},
{12, "SKYLIB_NDN_TX_STALL"},
{13, "SKYLIB_SDN_TX_STALL"},
{14, "SKYLIB_UDN_TX_STALL"},
{15, "SKYLIB_CDN_RX_STALL"},
{16, "SKYLIB_DDN_RX_STALL"},
{17, "SKYLIB_NDN_RX_STALL"},
{18, "SKYLIB_SDN_RX_STALL"},
{19, "SKYLIB_UDN_RX_STALL"},
{20, "SKYLIB_CHI_REQ0_TX_FLITS"},
{21, "SKYLIB_CHI_DATA0_TX_FLITS"},
{22, "SKYLIB_CHI_RESP0_TX_FLITS"},
{23, "SKYLIB_CHI_SNP0_TX_FLITS"},
{24, "SKYLIB_CHI_REQ1_TX_FLITS"},
{25, "SKYLIB_CHI_DATA1_TX_FLITS"},
{26, "SKYLIB_CHI_RESP1_TX_FLITS"},
{27, "SKYLIB_CHI_SNP1_TX_FLITS"},
{28, "SKYLIB_CHI_REQ2_TX_FLITS"},
{29, "SKYLIB_CHI_DATA2_TX_FLITS"},
{30, "SKYLIB_CHI_RESP2_TX_FLITS"},
{31, "SKYLIB_CHI_SNP2_TX_FLITS"},
{32, "SKYLIB_CHI_REQ3_TX_FLITS"},
{33, "SKYLIB_CHI_DATA3_TX_FLITS"},
{34, "SKYLIB_CHI_RESP3_TX_FLITS"},
{35, "SKYLIB_CHI_SNP3_TX_FLITS"},
{36, "SKYLIB_TLP_REQ_TX_FLITS"},
{37, "SKYLIB_TLP_RESP_TX_FLITS"},
{38, "SKYLIB_TLP_META_TX_FLITS"},
{39, "SKYLIB_AXIS_DATA_TX_FLITS"},
{40, "SKYLIB_AXIS_CRED_TX_FLITS"},
{41, "SKYLIB_APB_TX_FLITS"},
{42, "SKYLIB_VW_TX_FLITS"},
{43, "SKYLIB_GGA_MSN_W_TX_FLITS"},
{44, "SKYLIB_GGA_MSN_N_TX_FLITS"},
{45, "SKYLIB_CR_REQ_TX_FLITS"},
{46, "SKYLIB_CR_RESP_TX_FLITS"},
{47, "SKYLIB_MSN_PRNF_TX_FLITS"},
{48, "SKYLIB_DBG_DATA_TX_FLITS"},
{49, "SKYLIB_DBG_CRED_TX_FLITS"},
{50, "SKYLIB_CHI_REQ0_RX_FLITS"},
{51, "SKYLIB_CHI_DATA0_RX_FLITS"},
{52, "SKYLIB_CHI_RESP0_RX_FLITS"},
{53, "SKYLIB_CHI_SNP0_RX_FLITS"},
{54, "SKYLIB_CHI_REQ1_RX_FLITS"},
{55, "SKYLIB_CHI_DATA1_RX_FLITS"},
{56, "SKYLIB_CHI_RESP1_RX_FLITS"},
{57, "SKYLIB_CHI_SNP1_RX_FLITS"},
{58, "SKYLIB_CHI_REQ2_RX_FLITS"},
{59, "SKYLIB_CHI_DATA2_RX_FLITS"},
{60, "SKYLIB_CHI_RESP2_RX_FLITS"},
{61, "SKYLIB_CHI_SNP2_RX_FLITS"},
{62, "SKYLIB_CHI_REQ3_RX_FLITS"},
{63, "SKYLIB_CHI_DATA3_RX_FLITS"},
{64, "SKYLIB_CHI_RESP3_RX_FLITS"},
{65, "SKYLIB_CHI_SNP3_RX_FLITS"},
{66, "SKYLIB_TLP_REQ_RX_FLITS"},
{67, "SKYLIB_TLP_RESP_RX_FLITS"},
{68, "SKYLIB_TLP_META_RX_FLITS"},
{69, "SKYLIB_AXIS_DATA_RX_FLITS"},
{70, "SKYLIB_AXIS_CRED_RX_FLITS"},
{71, "SKYLIB_APB_RX_FLITS"},
{72, "SKYLIB_VW_RX_FLITS"},
{73, "SKYLIB_GGA_MSN_W_RX_FLITS"},
{74, "SKYLIB_GGA_MSN_N_RX_FLITS"},
{75, "SKYLIB_CR_REQ_RX_FLITS"},
{76, "SKYLIB_CR_RESP_RX_FLITS"},
{77, "SKYLIB_MSN_PRNF_RX_FLITS"},
{78, "SKYLIB_DBG_DATA_RX_FLITS"},
{79, "SKYLIB_DBG_CRED_RX_FLITS"},
{80, "SKYLIB_CHI_REQ0_TX_STALL"},
{81, "SKYLIB_CHI_DATA0_TX_STALL"},
{82, "SKYLIB_CHI_RESP0_TX_STALL"},
{83, "SKYLIB_CHI_SNP0_TX_STALL"},
{84, "SKYLIB_CHI_REQ1_TX_STALL"},
{85, "SKYLIB_CHI_DATA1_TX_STALL"},
{86, "SKYLIB_CHI_RESP1_TX_STALL"},
{87, "SKYLIB_CHI_SNP1_TX_STALL"},
{88, "SKYLIB_CHI_REQ2_TX_STALL"},
{89, "SKYLIB_CHI_DATA2_TX_STALL"},
{90, "SKYLIB_CHI_RESP2_TX_STALL"},
{91, "SKYLIB_CHI_SNP2_TX_STALL"},
{92, "SKYLIB_CHI_REQ3_TX_STALL"},
{93, "SKYLIB_CHI_DATA3_TX_STALL"},
{94, "SKYLIB_CHI_RESP3_TX_STALL"},
{95, "SKYLIB_CHI_SNP3_TX_STALL"},
{96, "SKYLIB_TLP_REQ_TX_STALL"},
{97, "SKYLIB_TLP_RESP_TX_STALL"},
{98, "SKYLIB_TLP_META_TX_STALL"},
{99, "SKYLIB_AXIS_DATA_TX_STALL"},
{100, "SKYLIB_AXIS_CRED_TX_STALL"},
{101, "SKYLIB_APB_TX_STALL"},
{102, "SKYLIB_VW_TX_STALL"},
{103, "SKYLIB_GGA_MSN_W_TX_STALL"},
{104, "SKYLIB_GGA_MSN_N_TX_STALL"},
{105, "SKYLIB_CR_REQ_TX_STALL"},
{106, "SKYLIB_CR_RESP_TX_STALL"},
{107, "SKYLIB_MSN_PRNF_TX_STALL"},
{108, "SKYLIB_DBG_DATA_TX_STALL"},
{109, "SKYLIB_DBG_CRED_TX_STALL"},
{110, "SKYLIB_CHI_REQ0_RX_STALL"},
{111, "SKYLIB_CHI_DATA0_RX_STALL"},
{112, "SKYLIB_CHI_RESP0_RX_STALL"},
{113, "SKYLIB_CHI_SNP0_RX_STALL"},
{114, "SKYLIB_CHI_REQ1_RX_STALL"},
{115, "SKYLIB_CHI_DATA1_RX_STALL"},
{116, "SKYLIB_CHI_RESP1_RX_STALL"},
{117, "SKYLIB_CHI_SNP1_RX_STALL"},
{118, "SKYLIB_CHI_REQ2_RX_STALL"},
{119, "SKYLIB_CHI_DATA2_RX_STALL"},
{120, "SKYLIB_CHI_RESP2_RX_STALL"},
{121, "SKYLIB_CHI_SNP2_RX_STALL"},
{122, "SKYLIB_CHI_REQ3_RX_STALL"},
{123, "SKYLIB_CHI_DATA3_RX_STALL"},
{124, "SKYLIB_CHI_RESP3_RX_STALL"},
{125, "SKYLIB_CHI_SNP3_RX_STALL"},
{126, "SKYLIB_TLP_REQ_RX_STALL"},
{127, "SKYLIB_TLP_RESP_RX_STALL"},
{128, "SKYLIB_TLP_META_RX_STALL"},
{129, "SKYLIB_AXIS_DATA_RX_STALL"},
{130, "SKYLIB_AXIS_CRED_RX_STALL"},
{131, "SKYLIB_APB_RX_STALL"},
{132, "SKYLIB_VW_RX_STALL"},
{133, "SKYLIB_GGA_MSN_W_RX_STALL"},
{134, "SKYLIB_GGA_MSN_N_RX_STALL"},
{135, "SKYLIB_CR_REQ_RX_STALL"},
{136, "SKYLIB_CR_RESP_RX_STALL"},
{137, "SKYLIB_MSN_PRNF_RX_STALL"},
{138, "SKYLIB_DBG_DATA_RX_STALL"},
{139, "SKYLIB_DBG_CRED_RX_STALL"},
{140, "SKYLIB_CDN_LOOPBACK_FLITS"},
{141, "SKYLIB_DDN_LOOPBACK_FLITS"},
{142, "SKYLIB_NDN_LOOPBACK_FLITS"},
{143, "SKYLIB_SDN_LOOPBACK_FLITS"},
{144, "SKYLIB_UDN_LOOPBACK_FLITS"},
{145, "HISTOGRAM_HISTOGRAM_BIN0"},
{146, "HISTOGRAM_HISTOGRAM_BIN1"},
{147, "HISTOGRAM_HISTOGRAM_BIN2"},
{148, "HISTOGRAM_HISTOGRAM_BIN3"},
{149, "HISTOGRAM_HISTOGRAM_BIN4"},
{150, "HISTOGRAM_HISTOGRAM_BIN5"},
{151, "HISTOGRAM_HISTOGRAM_BIN6"},
{152, "HISTOGRAM_HISTOGRAM_BIN7"},
{153, "HISTOGRAM_HISTOGRAM_BIN8"},
{154, "HISTOGRAM_HISTOGRAM_BIN9"},
};
static const struct mlxbf_pmc_events mlxbf_pmc_hnf_events[] = {
{ 0x0, "DISABLE" },
{ 0x45, "HNF_REQUESTS" },
@ -429,6 +605,260 @@ static const struct mlxbf_pmc_events mlxbf_pmc_l3c_events[] = {
{ 0x2b, "ANY_REJECT_BANK1" },
};
static const struct mlxbf_pmc_events mlxbf_pmc_llt_events[] = {
{0, "HNF0_CYCLES"},
{1, "HNF0_REQS_RECEIVED"},
{2, "HNF0_REQS_PROCESSED"},
{3, "HNF0_DIR_HIT"},
{4, "HNF0_DIR_MISS"},
{5, "HNF0_DIR_RD_ALLOC"},
{6, "HNF0_DIR_WR_ALLOC"},
{7, "HNF0_DIR_VICTIM"},
{8, "HNF0_CL_HAZARD"},
{9, "HNF0_ALL_HAZARD"},
{10, "HNF0_PIPE_STALLS"},
{11, "HNF0_MEM_READS"},
{12, "HNF0_MEM_WRITES"},
{13, "HNF0_MEM_ACCESS"},
{14, "HNF0_DCL_READ"},
{15, "HNF0_DCL_INVAL"},
{16, "HNF0_CHI_RXDAT"},
{17, "HNF0_CHI_RXRSP"},
{18, "HNF0_CHI_TXDAT"},
{19, "HNF0_CHI_TXRSP"},
{20, "HNF0_CHI_TXSNP"},
{21, "HNF0_DCT_SNP"},
{22, "HNF0_SNP_FWD_DATA"},
{23, "HNF0_SNP_FWD_RSP"},
{24, "HNF0_SNP_RSP"},
{25, "HNF0_EXCL_FULL"},
{26, "HNF0_EXCL_WRITE_F"},
{27, "HNF0_EXCL_WRITE_S"},
{28, "HNF0_EXCL_WRITE"},
{29, "HNF0_EXCL_READ"},
{30, "HNF0_REQ_BUF_EMPTY"},
{31, "HNF0_ALL_MAFS_BUSY"},
{32, "HNF0_TXDAT_NO_LCRD"},
{33, "HNF0_TXSNP_NO_LCRD"},
{34, "HNF0_TXRSP_NO_LCRD"},
{35, "HNF0_TXREQ_NO_LCRD"},
{36, "HNF0_WRITE"},
{37, "HNF0_READ"},
{38, "HNF0_ACCESS"},
{39, "HNF0_MAF_N_BUSY"},
{40, "HNF0_MAF_N_REQS"},
{41, "HNF0_SEL_OPCODE"},
{42, "HNF1_CYCLES"},
{43, "HNF1_REQS_RECEIVED"},
{44, "HNF1_REQS_PROCESSED"},
{45, "HNF1_DIR_HIT"},
{46, "HNF1_DIR_MISS"},
{47, "HNF1_DIR_RD_ALLOC"},
{48, "HNF1_DIR_WR_ALLOC"},
{49, "HNF1_DIR_VICTIM"},
{50, "HNF1_CL_HAZARD"},
{51, "HNF1_ALL_HAZARD"},
{52, "HNF1_PIPE_STALLS"},
{53, "HNF1_MEM_READS"},
{54, "HNF1_MEM_WRITES"},
{55, "HNF1_MEM_ACCESS"},
{56, "HNF1_DCL_READ"},
{57, "HNF1_DCL_INVAL"},
{58, "HNF1_CHI_RXDAT"},
{59, "HNF1_CHI_RXRSP"},
{60, "HNF1_CHI_TXDAT"},
{61, "HNF1_CHI_TXRSP"},
{62, "HNF1_CHI_TXSNP"},
{63, "HNF1_DCT_SNP"},
{64, "HNF1_SNP_FWD_DATA"},
{65, "HNF1_SNP_FWD_RSP"},
{66, "HNF1_SNP_RSP"},
{67, "HNF1_EXCL_FULL"},
{68, "HNF1_EXCL_WRITE_F"},
{69, "HNF1_EXCL_WRITE_S"},
{70, "HNF1_EXCL_WRITE"},
{71, "HNF1_EXCL_READ"},
{72, "HNF1_REQ_BUF_EMPTY"},
{73, "HNF1_ALL_MAFS_BUSY"},
{74, "HNF1_TXDAT_NO_LCRD"},
{75, "HNF1_TXSNP_NO_LCRD"},
{76, "HNF1_TXRSP_NO_LCRD"},
{77, "HNF1_TXREQ_NO_LCRD"},
{78, "HNF1_WRITE"},
{79, "HNF1_READ"},
{80, "HNF1_ACCESS"},
{81, "HNF1_MAF_N_BUSY"},
{82, "HNF1_MAF_N_REQS"},
{83, "HNF1_SEL_OPCODE"},
{84, "GDC_BANK0_RD_REQ"},
{85, "GDC_BANK0_WR_REQ"},
{86, "GDC_BANK0_ALLOCATE"},
{87, "GDC_BANK0_HIT"},
{88, "GDC_BANK0_MISS"},
{89, "GDC_BANK0_INVALIDATE"},
{90, "GDC_BANK0_EVICT"},
{91, "GDC_BANK0_RD_RESP"},
{92, "GDC_BANK0_WR_ACK"},
{93, "GDC_BANK0_SNOOP"},
{94, "GDC_BANK0_SNOOP_NORMAL"},
{95, "GDC_BANK0_SNOOP_FWD"},
{96, "GDC_BANK0_SNOOP_STASH"},
{97, "GDC_BANK0_SNOOP_STASH_INDPND_RD"},
{98, "GDC_BANK0_FOLLOWER"},
{99, "GDC_BANK0_FW"},
{100, "GDC_BANK0_HIT_DCL_BOTH"},
{101, "GDC_BANK0_HIT_DCL_PARTIAL"},
{102, "GDC_BANK0_EVICT_DCL"},
{103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA0"},
{103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA1"},
{105, "GDC_BANK0_ARB_STRB"},
{106, "GDC_BANK0_ARB_WAIT"},
{107, "GDC_BANK0_GGA_STRB"},
{108, "GDC_BANK0_GGA_WAIT"},
{109, "GDC_BANK0_FW_STRB"},
{110, "GDC_BANK0_FW_WAIT"},
{111, "GDC_BANK0_SNP_STRB"},
{112, "GDC_BANK0_SNP_WAIT"},
{113, "GDC_BANK0_MISS_INARB_STRB"},
{114, "GDC_BANK0_MISS_INARB_WAIT"},
{115, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD0"},
{116, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD1"},
{117, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD2"},
{118, "GDC_BANK0_G_FIFO_FF_GGA_RSP_RD3"},
{119, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR0"},
{120, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR1"},
{121, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR2"},
{122, "GDC_BANK0_G_FIFO_FF_GGA_RSP_WR3"},
{123, "GDC_BANK1_RD_REQ"},
{124, "GDC_BANK1_WR_REQ"},
{125, "GDC_BANK1_ALLOCATE"},
{126, "GDC_BANK1_HIT"},
{127, "GDC_BANK1_MISS"},
{128, "GDC_BANK1_INVALIDATE"},
{129, "GDC_BANK1_EVICT"},
{130, "GDC_BANK1_RD_RESP"},
{131, "GDC_BANK1_WR_ACK"},
{132, "GDC_BANK1_SNOOP"},
{133, "GDC_BANK1_SNOOP_NORMAL"},
{134, "GDC_BANK1_SNOOP_FWD"},
{135, "GDC_BANK1_SNOOP_STASH"},
{136, "GDC_BANK1_SNOOP_STASH_INDPND_RD"},
{137, "GDC_BANK1_FOLLOWER"},
{138, "GDC_BANK1_FW"},
{139, "GDC_BANK1_HIT_DCL_BOTH"},
{140, "GDC_BANK1_HIT_DCL_PARTIAL"},
{141, "GDC_BANK1_EVICT_DCL"},
{142, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA0"},
{143, "GDC_BANK1_G_RSE_PIPE_CACHE_DATA1"},
{144, "GDC_BANK1_ARB_STRB"},
{145, "GDC_BANK1_ARB_WAIT"},
{146, "GDC_BANK1_GGA_STRB"},
{147, "GDC_BANK1_GGA_WAIT"},
{148, "GDC_BANK1_FW_STRB"},
{149, "GDC_BANK1_FW_WAIT"},
{150, "GDC_BANK1_SNP_STRB"},
{151, "GDC_BANK1_SNP_WAIT"},
{152, "GDC_BANK1_MISS_INARB_STRB"},
{153, "GDC_BANK1_MISS_INARB_WAIT"},
{154, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD0"},
{155, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD1"},
{156, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD2"},
{157, "GDC_BANK1_G_FIFO_FF_GGA_RSP_RD3"},
{158, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR0"},
{159, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR1"},
{160, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR2"},
{161, "GDC_BANK1_G_FIFO_FF_GGA_RSP_WR3"},
{162, "HISTOGRAM_HISTOGRAM_BIN0"},
{163, "HISTOGRAM_HISTOGRAM_BIN1"},
{164, "HISTOGRAM_HISTOGRAM_BIN2"},
{165, "HISTOGRAM_HISTOGRAM_BIN3"},
{166, "HISTOGRAM_HISTOGRAM_BIN4"},
{167, "HISTOGRAM_HISTOGRAM_BIN5"},
{168, "HISTOGRAM_HISTOGRAM_BIN6"},
{169, "HISTOGRAM_HISTOGRAM_BIN7"},
{170, "HISTOGRAM_HISTOGRAM_BIN8"},
{171, "HISTOGRAM_HISTOGRAM_BIN9"},
};
static const struct mlxbf_pmc_events mlxbf_pmc_llt_miss_events[] = {
{0, "GDC_MISS_MACHINE_RD_REQ"},
{1, "GDC_MISS_MACHINE_WR_REQ"},
{2, "GDC_MISS_MACHINE_SNP_REQ"},
{3, "GDC_MISS_MACHINE_EVICT_REQ"},
{4, "GDC_MISS_MACHINE_FW_REQ"},
{5, "GDC_MISS_MACHINE_RD_RESP"},
{6, "GDC_MISS_MACHINE_WR_RESP"},
{7, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP"},
{8, "GDC_MISS_MACHINE_SNP_STASH_DATAPULL_DROP_TXDAT"},
{9, "GDC_MISS_MACHINE_CHI_TXREQ"},
{10, "GDC_MISS_MACHINE_CHI_RXRSP"},
{11, "GDC_MISS_MACHINE_CHI_TXDAT"},
{12, "GDC_MISS_MACHINE_CHI_RXDAT"},
{13, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_0"},
{14, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_1 "},
{15, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_2"},
{16, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_3 "},
{17, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_0 "},
{18, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_1 "},
{19, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_2 "},
{20, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_3 "},
{21, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_0"},
{22, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_1"},
{23, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_2"},
{24, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_3"},
{25, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_0 "},
{26, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_1"},
{27, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_2"},
{28, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_3"},
{29, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_0"},
{30, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_1"},
{31, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_2"},
{32, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_3"},
{33, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_4"},
{34, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_5"},
{35, "GDC_MISS_MACHINE_GDC_LINK_LIST_FF_6"},
{36, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_0"},
{37, "GDC_MISS_MACHINE_G_RSE_PIPE_TXREQ_1"},
{38, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_0"},
{39, "GDC_MISS_MACHINE_G_CREDIT_TXREQ_1"},
{40, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_0"},
{41, "GDC_MISS_MACHINE_G_RSE_PIPE_TXDAT_1"},
{42, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_0"},
{43, "GDC_MISS_MACHINE_G_CREDIT_TXDAT_1"},
{44, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_0"},
{45, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_1"},
{46, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_2"},
{47, "GDC_MISS_MACHINE_G_FIFO_FF_COMPACK_3"},
{48, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_0"},
{49, "GDC_MISS_MACHINE_G_RSE_PIPE_TXRSP_1"},
{50, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_0"},
{51, "GDC_MISS_MACHINE_G_CREDIT_TXRSP_1"},
{52, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_0"},
{53, "GDC_MISS_MACHINE_G_RSE_PIPE_INARB_1"},
{54, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_0"},
{55, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_1"},
{56, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_2"},
{57, "GDC_MISS_MACHINE_G_FIFO_FF_SNOOP_IN_3"},
{58, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_0"},
{59, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_1"},
{60, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_2"},
{61, "GDC_MISS_MACHINE_G_FIFO_FF_TXRSP_SNOOP_DATAPULL_3"},
{62, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_4"},
{63, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_5"},
{64, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_6"},
{65, "GDC_MISS_MACHINE_G_FIFO_FF_TXDAT_SNOOP_DATAPULL_7"},
{66, "HISTOGRAM_HISTOGRAM_BIN0"},
{67, "HISTOGRAM_HISTOGRAM_BIN1"},
{68, "HISTOGRAM_HISTOGRAM_BIN2"},
{69, "HISTOGRAM_HISTOGRAM_BIN3"},
{70, "HISTOGRAM_HISTOGRAM_BIN4"},
{71, "HISTOGRAM_HISTOGRAM_BIN5"},
{72, "HISTOGRAM_HISTOGRAM_BIN6"},
{73, "HISTOGRAM_HISTOGRAM_BIN7"},
{74, "HISTOGRAM_HISTOGRAM_BIN8"},
{75, "HISTOGRAM_HISTOGRAM_BIN9"},
};
static struct mlxbf_pmc_context *pmc;
/* UUID used to probe ATF service. */
@ -569,8 +999,21 @@ static const struct mlxbf_pmc_events *mlxbf_pmc_event_list(const char *blk,
break;
}
} else if (strstr(blk, "mss")) {
events = mlxbf_pmc_mss_events;
*size = ARRAY_SIZE(mlxbf_pmc_mss_events);
switch (pmc->event_set) {
case MLXBF_PMC_EVENT_SET_BF1:
case MLXBF_PMC_EVENT_SET_BF2:
events = mlxbf_pmc_mss_events_1;
*size = ARRAY_SIZE(mlxbf_pmc_mss_events_1);
break;
case MLXBF_PMC_EVENT_SET_BF3:
events = mlxbf_pmc_mss_events_3;
*size = ARRAY_SIZE(mlxbf_pmc_mss_events_3);
break;
default:
events = NULL;
*size = 0;
break;
}
} else if (strstr(blk, "ecc")) {
events = mlxbf_pmc_ecc_events;
*size = ARRAY_SIZE(mlxbf_pmc_ecc_events);
@ -586,6 +1029,12 @@ static const struct mlxbf_pmc_events *mlxbf_pmc_event_list(const char *blk,
} else if (strstr(blk, "smmu")) {
events = mlxbf_pmc_smgen_events;
*size = ARRAY_SIZE(mlxbf_pmc_smgen_events);
} else if (strstr(blk, "llt_miss")) {
events = mlxbf_pmc_llt_miss_events;
*size = ARRAY_SIZE(mlxbf_pmc_llt_miss_events);
} else if (strstr(blk, "llt")) {
events = mlxbf_pmc_llt_events;
*size = ARRAY_SIZE(mlxbf_pmc_llt_events);
} else {
events = NULL;
*size = 0;
@ -712,6 +1161,43 @@ static int mlxbf_pmc_program_l3_counter(int blk_num, uint32_t cnt_num,
return mlxbf_pmc_write(pmcaddr, MLXBF_PMC_WRITE_REG_32, *wordaddr);
}
/* Method to handle crspace counter programming */
static int mlxbf_pmc_program_crspace_counter(int blk_num, uint32_t cnt_num,
uint32_t evt)
{
uint32_t word;
void *addr;
int ret;
addr = pmc->block[blk_num].mmio_base +
(rounddown(cnt_num, 2) * MLXBF_PMC_CRSPACE_PERFSEL_SZ);
ret = mlxbf_pmc_readl(addr, &word);
if (ret)
return ret;
if (cnt_num % 2) {
word &= ~MLXBF_PMC_CRSPACE_PERFSEL1;
word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFSEL1, evt);
} else {
word &= ~MLXBF_PMC_CRSPACE_PERFSEL0;
word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFSEL0, evt);
}
return mlxbf_pmc_write(addr, MLXBF_PMC_WRITE_REG_32, word);
}
/* Method to clear crspace counter value */
static int mlxbf_pmc_clear_crspace_counter(int blk_num, uint32_t cnt_num)
{
void *addr;
addr = pmc->block[blk_num].mmio_base +
MLXBF_PMC_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) +
(cnt_num * 4);
return mlxbf_pmc_write(addr, MLXBF_PMC_WRITE_REG_32, 0x0);
}
/* Method to program a counter to monitor an event */
static int mlxbf_pmc_program_counter(int blk_num, uint32_t cnt_num,
uint32_t evt, bool is_l3)
@ -724,6 +1210,10 @@ static int mlxbf_pmc_program_counter(int blk_num, uint32_t cnt_num,
if (is_l3)
return mlxbf_pmc_program_l3_counter(blk_num, cnt_num, evt);
if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)
return mlxbf_pmc_program_crspace_counter(blk_num, cnt_num,
evt);
/* Configure the counter */
perfctl = FIELD_PREP(MLXBF_PMC_PERFCTL_EN0, 1);
perfctl |= FIELD_PREP(MLXBF_PMC_PERFCTL_EB0, 0);
@ -778,7 +1268,7 @@ static int mlxbf_pmc_read_l3_counter(int blk_num, uint32_t cnt_num,
{
uint32_t perfcnt_low = 0, perfcnt_high = 0;
uint64_t value;
int status = 0;
int status;
status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
MLXBF_PMC_L3C_PERF_CNT_LOW +
@ -804,6 +1294,24 @@ static int mlxbf_pmc_read_l3_counter(int blk_num, uint32_t cnt_num,
return 0;
}
/* Method to handle crspace counter reads */
static int mlxbf_pmc_read_crspace_counter(int blk_num, uint32_t cnt_num,
uint64_t *result)
{
uint32_t value;
int status = 0;
status = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
MLXBF_PMC_CRSPACE_PERFMON_VAL0(pmc->block[blk_num].counters) +
(cnt_num * 4), &value);
if (status)
return status;
*result = value;
return 0;
}
/* Method to read the counter value */
static int mlxbf_pmc_read_counter(int blk_num, uint32_t cnt_num, bool is_l3,
uint64_t *result)
@ -818,6 +1326,9 @@ static int mlxbf_pmc_read_counter(int blk_num, uint32_t cnt_num, bool is_l3,
if (is_l3)
return mlxbf_pmc_read_l3_counter(blk_num, cnt_num, result);
if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)
return mlxbf_pmc_read_crspace_counter(blk_num, cnt_num, result);
perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE;
perfval_offset = perfcfg_offset +
pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE;
@ -893,6 +1404,30 @@ static int mlxbf_pmc_read_l3_event(int blk_num, uint32_t cnt_num,
return 0;
}
/* Method to read crspace block event */
static int mlxbf_pmc_read_crspace_event(int blk_num, uint32_t cnt_num,
uint64_t *result)
{
uint32_t word, evt;
void *addr;
int ret;
addr = pmc->block[blk_num].mmio_base +
(rounddown(cnt_num, 2) * MLXBF_PMC_CRSPACE_PERFSEL_SZ);
ret = mlxbf_pmc_readl(addr, &word);
if (ret)
return ret;
if (cnt_num % 2)
evt = FIELD_GET(MLXBF_PMC_CRSPACE_PERFSEL1, word);
else
evt = FIELD_GET(MLXBF_PMC_CRSPACE_PERFSEL0, word);
*result = evt;
return 0;
}
/* Method to find the event currently being monitored by a counter */
static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3,
uint64_t *result)
@ -906,6 +1441,9 @@ static int mlxbf_pmc_read_event(int blk_num, uint32_t cnt_num, bool is_l3,
if (is_l3)
return mlxbf_pmc_read_l3_event(blk_num, cnt_num, result);
if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)
return mlxbf_pmc_read_crspace_event(blk_num, cnt_num, result);
perfcfg_offset = cnt_num * MLXBF_PMC_REG_SIZE;
perfval_offset = perfcfg_offset +
pmc->block[blk_num].counters * MLXBF_PMC_REG_SIZE;
@ -982,7 +1520,8 @@ static ssize_t mlxbf_pmc_counter_show(struct device *dev,
if (strstr(pmc->block_name[blk_num], "l3cache"))
is_l3 = true;
if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) {
if ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) ||
(pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE)) {
if (mlxbf_pmc_read_counter(blk_num, cnt_num, is_l3, &value))
return -EINVAL;
} else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER) {
@ -1040,6 +1579,10 @@ static ssize_t mlxbf_pmc_counter_store(struct device *dev,
err = mlxbf_pmc_write_reg(blk_num, offset, data);
if (err)
return err;
} else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {
if (sscanf(attr->attr.name, "counter%d", &cnt_num) != 1)
return -EINVAL;
err = mlxbf_pmc_clear_crspace_counter(blk_num, cnt_num);
} else
return -EINVAL;
@ -1137,28 +1680,37 @@ static ssize_t mlxbf_pmc_event_list_show(struct device *dev,
return ret;
}
/* Show function for "enable" sysfs files - only for l3cache */
/* Show function for "enable" sysfs files - only for l3cache & crspace */
static ssize_t mlxbf_pmc_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mlxbf_pmc_attribute *attr_enable = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
uint32_t perfcnt_cfg;
uint32_t perfcnt_cfg, word;
int blk_num, value;
blk_num = attr_enable->nr;
if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
MLXBF_PMC_L3C_PERF_CNT_CFG,
&perfcnt_cfg))
return -EINVAL;
if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {
if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),
&word))
return -EINVAL;
value = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_CFG_EN, perfcnt_cfg);
value = FIELD_GET(MLXBF_PMC_CRSPACE_PERFMON_EN, word);
} else {
if (mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
MLXBF_PMC_L3C_PERF_CNT_CFG,
&perfcnt_cfg))
return -EINVAL;
value = FIELD_GET(MLXBF_PMC_L3C_PERF_CNT_CFG_EN, perfcnt_cfg);
}
return sysfs_emit(buf, "%d\n", value);
}
/* Store function for "enable" sysfs files - only for l3cache */
/* Store function for "enable" sysfs files - only for l3cache & crspace */
static ssize_t mlxbf_pmc_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@ -1166,6 +1718,7 @@ static ssize_t mlxbf_pmc_enable_store(struct device *dev,
struct mlxbf_pmc_attribute *attr_enable = container_of(
attr, struct mlxbf_pmc_attribute, dev_attr);
int err, en, blk_num;
uint32_t word;
blk_num = attr_enable->nr;
@ -1173,19 +1726,35 @@ static ssize_t mlxbf_pmc_enable_store(struct device *dev,
if (err < 0)
return err;
if (!en) {
err = mlxbf_pmc_config_l3_counters(blk_num, false, false);
if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) {
err = mlxbf_pmc_readl(pmc->block[blk_num].mmio_base +
MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),
&word);
if (err)
return -EINVAL;
word &= ~MLXBF_PMC_CRSPACE_PERFMON_EN;
word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFMON_EN, en);
if (en)
word |= FIELD_PREP(MLXBF_PMC_CRSPACE_PERFMON_CLR, 1);
mlxbf_pmc_write(pmc->block[blk_num].mmio_base +
MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters),
MLXBF_PMC_WRITE_REG_32, word);
} else {
if (en && en != 1)
return -EINVAL;
err = mlxbf_pmc_config_l3_counters(blk_num, false, !!en);
if (err)
return err;
} else if (en == 1) {
err = mlxbf_pmc_config_l3_counters(blk_num, false, true);
if (err)
return err;
err = mlxbf_pmc_config_l3_counters(blk_num, true, false);
if (err)
return err;
} else
return -EINVAL;
if (en == 1) {
err = mlxbf_pmc_config_l3_counters(blk_num, true, false);
if (err)
return err;
}
}
return count;
}
@ -1206,7 +1775,8 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, int blk_num)
attr = NULL;
/* "enable" sysfs to start/stop the counters. Only in L3C blocks */
if (strstr(pmc->block_name[blk_num], "l3cache")) {
if (strstr(pmc->block_name[blk_num], "l3cache") ||
((pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE))) {
attr = &pmc->block[blk_num].attr_enable;
attr->dev_attr.attr.mode = 0644;
attr->dev_attr.show = mlxbf_pmc_enable_show;
@ -1297,7 +1867,8 @@ static int mlxbf_pmc_create_groups(struct device *dev, int blk_num)
int err;
/* Populate attributes based on counter type */
if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER)
if ((pmc->block[blk_num].type == MLXBF_PMC_TYPE_COUNTER) ||
(pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE))
err = mlxbf_pmc_init_perftype_counter(dev, blk_num);
else if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_REGISTER)
err = mlxbf_pmc_init_perftype_reg(dev, blk_num);
@ -1311,7 +1882,8 @@ static int mlxbf_pmc_create_groups(struct device *dev, int blk_num)
pmc->block[blk_num].block_attr_grp.attrs = pmc->block[blk_num].block_attr;
pmc->block[blk_num].block_attr_grp.name = devm_kasprintf(
dev, GFP_KERNEL, pmc->block_name[blk_num]);
pmc->groups[blk_num] = &pmc->block[blk_num].block_attr_grp;
pmc->groups[pmc->group_num] = &pmc->block[blk_num].block_attr_grp;
pmc->group_num++;
return 0;
}
@ -1334,13 +1906,52 @@ static int mlxbf_pmc_map_counters(struct device *dev)
int i, tile_num, ret;
for (i = 0; i < pmc->total_blocks; ++i) {
if (strstr(pmc->block_name[i], "tile")) {
/* Create sysfs for tiles only if block number < tile_count */
if (strstr(pmc->block_name[i], "tilenet")) {
if (sscanf(pmc->block_name[i], "tilenet%d", &tile_num) != 1)
continue;
if (tile_num >= pmc->tile_count)
continue;
} else if (strstr(pmc->block_name[i], "tile")) {
if (sscanf(pmc->block_name[i], "tile%d", &tile_num) != 1)
return -EINVAL;
continue;
if (tile_num >= pmc->tile_count)
continue;
}
/* Create sysfs only for enabled MSS blocks */
if (strstr(pmc->block_name[i], "mss") &&
pmc->event_set == MLXBF_PMC_EVENT_SET_BF3) {
int mss_num;
if (sscanf(pmc->block_name[i], "mss%d", &mss_num) != 1)
continue;
if (!((pmc->mss_enable >> mss_num) & 0x1))
continue;
}
/* Create sysfs only for enabled LLT blocks */
if (strstr(pmc->block_name[i], "llt_miss")) {
int llt_num;
if (sscanf(pmc->block_name[i], "llt_miss%d", &llt_num) != 1)
continue;
if (!((pmc->llt_enable >> llt_num) & 0x1))
continue;
} else if (strstr(pmc->block_name[i], "llt")) {
int llt_num;
if (sscanf(pmc->block_name[i], "llt%d", &llt_num) != 1)
continue;
if (!((pmc->llt_enable >> llt_num) & 0x1))
continue;
}
ret = device_property_read_u64_array(dev, pmc->block_name[i],
info, MLXBF_PMC_INFO_SZ);
if (ret)
@ -1417,6 +2028,8 @@ static int mlxbf_pmc_probe(struct platform_device *pdev)
pmc->event_set = MLXBF_PMC_EVENT_SET_BF1;
else if (!strcmp(hid, "MLNXBFD1"))
pmc->event_set = MLXBF_PMC_EVENT_SET_BF2;
else if (!strcmp(hid, "MLNXBFD2"))
pmc->event_set = MLXBF_PMC_EVENT_SET_BF3;
else
return -ENODEV;
@ -1430,11 +2043,19 @@ static int mlxbf_pmc_probe(struct platform_device *pdev)
if (ret != pmc->total_blocks)
return -EFAULT;
ret = device_property_read_u32(dev, "tile_num", &pmc->tile_count);
if (ret)
return ret;
if (device_property_read_u32(dev, "tile_num", &pmc->tile_count)) {
if (device_property_read_u8(dev, "llt_enable", &pmc->llt_enable)) {
dev_err(dev, "Number of tiles/LLTs undefined\n");
return -EINVAL;
}
if (device_property_read_u8(dev, "mss_enable", &pmc->mss_enable)) {
dev_err(dev, "Number of tiles/MSSs undefined\n");
return -EINVAL;
}
}
pmc->pdev = pdev;
pmc->group_num = 0;
ret = mlxbf_pmc_map_counters(dev);
if (ret)
@ -1449,6 +2070,7 @@ static int mlxbf_pmc_probe(struct platform_device *pdev)
static const struct acpi_device_id mlxbf_pmc_acpi_ids[] = { { "MLNXBFD0", 0 },
{ "MLNXBFD1", 0 },
{ "MLNXBFD2", 0 },
{}, };
MODULE_DEVICE_TABLE(acpi, mlxbf_pmc_acpi_ids);

View File

@ -1364,13 +1364,11 @@ fail:
}
/* Device remove function. */
static int mlxbf_tmfifo_remove(struct platform_device *pdev)
static void mlxbf_tmfifo_remove(struct platform_device *pdev)
{
struct mlxbf_tmfifo *fifo = platform_get_drvdata(pdev);
mlxbf_tmfifo_cleanup(fifo);
return 0;
}
static const struct acpi_device_id mlxbf_tmfifo_acpi_match[] = {
@ -1381,7 +1379,7 @@ MODULE_DEVICE_TABLE(acpi, mlxbf_tmfifo_acpi_match);
static struct platform_driver mlxbf_tmfifo_driver = {
.probe = mlxbf_tmfifo_probe,
.remove = mlxbf_tmfifo_remove,
.remove_new = mlxbf_tmfifo_remove,
.driver = {
.name = "bf-tmfifo",
.acpi_match_table = mlxbf_tmfifo_acpi_match,

View File

@ -786,15 +786,13 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
return 0;
}
static int mlxreg_hotplug_remove(struct platform_device *pdev)
static void mlxreg_hotplug_remove(struct platform_device *pdev)
{
struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(&pdev->dev);
/* Clean interrupts setup. */
mlxreg_hotplug_unset_irq(priv);
devm_free_irq(&pdev->dev, priv->irq, priv);
return 0;
}
static struct platform_driver mlxreg_hotplug_driver = {
@ -802,7 +800,7 @@ static struct platform_driver mlxreg_hotplug_driver = {
.name = "mlxreg-hotplug",
},
.probe = mlxreg_hotplug_probe,
.remove = mlxreg_hotplug_remove,
.remove_new = mlxreg_hotplug_remove,
};
module_platform_driver(mlxreg_hotplug_driver);

View File

@ -263,13 +263,11 @@ static int mlxreg_io_probe(struct platform_device *pdev)
return 0;
}
static int mlxreg_io_remove(struct platform_device *pdev)
static void mlxreg_io_remove(struct platform_device *pdev)
{
struct mlxreg_io_priv_data *priv = dev_get_drvdata(&pdev->dev);
mutex_destroy(&priv->io_lock);
return 0;
}
static struct platform_driver mlxreg_io_driver = {
@ -277,7 +275,7 @@ static struct platform_driver mlxreg_io_driver = {
.name = "mlxreg-io",
},
.probe = mlxreg_io_probe,
.remove = mlxreg_io_remove,
.remove_new = mlxreg_io_remove,
};
module_platform_driver(mlxreg_io_driver);

View File

@ -907,7 +907,7 @@ i2c_get_adapter_fail:
return err;
}
static int mlxreg_lc_remove(struct platform_device *pdev)
static void mlxreg_lc_remove(struct platform_device *pdev)
{
struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev);
struct mlxreg_lc *mlxreg_lc = platform_get_drvdata(pdev);
@ -921,7 +921,7 @@ static int mlxreg_lc_remove(struct platform_device *pdev)
* is nothing to remove.
*/
if (!data->notifier || !data->notifier->handle)
return 0;
return;
/* Clear event notification callback and handle. */
data->notifier->user_handler = NULL;
@ -940,13 +940,11 @@ static int mlxreg_lc_remove(struct platform_device *pdev)
i2c_put_adapter(data->hpdev.adapter);
data->hpdev.adapter = NULL;
}
return 0;
}
static struct platform_driver mlxreg_lc_driver = {
.probe = mlxreg_lc_probe,
.remove = mlxreg_lc_remove,
.remove_new = mlxreg_lc_remove,
.driver = {
.name = "mlxreg-lc",
},

View File

@ -1217,7 +1217,7 @@ static int nvsw_sn2201_probe(struct platform_device *pdev)
return nvsw_sn2201_config_pre_init(nvsw_sn2201);
}
static int nvsw_sn2201_remove(struct platform_device *pdev)
static void nvsw_sn2201_remove(struct platform_device *pdev)
{
struct nvsw_sn2201 *nvsw_sn2201 = platform_get_drvdata(pdev);
@ -1239,8 +1239,6 @@ static int nvsw_sn2201_remove(struct platform_device *pdev)
/* Unregister I2C controller. */
if (nvsw_sn2201->pdev_i2c)
platform_device_unregister(nvsw_sn2201->pdev_i2c);
return 0;
}
static const struct acpi_device_id nvsw_sn2201_acpi_ids[] = {
@ -1252,7 +1250,7 @@ MODULE_DEVICE_TABLE(acpi, nvsw_sn2201_acpi_ids);
static struct platform_driver nvsw_sn2201_driver = {
.probe = nvsw_sn2201_probe,
.remove = nvsw_sn2201_remove,
.remove_new = nvsw_sn2201_remove,
.driver = {
.name = "nvsw-sn2201",
.acpi_match_table = nvsw_sn2201_acpi_ids,

View File

@ -226,14 +226,13 @@ static int __init s3_wmi_probe(struct platform_device *pdev)
return error;
}
static int s3_wmi_remove(struct platform_device *device)
static void s3_wmi_remove(struct platform_device *device)
{
/* remove the hotplug context from the acpi device */
s3_wmi.touchscreen_adev->hp = NULL;
/* reinstall the actual PNPC0C0D LID default handle */
acpi_bus_scan(s3_wmi.pnp0c0d_adev->handle);
return 0;
}
static int __maybe_unused s3_wmi_resume(struct device *dev)
@ -248,7 +247,7 @@ static struct platform_driver s3_wmi_driver = {
.name = "surface3-wmi",
.pm = &s3_wmi_pm,
},
.remove = s3_wmi_remove,
.remove_new = s3_wmi_remove,
};
static int __init s3_wmi_init(void)

View File

@ -854,7 +854,7 @@ err_enable_events:
return status;
}
static int san_remove(struct platform_device *pdev)
static void san_remove(struct platform_device *pdev)
{
acpi_handle san = ACPI_HANDLE(&pdev->dev);
@ -868,8 +868,6 @@ static int san_remove(struct platform_device *pdev)
* all delayed works they may have spawned are run to completion.
*/
flush_workqueue(san_wq);
return 0;
}
static const struct acpi_device_id san_match[] = {
@ -880,7 +878,7 @@ MODULE_DEVICE_TABLE(acpi, san_match);
static struct platform_driver surface_acpi_notify = {
.probe = san_probe,
.remove = san_remove,
.remove_new = san_remove,
.driver = {
.name = "surface_acpi_notify",
.acpi_match_table = san_match,

View File

@ -714,7 +714,7 @@ static int ssam_dbg_device_probe(struct platform_device *pdev)
return 0;
}
static int ssam_dbg_device_remove(struct platform_device *pdev)
static void ssam_dbg_device_remove(struct platform_device *pdev)
{
struct ssam_cdev *cdev = platform_get_drvdata(pdev);
struct ssam_cdev_client *client;
@ -757,14 +757,13 @@ static int ssam_dbg_device_remove(struct platform_device *pdev)
misc_deregister(&cdev->mdev);
ssam_cdev_put(cdev);
return 0;
}
static struct platform_device *ssam_cdev_device;
static struct platform_driver ssam_cdev_driver = {
.probe = ssam_dbg_device_probe,
.remove = ssam_dbg_device_remove,
.remove_new = ssam_dbg_device_remove,
.driver = {
.name = SSAM_CDEV_DEVICE_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View File

@ -418,19 +418,18 @@ static int ssam_platform_hub_probe(struct platform_device *pdev)
return status;
}
static int ssam_platform_hub_remove(struct platform_device *pdev)
static void ssam_platform_hub_remove(struct platform_device *pdev)
{
const struct software_node **nodes = platform_get_drvdata(pdev);
ssam_remove_clients(&pdev->dev);
set_secondary_fwnode(&pdev->dev, NULL);
software_node_unregister_node_group(nodes);
return 0;
}
static struct platform_driver ssam_platform_hub_driver = {
.probe = ssam_platform_hub_probe,
.remove = ssam_platform_hub_remove,
.remove_new = ssam_platform_hub_remove,
.driver = {
.name = "surface_aggregator_platform_hub",
.acpi_match_table = ssam_platform_hub_match,

View File

@ -1168,10 +1168,9 @@ static int surface_dtx_platform_probe(struct platform_device *pdev)
return 0;
}
static int surface_dtx_platform_remove(struct platform_device *pdev)
static void surface_dtx_platform_remove(struct platform_device *pdev)
{
sdtx_device_destroy(platform_get_drvdata(pdev));
return 0;
}
static const struct acpi_device_id surface_dtx_acpi_match[] = {
@ -1182,7 +1181,7 @@ MODULE_DEVICE_TABLE(acpi, surface_dtx_acpi_match);
static struct platform_driver surface_dtx_platform_driver = {
.probe = surface_dtx_platform_probe,
.remove = surface_dtx_platform_remove,
.remove_new = surface_dtx_platform_remove,
.driver = {
.name = "surface_dtx_pltf",
.acpi_match_table = surface_dtx_acpi_match,

View File

@ -267,20 +267,18 @@ static int surface_gpe_probe(struct platform_device *pdev)
return ret;
}
static int surface_gpe_remove(struct platform_device *pdev)
static void surface_gpe_remove(struct platform_device *pdev)
{
struct surface_lid_device *lid = dev_get_drvdata(&pdev->dev);
/* restore default behavior without this module */
surface_lid_enable_wakeup(&pdev->dev, false);
acpi_disable_gpe(NULL, lid->gpe_number);
return 0;
}
static struct platform_driver surface_gpe_driver = {
.probe = surface_gpe_probe,
.remove = surface_gpe_remove,
.remove_new = surface_gpe_remove,
.driver = {
.name = "surface_gpe",
.pm = &surface_gpe_pm,

View File

@ -183,7 +183,7 @@ static int shps_setup_irq(struct platform_device *pdev, enum shps_irq_type type)
return 0;
}
static int surface_hotplug_remove(struct platform_device *pdev)
static void surface_hotplug_remove(struct platform_device *pdev)
{
struct shps_device *sdev = platform_get_drvdata(pdev);
int i;
@ -195,8 +195,6 @@ static int surface_hotplug_remove(struct platform_device *pdev)
mutex_destroy(&sdev->lock[i]);
}
return 0;
}
static int surface_hotplug_probe(struct platform_device *pdev)
@ -261,7 +259,7 @@ MODULE_DEVICE_TABLE(acpi, surface_hotplug_acpi_match);
static struct platform_driver surface_hotplug_driver = {
.probe = surface_hotplug_probe,
.remove = surface_hotplug_remove,
.remove_new = surface_hotplug_remove,
.driver = {
.name = "surface_hotplug",
.acpi_match_table = surface_hotplug_acpi_match,

View File

@ -988,6 +988,17 @@ config TOUCHSCREEN_DMI
the OS-image for the device. This option supplies the missing info.
Enable this for x86 tablets with Silead or Chipone touchscreens.
config INSPUR_PLATFORM_PROFILE
tristate "Inspur WMI platform profile driver"
depends on ACPI_WMI
select ACPI_PLATFORM_PROFILE
help
This will allow users to determine and control the platform modes
between low-power, balanced and performance modes.
To compile this driver as a module, choose M here: the module
will be called inspur-platform-profile.
source "drivers/platform/x86/x86-android-tablets/Kconfig"
config FW_ATTR_CLASS

View File

@ -98,6 +98,9 @@ obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o
# before toshiba_acpi initializes
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
# Inspur
obj-$(CONFIG_INSPUR_PLATFORM_PROFILE) += inspur_platform_profile.o
# Laptop drivers
obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o
obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o

View File

@ -1922,7 +1922,6 @@ static void acer_rfkill_exit(void)
rfkill_unregister(threeg_rfkill);
rfkill_destroy(threeg_rfkill);
}
return;
}
static void acer_wmi_notify(u32 value, void *context)
@ -2517,7 +2516,6 @@ static void __exit acer_wmi_exit(void)
platform_driver_unregister(&acer_platform_driver);
pr_info("Acer Laptop WMI Extras unloaded\n");
return;
}
module_init(acer_wmi_init);

View File

@ -20,7 +20,7 @@
#include <linux/semaphore.h>
#define DRIVER_NAME "amd_hsmp"
#define DRIVER_VERSION "1.0"
#define DRIVER_VERSION "2.0"
/* HSMP Status / Error codes */
#define HSMP_STATUS_NOT_READY 0x00
@ -47,9 +47,29 @@
#define HSMP_INDEX_REG 0xc4
#define HSMP_DATA_REG 0xc8
static struct semaphore *hsmp_sem;
#define HSMP_CDEV_NAME "hsmp_cdev"
#define HSMP_DEVNODE_NAME "hsmp"
#define HSMP_METRICS_TABLE_NAME "metrics_bin"
static struct miscdevice hsmp_device;
#define HSMP_ATTR_GRP_NAME_SIZE 10
struct hsmp_socket {
struct bin_attribute hsmp_attr;
void __iomem *metric_tbl_addr;
struct semaphore hsmp_sem;
char name[HSMP_ATTR_GRP_NAME_SIZE];
u16 sock_ind;
};
struct hsmp_plat_device {
struct miscdevice hsmp_device;
struct hsmp_socket *sock;
struct device *dev;
u32 proto_ver;
u16 num_sockets;
};
static struct hsmp_plat_device plat_dev;
static int amd_hsmp_rdwr(struct pci_dev *root, u32 address,
u32 *value, bool write)
@ -188,6 +208,7 @@ static int validate_message(struct hsmp_message *msg)
int hsmp_send_message(struct hsmp_message *msg)
{
struct hsmp_socket *sock = &plat_dev.sock[msg->sock_ind];
struct amd_northbridge *nb;
int ret;
@ -208,14 +229,13 @@ int hsmp_send_message(struct hsmp_message *msg)
* In SMP system timeout of 100 millisecs should
* be enough for the previous thread to finish the operation
*/
ret = down_timeout(&hsmp_sem[msg->sock_ind],
msecs_to_jiffies(HSMP_MSG_TIMEOUT));
ret = down_timeout(&sock->hsmp_sem, msecs_to_jiffies(HSMP_MSG_TIMEOUT));
if (ret < 0)
return ret;
ret = __hsmp_send_message(nb->root, msg);
up(&hsmp_sem[msg->sock_ind]);
up(&sock->hsmp_sem);
return ret;
}
@ -317,32 +337,198 @@ static const struct file_operations hsmp_fops = {
.compat_ioctl = hsmp_ioctl,
};
static int hsmp_pltdrv_probe(struct platform_device *pdev)
static ssize_t hsmp_metric_tbl_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
int i;
struct hsmp_socket *sock = bin_attr->private;
struct hsmp_message msg = { 0 };
int ret;
hsmp_sem = devm_kzalloc(&pdev->dev,
(amd_nb_num() * sizeof(struct semaphore)),
GFP_KERNEL);
if (!hsmp_sem)
/* Do not support lseek(), reads entire metric table */
if (count < bin_attr->size) {
dev_err(plat_dev.dev, "Wrong buffer size\n");
return -EINVAL;
}
if (!sock) {
dev_err(plat_dev.dev, "Failed to read attribute private data\n");
return -EINVAL;
}
msg.msg_id = HSMP_GET_METRIC_TABLE;
msg.sock_ind = sock->sock_ind;
ret = hsmp_send_message(&msg);
if (ret)
return ret;
memcpy_fromio(buf, sock->metric_tbl_addr, bin_attr->size);
return bin_attr->size;
}
static int hsmp_get_tbl_dram_base(u16 sock_ind)
{
struct hsmp_socket *sock = &plat_dev.sock[sock_ind];
struct hsmp_message msg = { 0 };
phys_addr_t dram_addr;
int ret;
msg.sock_ind = sock_ind;
msg.response_sz = hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_DRAM_ADDR].response_sz;
msg.msg_id = HSMP_GET_METRIC_TABLE_DRAM_ADDR;
ret = hsmp_send_message(&msg);
if (ret)
return ret;
/*
* calculate the metric table DRAM address from lower and upper 32 bits
* sent from SMU and ioremap it to virtual address.
*/
dram_addr = msg.args[0] | ((u64)(msg.args[1]) << 32);
if (!dram_addr) {
dev_err(plat_dev.dev, "Invalid DRAM address for metric table\n");
return -ENOMEM;
}
sock->metric_tbl_addr = devm_ioremap(plat_dev.dev, dram_addr,
sizeof(struct hsmp_metric_table));
if (!sock->metric_tbl_addr) {
dev_err(plat_dev.dev, "Failed to ioremap metric table addr\n");
return -ENOMEM;
}
return 0;
}
static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
struct bin_attribute *battr, int id)
{
if (plat_dev.proto_ver == HSMP_PROTO_VER6)
return battr->attr.mode;
else
return 0;
}
static int hsmp_init_metric_tbl_bin_attr(struct bin_attribute **hattrs, u16 sock_ind)
{
struct bin_attribute *hattr = &plat_dev.sock[sock_ind].hsmp_attr;
sysfs_bin_attr_init(hattr);
hattr->attr.name = HSMP_METRICS_TABLE_NAME;
hattr->attr.mode = 0444;
hattr->read = hsmp_metric_tbl_read;
hattr->size = sizeof(struct hsmp_metric_table);
hattr->private = &plat_dev.sock[sock_ind];
hattrs[0] = hattr;
if (plat_dev.proto_ver == HSMP_PROTO_VER6)
return (hsmp_get_tbl_dram_base(sock_ind));
else
return 0;
}
/* One bin sysfs for metrics table*/
#define NUM_HSMP_ATTRS 1
static int hsmp_create_sysfs_interface(void)
{
const struct attribute_group **hsmp_attr_grps;
struct bin_attribute **hsmp_bin_attrs;
struct attribute_group *attr_grp;
int ret;
u16 i;
/* String formatting is currently limited to u8 sockets */
if (WARN_ON(plat_dev.num_sockets > U8_MAX))
return -ERANGE;
hsmp_attr_grps = devm_kzalloc(plat_dev.dev, sizeof(struct attribute_group *) *
(plat_dev.num_sockets + 1), GFP_KERNEL);
if (!hsmp_attr_grps)
return -ENOMEM;
for (i = 0; i < amd_nb_num(); i++)
sema_init(&hsmp_sem[i], 1);
/* Create a sysfs directory for each socket */
for (i = 0; i < plat_dev.num_sockets; i++) {
attr_grp = devm_kzalloc(plat_dev.dev, sizeof(struct attribute_group), GFP_KERNEL);
if (!attr_grp)
return -ENOMEM;
hsmp_device.name = "hsmp_cdev";
hsmp_device.minor = MISC_DYNAMIC_MINOR;
hsmp_device.fops = &hsmp_fops;
hsmp_device.parent = &pdev->dev;
hsmp_device.nodename = "hsmp";
hsmp_device.mode = 0644;
snprintf(plat_dev.sock[i].name, HSMP_ATTR_GRP_NAME_SIZE, "socket%u", (u8)i);
attr_grp->name = plat_dev.sock[i].name;
return misc_register(&hsmp_device);
/* Null terminated list of attributes */
hsmp_bin_attrs = devm_kzalloc(plat_dev.dev, sizeof(struct bin_attribute *) *
(NUM_HSMP_ATTRS + 1), GFP_KERNEL);
if (!hsmp_bin_attrs)
return -ENOMEM;
attr_grp->bin_attrs = hsmp_bin_attrs;
attr_grp->is_bin_visible = hsmp_is_sock_attr_visible;
hsmp_attr_grps[i] = attr_grp;
/* Now create the leaf nodes */
ret = hsmp_init_metric_tbl_bin_attr(hsmp_bin_attrs, i);
if (ret)
return ret;
}
return devm_device_add_groups(plat_dev.dev, hsmp_attr_grps);
}
static int hsmp_cache_proto_ver(void)
{
struct hsmp_message msg = { 0 };
int ret;
msg.msg_id = HSMP_GET_PROTO_VER;
msg.sock_ind = 0;
msg.response_sz = hsmp_msg_desc_table[HSMP_GET_PROTO_VER].response_sz;
ret = hsmp_send_message(&msg);
if (!ret)
plat_dev.proto_ver = msg.args[0];
return ret;
}
static int hsmp_pltdrv_probe(struct platform_device *pdev)
{
int ret, i;
plat_dev.sock = devm_kzalloc(&pdev->dev,
(plat_dev.num_sockets * sizeof(struct hsmp_socket)),
GFP_KERNEL);
if (!plat_dev.sock)
return -ENOMEM;
plat_dev.dev = &pdev->dev;
for (i = 0; i < plat_dev.num_sockets; i++) {
sema_init(&plat_dev.sock[i].hsmp_sem, 1);
plat_dev.sock[i].sock_ind = i;
}
plat_dev.hsmp_device.name = HSMP_CDEV_NAME;
plat_dev.hsmp_device.minor = MISC_DYNAMIC_MINOR;
plat_dev.hsmp_device.fops = &hsmp_fops;
plat_dev.hsmp_device.parent = &pdev->dev;
plat_dev.hsmp_device.nodename = HSMP_DEVNODE_NAME;
plat_dev.hsmp_device.mode = 0644;
ret = hsmp_cache_proto_ver();
if (ret) {
dev_err(plat_dev.dev, "Failed to read HSMP protocol version\n");
return ret;
}
ret = hsmp_create_sysfs_interface();
if (ret)
dev_err(plat_dev.dev, "Failed to create HSMP sysfs interface\n");
return misc_register(&plat_dev.hsmp_device);
}
static void hsmp_pltdrv_remove(struct platform_device *pdev)
{
misc_deregister(&hsmp_device);
misc_deregister(&plat_dev.hsmp_device);
}
static struct platform_driver amd_hsmp_driver = {
@ -358,7 +544,6 @@ static struct platform_device *amd_hsmp_platdev;
static int __init hsmp_plt_init(void)
{
int ret = -ENODEV;
u16 num_sockets;
int i;
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD || boot_cpu_data.x86 < 0x19) {
@ -371,18 +556,18 @@ static int __init hsmp_plt_init(void)
* amd_nb_num() returns number of SMN/DF interfaces present in the system
* if we have N SMN/DF interfaces that ideally means N sockets
*/
num_sockets = amd_nb_num();
if (num_sockets == 0)
plat_dev.num_sockets = amd_nb_num();
if (plat_dev.num_sockets == 0)
return ret;
/* Test the hsmp interface on each socket */
for (i = 0; i < num_sockets; i++) {
for (i = 0; i < plat_dev.num_sockets; i++) {
ret = hsmp_test(i, 0xDEADBEEF);
if (ret) {
pr_err("HSMP is not supported on Fam:%x model:%x\n",
pr_err("HSMP test message failed on Fam:%x model:%x\n",
boot_cpu_data.x86, boot_cpu_data.x86_model);
pr_err("Or Is HSMP disabled in BIOS ?\n");
return -EOPNOTSUPP;
pr_err("Is HSMP disabled in BIOS ?\n");
return ret;
}
}

View File

@ -52,9 +52,13 @@
#define AMD_S2D_REGISTER_ARGUMENT 0xA88
/* STB Spill to DRAM Parameters */
#define S2D_TELEMETRY_BYTES_MAX 0x100000
#define S2D_TELEMETRY_BYTES_MAX 0x100000U
#define S2D_RSVD_RAM_SPACE 0x100000
#define S2D_TELEMETRY_DRAMBYTES_MAX 0x1000000
/* STB Spill to DRAM Message Definition */
#define STB_FORCE_FLUSH_DATA 0xCF
/* Base address of SMU for mapping physical address to virtual address */
#define AMD_PMC_MAPPING_SIZE 0x01000
#define AMD_PMC_BASE_ADDR_OFFSET 0x10000
@ -119,6 +123,11 @@ enum s2d_arg {
S2D_DRAM_SIZE,
};
struct amd_pmc_stb_v2_data {
size_t size;
u8 data[] __counted_by(size);
};
struct amd_pmc_bit_map {
const char *name;
u32 bit_mask;
@ -157,6 +166,10 @@ static bool disable_workarounds;
module_param(disable_workarounds, bool, 0644);
MODULE_PARM_DESC(disable_workarounds, "Disable workarounds for platform bugs");
static bool dump_custom_stb;
module_param(dump_custom_stb, bool, 0644);
MODULE_PARM_DESC(dump_custom_stb, "Enable to dump full STB buffer");
static struct amd_pmc_dev pmc;
static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret);
static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf);
@ -233,10 +246,30 @@ static const struct file_operations amd_pmc_stb_debugfs_fops = {
.release = amd_pmc_stb_debugfs_release,
};
/* Enhanced STB Firmware Reporting Mechanism */
static int amd_pmc_stb_handle_efr(struct file *filp)
{
struct amd_pmc_dev *dev = filp->f_inode->i_private;
struct amd_pmc_stb_v2_data *stb_data_arr;
u32 fsize;
fsize = dev->dram_size - S2D_RSVD_RAM_SPACE;
stb_data_arr = kmalloc(struct_size(stb_data_arr, data, fsize), GFP_KERNEL);
if (!stb_data_arr)
return -ENOMEM;
stb_data_arr->size = fsize;
memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr, fsize);
filp->private_data = stb_data_arr;
return 0;
}
static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp)
{
struct amd_pmc_dev *dev = filp->f_inode->i_private;
u32 *buf, fsize, num_samples, stb_rdptr_offset = 0;
u32 fsize, num_samples, val, stb_rdptr_offset = 0;
struct amd_pmc_stb_v2_data *stb_data_arr;
int ret;
/* Write dummy postcode while reading the STB buffer */
@ -244,34 +277,55 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp)
if (ret)
dev_err(dev->dev, "error writing to STB: %d\n", ret);
buf = kzalloc(S2D_TELEMETRY_BYTES_MAX, GFP_KERNEL);
if (!buf)
return -ENOMEM;
/* Spill to DRAM num_samples uses separate SMU message port */
dev->msg_port = 1;
ret = amd_pmc_send_cmd(dev, 0, &val, STB_FORCE_FLUSH_DATA, 1);
if (ret)
dev_dbg_once(dev->dev, "S2D force flush not supported: %d\n", ret);
/*
* We have a custom stb size and the PMFW is supposed to give
* the enhanced dram size. Note that we land here only for the
* platforms that support enhanced dram size reporting.
*/
if (dump_custom_stb)
return amd_pmc_stb_handle_efr(filp);
/* Get the num_samples to calculate the last push location */
ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, dev->s2d_msg_id, true);
/* Clear msg_port for other SMU operation */
dev->msg_port = 0;
if (ret) {
dev_err(dev->dev, "error: S2D_NUM_SAMPLES not supported : %d\n", ret);
kfree(buf);
return ret;
}
/* Start capturing data from the last push location */
fsize = min(num_samples, S2D_TELEMETRY_BYTES_MAX);
stb_data_arr = kmalloc(struct_size(stb_data_arr, data, fsize), GFP_KERNEL);
if (!stb_data_arr)
return -ENOMEM;
stb_data_arr->size = fsize;
/*
* Start capturing data from the last push location.
* This is for general cases, where the stb limits
* are meant for standard usage.
*/
if (num_samples > S2D_TELEMETRY_BYTES_MAX) {
fsize = S2D_TELEMETRY_BYTES_MAX;
stb_rdptr_offset = num_samples - fsize;
/* First read oldest data starting 1 behind last write till end of ringbuffer */
stb_rdptr_offset = num_samples % S2D_TELEMETRY_BYTES_MAX;
fsize = S2D_TELEMETRY_BYTES_MAX - stb_rdptr_offset;
memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr + stb_rdptr_offset, fsize);
/* Second copy the newer samples from offset 0 - last write */
memcpy_fromio(stb_data_arr->data + fsize, dev->stb_virt_addr, stb_rdptr_offset);
} else {
fsize = num_samples;
stb_rdptr_offset = 0;
memcpy_fromio(stb_data_arr->data, dev->stb_virt_addr, fsize);
}
memcpy_fromio(buf, dev->stb_virt_addr + stb_rdptr_offset, fsize);
filp->private_data = buf;
filp->private_data = stb_data_arr;
return 0;
}
@ -279,11 +333,9 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp)
static ssize_t amd_pmc_stb_debugfs_read_v2(struct file *filp, char __user *buf, size_t size,
loff_t *pos)
{
if (!filp->private_data)
return -EINVAL;
struct amd_pmc_stb_v2_data *data = filp->private_data;
return simple_read_from_buffer(buf, size, pos, filp->private_data,
S2D_TELEMETRY_BYTES_MAX);
return simple_read_from_buffer(buf, size, pos, data->data, data->size);
}
static int amd_pmc_stb_debugfs_release_v2(struct inode *inode, struct file *filp)

View File

@ -16,6 +16,8 @@
#include <linux/dmi.h>
#include <linux/i8042.h>
#include <acpi/video.h>
#include "asus-wmi.h"
#define ASUS_NB_WMI_FILE "asus-nb-wmi"
@ -606,6 +608,19 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_END, 0},
};
static void asus_nb_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
unsigned int *value, bool *autorelease)
{
switch (*code) {
case ASUS_WMI_BRN_DOWN:
case ASUS_WMI_BRN_UP:
if (acpi_video_handles_brightness_key_presses())
*code = ASUS_WMI_KEY_IGNORE;
break;
}
}
static struct asus_wmi_driver asus_nb_wmi_driver = {
.name = ASUS_NB_WMI_FILE,
.owner = THIS_MODULE,
@ -614,6 +629,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
.input_name = "Asus WMI hotkeys",
.input_phys = ASUS_NB_WMI_FILE "/input0",
.detect_quirks = asus_nb_wmi_quirks,
.key_filter = asus_nb_wmi_key_filter,
};

View File

@ -148,16 +148,12 @@ static int asus_wireless_add(struct acpi_device *adev)
if (err)
return err;
for (id = device_ids; id->id[0]; id++) {
if (!strcmp((char *) id->id, acpi_device_hid(adev))) {
data->hswc_params =
(const struct hswc_params *)id->driver_data;
break;
}
}
if (!data->hswc_params)
id = acpi_match_acpi_device(device_ids, adev);
if (!id)
return 0;
data->hswc_params = (const struct hswc_params *)id->driver_data;
data->wq = create_singlethread_workqueue("asus_wireless_workqueue");
if (!data->wq)
return -ENOMEM;

View File

@ -25,6 +25,7 @@
#include <linux/input/sparse-keymap.h>
#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
@ -127,6 +128,10 @@ module_param(fnlock_default, bool, 0444);
#define NVIDIA_TEMP_MIN 75
#define NVIDIA_TEMP_MAX 87
#define ASUS_SCREENPAD_BRIGHT_MIN 20
#define ASUS_SCREENPAD_BRIGHT_MAX 255
#define ASUS_SCREENPAD_BRIGHT_DEFAULT 60
static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
static int throttle_thermal_policy_write(struct asus_wmi *);
@ -212,6 +217,7 @@ struct asus_wmi {
struct input_dev *inputdev;
struct backlight_device *backlight_device;
struct backlight_device *screenpad_backlight_device;
struct platform_device *platform_device;
struct led_classdev wlan_led;
@ -3776,6 +3782,124 @@ static int is_display_toggle(int code)
return 0;
}
/* Screenpad backlight *******************************************************/
static int read_screenpad_backlight_power(struct asus_wmi *asus)
{
int ret;
ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_SCREENPAD_POWER);
if (ret < 0)
return ret;
/* 1 == powered */
return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
}
static int read_screenpad_brightness(struct backlight_device *bd)
{
struct asus_wmi *asus = bl_get_data(bd);
u32 retval;
int err;
err = read_screenpad_backlight_power(asus);
if (err < 0)
return err;
/* The device brightness can only be read if powered, so return stored */
if (err == FB_BLANK_POWERDOWN)
return asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN;
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval);
if (err < 0)
return err;
return (retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK) - ASUS_SCREENPAD_BRIGHT_MIN;
}
static int update_screenpad_bl_status(struct backlight_device *bd)
{
struct asus_wmi *asus = bl_get_data(bd);
int power, err = 0;
u32 ctrl_param;
power = read_screenpad_backlight_power(asus);
if (power < 0)
return power;
if (bd->props.power != power) {
if (power != FB_BLANK_UNBLANK) {
/* Only brightness > 0 can power it back on */
ctrl_param = asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN;
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT,
ctrl_param, NULL);
} else {
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL);
}
} else if (power == FB_BLANK_UNBLANK) {
/* Only set brightness if powered on or we get invalid/unsync state */
ctrl_param = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN;
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, NULL);
}
/* Ensure brightness is stored to turn back on with */
if (err == 0)
asus->driver->screenpad_brightness = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN;
return err;
}
static const struct backlight_ops asus_screenpad_bl_ops = {
.get_brightness = read_screenpad_brightness,
.update_status = update_screenpad_bl_status,
.options = BL_CORE_SUSPENDRESUME,
};
static int asus_screenpad_init(struct asus_wmi *asus)
{
struct backlight_device *bd;
struct backlight_properties props;
int err, power;
int brightness = 0;
power = read_screenpad_backlight_power(asus);
if (power < 0)
return power;
if (power != FB_BLANK_POWERDOWN) {
err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness);
if (err < 0)
return err;
}
/* default to an acceptable min brightness on boot if too low */
if (brightness < ASUS_SCREENPAD_BRIGHT_MIN)
brightness = ASUS_SCREENPAD_BRIGHT_DEFAULT;
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW; /* ensure this bd is last to be picked */
props.max_brightness = ASUS_SCREENPAD_BRIGHT_MAX - ASUS_SCREENPAD_BRIGHT_MIN;
bd = backlight_device_register("asus_screenpad",
&asus->platform_device->dev, asus,
&asus_screenpad_bl_ops, &props);
if (IS_ERR(bd)) {
pr_err("Could not register backlight device\n");
return PTR_ERR(bd);
}
asus->screenpad_backlight_device = bd;
asus->driver->screenpad_brightness = brightness;
bd->props.brightness = brightness - ASUS_SCREENPAD_BRIGHT_MIN;
bd->props.power = power;
backlight_update_status(bd);
return 0;
}
static void asus_screenpad_exit(struct asus_wmi *asus)
{
backlight_device_unregister(asus->screenpad_backlight_device);
asus->screenpad_backlight_device = NULL;
}
/* Fn-lock ********************************************************************/
static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus)
@ -4424,6 +4548,12 @@ static int asus_wmi_add(struct platform_device *pdev)
} else if (asus->driver->quirks->wmi_backlight_set_devstate)
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);
if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT)) {
err = asus_screenpad_init(asus);
if (err && err != -ENODEV)
goto fail_screenpad;
}
if (asus_wmi_has_fnlock_key(asus)) {
asus->fnlock_locked = fnlock_default;
asus_wmi_fnlock_update(asus);
@ -4447,6 +4577,8 @@ fail_wmi_handler:
asus_wmi_backlight_exit(asus);
fail_backlight:
asus_wmi_rfkill_exit(asus);
fail_screenpad:
asus_screenpad_exit(asus);
fail_rfkill:
asus_wmi_led_exit(asus);
fail_leds:
@ -4473,6 +4605,7 @@ static int asus_wmi_remove(struct platform_device *device)
asus = platform_get_drvdata(device);
wmi_remove_notify_handler(asus->driver->event_guid);
asus_wmi_backlight_exit(asus);
asus_screenpad_exit(asus);
asus_wmi_input_exit(asus);
asus_wmi_led_exit(asus);
asus_wmi_rfkill_exit(asus);

View File

@ -57,6 +57,7 @@ struct quirk_entry {
struct asus_wmi_driver {
int brightness;
int panel_power;
int screenpad_brightness;
int wlan_ctrl_by_user;
const char *name;

View File

@ -19,7 +19,7 @@ struct bios_args {
u32 command;
u32 commandtype;
u32 datasize;
u8 data[];
u8 data[] __counted_by(datasize);
};
/**

View File

@ -0,0 +1,216 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Inspur WMI Platform Profile
*
* Copyright (C) 2018 Ai Chao <aichao@kylinos.cn>
*/
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/platform_profile.h>
#include <linux/wmi.h>
#define WMI_INSPUR_POWERMODE_BIOS_GUID "596C31E3-332D-43C9-AEE9-585493284F5D"
enum inspur_wmi_method_ids {
INSPUR_WMI_GET_POWERMODE = 0x02,
INSPUR_WMI_SET_POWERMODE = 0x03,
};
/*
* Power Mode:
* 0x0: Balance Mode
* 0x1: Performance Mode
* 0x2: Power Saver Mode
*/
enum inspur_tmp_profile {
INSPUR_TMP_PROFILE_BALANCE = 0,
INSPUR_TMP_PROFILE_PERFORMANCE = 1,
INSPUR_TMP_PROFILE_POWERSAVE = 2,
};
struct inspur_wmi_priv {
struct wmi_device *wdev;
struct platform_profile_handler handler;
};
static int inspur_wmi_perform_query(struct wmi_device *wdev,
enum inspur_wmi_method_ids query_id,
void *buffer, size_t insize,
size_t outsize)
{
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_buffer input = { insize, buffer};
union acpi_object *obj;
acpi_status status;
int ret = 0;
status = wmidev_evaluate_method(wdev, 0, query_id, &input, &output);
if (ACPI_FAILURE(status)) {
dev_err(&wdev->dev, "EC Powermode control failed: %s\n",
acpi_format_exception(status));
return -EIO;
}
obj = output.pointer;
if (!obj)
return -EINVAL;
if (obj->type != ACPI_TYPE_BUFFER ||
obj->buffer.length != outsize) {
ret = -EINVAL;
goto out_free;
}
memcpy(buffer, obj->buffer.pointer, obj->buffer.length);
out_free:
kfree(obj);
return ret;
}
/*
* Set Power Mode to EC RAM. If Power Mode value greater than 0x3,
* return error
* Method ID: 0x3
* Arg: 4 Bytes
* Byte [0]: Power Mode:
* 0x0: Balance Mode
* 0x1: Performance Mode
* 0x2: Power Saver Mode
* Return Value: 4 Bytes
* Byte [0]: Return Code
* 0x0: No Error
* 0x1: Error
*/
static int inspur_platform_profile_set(struct platform_profile_handler *pprof,
enum platform_profile_option profile)
{
struct inspur_wmi_priv *priv = container_of(pprof, struct inspur_wmi_priv,
handler);
u8 ret_code[4] = {0, 0, 0, 0};
int ret;
switch (profile) {
case PLATFORM_PROFILE_BALANCED:
ret_code[0] = INSPUR_TMP_PROFILE_BALANCE;
break;
case PLATFORM_PROFILE_PERFORMANCE:
ret_code[0] = INSPUR_TMP_PROFILE_PERFORMANCE;
break;
case PLATFORM_PROFILE_LOW_POWER:
ret_code[0] = INSPUR_TMP_PROFILE_POWERSAVE;
break;
default:
return -EOPNOTSUPP;
}
ret = inspur_wmi_perform_query(priv->wdev, INSPUR_WMI_SET_POWERMODE,
ret_code, sizeof(ret_code),
sizeof(ret_code));
if (ret < 0)
return ret;
if (ret_code[0])
return -EBADRQC;
return 0;
}
/*
* Get Power Mode from EC RAM, If Power Mode value greater than 0x3,
* return error
* Method ID: 0x2
* Return Value: 4 Bytes
* Byte [0]: Return Code
* 0x0: No Error
* 0x1: Error
* Byte [1]: Power Mode
* 0x0: Balance Mode
* 0x1: Performance Mode
* 0x2: Power Saver Mode
*/
static int inspur_platform_profile_get(struct platform_profile_handler *pprof,
enum platform_profile_option *profile)
{
struct inspur_wmi_priv *priv = container_of(pprof, struct inspur_wmi_priv,
handler);
u8 ret_code[4] = {0, 0, 0, 0};
int ret;
ret = inspur_wmi_perform_query(priv->wdev, INSPUR_WMI_GET_POWERMODE,
&ret_code, sizeof(ret_code),
sizeof(ret_code));
if (ret < 0)
return ret;
if (ret_code[0])
return -EBADRQC;
switch (ret_code[1]) {
case INSPUR_TMP_PROFILE_BALANCE:
*profile = PLATFORM_PROFILE_BALANCED;
break;
case INSPUR_TMP_PROFILE_PERFORMANCE:
*profile = PLATFORM_PROFILE_PERFORMANCE;
break;
case INSPUR_TMP_PROFILE_POWERSAVE:
*profile = PLATFORM_PROFILE_LOW_POWER;
break;
default:
return -EINVAL;
}
return 0;
}
static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
{
struct inspur_wmi_priv *priv;
priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->wdev = wdev;
dev_set_drvdata(&wdev->dev, priv);
priv->handler.profile_get = inspur_platform_profile_get;
priv->handler.profile_set = inspur_platform_profile_set;
set_bit(PLATFORM_PROFILE_LOW_POWER, priv->handler.choices);
set_bit(PLATFORM_PROFILE_BALANCED, priv->handler.choices);
set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->handler.choices);
return platform_profile_register(&priv->handler);
}
static void inspur_wmi_remove(struct wmi_device *wdev)
{
platform_profile_remove();
}
static const struct wmi_device_id inspur_wmi_id_table[] = {
{ .guid_string = WMI_INSPUR_POWERMODE_BIOS_GUID },
{ }
};
MODULE_DEVICE_TABLE(wmi, inspur_wmi_id_table);
static struct wmi_driver inspur_wmi_driver = {
.driver = {
.name = "inspur-wmi-platform-profile",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.id_table = inspur_wmi_id_table,
.probe = inspur_wmi_probe,
.remove = inspur_wmi_remove,
};
module_wmi_driver(inspur_wmi_driver);
MODULE_AUTHOR("Ai Chao <aichao@kylinos.cn>");
MODULE_DESCRIPTION("Platform Profile Support for Inspur");
MODULE_LICENSE("GPL");

View File

@ -158,17 +158,16 @@ static int crc_pwrsrc_probe(struct platform_device *pdev)
return 0;
}
static int crc_pwrsrc_remove(struct platform_device *pdev)
static void crc_pwrsrc_remove(struct platform_device *pdev)
{
struct crc_pwrsrc_data *data = platform_get_drvdata(pdev);
debugfs_remove_recursive(data->debug_dentry);
return 0;
}
static struct platform_driver crc_pwrsrc_driver = {
.probe = crc_pwrsrc_probe,
.remove = crc_pwrsrc_remove,
.remove_new = crc_pwrsrc_remove,
.driver = {
.name = "crystal_cove_pwrsrc",
},

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2022 Intel Corporation. */
#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/semaphore.h>
@ -10,13 +11,16 @@
#include "ifs.h"
#define X86_MATCH(model) \
#define X86_MATCH(model, array_gen) \
X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, \
INTEL_FAM6_##model, X86_FEATURE_CORE_CAPABILITIES, NULL)
INTEL_FAM6_##model, X86_FEATURE_CORE_CAPABILITIES, array_gen)
static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
X86_MATCH(SAPPHIRERAPIDS_X),
X86_MATCH(EMERALDRAPIDS_X),
X86_MATCH(SAPPHIRERAPIDS_X, ARRAY_GEN0),
X86_MATCH(EMERALDRAPIDS_X, ARRAY_GEN0),
X86_MATCH(GRANITERAPIDS_X, ARRAY_GEN0),
X86_MATCH(GRANITERAPIDS_D, ARRAY_GEN0),
X86_MATCH(ATOM_CRESTMONT_X, ARRAY_GEN1),
{}
};
MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
@ -94,6 +98,9 @@ static int __init ifs_init(void)
for (i = 0; i < IFS_NUMTESTS; i++) {
if (!(msrval & BIT(ifs_devices[i].test_caps->integrity_cap_bit)))
continue;
ifs_devices[i].rw_data.generation = FIELD_GET(MSR_INTEGRITY_CAPS_SAF_GEN_MASK,
msrval);
ifs_devices[i].rw_data.array_gen = (u32)m->driver_data;
ret = misc_register(&ifs_devices[i].misc);
if (ret)
goto err_exit;

View File

@ -137,6 +137,10 @@
#define MSR_CHUNKS_AUTHENTICATION_STATUS 0x000002c5
#define MSR_ACTIVATE_SCAN 0x000002c6
#define MSR_SCAN_STATUS 0x000002c7
#define MSR_ARRAY_TRIGGER 0x000002d6
#define MSR_ARRAY_STATUS 0x000002d7
#define MSR_SAF_CTRL 0x000004f0
#define SCAN_NOT_TESTED 0
#define SCAN_TEST_PASS 1
#define SCAN_TEST_FAIL 2
@ -144,6 +148,9 @@
#define IFS_TYPE_SAF 0
#define IFS_TYPE_ARRAY_BIST 1
#define ARRAY_GEN0 0
#define ARRAY_GEN1 1
/* MSR_SCAN_HASHES_STATUS bit fields */
union ifs_scan_hashes_status {
u64 data;
@ -158,6 +165,19 @@ union ifs_scan_hashes_status {
};
};
union ifs_scan_hashes_status_gen2 {
u64 data;
struct {
u16 chunk_size;
u16 num_chunks;
u32 error_code :8;
u32 chunks_in_stride :9;
u32 rsvd :2;
u32 max_core_limit :12;
u32 valid :1;
};
};
/* MSR_CHUNKS_AUTH_STATUS bit fields */
union ifs_chunks_auth_status {
u64 data;
@ -170,13 +190,31 @@ union ifs_chunks_auth_status {
};
};
union ifs_chunks_auth_status_gen2 {
u64 data;
struct {
u16 valid_chunks;
u16 total_chunks;
u32 error_code :8;
u32 rsvd2 :24;
};
};
/* MSR_ACTIVATE_SCAN bit fields */
union ifs_scan {
u64 data;
struct {
u32 start :8;
u32 stop :8;
u32 rsvd :16;
union {
struct {
u8 start;
u8 stop;
u16 rsvd;
} gen0;
struct {
u16 start;
u16 stop;
} gen2;
};
u32 delay :31;
u32 sigmce :1;
};
@ -186,9 +224,17 @@ union ifs_scan {
union ifs_status {
u64 data;
struct {
u32 chunk_num :8;
u32 chunk_stop_index :8;
u32 rsvd1 :16;
union {
struct {
u8 chunk_num;
u8 chunk_stop_index;
u16 rsvd1;
} gen0;
struct {
u16 chunk_num;
u16 chunk_stop_index;
} gen2;
};
u32 error_code :8;
u32 rsvd2 :22;
u32 control_error :1;
@ -229,6 +275,9 @@ struct ifs_test_caps {
* @status: it holds simple status pass/fail/untested
* @scan_details: opaque scan status code from h/w
* @cur_batch: number indicating the currently loaded test file
* @generation: IFS test generation enumerated by hardware
* @chunk_size: size of a test chunk
* @array_gen: test generation of array test
*/
struct ifs_data {
int loaded_version;
@ -238,6 +287,9 @@ struct ifs_data {
int status;
u64 scan_details;
u32 cur_batch;
u32 generation;
u32 chunk_size;
u32 array_gen;
};
struct ifs_work {

View File

@ -2,6 +2,7 @@
/* Copyright(c) 2022 Intel Corporation. */
#include <linux/firmware.h>
#include <linux/sizes.h>
#include <asm/cpu.h>
#include <asm/microcode.h>
@ -26,6 +27,11 @@ union meta_data {
#define IFS_HEADER_SIZE (sizeof(struct microcode_header_intel))
#define META_TYPE_IFS 1
#define INVALIDATE_STRIDE 0x1UL
#define IFS_GEN_STRIDE_AWARE 2
#define AUTH_INTERRUPTED_ERROR 5
#define IFS_AUTH_RETRY_CT 10
static struct microcode_header_intel *ifs_header_ptr; /* pointer to the ifs image header */
static u64 ifs_hash_ptr; /* Address of ifs metadata (hash) */
static u64 ifs_test_image_ptr; /* 256B aligned address of test pattern */
@ -44,7 +50,10 @@ static const char * const scan_hash_status[] = {
static const char * const scan_authentication_status[] = {
[0] = "No error reported",
[1] = "Attempt to authenticate a chunk which is already marked as authentic",
[2] = "Chunk authentication error. The hash of chunk did not match expected value"
[2] = "Chunk authentication error. The hash of chunk did not match expected value",
[3] = "Reserved",
[4] = "Chunk outside the current stride",
[5] = "Authentication flow interrupted",
};
#define MC_HEADER_META_TYPE_END (0)
@ -80,6 +89,23 @@ static struct metadata_header *find_meta_data(void *ucode, unsigned int meta_typ
return NULL;
}
static void hashcopy_err_message(struct device *dev, u32 err_code)
{
if (err_code >= ARRAY_SIZE(scan_hash_status))
dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
else
dev_err(dev, "Hash copy error : %s\n", scan_hash_status[err_code]);
}
static void auth_err_message(struct device *dev, u32 err_code)
{
if (err_code >= ARRAY_SIZE(scan_authentication_status))
dev_err(dev, "invalid error code 0x%x for authentication\n", err_code);
else
dev_err(dev, "Chunk authentication error : %s\n",
scan_authentication_status[err_code]);
}
/*
* To copy scan hashes and authenticate test chunks, the initiating cpu must point
* to the EDX:EAX to the test image in linear address.
@ -109,11 +135,7 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work)
if (!hashes_status.valid) {
ifsd->loading_error = true;
if (err_code >= ARRAY_SIZE(scan_hash_status)) {
dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
goto done;
}
dev_err(dev, "Hash copy error : %s", scan_hash_status[err_code]);
hashcopy_err_message(dev, err_code);
goto done;
}
@ -133,13 +155,7 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work)
if (err_code) {
ifsd->loading_error = true;
if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
dev_err(dev,
"invalid error code 0x%x for authentication\n", err_code);
goto done;
}
dev_err(dev, "Chunk authentication error %s\n",
scan_authentication_status[err_code]);
auth_err_message(dev, err_code);
goto done;
}
}
@ -147,6 +163,102 @@ done:
complete(&ifs_done);
}
static int get_num_chunks(int gen, union ifs_scan_hashes_status_gen2 status)
{
return gen >= IFS_GEN_STRIDE_AWARE ? status.chunks_in_stride : status.num_chunks;
}
static bool need_copy_scan_hashes(struct ifs_data *ifsd)
{
return !ifsd->loaded ||
ifsd->generation < IFS_GEN_STRIDE_AWARE ||
ifsd->loaded_version != ifs_header_ptr->rev;
}
static int copy_hashes_authenticate_chunks_gen2(struct device *dev)
{
union ifs_scan_hashes_status_gen2 hashes_status;
union ifs_chunks_auth_status_gen2 chunk_status;
u32 err_code, valid_chunks, total_chunks;
int i, num_chunks, chunk_size;
union meta_data *ifs_meta;
int starting_chunk_nr;
struct ifs_data *ifsd;
u64 linear_addr, base;
u64 chunk_table[2];
int retry_count;
ifsd = ifs_get_data(dev);
if (need_copy_scan_hashes(ifsd)) {
wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr);
rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data);
/* enumerate the scan image information */
chunk_size = hashes_status.chunk_size * SZ_1K;
err_code = hashes_status.error_code;
num_chunks = get_num_chunks(ifsd->generation, hashes_status);
if (!hashes_status.valid) {
hashcopy_err_message(dev, err_code);
return -EIO;
}
ifsd->loaded_version = ifs_header_ptr->rev;
ifsd->chunk_size = chunk_size;
} else {
num_chunks = ifsd->valid_chunks;
chunk_size = ifsd->chunk_size;
}
if (ifsd->generation >= IFS_GEN_STRIDE_AWARE) {
wrmsrl(MSR_SAF_CTRL, INVALIDATE_STRIDE);
rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
if (chunk_status.valid_chunks != 0) {
dev_err(dev, "Couldn't invalidate installed stride - %d\n",
chunk_status.valid_chunks);
return -EIO;
}
}
base = ifs_test_image_ptr;
ifs_meta = (union meta_data *)find_meta_data(ifs_header_ptr, META_TYPE_IFS);
starting_chunk_nr = ifs_meta->starting_chunk;
/* scan data authentication and copy chunks to secured memory */
for (i = 0; i < num_chunks; i++) {
retry_count = IFS_AUTH_RETRY_CT;
linear_addr = base + i * chunk_size;
chunk_table[0] = starting_chunk_nr + i;
chunk_table[1] = linear_addr;
do {
wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, (u64)chunk_table);
rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);
err_code = chunk_status.error_code;
} while (err_code == AUTH_INTERRUPTED_ERROR && --retry_count);
if (err_code) {
ifsd->loading_error = true;
auth_err_message(dev, err_code);
return -EIO;
}
}
valid_chunks = chunk_status.valid_chunks;
total_chunks = chunk_status.total_chunks;
if (valid_chunks != total_chunks) {
ifsd->loading_error = true;
dev_err(dev, "Couldn't authenticate all the chunks. Authenticated %d total %d.\n",
valid_chunks, total_chunks);
return -EIO;
}
ifsd->valid_chunks = valid_chunks;
return 0;
}
static int validate_ifs_metadata(struct device *dev)
{
struct ifs_data *ifsd = ifs_get_data(dev);
@ -179,6 +291,13 @@ static int validate_ifs_metadata(struct device *dev)
return ret;
}
if (ifs_meta->chunks_per_stride &&
(ifs_meta->starting_chunk % ifs_meta->chunks_per_stride != 0)) {
dev_warn(dev, "Starting chunk num %u not a multiple of chunks_per_stride %u\n",
ifs_meta->starting_chunk, ifs_meta->chunks_per_stride);
return ret;
}
return 0;
}
@ -199,7 +318,9 @@ static int scan_chunks_sanity_check(struct device *dev)
return ret;
ifsd->loading_error = false;
ifsd->loaded_version = ifs_header_ptr->rev;
if (ifsd->generation > 0)
return copy_hashes_authenticate_chunks_gen2(dev);
/* copy the scan hash and authenticate per package */
cpus_read_lock();
@ -219,6 +340,7 @@ static int scan_chunks_sanity_check(struct device *dev)
ifs_pkg_auth[curr_pkg] = 1;
}
ret = 0;
ifsd->loaded_version = ifs_header_ptr->rev;
out:
cpus_read_unlock();
@ -260,6 +382,7 @@ int ifs_load_firmware(struct device *dev)
{
const struct ifs_test_caps *test = ifs_get_test_caps(dev);
struct ifs_data *ifsd = ifs_get_data(dev);
unsigned int expected_size;
const struct firmware *fw;
char scan_path[64];
int ret = -EINVAL;
@ -274,6 +397,13 @@ int ifs_load_firmware(struct device *dev)
goto done;
}
expected_size = ((struct microcode_header_intel *)fw->data)->totalsize;
if (fw->size != expected_size) {
dev_err(dev, "File size mismatch (expected %u, actual %zu). Corrupted IFS image.\n",
expected_size, fw->size);
return -EINVAL;
}
ret = image_sanity_check(dev, (struct microcode_header_intel *)fw->data);
if (ret)
goto release;

View File

@ -40,6 +40,8 @@ enum ifs_status_err_code {
IFS_UNASSIGNED_ERROR_CODE = 7,
IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT = 8,
IFS_INTERRUPTED_DURING_EXECUTION = 9,
IFS_UNASSIGNED_ERROR_CODE_0xA = 0xA,
IFS_CORRUPTED_CHUNK = 0xB,
};
static const char * const scan_test_status[] = {
@ -55,6 +57,8 @@ static const char * const scan_test_status[] = {
[IFS_EXCEED_NUMBER_OF_THREADS_CONCURRENT] =
"Exceeded number of Logical Processors (LP) allowed to run Scan-At-Field concurrently",
[IFS_INTERRUPTED_DURING_EXECUTION] = "Interrupt occurred prior to SCAN start",
[IFS_UNASSIGNED_ERROR_CODE_0xA] = "Unassigned error code 0xA",
[IFS_CORRUPTED_CHUNK] = "Scan operation aborted due to corrupted image. Try reloading",
};
static void message_not_tested(struct device *dev, int cpu, union ifs_status status)
@ -123,6 +127,8 @@ static bool can_restart(union ifs_status status)
case IFS_MISMATCH_ARGUMENTS_BETWEEN_THREADS:
case IFS_CORE_NOT_CAPABLE_CURRENTLY:
case IFS_UNASSIGNED_ERROR_CODE:
case IFS_UNASSIGNED_ERROR_CODE_0xA:
case IFS_CORRUPTED_CHUNK:
break;
}
return false;
@ -171,21 +177,31 @@ static void ifs_test_core(int cpu, struct device *dev)
union ifs_status status;
unsigned long timeout;
struct ifs_data *ifsd;
int to_start, to_stop;
int status_chunk;
u64 msrvals[2];
int retries;
ifsd = ifs_get_data(dev);
activate.rsvd = 0;
activate.gen0.rsvd = 0;
activate.delay = IFS_THREAD_WAIT;
activate.sigmce = 0;
activate.start = 0;
activate.stop = ifsd->valid_chunks - 1;
to_start = 0;
to_stop = ifsd->valid_chunks - 1;
if (ifsd->generation) {
activate.gen2.start = to_start;
activate.gen2.stop = to_stop;
} else {
activate.gen0.start = to_start;
activate.gen0.stop = to_stop;
}
timeout = jiffies + HZ / 2;
retries = MAX_IFS_RETRIES;
while (activate.start <= activate.stop) {
while (to_start <= to_stop) {
if (time_after(jiffies, timeout)) {
status.error_code = IFS_SW_TIMEOUT;
break;
@ -196,13 +212,14 @@ static void ifs_test_core(int cpu, struct device *dev)
status.data = msrvals[1];
trace_ifs_status(cpu, activate, status);
trace_ifs_status(cpu, to_start, to_stop, status.data);
/* Some cases can be retried, give up for others */
if (!can_restart(status))
break;
if (status.chunk_num == activate.start) {
status_chunk = ifsd->generation ? status.gen2.chunk_num : status.gen0.chunk_num;
if (status_chunk == to_start) {
/* Check for forward progress */
if (--retries == 0) {
if (status.error_code == IFS_NO_ERROR)
@ -211,7 +228,11 @@ static void ifs_test_core(int cpu, struct device *dev)
}
} else {
retries = MAX_IFS_RETRIES;
activate.start = status.chunk_num;
if (ifsd->generation)
activate.gen2.start = status_chunk;
else
activate.gen0.start = status_chunk;
to_start = status_chunk;
}
}
@ -308,6 +329,38 @@ static void ifs_array_test_core(int cpu, struct device *dev)
ifsd->status = SCAN_TEST_PASS;
}
#define ARRAY_GEN1_TEST_ALL_ARRAYS 0x0ULL
#define ARRAY_GEN1_STATUS_FAIL 0x1ULL
static int do_array_test_gen1(void *status)
{
int cpu = smp_processor_id();
int first;
first = cpumask_first(cpu_smt_mask(cpu));
if (cpu == first) {
wrmsrl(MSR_ARRAY_TRIGGER, ARRAY_GEN1_TEST_ALL_ARRAYS);
rdmsrl(MSR_ARRAY_STATUS, *((u64 *)status));
}
return 0;
}
static void ifs_array_test_gen1(int cpu, struct device *dev)
{
struct ifs_data *ifsd = ifs_get_data(dev);
u64 status = 0;
stop_core_cpuslocked(cpu, do_array_test_gen1, &status);
ifsd->scan_details = status;
if (status & ARRAY_GEN1_STATUS_FAIL)
ifsd->status = SCAN_TEST_FAIL;
else
ifsd->status = SCAN_TEST_PASS;
}
/*
* Initiate per core test. It wakes up work queue threads on the target cpu and
* its sibling cpu. Once all sibling threads wake up, the scan test gets executed and
@ -336,7 +389,10 @@ int do_core_test(int cpu, struct device *dev)
ifs_test_core(cpu, dev);
break;
case IFS_TYPE_ARRAY_BIST:
ifs_array_test_core(cpu, dev);
if (ifsd->array_gen == ARRAY_GEN0)
ifs_array_test_core(cpu, dev);
else
ifs_array_test_gen1(cpu, dev);
break;
default:
ret = -EINVAL;

View File

@ -18,16 +18,17 @@
struct isst_mmio_range {
int beg;
int end;
int size;
};
static struct isst_mmio_range mmio_range_devid_0[] = {
{0x04, 0x14},
{0x20, 0xD0},
{0x04, 0x14, 0x18},
{0x20, 0xD0, 0xD4},
};
static struct isst_mmio_range mmio_range_devid_1[] = {
{0x04, 0x14},
{0x20, 0x11C},
{0x04, 0x14, 0x18},
{0x20, 0x11C, 0x120},
};
struct isst_if_device {
@ -93,6 +94,7 @@ static int isst_if_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct isst_if_device *punit_dev;
struct isst_if_cmd_cb cb;
u32 mmio_base, pcu_base;
struct resource r;
u64 base_addr;
int ret;
@ -114,13 +116,16 @@ static int isst_if_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pcu_base &= GENMASK(10, 0);
base_addr = (u64)mmio_base << 23 | (u64) pcu_base << 12;
punit_dev->punit_mmio = devm_ioremap(&pdev->dev, base_addr, 256);
if (!punit_dev->punit_mmio)
return -ENOMEM;
punit_dev->mmio_range = (struct isst_mmio_range *) ent->driver_data;
r = DEFINE_RES_MEM(base_addr, punit_dev->mmio_range[1].size);
punit_dev->punit_mmio = devm_ioremap_resource(&pdev->dev, &r);
if (IS_ERR(punit_dev->punit_mmio))
return PTR_ERR(punit_dev->punit_mmio);
mutex_init(&punit_dev->mutex);
pci_set_drvdata(pdev, punit_dev);
punit_dev->mmio_range = (struct isst_mmio_range *) ent->driver_data;
memset(&cb, 0, sizeof(cb));
cb.cmd_size = sizeof(struct isst_if_io_reg);

View File

@ -30,7 +30,8 @@
#include "isst_if_common.h"
/* Supported SST hardware version by this driver */
#define ISST_HEADER_VERSION 1
#define ISST_MAJOR_VERSION 0
#define ISST_MINOR_VERSION 1
/*
* Used to indicate if value read from MMIO needs to get multiplied
@ -352,21 +353,25 @@ static int sst_main(struct auxiliary_device *auxdev, struct tpmi_per_power_domai
pd_info->sst_header.cp_offset *= 8;
pd_info->sst_header.pp_offset *= 8;
if (pd_info->sst_header.interface_version != ISST_HEADER_VERSION) {
dev_err(&auxdev->dev, "SST: Unsupported version:%x\n",
pd_info->sst_header.interface_version);
if (pd_info->sst_header.interface_version == TPMI_VERSION_INVALID)
return -ENODEV;
if (TPMI_MAJOR_VERSION(pd_info->sst_header.interface_version) != ISST_MAJOR_VERSION) {
dev_err(&auxdev->dev, "SST: Unsupported major version:%lx\n",
TPMI_MAJOR_VERSION(pd_info->sst_header.interface_version));
return -ENODEV;
}
if (TPMI_MINOR_VERSION(pd_info->sst_header.interface_version) != ISST_MINOR_VERSION)
dev_info(&auxdev->dev, "SST: Ignore: Unsupported minor version:%lx\n",
TPMI_MINOR_VERSION(pd_info->sst_header.interface_version));
/* Read SST CP Header */
*((u64 *)&pd_info->cp_header) = readq(pd_info->sst_base + pd_info->sst_header.cp_offset);
/* Read PP header */
*((u64 *)&pd_info->pp_header) = readq(pd_info->sst_base + pd_info->sst_header.pp_offset);
/* Force level_en_mask level 0 */
pd_info->pp_header.level_en_mask |= 0x01;
mask = 0x01;
levels = 0;
for (i = 0; i < 8; ++i) {
@ -704,7 +709,7 @@ static int isst_if_get_perf_level(void __user *argp)
return -EINVAL;
perf_level.max_level = power_domain_info->max_level;
perf_level.level_mask = power_domain_info->pp_header.allowed_level_mask;
perf_level.level_mask = power_domain_info->pp_header.level_en_mask;
perf_level.feature_rev = power_domain_info->pp_header.feature_rev;
_read_pp_info("current_level", perf_level.current_level, SST_PP_STATUS_OFFSET,
SST_PP_LEVEL_START, SST_PP_LEVEL_WIDTH, SST_MUL_FACTOR_NONE)

View File

@ -143,6 +143,33 @@ struct tpmi_info_header {
u64 lock:1;
} __packed;
/**
* struct tpmi_feature_state - Structure to read hardware state of a feature
* @enabled: Enable state of a feature, 1: enabled, 0: disabled
* @reserved_1: Reserved for future use
* @write_blocked: Writes are blocked means all write operations are ignored
* @read_blocked: Reads are blocked means will read 0xFFs
* @pcs_select: Interface used by out of band software, not used in OS
* @reserved_2: Reserved for future use
* @id: TPMI ID of the feature
* @reserved_3: Reserved for future use
* @locked: When set to 1, OS can't change this register.
*
* The structure is used to read hardware state of a TPMI feature. This
* information is used for debug and restricting operations for this feature.
*/
struct tpmi_feature_state {
u32 enabled:1;
u32 reserved_1:3;
u32 write_blocked:1;
u32 read_blocked:1;
u32 pcs_select:1;
u32 reserved_2:1;
u32 id:8;
u32 reserved_3:15;
u32 locked:1;
} __packed;
/*
* List of supported TMPI IDs.
* Some TMPI IDs are not used by Linux, so the numbers are not consecutive.
@ -202,6 +229,7 @@ EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);
#define TPMI_CONTROL_STATUS_OFFSET 0x00
#define TPMI_COMMAND_OFFSET 0x08
#define TMPI_CONTROL_DATA_VAL_OFFSET 0x0c
/*
* Spec is calling for max 1 seconds to get ownership at the worst
@ -230,7 +258,6 @@ EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);
/* TPMI command data registers */
#define TMPI_CONTROL_DATA_CMD GENMASK_ULL(7, 0)
#define TMPI_CONTROL_DATA_VAL GENMASK_ULL(63, 32)
#define TPMI_CONTROL_DATA_VAL_FEATURE GENMASK_ULL(48, 40)
/* Command to send via control interface */
@ -240,9 +267,6 @@ EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);
#define TPMI_CMD_LEN_MASK GENMASK_ULL(18, 16)
#define TPMI_STATE_DISABLED BIT_ULL(0)
#define TPMI_STATE_LOCKED BIT_ULL(31)
/* Mutex to complete get feature status without interruption */
static DEFINE_MUTEX(tpmi_dev_lock);
@ -256,7 +280,7 @@ static int tpmi_wait_for_owner(struct intel_tpmi_info *tpmi_info, u8 owner)
}
static int tpmi_read_feature_status(struct intel_tpmi_info *tpmi_info, int feature_id,
int *locked, int *disabled)
struct tpmi_feature_state *feature_state)
{
u64 control, data;
int ret;
@ -306,17 +330,8 @@ static int tpmi_read_feature_status(struct intel_tpmi_info *tpmi_info, int featu
}
/* Response is ready */
data = readq(tpmi_info->tpmi_control_mem + TPMI_COMMAND_OFFSET);
data = FIELD_GET(TMPI_CONTROL_DATA_VAL, data);
*disabled = 0;
*locked = 0;
if (!(data & TPMI_STATE_DISABLED))
*disabled = 1;
if (data & TPMI_STATE_LOCKED)
*locked = 1;
memcpy_fromio(feature_state, tpmi_info->tpmi_control_mem + TMPI_CONTROL_DATA_VAL_OFFSET,
sizeof(*feature_state));
ret = 0;
@ -335,34 +350,50 @@ int tpmi_get_feature_status(struct auxiliary_device *auxdev, int feature_id,
{
struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(auxdev->dev.parent);
struct intel_tpmi_info *tpmi_info = auxiliary_get_drvdata(&intel_vsec_dev->auxdev);
struct tpmi_feature_state feature_state;
int ret;
return tpmi_read_feature_status(tpmi_info, feature_id, locked, disabled);
ret = tpmi_read_feature_status(tpmi_info, feature_id, &feature_state);
if (ret)
return ret;
*locked = feature_state.locked;
*disabled = !feature_state.enabled;
return 0;
}
EXPORT_SYMBOL_NS_GPL(tpmi_get_feature_status, INTEL_TPMI);
static int tpmi_pfs_dbg_show(struct seq_file *s, void *unused)
{
struct intel_tpmi_info *tpmi_info = s->private;
int locked, disabled, read_blocked, write_blocked;
struct tpmi_feature_state feature_state;
struct intel_tpmi_pm_feature *pfs;
int locked, disabled, ret, i;
int ret, i;
seq_printf(s, "tpmi PFS start offset 0x:%llx\n", tpmi_info->pfs_start);
seq_puts(s, "tpmi_id\t\tentries\t\tsize\t\tcap_offset\tattribute\tvsec_offset\tlocked\tdisabled\n");
seq_puts(s, "tpmi_id\t\tentries\t\tsize\t\tcap_offset\tattribute\tvsec_offset\tlocked\tdisabled\tread_blocked\twrite_blocked\n");
for (i = 0; i < tpmi_info->feature_count; ++i) {
pfs = &tpmi_info->tpmi_features[i];
ret = tpmi_read_feature_status(tpmi_info, pfs->pfs_header.tpmi_id, &locked,
&disabled);
ret = tpmi_read_feature_status(tpmi_info, pfs->pfs_header.tpmi_id, &feature_state);
if (ret) {
locked = 'U';
disabled = 'U';
read_blocked = 'U';
write_blocked = 'U';
} else {
disabled = disabled ? 'Y' : 'N';
locked = locked ? 'Y' : 'N';
disabled = feature_state.enabled ? 'N' : 'Y';
locked = feature_state.locked ? 'Y' : 'N';
read_blocked = feature_state.read_blocked ? 'Y' : 'N';
write_blocked = feature_state.write_blocked ? 'Y' : 'N';
}
seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%08x\t%c\t%c\n",
seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%08x\t%c\t%c\t\t%c\t\t%c\n",
pfs->pfs_header.tpmi_id, pfs->pfs_header.num_entries,
pfs->pfs_header.entry_size, pfs->pfs_header.cap_offset,
pfs->pfs_header.attribute, pfs->vsec_offset, locked, disabled);
pfs->pfs_header.attribute, pfs->vsec_offset, locked, disabled,
read_blocked, write_blocked);
}
return 0;

View File

@ -28,7 +28,8 @@
#include "uncore-frequency-common.h"
#define UNCORE_HEADER_VERSION 1
#define UNCORE_MAJOR_VERSION 0
#define UNCORE_MINOR_VERSION 1
#define UNCORE_HEADER_INDEX 0
#define UNCORE_FABRIC_CLUSTER_OFFSET 8
@ -302,12 +303,21 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
/* Check for version and skip this resource if there is mismatch */
header = readq(pd_info->uncore_base);
pd_info->ufs_header_ver = header & UNCORE_VERSION_MASK;
if (pd_info->ufs_header_ver != UNCORE_HEADER_VERSION) {
dev_info(&auxdev->dev, "Uncore: Unsupported version:%d\n",
pd_info->ufs_header_ver);
if (pd_info->ufs_header_ver == TPMI_VERSION_INVALID)
continue;
if (TPMI_MAJOR_VERSION(pd_info->ufs_header_ver) != UNCORE_MAJOR_VERSION) {
dev_err(&auxdev->dev, "Uncore: Unsupported major version:%lx\n",
TPMI_MAJOR_VERSION(pd_info->ufs_header_ver));
ret = -ENODEV;
goto remove_clusters;
}
if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) != UNCORE_MINOR_VERSION)
dev_info(&auxdev->dev, "Uncore: Ignore: Unsupported minor version:%lx\n",
TPMI_MINOR_VERSION(pd_info->ufs_header_ver));
/* Get Cluster ID Mask */
cluster_mask = FIELD_GET(UNCORE_LOCAL_FABRIC_CLUSTER_ID_MASK, header);
if (!cluster_mask) {

View File

@ -368,7 +368,7 @@ struct mlxplat_priv {
};
static struct platform_device *mlxplat_dev;
static int mlxplat_i2c_main_complition_notify(void *handle, int id);
static int mlxplat_i2c_main_completion_notify(void *handle, int id);
static void __iomem *i2c_bridge_addr, *jtag_bridge_addr;
/* Regions for LPC I2C controller and LPC base register space */
@ -384,7 +384,7 @@ static const struct resource mlxplat_lpc_resources[] = {
/* Platform systems default i2c data */
static struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_i2c_default_data = {
.completion_notify = mlxplat_i2c_main_complition_notify,
.completion_notify = mlxplat_i2c_main_completion_notify,
};
/* Platform i2c next generation systems data */
@ -409,7 +409,7 @@ static struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_i2c_ng_data = {
.mask = MLXPLAT_CPLD_AGGR_MASK_COMEX,
.cell_low = MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET,
.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_I2C,
.completion_notify = mlxplat_i2c_main_complition_notify,
.completion_notify = mlxplat_i2c_main_completion_notify,
};
/* Platform default channels */
@ -6291,7 +6291,7 @@ static void mlxplat_pci_fpga_devices_exit(void)
}
static int
mlxplat_pre_init(struct resource **hotplug_resources, unsigned int *hotplug_resources_size)
mlxplat_logicdev_init(struct resource **hotplug_resources, unsigned int *hotplug_resources_size)
{
int err;
@ -6302,7 +6302,7 @@ mlxplat_pre_init(struct resource **hotplug_resources, unsigned int *hotplug_reso
return err;
}
static void mlxplat_post_exit(void)
static void mlxplat_logicdev_exit(void)
{
if (lpc_bridge)
mlxplat_pci_fpga_devices_exit();
@ -6310,7 +6310,7 @@ static void mlxplat_post_exit(void)
mlxplat_lpc_cpld_device_exit();
}
static int mlxplat_post_init(struct mlxplat_priv *priv)
static int mlxplat_platdevs_init(struct mlxplat_priv *priv)
{
int i = 0, err;
@ -6407,7 +6407,7 @@ fail_platform_hotplug_register:
return err;
}
static void mlxplat_pre_exit(struct mlxplat_priv *priv)
static void mlxplat_platdevs_exit(struct mlxplat_priv *priv)
{
int i;
@ -6429,7 +6429,7 @@ mlxplat_i2c_mux_complition_notify(void *handle, struct i2c_adapter *parent,
{
struct mlxplat_priv *priv = handle;
return mlxplat_post_init(priv);
return mlxplat_platdevs_init(priv);
}
static int mlxplat_i2c_mux_topology_init(struct mlxplat_priv *priv)
@ -6471,7 +6471,7 @@ static void mlxplat_i2c_mux_topology_exit(struct mlxplat_priv *priv)
}
}
static int mlxplat_i2c_main_complition_notify(void *handle, int id)
static int mlxplat_i2c_main_completion_notify(void *handle, int id)
{
struct mlxplat_priv *priv = handle;
@ -6522,7 +6522,7 @@ fail_mlxplat_mlxcpld_verify_bus_topology:
static void mlxplat_i2c_main_exit(struct mlxplat_priv *priv)
{
mlxplat_pre_exit(priv);
mlxplat_platdevs_exit(priv);
mlxplat_i2c_mux_topology_exit(priv);
if (priv->pdev_i2c)
platform_device_unregister(priv->pdev_i2c);
@ -6544,7 +6544,7 @@ static int mlxplat_probe(struct platform_device *pdev)
mlxplat_dev = pdev;
}
err = mlxplat_pre_init(&hotplug_resources, &hotplug_resources_size);
err = mlxplat_logicdev_init(&hotplug_resources, &hotplug_resources_size);
if (err)
return err;
@ -6603,12 +6603,12 @@ fail_regcache_sync:
fail_mlxplat_i2c_main_init:
fail_regmap_write:
fail_alloc:
mlxplat_post_exit();
mlxplat_logicdev_exit();
return err;
}
static int mlxplat_remove(struct platform_device *pdev)
static void mlxplat_remove(struct platform_device *pdev)
{
struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
@ -6617,8 +6617,7 @@ static int mlxplat_remove(struct platform_device *pdev)
if (mlxplat_reboot_nb)
unregister_reboot_notifier(mlxplat_reboot_nb);
mlxplat_i2c_main_exit(priv);
mlxplat_post_exit();
return 0;
mlxplat_logicdev_exit();
}
static const struct acpi_device_id mlxplat_acpi_table[] = {
@ -6634,7 +6633,7 @@ static struct platform_driver mlxplat_driver = {
.probe_type = PROBE_FORCE_SYNCHRONOUS,
},
.probe = mlxplat_probe,
.remove = mlxplat_remove,
.remove_new = mlxplat_remove,
};
static int __init mlxplat_init(void)

View File

@ -58,7 +58,7 @@ static struct msi_ec_conf CONF0 __initdata = {
.block_address = 0x2f,
.bit = 1,
},
.fn_super_swap = {
.fn_win_swap = {
.address = 0xbf,
.bit = 4,
},
@ -138,7 +138,7 @@ static struct msi_ec_conf CONF1 __initdata = {
.block_address = 0x2f,
.bit = 1,
},
.fn_super_swap = {
.fn_win_swap = {
.address = 0xbf,
.bit = 4,
},
@ -215,7 +215,7 @@ static struct msi_ec_conf CONF2 __initdata = {
.block_address = 0x2f,
.bit = 1,
},
.fn_super_swap = {
.fn_win_swap = {
.address = 0xe8,
.bit = 4,
},
@ -293,7 +293,7 @@ static struct msi_ec_conf CONF3 __initdata = {
.block_address = 0x2f,
.bit = 1,
},
.fn_super_swap = {
.fn_win_swap = {
.address = 0xe8,
.bit = 4,
},
@ -371,7 +371,7 @@ static struct msi_ec_conf CONF4 __initdata = {
.block_address = 0x2f,
.bit = 1,
},
.fn_super_swap = {
.fn_win_swap = {
.address = MSI_EC_ADDR_UNKNOWN, // supported, but unknown
.bit = 4,
},
@ -450,7 +450,7 @@ static struct msi_ec_conf CONF5 __initdata = {
.block_address = 0x2f,
.bit = 1,
},
.fn_super_swap = { // todo: reverse
.fn_win_swap = { // todo: reverse
.address = 0xbf,
.bit = 4,
},
@ -528,7 +528,7 @@ static struct msi_ec_conf CONF6 __initdata = {
.block_address = MSI_EC_ADDR_UNSUPP,
.bit = 1,
},
.fn_super_swap = {
.fn_win_swap = {
.address = 0xbf, // todo: reverse
.bit = 4,
},
@ -608,7 +608,7 @@ static struct msi_ec_conf CONF7 __initdata = {
.block_address = MSI_EC_ADDR_UNSUPP,
.bit = 1,
},
.fn_super_swap = {
.fn_win_swap = {
.address = 0xbf, // needs testing
.bit = 4,
},
@ -667,6 +667,467 @@ static struct msi_ec_conf CONF7 __initdata = {
},
};
static const char * const ALLOWED_FW_8[] __initconst = {
"14F1EMS1.115",
NULL
};
static struct msi_ec_conf CONF8 __initdata = {
.allowed_fw = ALLOWED_FW_8,
.charge_control = {
.address = 0xd7,
.offset_start = 0x8a,
.offset_end = 0x80,
.range_min = 0x8a,
.range_max = 0xe4,
},
.webcam = {
.address = 0x2e,
.block_address = MSI_EC_ADDR_UNSUPP,
.bit = 1,
},
.fn_win_swap = {
.address = 0xe8,
.bit = 4,
},
.cooler_boost = {
.address = 0x98,
.bit = 7,
},
.shift_mode = {
.address = 0xd2,
.modes = {
{ SM_ECO_NAME, 0xc2 },
{ SM_COMFORT_NAME, 0xc1 },
{ SM_SPORT_NAME, 0xc0 },
MSI_EC_MODE_NULL
},
},
.super_battery = {
.address = 0xeb,
.mask = 0x0f,
},
.fan_mode = {
.address = 0xd4,
.modes = {
{ FM_AUTO_NAME, 0x0d },
{ FM_SILENT_NAME, 0x1d },
{ FM_BASIC_NAME, 0x4d },
MSI_EC_MODE_NULL
},
},
.cpu = {
.rt_temp_address = 0x68,
.rt_fan_speed_address = 0x71,
.rt_fan_speed_base_min = 0x19,
.rt_fan_speed_base_max = 0x37,
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
.bs_fan_speed_base_min = 0x00,
.bs_fan_speed_base_max = 0x0f,
},
.gpu = {
.rt_temp_address = MSI_EC_ADDR_UNKNOWN,
.rt_fan_speed_address = MSI_EC_ADDR_UNKNOWN,
},
.leds = {
.micmute_led_address = MSI_EC_ADDR_UNSUPP,
.mute_led_address = 0x2d,
.bit = 1,
},
.kbd_bl = {
.bl_mode_address = MSI_EC_ADDR_UNKNOWN, // ?
.bl_modes = { 0x00, 0x08 }, // ?
.max_mode = 1, // ?
.bl_state_address = MSI_EC_ADDR_UNSUPP, // not functional
.state_base_value = 0x80,
.max_state = 3,
},
};
static const char * const ALLOWED_FW_9[] __initconst = {
"14JKEMS1.104",
NULL
};
static struct msi_ec_conf CONF9 __initdata = {
.allowed_fw = ALLOWED_FW_9,
.charge_control = {
.address = 0xef,
.offset_start = 0x8a,
.offset_end = 0x80,
.range_min = 0x8a,
.range_max = 0xe4,
},
.webcam = {
.address = 0x2e,
.block_address = 0x2f,
.bit = 1,
},
.fn_win_swap = {
.address = 0xbf,
.bit = 4,
},
.cooler_boost = {
.address = 0x98,
.bit = 7,
},
.shift_mode = {
.address = 0xf2,
.modes = {
{ SM_ECO_NAME, 0xc2 },
{ SM_COMFORT_NAME, 0xc1 },
{ SM_SPORT_NAME, 0xc0 },
MSI_EC_MODE_NULL
},
},
.super_battery = {
.address = MSI_EC_ADDR_UNSUPP, // unsupported or enabled by ECO shift
.mask = 0x0f,
},
.fan_mode = {
.address = 0xf4,
.modes = {
{ FM_AUTO_NAME, 0x0d },
{ FM_SILENT_NAME, 0x1d },
{ FM_ADVANCED_NAME, 0x8d },
MSI_EC_MODE_NULL
},
},
.cpu = {
.rt_temp_address = 0x68,
.rt_fan_speed_address = 0x71,
.rt_fan_speed_base_min = 0x00,
.rt_fan_speed_base_max = 0x96,
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
.bs_fan_speed_base_min = 0x00,
.bs_fan_speed_base_max = 0x0f,
},
.gpu = {
.rt_temp_address = MSI_EC_ADDR_UNSUPP,
.rt_fan_speed_address = MSI_EC_ADDR_UNSUPP,
},
.leds = {
.micmute_led_address = 0x2b,
.mute_led_address = 0x2c,
.bit = 2,
},
.kbd_bl = {
.bl_mode_address = MSI_EC_ADDR_UNSUPP, // not presented in MSI app
.bl_modes = { 0x00, 0x08 },
.max_mode = 1,
.bl_state_address = 0xf3,
.state_base_value = 0x80,
.max_state = 3,
},
};
static const char * const ALLOWED_FW_10[] __initconst = {
"1582EMS1.107", // GF66 11UC
NULL
};
static struct msi_ec_conf CONF10 __initdata = {
.allowed_fw = ALLOWED_FW_10,
.charge_control = {
.address = 0xd7,
.offset_start = 0x8a,
.offset_end = 0x80,
.range_min = 0x8a,
.range_max = 0xe4,
},
.webcam = {
.address = 0x2e,
.block_address = 0x2f,
.bit = 1,
},
.fn_win_swap = {
.address = MSI_EC_ADDR_UNSUPP,
.bit = 4,
},
.cooler_boost = {
.address = 0x98,
.bit = 7,
},
.shift_mode = {
.address = 0xd2,
.modes = {
{ SM_ECO_NAME, 0xc2 },
{ SM_COMFORT_NAME, 0xc1 },
{ SM_SPORT_NAME, 0xc0 },
{ SM_TURBO_NAME, 0xc4 },
MSI_EC_MODE_NULL
},
},
.super_battery = {
.address = 0xe5,
.mask = 0x0f,
},
.fan_mode = {
.address = 0xd4,
.modes = {
{ FM_AUTO_NAME, 0x0d },
{ FM_SILENT_NAME, 0x1d },
{ FM_ADVANCED_NAME, 0x8d },
MSI_EC_MODE_NULL
},
},
.cpu = {
.rt_temp_address = 0x68,
.rt_fan_speed_address = 0x71, // ?
.rt_fan_speed_base_min = 0x19,
.rt_fan_speed_base_max = 0x37,
.bs_fan_speed_address = MSI_EC_ADDR_UNKNOWN, // ?
.bs_fan_speed_base_min = 0x00,
.bs_fan_speed_base_max = 0x0f,
},
.gpu = {
.rt_temp_address = 0x80,
.rt_fan_speed_address = 0x89,
},
.leds = {
.micmute_led_address = 0x2c,
.mute_led_address = 0x2d,
.bit = 1,
},
.kbd_bl = {
.bl_mode_address = 0x2c,
.bl_modes = { 0x00, 0x08 },
.max_mode = 1,
.bl_state_address = 0xd3,
.state_base_value = 0x80,
.max_state = 3,
},
};
static const char * const ALLOWED_FW_11[] __initconst = {
"16S6EMS1.111", // Prestige 15 a11scx
"1552EMS1.115", // Modern 15 a11m
NULL
};
static struct msi_ec_conf CONF11 __initdata = {
.allowed_fw = ALLOWED_FW_11,
.charge_control = {
.address = 0xd7,
.offset_start = 0x8a,
.offset_end = 0x80,
.range_min = 0x8a,
.range_max = 0xe4,
},
.webcam = {
.address = 0x2e,
.block_address = MSI_EC_ADDR_UNKNOWN,
.bit = 1,
},
.fn_win_swap = {
.address = 0xe8,
.bit = 4,
},
.cooler_boost = {
.address = 0x98,
.bit = 7,
},
.shift_mode = {
.address = 0xd2,
.modes = {
{ SM_ECO_NAME, 0xc2 },
{ SM_COMFORT_NAME, 0xc1 },
{ SM_SPORT_NAME, 0xc0 },
MSI_EC_MODE_NULL
},
},
.super_battery = {
.address = 0xeb,
.mask = 0x0f,
},
.fan_mode = {
.address = 0xd4,
.modes = {
{ FM_AUTO_NAME, 0x0d },
{ FM_SILENT_NAME, 0x1d },
{ FM_ADVANCED_NAME, 0x4d },
MSI_EC_MODE_NULL
},
},
.cpu = {
.rt_temp_address = 0x68,
.rt_fan_speed_address = MSI_EC_ADDR_UNSUPP,
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
},
.gpu = {
.rt_temp_address = MSI_EC_ADDR_UNSUPP,
.rt_fan_speed_address = MSI_EC_ADDR_UNSUPP,
},
.leds = {
.micmute_led_address = 0x2c,
.mute_led_address = 0x2d,
.bit = 1,
},
.kbd_bl = {
.bl_mode_address = MSI_EC_ADDR_UNKNOWN,
.bl_modes = {}, // ?
.max_mode = 1, // ?
.bl_state_address = 0xd3,
.state_base_value = 0x80,
.max_state = 3,
},
};
static const char * const ALLOWED_FW_12[] __initconst = {
"16R6EMS1.104", // GF63 Thin 11UC
NULL
};
static struct msi_ec_conf CONF12 __initdata = {
.allowed_fw = ALLOWED_FW_12,
.charge_control = {
.address = 0xd7,
.offset_start = 0x8a,
.offset_end = 0x80,
.range_min = 0x8a,
.range_max = 0xe4,
},
.webcam = {
.address = 0x2e,
.block_address = 0x2f,
.bit = 1,
},
.fn_win_swap = {
.address = 0xe8,
.bit = 4,
},
.cooler_boost = {
.address = 0x98,
.bit = 7,
},
.shift_mode = {
.address = 0xd2,
.modes = {
{ SM_ECO_NAME, 0xc2 },
{ SM_COMFORT_NAME, 0xc1 },
{ SM_SPORT_NAME, 0xc0 },
{ SM_TURBO_NAME, 0xc4 },
MSI_EC_MODE_NULL
},
},
.super_battery = {
.address = MSI_EC_ADDR_UNSUPP, // 0xeb
.mask = 0x0f, // 00, 0f
},
.fan_mode = {
.address = 0xd4,
.modes = {
{ FM_AUTO_NAME, 0x0d },
{ FM_SILENT_NAME, 0x1d },
{ FM_ADVANCED_NAME, 0x8d },
MSI_EC_MODE_NULL
},
},
.cpu = {
.rt_temp_address = 0x68,
.rt_fan_speed_address = 0x71,
.rt_fan_speed_base_min = 0x19,
.rt_fan_speed_base_max = 0x37,
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
.bs_fan_speed_base_min = 0x00,
.bs_fan_speed_base_max = 0x0f,
},
.gpu = {
.rt_temp_address = MSI_EC_ADDR_UNSUPP,
.rt_fan_speed_address = 0x89,
},
.leds = {
.micmute_led_address = MSI_EC_ADDR_UNSUPP,
.mute_led_address = 0x2d,
.bit = 1,
},
.kbd_bl = {
.bl_mode_address = MSI_EC_ADDR_UNKNOWN,
.bl_modes = { 0x00, 0x08 },
.max_mode = 1,
.bl_state_address = 0xd3,
.state_base_value = 0x80,
.max_state = 3,
},
};
static const char * const ALLOWED_FW_13[] __initconst = {
"1594EMS1.109", // MSI Prestige 16 Studio A13VE
NULL
};
static struct msi_ec_conf CONF13 __initdata = {
.allowed_fw = ALLOWED_FW_13,
.charge_control = {
.address = 0xd7,
.offset_start = 0x8a,
.offset_end = 0x80,
.range_min = 0x8a,
.range_max = 0xe4,
},
.webcam = {
.address = 0x2e,
.block_address = 0x2f,
.bit = 1,
},
.fn_win_swap = {
.address = 0xe8,
.bit = 4, // 0x00-0x10
},
.cooler_boost = {
.address = 0x98,
.bit = 7,
},
.shift_mode = {
.address = 0xd2,
.modes = {
{ SM_ECO_NAME, 0xc2 }, // super battery
{ SM_COMFORT_NAME, 0xc1 }, // balanced
{ SM_TURBO_NAME, 0xc4 }, // extreme
MSI_EC_MODE_NULL
},
},
.super_battery = {
.address = MSI_EC_ADDR_UNSUPP,
.mask = 0x0f, // 00, 0f
},
.fan_mode = {
.address = 0xd4,
.modes = {
{ FM_AUTO_NAME, 0x0d },
{ FM_SILENT_NAME, 0x1d },
{ FM_ADVANCED_NAME, 0x8d },
MSI_EC_MODE_NULL
},
},
.cpu = {
.rt_temp_address = 0x68,
.rt_fan_speed_address = 0x71, // 0x0-0x96
.rt_fan_speed_base_min = 0x00,
.rt_fan_speed_base_max = 0x96,
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
.bs_fan_speed_base_min = 0x00,
.bs_fan_speed_base_max = 0x0f,
},
.gpu = {
.rt_temp_address = 0x80,
.rt_fan_speed_address = 0x89,
},
.leds = {
.micmute_led_address = 0x2c,
.mute_led_address = 0x2d,
.bit = 1,
},
.kbd_bl = {
.bl_mode_address = 0x2c, // KB auto turn off
.bl_modes = { 0x00, 0x08 }, // always on; off after 10 sec
.max_mode = 1,
.bl_state_address = 0xd3,
.state_base_value = 0x80,
.max_state = 3,
},
};
static struct msi_ec_conf *CONFIGS[] __initdata = {
&CONF0,
&CONF1,
@ -676,6 +1137,12 @@ static struct msi_ec_conf *CONFIGS[] __initdata = {
&CONF5,
&CONF6,
&CONF7,
&CONF8,
&CONF9,
&CONF10,
&CONF11,
&CONF12,
&CONF13,
NULL
};

View File

@ -40,7 +40,7 @@ struct msi_ec_webcam_conf {
int bit;
};
struct msi_ec_fn_super_swap_conf {
struct msi_ec_fn_win_swap_conf {
int address;
int bit;
};
@ -108,7 +108,7 @@ struct msi_ec_conf {
struct msi_ec_charge_control_conf charge_control;
struct msi_ec_webcam_conf webcam;
struct msi_ec_fn_super_swap_conf fn_super_swap;
struct msi_ec_fn_win_swap_conf fn_win_swap;
struct msi_ec_cooler_boost_conf cooler_boost;
struct msi_ec_shift_mode_conf shift_mode;
struct msi_ec_super_battery_conf super_battery;

View File

@ -218,15 +218,13 @@ err_platform:
return rs;
}
static int sel3350_remove(struct platform_device *pdev)
static void sel3350_remove(struct platform_device *pdev)
{
struct sel3350_data *sel3350 = platform_get_drvdata(pdev);
platform_device_unregister(sel3350->leds_pdev);
gpiod_remove_lookup_table(&sel3350_gpios_table);
gpiod_remove_lookup_table(&sel3350_leds_table);
return 0;
}
static const struct acpi_device_id sel3350_device_ids[] = {
@ -237,7 +235,7 @@ MODULE_DEVICE_TABLE(acpi, sel3350_device_ids);
static struct platform_driver sel3350_platform_driver = {
.probe = sel3350_probe,
.remove = sel3350_remove,
.remove_new = sel3350_remove,
.driver = {
.name = "sel3350-platform",
.acpi_match_table = sel3350_device_ids,

View File

@ -25,9 +25,9 @@ static struct gpiod_lookup_table simatic_ipc_batt_gpio_table_127e = {
},
};
static int simatic_ipc_batt_apollolake_remove(struct platform_device *pdev)
static void simatic_ipc_batt_apollolake_remove(struct platform_device *pdev)
{
return simatic_ipc_batt_remove(pdev, &simatic_ipc_batt_gpio_table_127e);
simatic_ipc_batt_remove(pdev, &simatic_ipc_batt_gpio_table_127e);
}
static int simatic_ipc_batt_apollolake_probe(struct platform_device *pdev)
@ -37,7 +37,7 @@ static int simatic_ipc_batt_apollolake_probe(struct platform_device *pdev)
static struct platform_driver simatic_ipc_batt_driver = {
.probe = simatic_ipc_batt_apollolake_probe,
.remove = simatic_ipc_batt_apollolake_remove,
.remove_new = simatic_ipc_batt_apollolake_remove,
.driver = {
.name = KBUILD_MODNAME,
},

View File

@ -25,9 +25,9 @@ static struct gpiod_lookup_table simatic_ipc_batt_gpio_table_bx_21a = {
},
};
static int simatic_ipc_batt_elkhartlake_remove(struct platform_device *pdev)
static void simatic_ipc_batt_elkhartlake_remove(struct platform_device *pdev)
{
return simatic_ipc_batt_remove(pdev, &simatic_ipc_batt_gpio_table_bx_21a);
simatic_ipc_batt_remove(pdev, &simatic_ipc_batt_gpio_table_bx_21a);
}
static int simatic_ipc_batt_elkhartlake_probe(struct platform_device *pdev)
@ -37,7 +37,7 @@ static int simatic_ipc_batt_elkhartlake_probe(struct platform_device *pdev)
static struct platform_driver simatic_ipc_batt_driver = {
.probe = simatic_ipc_batt_elkhartlake_probe,
.remove = simatic_ipc_batt_elkhartlake_remove,
.remove_new = simatic_ipc_batt_elkhartlake_remove,
.driver = {
.name = KBUILD_MODNAME,
},

View File

@ -45,9 +45,9 @@ static struct gpiod_lookup_table simatic_ipc_batt_gpio_table_bx_59a = {
}
};
static int simatic_ipc_batt_f7188x_remove(struct platform_device *pdev)
static void simatic_ipc_batt_f7188x_remove(struct platform_device *pdev)
{
return simatic_ipc_batt_remove(pdev, batt_lookup_table);
simatic_ipc_batt_remove(pdev, batt_lookup_table);
}
static int simatic_ipc_batt_f7188x_probe(struct platform_device *pdev)
@ -73,7 +73,7 @@ static int simatic_ipc_batt_f7188x_probe(struct platform_device *pdev)
static struct platform_driver simatic_ipc_batt_driver = {
.probe = simatic_ipc_batt_f7188x_probe,
.remove = simatic_ipc_batt_f7188x_remove,
.remove_new = simatic_ipc_batt_f7188x_remove,
.driver = {
.name = KBUILD_MODNAME,
},

View File

@ -146,10 +146,9 @@ static const struct hwmon_chip_info simatic_ipc_batt_chip_info = {
.info = simatic_ipc_batt_info,
};
int simatic_ipc_batt_remove(struct platform_device *pdev, struct gpiod_lookup_table *table)
void simatic_ipc_batt_remove(struct platform_device *pdev, struct gpiod_lookup_table *table)
{
gpiod_remove_lookup_table(table);
return 0;
}
EXPORT_SYMBOL_GPL(simatic_ipc_batt_remove);
@ -228,9 +227,9 @@ out:
}
EXPORT_SYMBOL_GPL(simatic_ipc_batt_probe);
static int simatic_ipc_batt_io_remove(struct platform_device *pdev)
static void simatic_ipc_batt_io_remove(struct platform_device *pdev)
{
return simatic_ipc_batt_remove(pdev, NULL);
simatic_ipc_batt_remove(pdev, NULL);
}
static int simatic_ipc_batt_io_probe(struct platform_device *pdev)
@ -240,7 +239,7 @@ static int simatic_ipc_batt_io_probe(struct platform_device *pdev)
static struct platform_driver simatic_ipc_batt_driver = {
.probe = simatic_ipc_batt_io_probe,
.remove = simatic_ipc_batt_io_remove,
.remove_new = simatic_ipc_batt_io_remove,
.driver = {
.name = KBUILD_MODNAME,
},

View File

@ -14,7 +14,7 @@
int simatic_ipc_batt_probe(struct platform_device *pdev,
struct gpiod_lookup_table *table);
int simatic_ipc_batt_remove(struct platform_device *pdev,
struct gpiod_lookup_table *table);
void simatic_ipc_batt_remove(struct platform_device *pdev,
struct gpiod_lookup_table *table);
#endif /* _SIMATIC_IPC_BATT_H */

View File

@ -15,7 +15,7 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mutex.h>
#include <linux/string.h>
#include <linux/string_helpers.h>
#include <linux/types.h>
#include <linux/dmi.h>
#include <linux/wmi.h>
@ -198,14 +198,6 @@ static struct think_lmi tlmi_priv;
static struct class *fw_attr_class;
static DEFINE_MUTEX(tlmi_mutex);
/* ------ Utility functions ------------*/
/* Strip out CR if one is present */
static void strip_cr(char *str)
{
char *p = strchrnul(str, '\n');
*p = '\0';
}
/* Convert BIOS WMI error string to suitable error code */
static int tlmi_errstr_to_err(const char *errstr)
{
@ -411,7 +403,7 @@ static ssize_t current_password_store(struct kobject *kobj,
strscpy(setting->password, buf, setting->maxlen);
/* Strip out CR if one is present, setting password won't work if it is present */
strip_cr(setting->password);
strreplace(setting->password, '\n', '\0');
return count;
}
@ -432,13 +424,11 @@ static ssize_t new_password_store(struct kobject *kobj,
if (!tlmi_priv.can_set_bios_password)
return -EOPNOTSUPP;
new_pwd = kstrdup(buf, GFP_KERNEL);
/* Strip out CR if one is present, setting password won't work if it is present */
new_pwd = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
if (!new_pwd)
return -ENOMEM;
/* Strip out CR if one is present, setting password won't work if it is present */
strip_cr(new_pwd);
/* Use lock in case multiple WMI operations needed */
mutex_lock(&tlmi_mutex);
@ -709,13 +699,11 @@ static ssize_t cert_to_password_store(struct kobject *kobj,
if (!setting->signature || !setting->signature[0])
return -EACCES;
passwd = kstrdup(buf, GFP_KERNEL);
/* Strip out CR if one is present */
passwd = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
if (!passwd)
return -ENOMEM;
/* Strip out CR if one is present */
strip_cr(passwd);
/* Format: 'Password,Signature' */
auth_str = kasprintf(GFP_KERNEL, "%s,%s", passwd, setting->signature);
if (!auth_str) {
@ -765,11 +753,10 @@ static ssize_t certificate_store(struct kobject *kobj,
return ret ?: count;
}
new_cert = kstrdup(buf, GFP_KERNEL);
/* Strip out CR if one is present */
new_cert = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
if (!new_cert)
return -ENOMEM;
/* Strip out CR if one is present */
strip_cr(new_cert);
if (setting->cert_installed) {
/* Certificate is installed so this is an update */
@ -817,13 +804,11 @@ static ssize_t signature_store(struct kobject *kobj,
if (!tlmi_priv.certificate_support)
return -EOPNOTSUPP;
new_signature = kstrdup(buf, GFP_KERNEL);
/* Strip out CR if one is present */
new_signature = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
if (!new_signature)
return -ENOMEM;
/* Strip out CR if one is present */
strip_cr(new_signature);
/* Free any previous signature */
kfree(setting->signature);
setting->signature = new_signature;
@ -846,13 +831,11 @@ static ssize_t save_signature_store(struct kobject *kobj,
if (!tlmi_priv.certificate_support)
return -EOPNOTSUPP;
new_signature = kstrdup(buf, GFP_KERNEL);
/* Strip out CR if one is present */
new_signature = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
if (!new_signature)
return -ENOMEM;
/* Strip out CR if one is present */
strip_cr(new_signature);
/* Free any previous signature */
kfree(setting->save_signature);
setting->save_signature = new_signature;
@ -930,7 +913,7 @@ static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *at
static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
char *item, *value, *p;
char *item, *value;
int ret;
ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID);
@ -943,8 +926,7 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a
ret = -EINVAL;
else {
/* On Workstations remove the Options part after the value */
p = strchrnul(value, ';');
*p = '\0';
strreplace(value, ';', '\0');
ret = sysfs_emit(buf, "%s\n", value + 1);
}
kfree(item);
@ -985,12 +967,17 @@ static ssize_t current_value_store(struct kobject *kobj,
if (!tlmi_priv.can_set_bios_settings)
return -EOPNOTSUPP;
new_setting = kstrdup(buf, GFP_KERNEL);
if (!new_setting)
return -ENOMEM;
/*
* If we are using bulk saves a reboot should be done once save has
* been called
*/
if (tlmi_priv.save_mode == TLMI_SAVE_BULK && tlmi_priv.reboot_required)
return -EPERM;
/* Strip out CR if one is present */
strip_cr(new_setting);
new_setting = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
if (!new_setting)
return -ENOMEM;
/* Use lock in case multiple WMI operations needed */
mutex_lock(&tlmi_mutex);
@ -1011,10 +998,11 @@ static ssize_t current_value_store(struct kobject *kobj,
ret = tlmi_simple_call(LENOVO_SET_BIOS_SETTING_CERT_GUID, set_str);
if (ret)
goto out;
ret = tlmi_simple_call(LENOVO_SAVE_BIOS_SETTING_CERT_GUID,
tlmi_priv.pwd_admin->save_signature);
if (ret)
goto out;
if (tlmi_priv.save_mode == TLMI_SAVE_BULK)
tlmi_priv.save_required = true;
else
ret = tlmi_simple_call(LENOVO_SAVE_BIOS_SETTING_CERT_GUID,
tlmi_priv.pwd_admin->save_signature);
} else if (tlmi_priv.opcode_support) {
/*
* If opcode support is present use that interface.
@ -1033,14 +1021,17 @@ static ssize_t current_value_store(struct kobject *kobj,
if (ret)
goto out;
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
tlmi_priv.pwd_admin->password);
if (ret)
goto out;
if (tlmi_priv.save_mode == TLMI_SAVE_BULK) {
tlmi_priv.save_required = true;
} else {
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
tlmi_priv.pwd_admin->password);
if (ret)
goto out;
}
ret = tlmi_save_bios_settings("");
}
ret = tlmi_save_bios_settings("");
} else { /* old non-opcode based authentication method (deprecated) */
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
@ -1068,10 +1059,14 @@ static ssize_t current_value_store(struct kobject *kobj,
if (ret)
goto out;
if (auth_str)
ret = tlmi_save_bios_settings(auth_str);
else
ret = tlmi_save_bios_settings("");
if (tlmi_priv.save_mode == TLMI_SAVE_BULK) {
tlmi_priv.save_required = true;
} else {
if (auth_str)
ret = tlmi_save_bios_settings(auth_str);
else
ret = tlmi_save_bios_settings("");
}
}
if (!ret && !tlmi_priv.pending_changes) {
tlmi_priv.pending_changes = true;
@ -1152,6 +1147,107 @@ static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *
static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot);
static const char * const save_mode_strings[] = {
[TLMI_SAVE_SINGLE] = "single",
[TLMI_SAVE_BULK] = "bulk",
[TLMI_SAVE_SAVE] = "save"
};
static ssize_t save_settings_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
/* Check that setting is valid */
if (WARN_ON(tlmi_priv.save_mode < TLMI_SAVE_SINGLE ||
tlmi_priv.save_mode > TLMI_SAVE_BULK))
return -EIO;
return sysfs_emit(buf, "%s\n", save_mode_strings[tlmi_priv.save_mode]);
}
static ssize_t save_settings_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
char *auth_str = NULL;
int ret = 0;
int cmd;
cmd = sysfs_match_string(save_mode_strings, buf);
if (cmd < 0)
return cmd;
/* Use lock in case multiple WMI operations needed */
mutex_lock(&tlmi_mutex);
switch (cmd) {
case TLMI_SAVE_SINGLE:
case TLMI_SAVE_BULK:
tlmi_priv.save_mode = cmd;
goto out;
case TLMI_SAVE_SAVE:
/* Check if supported*/
if (!tlmi_priv.can_set_bios_settings ||
tlmi_priv.save_mode == TLMI_SAVE_SINGLE) {
ret = -EOPNOTSUPP;
goto out;
}
/* Check there is actually something to save */
if (!tlmi_priv.save_required) {
ret = -ENOENT;
goto out;
}
/* Check if certificate authentication is enabled and active */
if (tlmi_priv.certificate_support && tlmi_priv.pwd_admin->cert_installed) {
if (!tlmi_priv.pwd_admin->signature ||
!tlmi_priv.pwd_admin->save_signature) {
ret = -EINVAL;
goto out;
}
ret = tlmi_simple_call(LENOVO_SAVE_BIOS_SETTING_CERT_GUID,
tlmi_priv.pwd_admin->save_signature);
if (ret)
goto out;
} else if (tlmi_priv.opcode_support) {
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
tlmi_priv.pwd_admin->password);
if (ret)
goto out;
}
ret = tlmi_save_bios_settings("");
} else { /* old non-opcode based authentication method (deprecated) */
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
tlmi_priv.pwd_admin->password,
encoding_options[tlmi_priv.pwd_admin->encoding],
tlmi_priv.pwd_admin->kbdlang);
if (!auth_str) {
ret = -ENOMEM;
goto out;
}
}
if (auth_str)
ret = tlmi_save_bios_settings(auth_str);
else
ret = tlmi_save_bios_settings("");
}
tlmi_priv.save_required = false;
tlmi_priv.reboot_required = true;
if (!ret && !tlmi_priv.pending_changes) {
tlmi_priv.pending_changes = true;
/* let userland know it may need to check reboot pending again */
kobject_uevent(&tlmi_priv.class_dev->kobj, KOBJ_CHANGE);
}
break;
}
out:
mutex_unlock(&tlmi_mutex);
kfree(auth_str);
return ret ?: count;
}
static struct kobj_attribute save_settings = __ATTR_RW(save_settings);
/* ---- Debug interface--------------------------------------------------------- */
static ssize_t debug_cmd_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
@ -1163,13 +1259,11 @@ static ssize_t debug_cmd_store(struct kobject *kobj, struct kobj_attribute *attr
if (!tlmi_priv.can_debug_cmd)
return -EOPNOTSUPP;
new_setting = kstrdup(buf, GFP_KERNEL);
/* Strip out CR if one is present */
new_setting = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL);
if (!new_setting)
return -ENOMEM;
/* Strip out CR if one is present */
strip_cr(new_setting);
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
tlmi_priv.pwd_admin->password,
@ -1221,6 +1315,8 @@ static void tlmi_release_attr(void)
}
}
sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr);
sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &save_settings.attr);
if (tlmi_priv.can_debug_cmd && debug_support)
sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
@ -1318,6 +1414,10 @@ static int tlmi_sysfs_init(void)
if (ret)
goto fail_create_attr;
ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &save_settings.attr);
if (ret)
goto fail_create_attr;
if (tlmi_priv.can_debug_cmd && debug_support) {
ret = sysfs_create_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr);
if (ret)
@ -1447,7 +1547,6 @@ static int tlmi_analyze(void)
for (i = 0; i < TLMI_SETTINGS_COUNT; ++i) {
struct tlmi_attr_setting *setting;
char *item = NULL;
char *p;
tlmi_priv.setting[i] = NULL;
ret = tlmi_setting(i, &item, LENOVO_BIOS_SETTING_GUID);
@ -1464,8 +1563,7 @@ static int tlmi_analyze(void)
strreplace(item, '/', '\\');
/* Remove the value part */
p = strchrnul(item, ',');
*p = '\0';
strreplace(item, ',', '\0');
/* Create a setting entry */
setting = kzalloc(sizeof(*setting), GFP_KERNEL);

View File

@ -27,6 +27,19 @@ enum level_option {
TLMI_LEVEL_MASTER,
};
/*
* There are a limit on the number of WMI operations you can do if you use
* the default implementation of saving on every set. This is due to a
* limitation in EFI variable space used.
* Have a 'bulk save' mode where you can manually trigger the save, and can
* therefore set unlimited variables - for users that need it.
*/
enum save_mode {
TLMI_SAVE_SINGLE,
TLMI_SAVE_BULK,
TLMI_SAVE_SAVE,
};
/* password configuration details */
struct tlmi_pwdcfg_core {
uint32_t password_mode;
@ -86,6 +99,9 @@ struct think_lmi {
bool can_debug_cmd;
bool opcode_support;
bool certificate_support;
enum save_mode save_mode;
bool save_required;
bool reboot_required;
struct tlmi_attr_setting *setting[TLMI_SETTINGS_COUNT];
struct device *class_dev;

View File

@ -9816,6 +9816,7 @@ static const struct tpacpi_quirk battery_quirk_table[] __initconst = {
* Individual addressing is broken on models that expose the
* primary battery as BAT1.
*/
TPACPI_Q_LNV('8', 'F', true), /* Thinkpad X120e */
TPACPI_Q_LNV('J', '7', true), /* B5400 */
TPACPI_Q_LNV('J', 'I', true), /* Thinkpad 11e */
TPACPI_Q_LNV3('R', '0', 'B', true), /* Thinkpad 11e gen 3 */
@ -10787,6 +10788,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[] = {
@ -10845,6 +10929,7 @@ static const struct attribute_group *tpacpi_groups[] = {
&proxsensor_attr_group,
&kbdlang_attr_group,
&dprc_attr_group,
&auxmac_attr_group,
NULL,
};
@ -11144,6 +11229,8 @@ invalid:
return '\0';
}
#define EC_FW_STRING_LEN 18
static void find_new_ec_fwstr(const struct dmi_header *dm, void *private)
{
char *ec_fw_string = (char *) private;
@ -11172,7 +11259,8 @@ static void find_new_ec_fwstr(const struct dmi_header *dm, void *private)
return;
/* fwstr is the first 8byte string */
strncpy(ec_fw_string, dmi_data + 0x0F, 8);
BUILD_BUG_ON(EC_FW_STRING_LEN <= 8);
memcpy(ec_fw_string, dmi_data + 0x0F, 8);
}
/* returns 0 - probe ok, or < 0 - probe error.
@ -11182,7 +11270,7 @@ static int __must_check __init get_thinkpad_model_data(
struct thinkpad_id_data *tp)
{
const struct dmi_device *dev = NULL;
char ec_fw_string[18] = {0};
char ec_fw_string[EC_FW_STRING_LEN] = {0};
char const *s;
char t;
@ -11416,6 +11504,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)

View File

@ -109,33 +109,13 @@ static const char * const allow_duplicates[] = {
NULL
};
#define dev_to_wblock(__dev) container_of_const(__dev, struct wmi_block, dev.dev)
#define dev_to_wdev(__dev) container_of_const(__dev, struct wmi_device, dev)
/*
* GUID parsing functions
*/
static acpi_status find_guid(const char *guid_string, struct wmi_block **out)
{
guid_t guid_input;
struct wmi_block *wblock;
if (!guid_string)
return AE_BAD_PARAMETER;
if (guid_parse(guid_string, &guid_input))
return AE_BAD_PARAMETER;
list_for_each_entry(wblock, &wmi_block_list, list) {
if (guid_equal(&wblock->gblock.guid, &guid_input)) {
if (out)
*out = wblock;
return AE_OK;
}
}
return AE_NOT_FOUND;
}
static bool guid_parse_and_compare(const char *string, const guid_t *guid)
{
guid_t guid_input;
@ -245,6 +225,41 @@ static acpi_status get_event_data(const struct wmi_block *wblock, struct acpi_bu
return acpi_evaluate_object(wblock->acpi_device->handle, "_WED", &input, out);
}
static int wmidev_match_guid(struct device *dev, const void *data)
{
struct wmi_block *wblock = dev_to_wblock(dev);
const guid_t *guid = data;
if (guid_equal(guid, &wblock->gblock.guid))
return 1;
return 0;
}
static struct bus_type wmi_bus_type;
static struct wmi_device *wmi_find_device_by_guid(const char *guid_string)
{
struct device *dev;
guid_t guid;
int ret;
ret = guid_parse(guid_string, &guid);
if (ret < 0)
return ERR_PTR(ret);
dev = bus_find_device(&wmi_bus_type, NULL, &guid, wmidev_match_guid);
if (!dev)
return ERR_PTR(-ENODEV);
return dev_to_wdev(dev);
}
static void wmi_device_put(struct wmi_device *wdev)
{
put_device(&wdev->dev);
}
/*
* Exported WMI functions
*/
@ -279,18 +294,17 @@ EXPORT_SYMBOL_GPL(set_required_buffer_size);
*/
int wmi_instance_count(const char *guid_string)
{
struct wmi_block *wblock;
acpi_status status;
struct wmi_device *wdev;
int ret;
status = find_guid(guid_string, &wblock);
if (ACPI_FAILURE(status)) {
if (status == AE_BAD_PARAMETER)
return -EINVAL;
wdev = wmi_find_device_by_guid(guid_string);
if (IS_ERR(wdev))
return PTR_ERR(wdev);
return -ENODEV;
}
ret = wmidev_instance_count(wdev);
wmi_device_put(wdev);
return wmidev_instance_count(&wblock->dev);
return ret;
}
EXPORT_SYMBOL_GPL(wmi_instance_count);
@ -325,15 +339,18 @@ EXPORT_SYMBOL_GPL(wmidev_instance_count);
acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, u32 method_id,
const struct acpi_buffer *in, struct acpi_buffer *out)
{
struct wmi_block *wblock = NULL;
struct wmi_device *wdev;
acpi_status status;
status = find_guid(guid_string, &wblock);
if (ACPI_FAILURE(status))
return status;
wdev = wmi_find_device_by_guid(guid_string);
if (IS_ERR(wdev))
return AE_ERROR;
return wmidev_evaluate_method(&wblock->dev, instance, method_id,
in, out);
status = wmidev_evaluate_method(wdev, instance, method_id, in, out);
wmi_device_put(wdev);
return status;
}
EXPORT_SYMBOL_GPL(wmi_evaluate_method);
@ -472,13 +489,19 @@ acpi_status wmi_query_block(const char *guid_string, u8 instance,
struct acpi_buffer *out)
{
struct wmi_block *wblock;
struct wmi_device *wdev;
acpi_status status;
status = find_guid(guid_string, &wblock);
if (ACPI_FAILURE(status))
return status;
wdev = wmi_find_device_by_guid(guid_string);
if (IS_ERR(wdev))
return AE_ERROR;
return __query_block(wblock, instance, out);
wblock = container_of(wdev, struct wmi_block, dev);
status = __query_block(wblock, instance, out);
wmi_device_put(wdev);
return status;
}
EXPORT_SYMBOL_GPL(wmi_query_block);
@ -516,8 +539,9 @@ EXPORT_SYMBOL_GPL(wmidev_block_query);
acpi_status wmi_set_block(const char *guid_string, u8 instance,
const struct acpi_buffer *in)
{
struct wmi_block *wblock = NULL;
struct wmi_block *wblock;
struct guid_block *block;
struct wmi_device *wdev;
acpi_handle handle;
struct acpi_object_list input;
union acpi_object params[2];
@ -527,19 +551,26 @@ acpi_status wmi_set_block(const char *guid_string, u8 instance,
if (!in)
return AE_BAD_DATA;
status = find_guid(guid_string, &wblock);
if (ACPI_FAILURE(status))
return status;
wdev = wmi_find_device_by_guid(guid_string);
if (IS_ERR(wdev))
return AE_ERROR;
wblock = container_of(wdev, struct wmi_block, dev);
block = &wblock->gblock;
handle = wblock->acpi_device->handle;
if (block->instance_count <= instance)
return AE_BAD_PARAMETER;
if (block->instance_count <= instance) {
status = AE_BAD_PARAMETER;
goto err_wdev_put;
}
/* Check GUID is a data block */
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
return AE_ERROR;
if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD)) {
status = AE_ERROR;
goto err_wdev_put;
}
input.count = 2;
input.pointer = params;
@ -551,7 +582,12 @@ acpi_status wmi_set_block(const char *guid_string, u8 instance,
get_acpi_method_name(wblock, 'S', method);
return acpi_evaluate_object(handle, method, &input, NULL);
status = acpi_evaluate_object(handle, method, &input, NULL);
err_wdev_put:
wmi_device_put(wdev);
return status;
}
EXPORT_SYMBOL_GPL(wmi_set_block);
@ -742,7 +778,15 @@ EXPORT_SYMBOL_GPL(wmi_get_event_data);
*/
bool wmi_has_guid(const char *guid_string)
{
return ACPI_SUCCESS(find_guid(guid_string, NULL));
struct wmi_device *wdev;
wdev = wmi_find_device_by_guid(guid_string);
if (IS_ERR(wdev))
return false;
wmi_device_put(wdev);
return true;
}
EXPORT_SYMBOL_GPL(wmi_has_guid);
@ -756,20 +800,23 @@ EXPORT_SYMBOL_GPL(wmi_has_guid);
*/
char *wmi_get_acpi_device_uid(const char *guid_string)
{
struct wmi_block *wblock = NULL;
acpi_status status;
struct wmi_block *wblock;
struct wmi_device *wdev;
char *uid;
status = find_guid(guid_string, &wblock);
if (ACPI_FAILURE(status))
wdev = wmi_find_device_by_guid(guid_string);
if (IS_ERR(wdev))
return NULL;
return acpi_device_uid(wblock->acpi_device);
wblock = container_of(wdev, struct wmi_block, dev);
uid = acpi_device_uid(wblock->acpi_device);
wmi_device_put(wdev);
return uid;
}
EXPORT_SYMBOL_GPL(wmi_get_acpi_device_uid);
#define dev_to_wblock(__dev) container_of_const(__dev, struct wmi_block, dev.dev)
#define dev_to_wdev(__dev) container_of_const(__dev, struct wmi_device, dev)
static inline struct wmi_driver *drv_to_wdrv(struct device_driver *drv)
{
return container_of(drv, struct wmi_driver, driver);
@ -911,21 +958,13 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver)
}
static int wmi_char_open(struct inode *inode, struct file *filp)
{
const char *driver_name = filp->f_path.dentry->d_iname;
struct wmi_block *wblock;
struct wmi_block *next;
/*
* The miscdevice already stores a pointer to itself
* inside filp->private_data
*/
struct wmi_block *wblock = container_of(filp->private_data, struct wmi_block, char_dev);
list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
if (!wblock->dev.dev.driver)
continue;
if (strcmp(driver_name, wblock->dev.dev.driver->name) == 0) {
filp->private_data = wblock;
break;
}
}
if (!filp->private_data)
return -ENODEV;
filp->private_data = wblock;
return nonseekable_open(inode, filp);
}
@ -1221,17 +1260,24 @@ static int wmi_create_device(struct device *wmi_bus_dev,
return 0;
}
static void wmi_free_devices(struct acpi_device *device)
static int wmi_add_device(struct platform_device *pdev, struct wmi_device *wdev)
{
struct wmi_block *wblock, *next;
struct device_link *link;
/* Delete devices for all the GUIDs */
list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
if (wblock->acpi_device == device) {
list_del(&wblock->list);
device_unregister(&wblock->dev.dev);
}
}
/*
* Many aggregate WMI drivers do not use -EPROBE_DEFER when they
* are unable to find a WMI device during probe, instead they require
* all WMI devices associated with an platform device to become available
* at once. This device link thus prevents WMI drivers from probing until
* the associated platform device has finished probing (and has registered
* all discovered WMI devices).
*/
link = device_link_add(&wdev->dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
if (!link)
return -EINVAL;
return device_add(&wdev->dev);
}
static bool guid_already_parsed_for_legacy(struct acpi_device *device, const guid_t *guid)
@ -1263,15 +1309,16 @@ static bool guid_already_parsed_for_legacy(struct acpi_device *device, const gui
/*
* Parse the _WDG method for the GUID data blocks
*/
static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
static int parse_wdg(struct device *wmi_bus_dev, struct platform_device *pdev)
{
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
const struct guid_block *gblock;
struct wmi_block *wblock, *next;
struct wmi_block *wblock;
union acpi_object *obj;
acpi_status status;
int retval = 0;
u32 i, total;
int retval;
status = acpi_evaluate_object(device->handle, "_WDG", NULL, &out);
if (ACPI_FAILURE(status))
@ -1282,8 +1329,8 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
return -ENXIO;
if (obj->type != ACPI_TYPE_BUFFER) {
retval = -ENXIO;
goto out_free_pointer;
kfree(obj);
return -ENXIO;
}
gblock = (const struct guid_block *)obj->buffer.pointer;
@ -1298,8 +1345,8 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
wblock = kzalloc(sizeof(*wblock), GFP_KERNEL);
if (!wblock) {
retval = -ENOMEM;
break;
dev_err(wmi_bus_dev, "Failed to allocate %pUL\n", &gblock[i].guid);
continue;
}
wblock->acpi_device = device;
@ -1317,30 +1364,22 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
wblock->handler = wmi_notify_debug;
wmi_method_enable(wblock, true);
}
}
/*
* Now that all of the devices are created, add them to the
* device tree and probe subdrivers.
*/
list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
if (wblock->acpi_device != device)
continue;
retval = device_add(&wblock->dev.dev);
retval = wmi_add_device(pdev, &wblock->dev);
if (retval) {
dev_err(wmi_bus_dev, "failed to register %pUL\n",
&wblock->gblock.guid);
if (debug_event)
wmi_method_enable(wblock, false);
list_del(&wblock->list);
put_device(&wblock->dev.dev);
}
}
out_free_pointer:
kfree(out.pointer);
return retval;
kfree(obj);
return 0;
}
/*
@ -1435,16 +1474,28 @@ static void acpi_wmi_notify_handler(acpi_handle handle, u32 event,
event, 0);
}
static int wmi_remove_device(struct device *dev, void *data)
{
struct wmi_block *wblock = dev_to_wblock(dev);
list_del(&wblock->list);
device_unregister(dev);
return 0;
}
static void acpi_wmi_remove(struct platform_device *device)
{
struct acpi_device *acpi_device = ACPI_COMPANION(&device->dev);
struct device *wmi_bus_device = dev_get_drvdata(&device->dev);
acpi_remove_notify_handler(acpi_device->handle, ACPI_ALL_NOTIFY,
acpi_wmi_notify_handler);
acpi_remove_address_space_handler(acpi_device->handle,
ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
wmi_free_devices(acpi_device);
device_unregister(dev_get_drvdata(&device->dev));
device_for_each_child_reverse(wmi_bus_device, NULL, wmi_remove_device);
device_unregister(wmi_bus_device);
}
static int acpi_wmi_probe(struct platform_device *device)
@ -1487,7 +1538,7 @@ static int acpi_wmi_probe(struct platform_device *device)
}
dev_set_drvdata(&device->dev, wmi_bus_dev);
error = parse_wdg(wmi_bus_dev, acpi_device);
error = parse_wdg(wmi_bus_dev, device);
if (error) {
pr_err("Failed to parse WDG method\n");
goto err_remove_busdev;

View File

@ -24,6 +24,21 @@
static struct platform_device *x86_android_tablet_device;
/*
* This helper allows getting a gpio_desc *before* the actual device consuming
* the GPIO has been instantiated. This function _must_ only be used to handle
* this special case such as e.g. :
*
* 1. Getting an IRQ from a GPIO for i2c_board_info.irq which is passed to
* i2c_client_new() to instantiate i2c_client-s; or
* 2. Calling desc_to_gpio() to get an old style GPIO number for gpio_keys
* platform_data which still uses old style GPIO numbers.
*
* Since the consuming device has not been instatiated yet a dynamic lookup
* is generated using the special x86_android_tablet dev for dev_id.
*
* For normal GPIO lookups a standard static gpiod_lookup_table _must_ be used.
*/
int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id,
bool active_low, enum gpiod_flags dflags,
struct gpio_desc **desc)

View File

@ -436,7 +436,7 @@ static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void)
/* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, "yoga_bootstrap",
false, GPIOD_IN, &gpiod);
false, GPIOD_ASIS, &gpiod);
if (ret)
return ret;

View File

@ -81,9 +81,9 @@ static SIMPLE_DEV_PM_OPS(ebook_switch_pm, NULL, ebook_switch_resume);
static int ebook_switch_add(struct acpi_device *device)
{
const struct acpi_device_id *id;
struct ebook_switch *button;
struct input_dev *input;
const char *hid = acpi_device_hid(device);
char *name, *class;
int error;
@ -102,8 +102,9 @@ static int ebook_switch_add(struct acpi_device *device)
name = acpi_device_name(device);
class = acpi_device_class(device);
if (strcmp(hid, XO15_EBOOK_HID)) {
pr_err("Unsupported hid [%s]\n", hid);
id = acpi_match_acpi_device(ebook_device_ids, device);
if (!id) {
dev_err(&device->dev, "Unsupported hid\n");
error = -ENODEV;
goto err_free_input;
}
@ -111,7 +112,7 @@ static int ebook_switch_add(struct acpi_device *device)
strcpy(name, XO15_EBOOK_DEVICE_NAME);
sprintf(class, "%s/%s", XO15_EBOOK_CLASS, XO15_EBOOK_SUBCLASS);
snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
snprintf(button->phys, sizeof(button->phys), "%s/button/input0", id->id);
input->name = name;
input->phys = button->phys;

View File

@ -6,6 +6,12 @@
#ifndef _INTEL_TPMI_H_
#define _INTEL_TPMI_H_
#include <linux/bitfield.h>
#define TPMI_VERSION_INVALID 0xff
#define TPMI_MINOR_VERSION(val) FIELD_GET(GENMASK(4, 0), val)
#define TPMI_MAJOR_VERSION(val) FIELD_GET(GENMASK(7, 5), val)
/**
* struct intel_tpmi_plat_info - Platform information for a TPMI device instance
* @package_id: CPU Package id

View File

@ -58,6 +58,10 @@
#define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021
#define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */
#define ASUS_WMI_DEVID_LIGHTBAR 0x00050025
/* This can only be used to disable the screen, not re-enable */
#define ASUS_WMI_DEVID_SCREENPAD_POWER 0x00050031
/* Writing a brightness re-enables the screen if disabled */
#define ASUS_WMI_DEVID_SCREENPAD_LIGHT 0x00050032
#define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018
#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075

View File

@ -44,7 +44,7 @@ struct ssam_event {
u8 command_id;
u8 instance_id;
u16 length;
u8 data[];
u8 data[] __counted_by(length);
};
/**

View File

@ -10,25 +10,25 @@
TRACE_EVENT(ifs_status,
TP_PROTO(int cpu, union ifs_scan activate, union ifs_status status),
TP_PROTO(int cpu, int start, int stop, u64 status),
TP_ARGS(cpu, activate, status),
TP_ARGS(cpu, start, stop, status),
TP_STRUCT__entry(
__field( u64, status )
__field( int, cpu )
__field( u8, start )
__field( u8, stop )
__field( u16, start )
__field( u16, stop )
),
TP_fast_assign(
__entry->cpu = cpu;
__entry->start = activate.start;
__entry->stop = activate.stop;
__entry->status = status.data;
__entry->start = start;
__entry->stop = stop;
__entry->status = status;
),
TP_printk("cpu: %d, start: %.2x, stop: %.2x, status: %llx",
TP_printk("cpu: %d, start: %.4x, stop: %.4x, status: %.16llx",
__entry->cpu,
__entry->start,
__entry->stop,

View File

@ -4,8 +4,8 @@
* Copyright (c) 2019 Intel Corporation.
*/
#include <ctype.h>
#include <linux/isst_if.h>
#include <sys/utsname.h>
#include "isst.h"
@ -16,7 +16,7 @@ struct process_cmd_struct {
int arg;
};
static const char *version_str = "v1.17";
static const char *version_str = "v1.18";
static const int supported_api_ver = 2;
static struct isst_if_platform_info isst_platform_info;
@ -27,7 +27,7 @@ static FILE *outf;
static int cpu_model;
static int cpu_stepping;
#define MAX_CPUS_IN_ONE_REQ 256
#define MAX_CPUS_IN_ONE_REQ 512
static short max_target_cpus;
static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
@ -55,6 +55,8 @@ static int clos_min = -1;
static int clos_max = -1;
static int clos_desired = -1;
static int clos_priority_type;
static int cpu_0_cgroupv2;
static int cpu_0_workaround(int isolate);
struct _cpu_map {
unsigned short core_id;
@ -474,42 +476,15 @@ static unsigned int is_cpu_online(int cpu)
return online;
}
static int get_kernel_version(int *major, int *minor)
{
struct utsname buf;
int ret;
ret = uname(&buf);
if (ret)
return ret;
ret = sscanf(buf.release, "%d.%d", major, minor);
if (ret != 2)
return ret;
return 0;
}
#define CPU0_HOTPLUG_DEPRECATE_MAJOR_VER 6
#define CPU0_HOTPLUG_DEPRECATE_MINOR_VER 5
void set_cpu_online_offline(int cpu, int state)
{
char buffer[128];
int fd, ret;
if (!cpu) {
int major, minor;
ret = get_kernel_version(&major, &minor);
if (!ret) {
if (major > CPU0_HOTPLUG_DEPRECATE_MAJOR_VER || (major == CPU0_HOTPLUG_DEPRECATE_MAJOR_VER &&
minor >= CPU0_HOTPLUG_DEPRECATE_MINOR_VER)) {
debug_printf("Ignore CPU 0 offline/online for kernel version >= %d.%d\n", major, minor);
debug_printf("Use cgroups to isolate CPU 0\n");
return;
}
}
if (cpu_0_cgroupv2 && !cpu) {
fprintf(stderr, "Will use cgroup v2 for CPU 0\n");
cpu_0_workaround(!state);
return;
}
snprintf(buffer, sizeof(buffer),
@ -517,9 +492,10 @@ void set_cpu_online_offline(int cpu, int state)
fd = open(buffer, O_WRONLY);
if (fd < 0) {
if (!cpu && state) {
if (!cpu) {
fprintf(stderr, "This system is not configured for CPU 0 online/offline\n");
fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n");
fprintf(stderr, "Will use cgroup v2\n");
cpu_0_workaround(!state);
return;
}
err(-1, "%s open failed", buffer);
@ -906,7 +882,7 @@ int enable_cpuset_controller(void)
return 0;
}
int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level)
int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level, int cpu_0_only)
{
int i, first, curr_index, index, ret, fd;
static char str[512], dir_name[64];
@ -949,6 +925,12 @@ int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int lev
curr_index = 0;
first = 1;
str[0] = '\0';
if (cpu_0_only) {
snprintf(str, str_len, "0");
goto create_partition;
}
for (i = 0; i < get_topo_max_cpus(); ++i) {
if (!is_cpu_in_power_domain(i, id))
continue;
@ -971,6 +953,7 @@ int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int lev
first = 0;
}
create_partition:
debug_printf("isolated CPUs list: package:%d curr_index:%d [%s]\n", id->pkg, curr_index ,str);
snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus", dir_name);
@ -1011,6 +994,74 @@ int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int lev
return 0;
}
static int cpu_0_workaround(int isolate)
{
int fd, fd1, len, ret;
cpu_set_t cpu_mask;
struct isst_id id;
char str[2];
debug_printf("isolate CPU 0 state: %d\n", isolate);
if (isolate)
goto isolate;
/* First check if CPU 0 was isolated to remove isolation. */
/* If the cpuset.cpus doesn't exist, that means that none of the CPUs are isolated*/
fd = open("/sys/fs/cgroup/0-0-0/cpuset.cpus", O_RDONLY, 0);
if (fd < 0)
return 0;
len = read(fd, str, sizeof(str));
/* Error check, but unlikely to fail. If fails that means that not isolated */
if (len == -1)
return 0;
/* Is CPU 0 is in isolate list, the display is sorted so first element will be CPU 0*/
if (str[0] != '0') {
close(fd);
return 0;
}
fd1 = open("/sys/fs/cgroup/0-0-0/cpuset.cpus.partition", O_RDONLY, 0);
/* Unlikely that, this attribute is not present, but handle error */
if (fd1 < 0) {
close(fd);
return 0;
}
/* Is CPU 0 already changed partition to "member" */
len = read(fd1, str, sizeof(str));
if (len != -1 && str[0] == 'm') {
close(fd1);
close(fd);
return 0;
}
close(fd1);
close(fd);
debug_printf("CPU 0 was isolated before, so remove isolation\n");
isolate:
ret = enable_cpuset_controller();
if (ret)
goto isolate_fail;
CPU_ZERO(&cpu_mask);
memset(&id, 0, sizeof(struct isst_id));
CPU_SET(0, &cpu_mask);
ret = isolate_cpus(&id, sizeof(cpu_mask), &cpu_mask, isolate, 1);
isolate_fail:
if (ret)
fprintf(stderr, "Can't isolate CPU 0\n");
return ret;
}
static int isst_fill_platform_info(void)
{
const char *pathname = "/dev/isst_interface";
@ -1457,7 +1508,8 @@ display_result:
if (ret)
goto use_offline;
ret = isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, tdp_level);
ret = isolate_cpus(id, ctdp_level.core_cpumask_size,
ctdp_level.core_cpumask, tdp_level, 0);
if (ret)
goto use_offline;
@ -2125,7 +2177,7 @@ static void set_fact_enable(int arg)
fprintf(stderr,
"Enable Intel Speed Select Technology Turbo frequency feature\n");
fprintf(stderr,
"Optional: -t|--trl : Specify turbo ratio limit\n");
"Optional: -t|--trl : Specify turbo ratio limit in hex starting with 0x\n");
fprintf(stderr,
"\tOptional Arguments: -a|--auto : Designate specified target CPUs with");
fprintf(stderr,
@ -2134,7 +2186,7 @@ static void set_fact_enable(int arg)
fprintf(stderr,
"Disable Intel Speed Select Technology turbo frequency feature\n");
fprintf(stderr,
"Optional: -t|--trl : Specify turbo ratio limit\n");
"Optional: -t|--trl : Specify turbo ratio limit in hex starting with 0x\n");
fprintf(stderr,
"\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
}
@ -2241,6 +2293,14 @@ static void enable_clos_qos_config(struct isst_id *id, void *arg1, void *arg2, v
{
int ret;
int status = *(int *)arg4;
int cp_state, cp_cap;
if (!isst_read_pm_config(id, &cp_state, &cp_cap)) {
if (!cp_cap) {
isst_display_error_info_message(1, "core-power not supported", 0, 0);
return;
}
}
if (is_skx_based_platform())
clos_priority_type = 1;
@ -2526,22 +2586,22 @@ static void set_turbo_mode_for_cpu(struct isst_id *id, int status)
}
if (status) {
isst_display_result(id, outf, "turbo-mode", "enable", 0);
} else {
isst_display_result(id, outf, "turbo-mode", "disable", 0);
} else {
isst_display_result(id, outf, "turbo-mode", "enable", 0);
}
}
static void set_turbo_mode(int arg)
{
int i, enable = arg;
int i, disable = arg;
struct isst_id id;
if (cmd_help) {
if (enable)
fprintf(stderr, "Set turbo mode enable\n");
else
if (disable)
fprintf(stderr, "Set turbo mode disable\n");
else
fprintf(stderr, "Set turbo mode enable\n");
exit(0);
}
@ -2559,7 +2619,7 @@ static void set_turbo_mode(int arg)
if (online) {
set_isst_id(&id, i);
set_turbo_mode_for_cpu(&id, enable);
set_turbo_mode_for_cpu(&id, disable);
}
}
@ -2573,6 +2633,9 @@ static void get_set_trl(struct isst_id *id, void *arg1, void *arg2, void *arg3,
int set = *(int *)arg4;
int ret;
if (id->cpu < 0)
return;
if (set && !fact_trl) {
isst_display_error_info_message(1, "Invalid TRL. Specify with [-t|--trl]", 0, 0);
exit(0);
@ -2596,7 +2659,7 @@ static void process_trl(int arg)
if (cmd_help) {
if (arg) {
fprintf(stderr, "Set TRL (turbo ratio limits)\n");
fprintf(stderr, "\t t|--trl: Specify turbo ratio limit for setting TRL\n");
fprintf(stderr, "\t t|--trl: Specify turbo ratio limit for setting TRL in hex starting with 0x\n");
} else {
fprintf(stderr, "Get TRL (turbo ratio limits)\n");
}
@ -2730,6 +2793,43 @@ error:
exit(-1);
}
static void check_optarg(char *option, int hex)
{
if (optarg) {
char *start = optarg;
int i;
if (hex && strlen(optarg) < 3) {
/* At least 0x plus one character must be present */
fprintf(stderr, "malformed arguments for:%s [%s]\n", option, optarg);
exit(0);
}
if (hex) {
if (optarg[0] != '0' || tolower(optarg[1]) != 'x') {
fprintf(stderr, "malformed arguments for:%s [%s]\n",
option, optarg);
exit(0);
}
start = &optarg[2];
}
for (i = 0; i < strlen(start); ++i) {
if (hex) {
if (!isxdigit(start[i])) {
fprintf(stderr, "malformed arguments for:%s [%s]\n",
option, optarg);
exit(0);
}
} else if (!isdigit(start[i])) {
fprintf(stderr, "malformed arguments for:%s [%s]\n",
option, optarg);
exit(0);
}
}
}
}
static void parse_cmd_args(int argc, int start, char **argv)
{
int opt;
@ -2763,18 +2863,21 @@ static void parse_cmd_args(int argc, int start, char **argv)
auto_mode = 1;
break;
case 'b':
check_optarg("bucket", 0);
fact_bucket = atoi(optarg);
break;
case 'h':
cmd_help = 1;
break;
case 'l':
check_optarg("level", 0);
tdp_level = atoi(optarg);
break;
case 'o':
force_online_offline = 1;
break;
case 't':
check_optarg("trl", 1);
sscanf(optarg, "0x%llx", &fact_trl);
break;
case 'r':
@ -2791,13 +2894,16 @@ static void parse_cmd_args(int argc, int start, char **argv)
break;
/* CLOS related */
case 'c':
check_optarg("clos", 0);
current_clos = atoi(optarg);
break;
case 'd':
check_optarg("desired", 0);
clos_desired = atoi(optarg);
clos_desired /= isst_get_disp_freq_multiplier();
break;
case 'e':
check_optarg("epp", 0);
clos_epp = atoi(optarg);
if (is_skx_based_platform()) {
isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0);
@ -2805,14 +2911,17 @@ static void parse_cmd_args(int argc, int start, char **argv)
}
break;
case 'n':
check_optarg("min", 0);
clos_min = atoi(optarg);
clos_min /= isst_get_disp_freq_multiplier();
break;
case 'm':
check_optarg("max", 0);
clos_max = atoi(optarg);
clos_max /= isst_get_disp_freq_multiplier();
break;
case 'p':
check_optarg("priority", 0);
clos_priority_type = atoi(optarg);
if (is_skx_based_platform() && !clos_priority_type) {
isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0);
@ -2820,6 +2929,7 @@ static void parse_cmd_args(int argc, int start, char **argv)
}
break;
case 'w':
check_optarg("weight", 0);
clos_prop_prio = atoi(optarg);
if (is_skx_based_platform()) {
isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0);
@ -2995,6 +3105,7 @@ static void usage(void)
printf("\t[-n|--no-daemon : Don't run as daemon. By default --oob will turn on daemon mode\n");
printf("\t[-w|--delay : Delay for reading config level state change in OOB poll mode.\n");
printf("\t[-g|--cgroupv2 : Try to use cgroup v2 CPU isolation instead of CPU online/offline.\n");
printf("\t[-u|--cpu0-workaround : Don't try to online/offline CPU0 instead use cgroup v2.\n");
printf("\nResult format\n");
printf("\tResult display uses a common format for each command:\n");
printf("\tResults are formatted in text/JSON with\n");
@ -3048,6 +3159,7 @@ static void cmdline(int argc, char **argv)
{ "no-daemon", no_argument, 0, 'n' },
{ "poll-interval", required_argument, 0, 'w' },
{ "cgroupv2", required_argument, 0, 'g' },
{ "cpu0-workaround", required_argument, 0, 'u' },
{ 0, 0, 0, 0 }
};
@ -3078,7 +3190,7 @@ static void cmdline(int argc, char **argv)
goto out;
progname = argv[0];
while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:ng", long_options,
while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:ngu", long_options,
&option_index)) != -1) {
switch (opt) {
case 'a':
@ -3140,6 +3252,9 @@ static void cmdline(int argc, char **argv)
case 'g':
cgroupv2 = 1;
break;
case 'u':
cpu_0_cgroupv2 = 1;
break;
default:
usage();
}

View File

@ -90,7 +90,8 @@ void process_level_change(struct isst_id *id)
if (ret)
goto use_offline;
isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, pkg_dev.current_level);
isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask,
pkg_dev.current_level, 0);
goto free_mask;
}

View File

@ -318,7 +318,8 @@ extern struct isst_platform_ops *tpmi_get_platform_ops(void);
/* Cgroup related interface */
extern int enable_cpuset_controller(void);
extern int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level);
extern int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask,
int level, int cpu_0_only);
extern int use_cgroupv2(void);
#endif