From 8055db3a5b7508872a2d0ab55ff8688ce0b1df63 Mon Sep 17 00:00:00 2001 From: Zhang Xianwei Date: Thu, 11 Oct 2018 13:59:31 +0800 Subject: [PATCH 01/41] platform/x86: thinkpad_acpi: Change the keymap for Favorites hotkey The keycode KEY_FAVORITES(0x16c) used in thinkpad_acpi driver is too big (out of range > 255) for xorg to handle. xkeyboard-config has already mapped KEY_BOOKMARKS(156) to XF86Favorites: keycodes/evdev: = 164; // #define KEY_BOOKMARKS 156 symbols/inet: key { [ XF86Favorites ] }; So change the keymap to KEY_BOOKMARKS for Favorites hotkey. Signed-off-by: Zhang Xianwei Signed-off-by: Andy Shevchenko --- drivers/platform/x86/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index fde08a997557..a86cf47292e9 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3457,7 +3457,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, - KEY_FAVORITES, /* Favorite app, 0x311 */ + KEY_BOOKMARKS, /* Favorite app, 0x311 */ KEY_RESERVED, /* Clipping tool */ KEY_CALC, /* Calculator (above numpad, P52) */ KEY_BLUETOOTH, /* Bluetooth */ From 78f3ac76d9e5219589718b9e4733bee21627b3f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Rechi=20Vita?= Date: Wed, 31 Oct 2018 17:21:26 -0700 Subject: [PATCH 02/41] platform/x86: asus-wmi: Tell the EC the OS will handle the display off hotkey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the past, Asus firmwares would change the panel backlight directly through the EC when the display off hotkey (Fn+F7) was pressed, and only notify the OS of such change, with 0x33 when the LCD was ON and 0x34 when the LCD was OFF. These are currently mapped to KEY_DISPLAYTOGGLE and KEY_DISPLAY_OFF, respectively. Most recently the EC on Asus most machines lost ability to toggle the LCD backlight directly, but unless the OS informs the firmware it is going to handle the display toggle hotkey events, the firmware still tries change the brightness through the EC, to no effect. The end result is a long list (at Endless we counted 11) of Asus laptop models where the display toggle hotkey does not perform any action. Our firmware engineers contacts at Asus were surprised that there were still machines out there with the old behavior. Calling WMNB(ASUS_WMI_DEVID_BACKLIGHT==0x00050011, 2) on the _WDG device tells the firmware that it should let the OS handle the display toggle event, in which case it will simply notify the OS of a key press with 0x35, as shown by the DSDT excerpts bellow. Scope (_SB) { (...) Device (ATKD) { (...) Name (_WDG, Buffer (0x28) { /* 0000 */ 0xD0, 0x5E, 0x84, 0x97, 0x6D, 0x4E, 0xDE, 0x11, /* 0008 */ 0x8A, 0x39, 0x08, 0x00, 0x20, 0x0C, 0x9A, 0x66, /* 0010 */ 0x4E, 0x42, 0x01, 0x02, 0x35, 0xBB, 0x3C, 0x0B, /* 0018 */ 0xC2, 0xE3, 0xED, 0x45, 0x91, 0xC2, 0x4C, 0x5A, /* 0020 */ 0x6D, 0x19, 0x5D, 0x1C, 0xFF, 0x00, 0x01, 0x08 }) Method (WMNB, 3, Serialized) { CreateDWordField (Arg2, Zero, IIA0) CreateDWordField (Arg2, 0x04, IIA1) Local0 = (Arg1 & 0xFFFFFFFF) (...) If ((Local0 == 0x53564544)) { (...) If ((IIA0 == 0x00050011)) { If ((IIA1 == 0x02)) { ^^PCI0.SBRG.EC0.SPIN (0x72, One) ^^PCI0.SBRG.EC0.BLCT = One } Return (One) } } (...) } (...) } (...) } (...) Scope (_SB.PCI0.SBRG.EC0) { (...) Name (BLCT, Zero) (...) Method (_Q10, 0, NotSerialized) // _Qxx: EC Query { If ((BLCT == Zero)) { Local0 = One Local0 = RPIN (0x72) Local0 ^= One SPIN (0x72, Local0) If (ATKP) { Local0 = (0x34 - Local0) ^^^^ATKD.IANE (Local0) } } ElseIf ((BLCT == One)) { If (ATKP) { ^^^^ATKD.IANE (0x35) } } } (...) } Signed-off-by: João Paulo Rechi Vita Signed-off-by: Andy Shevchenko --- drivers/platform/x86/asus-wmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index c285a16675ee..37b5de541270 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -2131,7 +2131,8 @@ static int asus_wmi_add(struct platform_device *pdev) err = asus_wmi_backlight_init(asus); if (err && err != -ENODEV) goto fail_backlight; - } + } else + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL); status = wmi_install_notify_handler(asus->driver->event_guid, asus_wmi_notify, asus); From b3f2f3799a972d3863d0fdc2ab6287aef6ca631f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Rechi=20Vita?= Date: Wed, 31 Oct 2018 17:21:27 -0700 Subject: [PATCH 03/41] platform/x86: asus-nb-wmi: Map 0x35 to KEY_SCREENLOCK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the OS registers to handle events from the display off hotkey the EC will send a notification with 0x35 for every key press, independent of the backlight state. The behavior of this key on Windows, with the ATKACPI driver from Asus installed, is turning off the backlight of all connected displays with a fading effect, and any cursor input or key press turning the backlight back on. The key press or cursor input that wakes up the display is also passed through to the application under the cursor or under focus. The key that matches this behavior the closest is KEY_SCREENLOCK. Signed-off-by: João Paulo Rechi Vita Signed-off-by: Andy Shevchenko --- drivers/platform/x86/asus-nb-wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index db2af09067db..5a00a7665f9b 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -444,6 +444,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x32, { KEY_MUTE } }, { KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */ { KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */ + { KE_KEY, 0x35, { KEY_SCREENLOCK } }, { KE_KEY, 0x40, { KEY_PREVIOUSSONG } }, { KE_KEY, 0x41, { KEY_NEXTSONG } }, { KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */ From 71b12beaf12f21a53bfe100795d0797f1035b570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Rechi=20Vita?= Date: Wed, 31 Oct 2018 17:21:28 -0700 Subject: [PATCH 04/41] platform/x86: asus-nb-wmi: Drop mapping of 0x33 and 0x34 scan codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to Asus firmware engineers, the meaning of these codes is only to notify the OS that the screen brightness has been turned on/off by the EC. This does not match the meaning of KEY_DISPLAYTOGGLE / KEY_DISPLAY_OFF, where userspace is expected to change the display brightness. Signed-off-by: João Paulo Rechi Vita Signed-off-by: Andy Shevchenko --- drivers/platform/x86/asus-nb-wmi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 5a00a7665f9b..b6f2ff95c3ed 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -442,8 +442,6 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x30, { KEY_VOLUMEUP } }, { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, { KE_KEY, 0x32, { KEY_MUTE } }, - { KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */ - { KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */ { KE_KEY, 0x35, { KEY_SCREENLOCK } }, { KE_KEY, 0x40, { KEY_PREVIOUSSONG } }, { KE_KEY, 0x41, { KEY_NEXTSONG } }, From 2eb150558bb79ee01c39b64c2868216c0be2904f Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Fri, 9 Nov 2018 00:32:42 +0530 Subject: [PATCH 05/41] platform/x86: intel_pmc_core: Show Latency Tolerance info This adds support to show the Latency Tolerance Reporting for the IPs on the PCH as reported by the PMC. The format shown here is raw LTR data payload that can further be decoded as per the PCI specification. This also fixes some minor alignment issues in the header file by removing spaces and converting to tabs at some places. Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_pmc_core.c | 69 +++++++++++++++++++++++++++ drivers/platform/x86/intel_pmc_core.h | 57 +++++++++++++++++++--- 2 files changed, 119 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index 6b31d410cb09..54080c0e52fb 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -101,10 +101,35 @@ static const struct pmc_bit_map spt_pfear_map[] = { {}, }; +static const struct pmc_bit_map spt_ltr_show_map[] = { + {"SOUTHPORT_A", SPT_PMC_LTR_SPA}, + {"SOUTHPORT_B", SPT_PMC_LTR_SPB}, + {"SATA", SPT_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", SPT_PMC_LTR_GBE}, + {"XHCI", SPT_PMC_LTR_XHCI}, + {"ME", SPT_PMC_LTR_ME}, + /* EVA is Enterprise Value Add, doesn't really exist on PCH */ + {"EVA", SPT_PMC_LTR_EVA}, + {"SOUTHPORT_C", SPT_PMC_LTR_SPC}, + {"HD_AUDIO", SPT_PMC_LTR_AZ}, + {"LPSS", SPT_PMC_LTR_LPSS}, + {"SOUTHPORT_D", SPT_PMC_LTR_SPD}, + {"SOUTHPORT_E", SPT_PMC_LTR_SPE}, + {"CAMERA", SPT_PMC_LTR_CAM}, + {"ESPI", SPT_PMC_LTR_ESPI}, + {"SCC", SPT_PMC_LTR_SCC}, + {"ISH", SPT_PMC_LTR_ISH}, + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", SPT_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", SPT_PMC_LTR_CUR_ASLT}, + {} +}; + static const struct pmc_reg_map spt_reg_map = { .pfear_sts = spt_pfear_map, .mphy_sts = spt_mphy_map, .pll_sts = spt_pll_map, + .ltr_show_sts = spt_ltr_show_map, .slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET, .ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET, .regmap_length = SPT_PMC_MMIO_REG_LEN, @@ -243,10 +268,38 @@ static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = { NULL, }; +static const struct pmc_bit_map cnp_ltr_show_map[] = { + {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, + {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, + {"SATA", CNP_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, + {"XHCI", CNP_PMC_LTR_XHCI}, + {"ME", CNP_PMC_LTR_ME}, + /* EVA is Enterprise Value Add, doesn't really exist on PCH */ + {"EVA", CNP_PMC_LTR_EVA}, + {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, + {"HD_AUDIO", CNP_PMC_LTR_AZ}, + {"CNV", CNP_PMC_LTR_CNV}, + {"LPSS", CNP_PMC_LTR_LPSS}, + {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, + {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, + {"CAMERA", CNP_PMC_LTR_CAM}, + {"ESPI", CNP_PMC_LTR_ESPI}, + {"SCC", CNP_PMC_LTR_SCC}, + {"ISH", CNP_PMC_LTR_ISH}, + {"UFSX2", CNP_PMC_LTR_UFSX2}, + {"EMMC", CNP_PMC_LTR_EMMC}, + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, + {} +}; + static const struct pmc_reg_map cnp_reg_map = { .pfear_sts = cnp_pfear_map, .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, .slps0_dbg_maps = cnp_slps0_dbg_maps, + .ltr_show_sts = cnp_ltr_show_map, .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, .regmap_length = CNP_PMC_MMIO_REG_LEN, @@ -583,6 +636,20 @@ static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) } DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg); +static int pmc_core_ltr_show(struct seq_file *s, void *unused) +{ + struct pmc_dev *pmcdev = s->private; + const struct pmc_bit_map *map = pmcdev->map->ltr_show_sts; + int index; + + for (index = 0; map[index].name ; index++) { + seq_printf(s, "%-32s\tRAW LTR: 0x%x\n", map[index].name, + pmc_core_reg_read(pmcdev, map[index].bit_mask)); + } + return 0; +} +DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); + static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) { debugfs_remove_recursive(pmcdev->dbgfs_dir); @@ -607,6 +674,8 @@ static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev) debugfs_create_file("ltr_ignore", 0644, dir, pmcdev, &pmc_core_ltr_ignore_ops); + debugfs_create_file("ltr_show", 0644, dir, pmcdev, &pmc_core_ltr_fops); + if (pmcdev->map->pll_sts) debugfs_create_file("pll_status", 0444, dir, pmcdev, &pmc_core_pll_ops); diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h index be045348ad86..fcb13ca1f2bd 100644 --- a/drivers/platform/x86/intel_pmc_core.h +++ b/drivers/platform/x86/intel_pmc_core.h @@ -37,6 +37,25 @@ #define NUM_RETRIES 100 #define NUM_IP_IGN_ALLOWED 17 +#define SPT_PMC_LTR_CUR_PLT 0x350 +#define SPT_PMC_LTR_CUR_ASLT 0x354 +#define SPT_PMC_LTR_SPA 0x360 +#define SPT_PMC_LTR_SPB 0x364 +#define SPT_PMC_LTR_SATA 0x368 +#define SPT_PMC_LTR_GBE 0x36C +#define SPT_PMC_LTR_XHCI 0x370 +#define SPT_PMC_LTR_ME 0x378 +#define SPT_PMC_LTR_EVA 0x37C +#define SPT_PMC_LTR_SPC 0x380 +#define SPT_PMC_LTR_AZ 0x384 +#define SPT_PMC_LTR_LPSS 0x38C +#define SPT_PMC_LTR_CAM 0x390 +#define SPT_PMC_LTR_SPD 0x394 +#define SPT_PMC_LTR_SPE 0x398 +#define SPT_PMC_LTR_ESPI 0x39C +#define SPT_PMC_LTR_SCC 0x3A0 +#define SPT_PMC_LTR_ISH 0x3A4 + /* Sunrise Point: PGD PFET Enable Ack Status Registers */ enum ppfear_regs { SPT_PMC_XRAM_PPFEAR0A = 0x590, @@ -115,18 +134,40 @@ enum ppfear_regs { #define SPT_PMC_BIT_MPHY_CMN_LANE3 BIT(3) /* Cannonlake Power Management Controller register offsets */ -#define CNP_PMC_SLP_S0_RES_COUNTER_OFFSET 0x193C -#define CNP_PMC_LTR_IGNORE_OFFSET 0x1B0C -#define CNP_PMC_PM_CFG_OFFSET 0x1818 #define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4 +#define CNP_PMC_PM_CFG_OFFSET 0x1818 +#define CNP_PMC_SLP_S0_RES_COUNTER_OFFSET 0x193C +#define CNP_PMC_LTR_IGNORE_OFFSET 0x1B0C /* Cannonlake: PGD PFET Enable Ack Status Register(s) start */ -#define CNP_PMC_HOST_PPFEAR0A 0x1D90 +#define CNP_PMC_HOST_PPFEAR0A 0x1D90 -#define CNP_PMC_MMIO_REG_LEN 0x2000 -#define CNP_PPFEAR_NUM_ENTRIES 8 -#define CNP_PMC_READ_DISABLE_BIT 22 #define CNP_PMC_LATCH_SLPS0_EVENTS BIT(31) +#define CNP_PMC_MMIO_REG_LEN 0x2000 +#define CNP_PPFEAR_NUM_ENTRIES 8 +#define CNP_PMC_READ_DISABLE_BIT 22 +#define CNP_PMC_LTR_CUR_PLT 0x1B50 +#define CNP_PMC_LTR_CUR_ASLT 0x1B54 +#define CNP_PMC_LTR_SPA 0x1B60 +#define CNP_PMC_LTR_SPB 0x1B64 +#define CNP_PMC_LTR_SATA 0x1B68 +#define CNP_PMC_LTR_GBE 0x1B6C +#define CNP_PMC_LTR_XHCI 0x1B70 +#define CNP_PMC_LTR_ME 0x1B78 +#define CNP_PMC_LTR_EVA 0x1B7C +#define CNP_PMC_LTR_SPC 0x1B80 +#define CNP_PMC_LTR_AZ 0x1B84 +#define CNP_PMC_LTR_LPSS 0x1B8C +#define CNP_PMC_LTR_CAM 0x1B90 +#define CNP_PMC_LTR_SPD 0x1B94 +#define CNP_PMC_LTR_SPE 0x1B98 +#define CNP_PMC_LTR_ESPI 0x1B9C +#define CNP_PMC_LTR_SCC 0x1BA0 +#define CNP_PMC_LTR_ISH 0x1BA4 +#define CNP_PMC_LTR_CNV 0x1BF0 +#define CNP_PMC_LTR_EMMC 0x1BF4 +#define CNP_PMC_LTR_UFSX2 0x1BF8 + struct pmc_bit_map { const char *name; u32 bit_mask; @@ -139,6 +180,7 @@ struct pmc_bit_map { * @mphy_sts: Maps name of MPHY lane to MPHY status lane status bit * @pll_sts: Maps name of PLL to corresponding bit status * @slps0_dbg_maps: Array of SLP_S0_DBG* registers containing debug info + * @ltr_show_sts: Maps PCH IP Names to their MMIO register offsets * @slp_s0_offset: PWRMBASE offset to read SLP_S0 residency * @ltr_ignore_offset: PWRMBASE offset to read/write LTR ignore bit * @regmap_length: Length of memory to map from PWRMBASE address to access @@ -157,6 +199,7 @@ struct pmc_reg_map { const struct pmc_bit_map *mphy_sts; const struct pmc_bit_map *pll_sts; const struct pmc_bit_map **slps0_dbg_maps; + const struct pmc_bit_map *ltr_show_sts; const u32 slp_s0_offset; const u32 ltr_ignore_offset; const int regmap_length; From 2d649d972bae50199a498f46b945ef8fd78cad5a Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Fri, 9 Nov 2018 00:32:43 +0530 Subject: [PATCH 06/41] platform/x86: intel_pmc_core: Fix LTR IGNORE Max offset Cannonlake PCH allows us to ignore LTR from more IPs than Sunrisepoint PCH so make the LTR ignore platform specific. Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_pmc_core.c | 4 +++- drivers/platform/x86/intel_pmc_core.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index 54080c0e52fb..0c18f328cd0d 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -137,6 +137,7 @@ static const struct pmc_reg_map spt_reg_map = { .ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES, .pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT, + .ltr_ignore_max = SPT_NUM_IP_IGN_ALLOWED, }; /* Cannonlake: PGD PFET Enable Ack Status Register(s) bitmap */ @@ -307,6 +308,7 @@ static const struct pmc_reg_map cnp_reg_map = { .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, + .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED, }; static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset) @@ -553,7 +555,7 @@ static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user goto out_unlock; } - if (val > NUM_IP_IGN_ALLOWED) { + if (val > map->ltr_ignore_max) { err = -EINVAL; goto out_unlock; } diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h index fcb13ca1f2bd..e57b26cdb442 100644 --- a/drivers/platform/x86/intel_pmc_core.h +++ b/drivers/platform/x86/intel_pmc_core.h @@ -35,7 +35,7 @@ #define SPT_PMC_READ_DISABLE_BIT 0x16 #define SPT_PMC_MSG_FULL_STS_BIT 0x18 #define NUM_RETRIES 100 -#define NUM_IP_IGN_ALLOWED 17 +#define SPT_NUM_IP_IGN_ALLOWED 17 #define SPT_PMC_LTR_CUR_PLT 0x350 #define SPT_PMC_LTR_CUR_ASLT 0x354 @@ -146,6 +146,7 @@ enum ppfear_regs { #define CNP_PMC_MMIO_REG_LEN 0x2000 #define CNP_PPFEAR_NUM_ENTRIES 8 #define CNP_PMC_READ_DISABLE_BIT 22 +#define CNP_NUM_IP_IGN_ALLOWED 19 #define CNP_PMC_LTR_CUR_PLT 0x1B50 #define CNP_PMC_LTR_CUR_ASLT 0x1B54 #define CNP_PMC_LTR_SPA 0x1B60 @@ -208,6 +209,7 @@ struct pmc_reg_map { const u32 pm_cfg_offset; const int pm_read_disable_bit; const u32 slps0_dbg_offset; + const u32 ltr_ignore_max; }; /** From 8122e7cd806df4c696eed0c9a6ad1e69dfe783fc Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Fri, 9 Nov 2018 00:32:44 +0530 Subject: [PATCH 07/41] platform/x86: intel_pmc_core: Decode Snoop / Non Snoop LTR The LTR values follow PCIE LTR encoding format and can be decoded as per https://pcisig.com/sites/default/files/specification_documents/ECN_LatencyTolnReporting_14Aug08.pdf This adds support to translate the raw LTR values as read from the PMC to meaningful values in nanosecond units of time. Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_pmc_core.c | 62 ++++++++++++++++++++++++++- drivers/platform/x86/intel_pmc_core.h | 7 +++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index 0c18f328cd0d..eba6f5c27e2f 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -12,6 +12,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include @@ -638,15 +639,72 @@ static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) } DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg); +static u32 convert_ltr_scale(u32 val) +{ + /* + * As per PCIE specification supporting document + * ECN_LatencyTolnReporting_14Aug08.pdf the Latency + * Tolerance Reporting data payload is encoded in a + * 3 bit scale and 10 bit value fields. Values are + * multiplied by the indicated scale to yield an absolute time + * value, expressible in a range from 1 nanosecond to + * 2^25*(2^10-1) = 34,326,183,936 nanoseconds. + * + * scale encoding is as follows: + * + * ---------------------------------------------- + * |scale factor | Multiplier (ns) | + * ---------------------------------------------- + * | 0 | 1 | + * | 1 | 32 | + * | 2 | 1024 | + * | 3 | 32768 | + * | 4 | 1048576 | + * | 5 | 33554432 | + * | 6 | Invalid | + * | 7 | Invalid | + * ---------------------------------------------- + */ + if (val > 5) { + pr_warn("Invalid LTR scale factor.\n"); + return 0; + } + + return 1U << (5 * val); +} + static int pmc_core_ltr_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; const struct pmc_bit_map *map = pmcdev->map->ltr_show_sts; + u64 decoded_snoop_ltr, decoded_non_snoop_ltr; + u32 ltr_raw_data, scale, val; + u16 snoop_ltr, nonsnoop_ltr; int index; for (index = 0; map[index].name ; index++) { - seq_printf(s, "%-32s\tRAW LTR: 0x%x\n", map[index].name, - pmc_core_reg_read(pmcdev, map[index].bit_mask)); + decoded_snoop_ltr = decoded_non_snoop_ltr = 0; + ltr_raw_data = pmc_core_reg_read(pmcdev, + map[index].bit_mask); + snoop_ltr = ltr_raw_data & ~MTPMC_MASK; + nonsnoop_ltr = (ltr_raw_data >> 0x10) & ~MTPMC_MASK; + + if (FIELD_GET(LTR_REQ_NONSNOOP, ltr_raw_data)) { + scale = FIELD_GET(LTR_DECODED_SCALE, nonsnoop_ltr); + val = FIELD_GET(LTR_DECODED_VAL, nonsnoop_ltr); + decoded_non_snoop_ltr = val * convert_ltr_scale(scale); + } + + if (FIELD_GET(LTR_REQ_SNOOP, ltr_raw_data)) { + scale = FIELD_GET(LTR_DECODED_SCALE, snoop_ltr); + val = FIELD_GET(LTR_DECODED_VAL, snoop_ltr); + decoded_snoop_ltr = val * convert_ltr_scale(scale); + } + + seq_printf(s, "%-32s\tLTR: RAW: 0x%-16x\tNon-Snoop(ns): %-16llu\tSnoop(ns): %-16llu\n", + map[index].name, ltr_raw_data, + decoded_non_snoop_ltr, + decoded_snoop_ltr); } return 0; } diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h index e57b26cdb442..89554cba5758 100644 --- a/drivers/platform/x86/intel_pmc_core.h +++ b/drivers/platform/x86/intel_pmc_core.h @@ -12,6 +12,8 @@ #ifndef PMC_CORE_H #define PMC_CORE_H +#include + #define PMC_BASE_ADDR_DEFAULT 0xFE000000 /* Sunrise Point Power Management Controller PCI Device ID */ @@ -169,6 +171,11 @@ enum ppfear_regs { #define CNP_PMC_LTR_EMMC 0x1BF4 #define CNP_PMC_LTR_UFSX2 0x1BF8 +#define LTR_DECODED_VAL GENMASK(9, 0) +#define LTR_DECODED_SCALE GENMASK(12, 10) +#define LTR_REQ_SNOOP BIT(15) +#define LTR_REQ_NONSNOOP BIT(31) + struct pmc_bit_map { const char *name; u32 bit_mask; From 91a753608262d26faf48b1805aed60aa3283be93 Mon Sep 17 00:00:00 2001 From: Loic WEI YU NENG Date: Wed, 14 Nov 2018 07:12:12 -0800 Subject: [PATCH 08/41] platform/x86: ideapad-laptop: Add Yoga 2 13 to no_hw_rfkill list Some Lenovo IdeaPad models lack a physical rfkill switch. On Lenovo models Yoga 2 13, ideapad-laptop would wrongly report all radios as blocked by hardware which caused wireless network connections to fail. Add these models without an rfkill switch to the no_hw_rfkill list. Signed-off-by: Loic WEI YU NENG Signed-off-by: Andy Shevchenko --- drivers/platform/x86/ideapad-laptop.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index b6489cba2985..1589dffab9fa 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -1188,6 +1188,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { DMI_MATCH(DMI_BOARD_NAME, "Yoga2"), }, }, + { + .ident = "Lenovo Yoga 2 13", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Yoga 2 13"), + }, + }, { .ident = "Lenovo Yoga 3 1170 / 1470", .matches = { From 4ecd94b8e13b014a28be48c94f751fb62f7c749e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 5 Jul 2018 15:38:07 -0500 Subject: [PATCH 09/41] platform/x86: dell-laptop: Mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-laptop.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 06978c14c83b..63121fd22c2e 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -1565,8 +1565,10 @@ static ssize_t kbd_led_timeout_store(struct device *dev, switch (unit) { case KBD_TIMEOUT_DAYS: value *= 24; + /* fall through */ case KBD_TIMEOUT_HOURS: value *= 60; + /* fall through */ case KBD_TIMEOUT_MINUTES: value *= 60; unit = KBD_TIMEOUT_SECONDS; From 6734489667e240b14170a70dc7e72d333e93d5ad Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:21 +0200 Subject: [PATCH 10/41] platform/x86: intel_cht_int33fe: Remove duplicate NULL check Since i2c_unregister_device() became NULL-aware we may remove duplicate NULL check. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/intel_cht_int33fe.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c index 464fe93657b5..431151d4e611 100644 --- a/drivers/platform/x86/intel_cht_int33fe.c +++ b/drivers/platform/x86/intel_cht_int33fe.c @@ -213,8 +213,7 @@ static int cht_int33fe_probe(struct platform_device *pdev) i2c_unregister_device(data->fusb302); out_unregister_max17047: - if (data->max17047) - i2c_unregister_device(data->max17047); + i2c_unregister_device(data->max17047); device_connections_remove(data->connections); @@ -227,8 +226,7 @@ static int cht_int33fe_remove(struct platform_device *pdev) i2c_unregister_device(data->pi3usb30532); i2c_unregister_device(data->fusb302); - if (data->max17047) - i2c_unregister_device(data->max17047); + i2c_unregister_device(data->max17047); device_connections_remove(data->connections); From 5ae9ce13261490e0c65d7012c366bdd3cc9e2d77 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:22 +0200 Subject: [PATCH 11/41] platform/x86: intel_cht_int33fe: Accept errors of i2c_acpi_new_device() In the future i2c_acpi_new_device() will return error pointer in some cases. Prepare intel_cht_int33fe driver to support that. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/intel_cht_int33fe.c | 28 +++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c index 431151d4e611..367d6e304ade 100644 --- a/drivers/platform/x86/intel_cht_int33fe.c +++ b/drivers/platform/x86/intel_cht_int33fe.c @@ -168,8 +168,14 @@ static int cht_int33fe_probe(struct platform_device *pdev) board_info.dev_name = "max17047"; board_info.properties = max17047_props; data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); - if (!data->max17047) - return -EPROBE_DEFER; /* Wait for i2c-adapter to load */ + if (IS_ERR(data->max17047)) + ret = PTR_ERR(data->max17047); + else if (!data->max17047) + ret = -EPROBE_DEFER; /* Wait for i2c-adapter to load */ + else + ret = 0; + if (ret) + return ret; } data->connections[0].endpoint[0] = "port0"; @@ -194,7 +200,13 @@ static int cht_int33fe_probe(struct platform_device *pdev) board_info.irq = fusb302_irq; data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info); - if (!data->fusb302) + if (IS_ERR(data->fusb302)) + ret = PTR_ERR(data->fusb302); + else if (!data->fusb302) + ret = -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ + else + ret = 0; + if (ret) goto out_unregister_max17047; memset(&board_info, 0, sizeof(board_info)); @@ -202,7 +214,13 @@ static int cht_int33fe_probe(struct platform_device *pdev) strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE); data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info); - if (!data->pi3usb30532) + if (IS_ERR(data->pi3usb30532)) + ret = PTR_ERR(data->pi3usb30532); + else if (!data->pi3usb30532) + ret = -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ + else + ret = 0; + if (ret) goto out_unregister_fusb302; platform_set_drvdata(pdev, data); @@ -217,7 +235,7 @@ static int cht_int33fe_probe(struct platform_device *pdev) device_connections_remove(data->connections); - return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ + return ret; } static int cht_int33fe_remove(struct platform_device *pdev) From 41daf985820c72b6768512943dab23f5f41ef865 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:23 +0200 Subject: [PATCH 12/41] platform/x86: i2c-multi-instantiate: Accept errors of i2c_acpi_new_device() In the future i2c_acpi_new_device() will return error pointer in some cases. Prepare i2c-multi-instantiate driver to support that. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/i2c-multi-instantiate.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index 5456581b473c..e3345da82c84 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -72,9 +72,14 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) board_info.irq = ret; } multi->clients[i] = i2c_acpi_new_device(dev, i, &board_info); - if (!multi->clients[i]) { - dev_err(dev, "Error creating i2c-client, idx %d\n", i); + if (IS_ERR(multi->clients[i])) + ret = PTR_ERR(multi->clients[i]); + else if (!multi->clients[i]) ret = -ENODEV; + else + ret = 0; + if (ret) { + dev_err(dev, "Error creating i2c-client, idx %d\n", i); goto error; } } From 1aaeae493aad4d71f75f4129e676fbfcdf8b1422 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:24 +0200 Subject: [PATCH 13/41] platform/x86: i2c-multi-instantiate: Defer probe when no adapter found Likewise the rest of the i2c_acpi_new_device() users, defer the probe of the i2c-multi-intantiate driver in case adapter is not yet found. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/i2c-multi-instantiate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index e3345da82c84..16a0eabe1e31 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -75,7 +75,7 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) if (IS_ERR(multi->clients[i])) ret = PTR_ERR(multi->clients[i]); else if (!multi->clients[i]) - ret = -ENODEV; + ret = -EPROBE_DEFER; /* Wait for i2c-adapter to load */ else ret = 0; if (ret) { From 2dea645ffc21f927067e8e35147985887b1a843d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:25 +0200 Subject: [PATCH 14/41] i2c: acpi: Return error pointers from i2c_acpi_new_device() The caller would like to know the reason why the i2c_acpi_new_device() fails. For example, if adapter is not available, it might be in the future and we would like to re-probe the clients again. But at the same time we would like to bail out if the error seems unrecoverable, such as invalid argument supplied. To achieve this, return error pointer in some cases. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede Acked-by: Mika Westerberg Acked-by: Wolfram Sang --- drivers/i2c/i2c-core-acpi.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 32affd3fa8bd..689c0c467e97 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -386,20 +386,22 @@ struct notifier_block i2c_acpi_notifier = { * * Also see i2c_new_device, which this function calls to create the i2c-client. * - * Returns a pointer to the new i2c-client, or NULL if the adapter is not found. + * Returns a pointer to the new i2c-client, or error pointer in case of failure. + * Specifically, -EPROBE_DEFER is returned if the adapter is not found. */ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, struct i2c_board_info *info) { struct i2c_acpi_lookup lookup; struct i2c_adapter *adapter; + struct i2c_client *client; struct acpi_device *adev; LIST_HEAD(resource_list); int ret; adev = ACPI_COMPANION(dev); if (!adev) - return NULL; + return ERR_PTR(-EINVAL); memset(&lookup, 0, sizeof(lookup)); lookup.info = info; @@ -408,16 +410,23 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, ret = acpi_dev_get_resources(adev, &resource_list, i2c_acpi_fill_info, &lookup); + if (ret < 0) + return ERR_PTR(ret); + acpi_dev_free_resource_list(&resource_list); - if (ret < 0 || !info->addr) - return NULL; + if (!info->addr) + return ERR_PTR(-EADDRNOTAVAIL); adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle); if (!adapter) - return NULL; + return ERR_PTR(-EPROBE_DEFER); - return i2c_new_device(adapter, info); + client = i2c_new_device(adapter, info); + if (!client) + return ERR_PTR(-ENODEV); + + return client; } EXPORT_SYMBOL_GPL(i2c_acpi_new_device); From 09e568f783efbd40c60d2118be0a1b0aa6e35177 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:26 +0200 Subject: [PATCH 15/41] platform/x86: intel_cht_int33fe: Get rid of obsolete conditional Now, when i2c_acpi_new_device() never returns NULL, there is no point to check for it. Besides that, i2c_acpi_new_device() returns -EPROBE_DEFER directly and caller doesn't need to guess is better. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/intel_cht_int33fe.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c index 367d6e304ade..616b8853a91f 100644 --- a/drivers/platform/x86/intel_cht_int33fe.c +++ b/drivers/platform/x86/intel_cht_int33fe.c @@ -169,13 +169,7 @@ static int cht_int33fe_probe(struct platform_device *pdev) board_info.properties = max17047_props; data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); if (IS_ERR(data->max17047)) - ret = PTR_ERR(data->max17047); - else if (!data->max17047) - ret = -EPROBE_DEFER; /* Wait for i2c-adapter to load */ - else - ret = 0; - if (ret) - return ret; + return PTR_ERR(data->max17047); } data->connections[0].endpoint[0] = "port0"; @@ -200,28 +194,20 @@ static int cht_int33fe_probe(struct platform_device *pdev) board_info.irq = fusb302_irq; data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info); - if (IS_ERR(data->fusb302)) + if (IS_ERR(data->fusb302)) { ret = PTR_ERR(data->fusb302); - else if (!data->fusb302) - ret = -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ - else - ret = 0; - if (ret) goto out_unregister_max17047; + } memset(&board_info, 0, sizeof(board_info)); board_info.dev_name = "pi3usb30532"; strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE); data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info); - if (IS_ERR(data->pi3usb30532)) + if (IS_ERR(data->pi3usb30532)) { ret = PTR_ERR(data->pi3usb30532); - else if (!data->pi3usb30532) - ret = -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ - else - ret = 0; - if (ret) goto out_unregister_fusb302; + } platform_set_drvdata(pdev, data); From 79dd67306fd5f2e0a9e5697bbbfc9bfa6d8d7673 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:27 +0200 Subject: [PATCH 16/41] platform/x86: i2c-multi-instantiate: Get rid of obsolete conditional Now, when i2c_acpi_new_device() never returns NULL, there is no point to check for it. Besides that, i2c_acpi_new_device() returns -EPROBE_DEFER directly and caller doesn't need to guess is better. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/i2c-multi-instantiate.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index 16a0eabe1e31..724535673089 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -72,14 +72,10 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) board_info.irq = ret; } multi->clients[i] = i2c_acpi_new_device(dev, i, &board_info); - if (IS_ERR(multi->clients[i])) + if (IS_ERR(multi->clients[i])) { ret = PTR_ERR(multi->clients[i]); - else if (!multi->clients[i]) - ret = -EPROBE_DEFER; /* Wait for i2c-adapter to load */ - else - ret = 0; - if (ret) { - dev_err(dev, "Error creating i2c-client, idx %d\n", i); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Error creating i2c-client, idx %d\n", i); goto error; } } From 5f59d6a1109ce6ade2ad0ba2eb09d8011155daaf Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:28 +0200 Subject: [PATCH 17/41] i2c: acpi: Use ACPI_FAILURE instead of !ACPI_SUCCESS Convert to use ACPI_FAILURE instead of !ACPI_SUCCESS. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede Acked-by: Mika Westerberg Acked-by: Wolfram Sang --- drivers/i2c/i2c-core-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 689c0c467e97..8a88586e0902 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -65,7 +65,7 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) status = acpi_get_handle(lookup->device_handle, sb->resource_source.string_ptr, &lookup->adapter_handle); - if (!ACPI_SUCCESS(status)) + if (ACPI_FAILURE(status)) return 1; info->addr = sb->slave_address; From 0d5102fe85302aa06a3e5fd8e63b09294aed4c48 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:29 +0200 Subject: [PATCH 18/41] i2c: acpi: Introduce i2c_acpi_get_i2c_resource() helper Besides current two users one more is coming. Definitely makes sense to introduce a helper. No functional change intended. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede Acked-by: Mika Westerberg Acked-by: Wolfram Sang --- drivers/i2c/i2c-core-acpi.c | 41 ++++++++++++++++++++++++++----------- include/linux/acpi.h | 11 ++++++++++ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 8a88586e0902..272800692088 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -45,6 +45,33 @@ struct i2c_acpi_lookup { u32 min_speed; }; +/** + * i2c_acpi_get_i2c_resource - Gets I2cSerialBus resource if type matches + * @ares: ACPI resource + * @i2c: Pointer to I2cSerialBus resource will be returned here + * + * Checks if the given ACPI resource is of type I2cSerialBus. + * In this case, returns a pointer to it to the caller. + * + * Returns true if resource type is of I2cSerialBus, otherwise false. + */ +bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, + struct acpi_resource_i2c_serialbus **i2c) +{ + struct acpi_resource_i2c_serialbus *sb; + + if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) + return false; + + sb = &ares->data.i2c_serial_bus; + if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) + return false; + + *i2c = sb; + return true; +} +EXPORT_SYMBOL_GPL(i2c_acpi_get_i2c_resource); + static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) { struct i2c_acpi_lookup *lookup = data; @@ -52,11 +79,7 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data) struct acpi_resource_i2c_serialbus *sb; acpi_status status; - if (info->addr || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) - return 1; - - sb = &ares->data.i2c_serial_bus; - if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) + if (info->addr || !i2c_acpi_get_i2c_resource(ares, &sb)) return 1; if (lookup->index != -1 && lookup->n++ != lookup->index) @@ -534,13 +557,7 @@ i2c_acpi_space_handler(u32 function, acpi_physical_address command, goto err; } - if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { - ret = AE_BAD_PARAMETER; - goto err; - } - - sb = &ares->data.i2c_serial_bus; - if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) { + if (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) { ret = AE_BAD_PARAMETER; goto err; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ed80f147bd50..6afc6e3c4c5c 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1054,6 +1054,17 @@ static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) } #endif +#if defined(CONFIG_ACPI) && IS_ENABLED(CONFIG_I2C) +bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, + struct acpi_resource_i2c_serialbus **i2c); +#else +static inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, + struct acpi_resource_i2c_serialbus **i2c) +{ + return false; +} +#endif + /* Device properties */ #ifdef CONFIG_ACPI From a729656697e306595f5349b9176cebea459d7519 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:30 +0200 Subject: [PATCH 19/41] platform/x86: i2c-multi-instantiate: Count I2cSerialBus() resources Instead of relying on hard coded and thus expected number of I2C clients, count the real amount provided by firmware. This allows to support non-fixed amount of the slaves. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/i2c-multi-instantiate.c | 41 ++++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index 724535673089..d99bbaed0ca2 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -12,6 +12,7 @@ #include #include #include +#include struct i2c_inst_data { const char *type; @@ -23,6 +24,31 @@ struct i2c_multi_inst_data { struct i2c_client *clients[0]; }; +static int i2c_multi_inst_count(struct acpi_resource *ares, void *data) +{ + struct acpi_resource_i2c_serialbus *sb; + int *count = data; + + if (i2c_acpi_get_i2c_resource(ares, &sb)) + *count = *count + 1; + + return 1; +} + +static int i2c_multi_inst_count_resources(struct acpi_device *adev) +{ + LIST_HEAD(r); + int count = 0; + int ret; + + ret = acpi_dev_get_resources(adev, &r, i2c_multi_inst_count, &count); + if (ret < 0) + return ret; + + acpi_dev_free_resource_list(&r); + return count; +} + static int i2c_multi_inst_probe(struct platform_device *pdev) { struct i2c_multi_inst_data *multi; @@ -44,17 +70,19 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) adev = ACPI_COMPANION(dev); /* Count number of clients to instantiate */ - for (i = 0; inst_data[i].type; i++) {} + ret = i2c_multi_inst_count_resources(adev); + if (ret < 0) + return ret; multi = devm_kmalloc(dev, - offsetof(struct i2c_multi_inst_data, clients[i]), + offsetof(struct i2c_multi_inst_data, clients[ret]), GFP_KERNEL); if (!multi) return -ENOMEM; - multi->num_clients = i; + multi->num_clients = ret; - for (i = 0; i < multi->num_clients; i++) { + for (i = 0; i < multi->num_clients && inst_data[i].type; i++) { memset(&board_info, 0, sizeof(board_info)); strlcpy(board_info.type, inst_data[i].type, I2C_NAME_SIZE); snprintf(name, sizeof(name), "%s-%s", match->id, @@ -79,6 +107,11 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) goto error; } } + if (i < multi->num_clients) { + dev_err(dev, "Error finding driver, idx %d\n", i); + ret = -ENODEV; + goto error; + } platform_set_drvdata(pdev, multi); return 0; From 870ab9a379b6753ed45736152b0237ccc726172c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:31 +0200 Subject: [PATCH 20/41] platform/x86: i2c-multi-instantiate: Distinguish IRQ resource type As a preparatory patch switch the driver to distinguish IRQ resource type. For now, only GpioInt() is supported. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/i2c-multi-instantiate.c | 27 +++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index d99bbaed0ca2..99db3e336718 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -14,9 +15,14 @@ #include #include +#define IRQ_RESOURCE_TYPE GENMASK(1, 0) +#define IRQ_RESOURCE_NONE 0 +#define IRQ_RESOURCE_GPIO 1 + struct i2c_inst_data { const char *type; - int gpio_irq_idx; + unsigned int flags; + int irq_idx; }; struct i2c_multi_inst_data { @@ -88,16 +94,19 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) snprintf(name, sizeof(name), "%s-%s", match->id, inst_data[i].type); board_info.dev_name = name; - board_info.irq = 0; - if (inst_data[i].gpio_irq_idx != -1) { - ret = acpi_dev_gpio_irq_get(adev, - inst_data[i].gpio_irq_idx); + switch (inst_data[i].flags & IRQ_RESOURCE_TYPE) { + case IRQ_RESOURCE_GPIO: + ret = acpi_dev_gpio_irq_get(adev, inst_data[i].irq_idx); if (ret < 0) { dev_err(dev, "Error requesting irq at index %d: %d\n", - inst_data[i].gpio_irq_idx, ret); + inst_data[i].irq_idx, ret); goto error; } board_info.irq = ret; + break; + default: + board_info.irq = 0; + break; } multi->clients[i] = i2c_acpi_new_device(dev, i, &board_info); if (IS_ERR(multi->clients[i])) { @@ -135,9 +144,9 @@ static int i2c_multi_inst_remove(struct platform_device *pdev) } static const struct i2c_inst_data bsg1160_data[] = { - { "bmc150_accel", 0 }, - { "bmc150_magn", -1 }, - { "bmg160", -1 }, + { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 }, + { "bmc150_magn" }, + { "bmg160" }, {} }; From 799d3379a6728794de5ed2be8acc5b4a65d776b6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:32 +0200 Subject: [PATCH 21/41] platform/x86: i2c-multi-instantiate: Introduce IOAPIC IRQ support If ACPI table provides an Interrupt() resource we may consider to use it instead of GpioInt() one. Here we leave an error condition, when getting IRQ resource, to the driver to decide how to proceed, because some drivers may consider IRQ resource optional. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/i2c-multi-instantiate.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index 99db3e336718..365457f9c424 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -18,6 +18,7 @@ #define IRQ_RESOURCE_TYPE GENMASK(1, 0) #define IRQ_RESOURCE_NONE 0 #define IRQ_RESOURCE_GPIO 1 +#define IRQ_RESOURCE_APIC 2 struct i2c_inst_data { const char *type; @@ -104,6 +105,14 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) } board_info.irq = ret; break; + case IRQ_RESOURCE_APIC: + ret = platform_get_irq(pdev, inst_data[i].irq_idx); + if (ret < 0) { + dev_dbg(dev, "Error requesting irq at index %d: %d\n", + inst_data[i].irq_idx, ret); + } + board_info.irq = ret; + break; default: board_info.irq = 0; break; From 2336dfadfb1e3a484f0daf4014305626a3d9df62 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:33 +0200 Subject: [PATCH 22/41] platform/x86: i2c-multi-instantiate: Allow to have same slaves Currently the driver will not enumerate the devices where I2C slaves are of the same type. Add an instance number to make them unique. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede --- drivers/platform/x86/i2c-multi-instantiate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index 365457f9c424..2439d4c71118 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -92,8 +92,8 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) for (i = 0; i < multi->num_clients && inst_data[i].type; i++) { memset(&board_info, 0, sizeof(board_info)); strlcpy(board_info.type, inst_data[i].type, I2C_NAME_SIZE); - snprintf(name, sizeof(name), "%s-%s", match->id, - inst_data[i].type); + snprintf(name, sizeof(name), "%s-%s.%d", match->id, + inst_data[i].type, i); board_info.dev_name = name; switch (inst_data[i].flags & IRQ_RESOURCE_TYPE) { case IRQ_RESOURCE_GPIO: From a3dd034a1707490119f32bd0c50e6047e42d2517 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:34 +0200 Subject: [PATCH 23/41] ACPI / scan: Create platform device for INT3515 ACPI nodes The ACPI device with INT3515 _HID is representing a complex USB PD hardware infrastructure which includes several I2C slave ICs. We add an ID to the I2C multi instantiate list to enumerate all I2C slaves correctly. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede Acked-by: Heikki Krogerus Acked-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 1 + drivers/platform/x86/i2c-multi-instantiate.c | 9 +++++++++ drivers/usb/typec/tps6598x.c | 8 ++++---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index bd1c59fb0e17..e9eda5558c1f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1541,6 +1541,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) static const struct acpi_device_id i2c_multi_instantiate_ids[] = { {"BSG1160", }, {"INT33FE", }, + {"INT3515", }, {} }; diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index 2439d4c71118..3d893e0ac250 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -159,12 +159,21 @@ static const struct i2c_inst_data bsg1160_data[] = { {} }; +static const struct i2c_inst_data int3515_data[] = { + { "tps6598x", IRQ_RESOURCE_APIC, 0 }, + { "tps6598x", IRQ_RESOURCE_APIC, 1 }, + { "tps6598x", IRQ_RESOURCE_APIC, 2 }, + { "tps6598x", IRQ_RESOURCE_APIC, 3 }, + {} +}; + /* * Note new device-ids must also be added to i2c_multi_instantiate_ids in * drivers/acpi/scan.c: acpi_device_enumeration_by_parent(). */ static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = { { "BSG1160", (unsigned long)bsg1160_data }, + { "INT3515", (unsigned long)int3515_data }, { } }; MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids); diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c index c84c8c189e90..1c0033ad8738 100644 --- a/drivers/usb/typec/tps6598x.c +++ b/drivers/usb/typec/tps6598x.c @@ -501,19 +501,19 @@ static int tps6598x_remove(struct i2c_client *client) return 0; } -static const struct acpi_device_id tps6598x_acpi_match[] = { - { "INT3515", 0 }, +static const struct i2c_device_id tps6598x_id[] = { + { "tps6598x" }, { } }; -MODULE_DEVICE_TABLE(acpi, tps6598x_acpi_match); +MODULE_DEVICE_TABLE(i2c, tps6598x_id); static struct i2c_driver tps6598x_i2c_driver = { .driver = { .name = "tps6598x", - .acpi_match_table = tps6598x_acpi_match, }, .probe_new = tps6598x_probe, .remove = tps6598x_remove, + .id_table = tps6598x_id, }; module_i2c_driver(tps6598x_i2c_driver); From e278558a1f4b91ed381d5b0168e2f6743a03ae20 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 28 Nov 2018 13:45:35 +0200 Subject: [PATCH 24/41] iio: inv_mpu6050: Use i2c_acpi_get_i2c_resource() helper ACPI provides a generic helper to get I2C Serial Bus resources. Use it instead of open coded variant. Signed-off-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Reviewed-by: Hans de Goede Acked-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c index d78a10403bac..a961b5a06fe6 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c @@ -91,18 +91,14 @@ static int asus_acpi_get_sensor_info(struct acpi_device *adev, static int acpi_i2c_check_resource(struct acpi_resource *ares, void *data) { + struct acpi_resource_i2c_serialbus *sb; u32 *addr = data; - if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { - struct acpi_resource_i2c_serialbus *sb; - - sb = &ares->data.i2c_serial_bus; - if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { - if (*addr) - *addr |= (sb->slave_address << 16); - else - *addr = sb->slave_address; - } + if (i2c_acpi_get_i2c_resource(ares, &sb)) { + if (*addr) + *addr |= (sb->slave_address << 16); + else + *addr = sb->slave_address; } /* Tell the ACPI core that we already copied this address */ From 9a92ed29ca961f118b45a2893416df753c287845 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 27 Nov 2018 11:09:38 +0800 Subject: [PATCH 25/41] platform/x86: intel_ips: remove unnecessary checks in ips_debugfs_init As Greg KH explained in: https://lkml.org/lkml/2015/8/15/114 There no need to check the return value of debugfs_create_file() and debugfs_create_dir(). This also fix static code checker warnings: drivers/platform/x86/intel_ips.c:1314 ips_debugfs_init() warn: passing zero to 'PTR_ERR' drivers/platform/x86/intel_ips.c:1328 ips_debugfs_init() warn: passing zero to 'PTR_ERR' Signed-off-by: YueHaibing Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 225638a1b09e..f37c07c6ad8e 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -1310,32 +1310,15 @@ static void ips_debugfs_init(struct ips_driver *ips) int i; ips->debug_root = debugfs_create_dir("ips", NULL); - if (!ips->debug_root) { - dev_err(ips->dev, "failed to create debugfs entries: %ld\n", - PTR_ERR(ips->debug_root)); - return; - } for (i = 0; i < ARRAY_SIZE(ips_debug_files); i++) { - struct dentry *ent; struct ips_debugfs_node *node = &ips_debug_files[i]; node->ips = ips; - ent = debugfs_create_file(node->name, S_IFREG | S_IRUGO, - ips->debug_root, node, - &ips_debugfs_ops); - if (!ent) { - dev_err(ips->dev, "failed to create debug file: %ld\n", - PTR_ERR(ent)); - goto err_cleanup; - } + debugfs_create_file(node->name, S_IFREG | S_IRUGO, + ips->debug_root, node, + &ips_debugfs_ops); } - - return; - -err_cleanup: - ips_debugfs_cleanup(ips); - return; } #endif /* CONFIG_DEBUG_FS */ From 0b8a6aeab9255a43b2a34b386d95004665e0fe9a Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sun, 2 Dec 2018 21:52:11 +0100 Subject: [PATCH 26/41] platform/x86: intel_ips: NULL check before some freeing functions is not needed NULL check before some freeing functions is not needed. Signed-off-by: Thomas Meyer Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index f37c07c6ad8e..221c090ac471 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -1300,9 +1300,7 @@ static const struct file_operations ips_debugfs_ops = { static void ips_debugfs_cleanup(struct ips_driver *ips) { - if (ips->debug_root) - debugfs_remove_recursive(ips->debug_root); - return; + debugfs_remove_recursive(ips->debug_root); } static void ips_debugfs_init(struct ips_driver *ips) From 1d5caaa853ea8315950a6dd952d7ec34394f4d60 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Dec 2018 20:17:40 +0200 Subject: [PATCH 27/41] platform/x86: intel_ips: Remove never happen condition At ->remove() stage we know that device had been instantiated properly, so, it can't be an invalid pointer to the driver data. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 221c090ac471..d613f287b420 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -1627,9 +1627,6 @@ static void ips_remove(struct pci_dev *dev) struct ips_driver *ips = pci_get_drvdata(dev); u64 turbo_override; - if (!ips) - return; - ips_debugfs_cleanup(ips); /* Release i915 driver */ From e6f5e6c2fbbc3c6910803819e71832fad278cd61 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 3 Dec 2018 21:07:03 +0200 Subject: [PATCH 28/41] platform/x86: intel_ips: Convert to use DEFINE_SHOW_ATTRIBUTE macro Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 59 ++++++++------------------------ 1 file changed, 15 insertions(+), 44 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index d613f287b420..bffe548187ee 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -1210,13 +1210,7 @@ static void ips_debugfs_cleanup(struct ips_driver *ips) { return; } /* Expose current state and limits in debugfs if possible */ -struct ips_debugfs_node { - struct ips_driver *ips; - char *name; - int (*show)(struct seq_file *m, void *data); -}; - -static int show_cpu_temp(struct seq_file *m, void *data) +static int cpu_temp_show(struct seq_file *m, void *data) { struct ips_driver *ips = m->private; @@ -1225,8 +1219,9 @@ static int show_cpu_temp(struct seq_file *m, void *data) return 0; } +DEFINE_SHOW_ATTRIBUTE(cpu_temp); -static int show_cpu_power(struct seq_file *m, void *data) +static int cpu_power_show(struct seq_file *m, void *data) { struct ips_driver *ips = m->private; @@ -1234,8 +1229,9 @@ static int show_cpu_power(struct seq_file *m, void *data) return 0; } +DEFINE_SHOW_ATTRIBUTE(cpu_power); -static int show_cpu_clamp(struct seq_file *m, void *data) +static int cpu_clamp_show(struct seq_file *m, void *data) { u64 turbo_override; int tdp, tdc; @@ -1255,8 +1251,9 @@ static int show_cpu_clamp(struct seq_file *m, void *data) return 0; } +DEFINE_SHOW_ATTRIBUTE(cpu_clamp); -static int show_mch_temp(struct seq_file *m, void *data) +static int mch_temp_show(struct seq_file *m, void *data) { struct ips_driver *ips = m->private; @@ -1265,8 +1262,9 @@ static int show_mch_temp(struct seq_file *m, void *data) return 0; } +DEFINE_SHOW_ATTRIBUTE(mch_temp); -static int show_mch_power(struct seq_file *m, void *data) +static int mch_power_show(struct seq_file *m, void *data) { struct ips_driver *ips = m->private; @@ -1274,29 +1272,7 @@ static int show_mch_power(struct seq_file *m, void *data) return 0; } - -static struct ips_debugfs_node ips_debug_files[] = { - { NULL, "cpu_temp", show_cpu_temp }, - { NULL, "cpu_power", show_cpu_power }, - { NULL, "cpu_clamp", show_cpu_clamp }, - { NULL, "mch_temp", show_mch_temp }, - { NULL, "mch_power", show_mch_power }, -}; - -static int ips_debugfs_open(struct inode *inode, struct file *file) -{ - struct ips_debugfs_node *node = inode->i_private; - - return single_open(file, node->show, node->ips); -} - -static const struct file_operations ips_debugfs_ops = { - .owner = THIS_MODULE, - .open = ips_debugfs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(mch_power); static void ips_debugfs_cleanup(struct ips_driver *ips) { @@ -1305,18 +1281,13 @@ static void ips_debugfs_cleanup(struct ips_driver *ips) static void ips_debugfs_init(struct ips_driver *ips) { - int i; - ips->debug_root = debugfs_create_dir("ips", NULL); - for (i = 0; i < ARRAY_SIZE(ips_debug_files); i++) { - struct ips_debugfs_node *node = &ips_debug_files[i]; - - node->ips = ips; - debugfs_create_file(node->name, S_IFREG | S_IRUGO, - ips->debug_root, node, - &ips_debugfs_ops); - } + debugfs_create_file("cpu_temp", 0444, ips->debug_root, ips, &cpu_temp_fops); + debugfs_create_file("cpu_power", 0444, ips->debug_root, ips, &cpu_power_fops); + debugfs_create_file("cpu_clamp", 0444, ips->debug_root, ips, &cpu_clamp_fops); + debugfs_create_file("mch_temp", 0444, ips->debug_root, ips, &mch_temp_fops); + debugfs_create_file("mch_power", 0444, ips->debug_root, ips, &mch_power_fops); } #endif /* CONFIG_DEBUG_FS */ From 8a7d7141528ad67e465bc6afacc6a3144d1fe320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 29 Nov 2018 19:44:44 +0200 Subject: [PATCH 29/41] platform/x86: Add the VLV ISP PCI ID to atomisp2_pm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the ISP is exposed as a PCI device VLV machines need the same treatment as CHV machines to power gate the ISP. Otherwise s0ix will not work. Cc: Hans de Goede Cc: Alan Cox Cc: Andy Shevchenko Cc: Darren Hart Signed-off-by: Ville Syrjälä Reviewed-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_atomisp2_pm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/intel_atomisp2_pm.c b/drivers/platform/x86/intel_atomisp2_pm.c index 9371603a0ac9..4a2ec5eeb6d8 100644 --- a/drivers/platform/x86/intel_atomisp2_pm.c +++ b/drivers/platform/x86/intel_atomisp2_pm.c @@ -99,6 +99,7 @@ static UNIVERSAL_DEV_PM_OPS(isp_pm_ops, isp_pci_suspend, isp_pci_resume, NULL); static const struct pci_device_id isp_id_table[] = { + { PCI_VDEVICE(INTEL, 0x0f38), }, { PCI_VDEVICE(INTEL, 0x22b8), }, { 0, } }; From 6a31061833a52a79c99221b6251db08cf377470e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 29 Nov 2018 19:44:45 +0200 Subject: [PATCH 30/41] platform/x86: Fix config space access for intel_atomisp2_pm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We lose even config space access when we power gate the ISP via the PUNIT. That makes lspci & co. produce gibberish. To fix that let's try to implement actual runtime pm hooks and inform the pci core that the device always goes to D3cold. That will cause the pci core to resume the device before attempting config space access. This introduces another annoyance though. We get the following error every time we try to resume the device: intel_atomisp2_pm 0000:00:03.0: Refused to change power state, currently in D3 The reason being that the pci core tries to put the device back into D0 via the standard PCI PM mechanism before calling the driver resume hook. To fix this properly we'd need to infiltrate the platform pm hooks (could turn ugly real fast), or use pm domains (which don't seem to exist on x86), or some extra early resume hook for the driver (which doesn't exist either). So maybe we just choose to live with the error? Cc: Hans de Goede Cc: Alan Cox Cc: Andy Shevchenko Cc: Darren Hart Signed-off-by: Ville Syrjälä Signed-off-by: Andy Shevchenko Reviewed-by: Hans de Goede --- drivers/platform/x86/intel_atomisp2_pm.c | 68 +++++++++++++++++------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/drivers/platform/x86/intel_atomisp2_pm.c b/drivers/platform/x86/intel_atomisp2_pm.c index 4a2ec5eeb6d8..b0f421fea2a5 100644 --- a/drivers/platform/x86/intel_atomisp2_pm.c +++ b/drivers/platform/x86/intel_atomisp2_pm.c @@ -33,46 +33,45 @@ #define ISPSSPM0_IUNIT_POWER_ON 0x0 #define ISPSSPM0_IUNIT_POWER_OFF 0x3 -static int isp_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int isp_set_power(struct pci_dev *dev, bool enable) { unsigned long timeout; - u32 val; + u32 val = enable ? ISPSSPM0_IUNIT_POWER_ON : + ISPSSPM0_IUNIT_POWER_OFF; - pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, 0); - - /* - * MRFLD IUNIT DPHY is located in an always-power-on island - * MRFLD HW design need all CSI ports are disabled before - * powering down the IUNIT. - */ - pci_read_config_dword(dev, PCI_CSI_CONTROL, &val); - val |= PCI_CSI_CONTROL_PORTS_OFF_MASK; - pci_write_config_dword(dev, PCI_CSI_CONTROL, val); - - /* Write 0x3 to ISPSSPM0 bit[1:0] to power off the IUNIT */ + /* Write to ISPSSPM0 bit[1:0] to power on/off the IUNIT */ iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, - ISPSSPM0_IUNIT_POWER_OFF, ISPSSPM0_ISPSSC_MASK); + val, ISPSSPM0_ISPSSC_MASK); /* * There should be no IUNIT access while power-down is * in progress HW sighting: 4567865 * Wait up to 50 ms for the IUNIT to shut down. + * And we do the same for power on. */ timeout = jiffies + msecs_to_jiffies(50); while (1) { - /* Wait until ISPSSPM0 bit[25:24] shows 0x3 */ - iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &val); - val = (val & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET; - if (val == ISPSSPM0_IUNIT_POWER_OFF) + u32 tmp; + + /* Wait until ISPSSPM0 bit[25:24] shows the right value */ + iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &tmp); + tmp = (tmp & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET; + if (tmp == val) break; if (time_after(jiffies, timeout)) { - dev_err(&dev->dev, "IUNIT power-off timeout.\n"); + dev_err(&dev->dev, "IUNIT power-%s timeout.\n", + enable ? "on" : "off"); return -EBUSY; } usleep_range(1000, 2000); } + return 0; +} + +static int isp_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ pm_runtime_allow(&dev->dev); pm_runtime_put_sync_suspend(&dev->dev); @@ -87,11 +86,40 @@ static void isp_remove(struct pci_dev *dev) static int isp_pci_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); + u32 val; + + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, 0); + + /* + * MRFLD IUNIT DPHY is located in an always-power-on island + * MRFLD HW design need all CSI ports are disabled before + * powering down the IUNIT. + */ + pci_read_config_dword(pdev, PCI_CSI_CONTROL, &val); + val |= PCI_CSI_CONTROL_PORTS_OFF_MASK; + pci_write_config_dword(pdev, PCI_CSI_CONTROL, val); + + /* + * We lose config space access when punit power gates + * the ISP. Can't use pci_set_power_state() because + * pmcsr won't actually change when we write to it. + */ + pci_save_state(pdev); + pdev->current_state = PCI_D3cold; + isp_set_power(pdev, false); + return 0; } static int isp_pci_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); + + isp_set_power(pdev, true); + pdev->current_state = PCI_D0; + pci_restore_state(pdev); + return 0; } From f25b6302b294c220d5be010342f6399d89dcabf3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 4 Dec 2018 10:20:04 +0100 Subject: [PATCH 31/41] platform/x86: touchscreen_dmi: Add info for the Mediacom Flexbook Edge 11 Add a DMI match for the Mediacom Flexbook Edge 11, this is the same hw as the Trekstor Primebook C11, so we use the same settings. Reported-by: rmbg Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/touchscreen_dmi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c index 5f2d7ea912b5..8c5d47c0aea6 100644 --- a/drivers/platform/x86/touchscreen_dmi.c +++ b/drivers/platform/x86/touchscreen_dmi.c @@ -614,6 +614,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = { DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"), }, }, + { + /* Mediacom Flexbook Edge 11 (same hw as TS Primebook C11) */ + .driver_data = (void *)&trekstor_primebook_c11_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDIACOM"), + DMI_MATCH(DMI_PRODUCT_NAME, "FlexBook edge11 - M-FBE11"), + }, + }, { /* Onda oBook 20 Plus */ .driver_data = (void *)&onda_obook_20_plus_data, From 599eefffcf6b9cff3e8cc2d96fd8eebfadab339c Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Wed, 5 Dec 2018 12:17:52 +0100 Subject: [PATCH 32/41] platform/x86: thinkpad_acpi: Cleanup quirks macros - Use generic quirks macros for fan quirks The fan-specific quirks macros were duplicates of the generic ones. - Remove useless #undef lines The referenced macros are not defined anywhere. Signed-off-by: Jouke Witteveen Acked-by: Henrique de Moraes Holschuh Signed-off-by: Andy Shevchenko --- drivers/platform/x86/thinkpad_acpi.c | 45 ++++++++-------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index a86cf47292e9..f5773cdfdebc 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -478,6 +478,12 @@ do { \ .ec = TPACPI_MATCH_ANY, \ .quirks = (__quirk) } +#define TPACPI_QEC_IBM(__id1, __id2, __quirk) \ + { .vendor = PCI_VENDOR_ID_IBM, \ + .bios = TPACPI_MATCH_ANY, \ + .ec = TPID(__id1, __id2), \ + .quirks = (__quirk) } + #define TPACPI_QEC_LNV(__id1, __id2, __quirk) \ { .vendor = PCI_VENDOR_ID_LENOVO, \ .bios = TPACPI_MATCH_ANY, \ @@ -5973,9 +5979,6 @@ static const struct tpacpi_quirk led_useful_qtable[] __initconst = { }, }; -#undef TPACPI_LEDQ_IBM -#undef TPACPI_LEDQ_LNV - static enum led_access_mode __init led_init_detect_mode(void) { acpi_status status; @@ -8710,40 +8713,18 @@ static const struct attribute_group fan_attr_group = { .attrs = fan_attributes, }; -#define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */ +#define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */ #define TPACPI_FAN_2FAN 0x0002 /* EC 0x31 bit 0 selects fan2 */ -#define TPACPI_FAN_QI(__id1, __id2, __quirks) \ - { .vendor = PCI_VENDOR_ID_IBM, \ - .bios = TPACPI_MATCH_ANY, \ - .ec = TPID(__id1, __id2), \ - .quirks = __quirks } - -#define TPACPI_FAN_QL(__id1, __id2, __quirks) \ - { .vendor = PCI_VENDOR_ID_LENOVO, \ - .bios = TPACPI_MATCH_ANY, \ - .ec = TPID(__id1, __id2), \ - .quirks = __quirks } - -#define TPACPI_FAN_QB(__id1, __id2, __quirks) \ - { .vendor = PCI_VENDOR_ID_LENOVO, \ - .bios = TPID(__id1, __id2), \ - .ec = TPACPI_MATCH_ANY, \ - .quirks = __quirks } - static const struct tpacpi_quirk fan_quirk_table[] __initconst = { - TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1), - TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1), - TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1), - TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1), - TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN), - TPACPI_FAN_QB('N', '1', TPACPI_FAN_2FAN), + TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1), + TPACPI_QEC_IBM('7', '8', TPACPI_FAN_Q1), + TPACPI_QEC_IBM('7', '6', TPACPI_FAN_Q1), + TPACPI_QEC_IBM('7', '0', TPACPI_FAN_Q1), + TPACPI_QEC_LNV('7', 'M', TPACPI_FAN_2FAN), + TPACPI_Q_LNV('N', '1', TPACPI_FAN_2FAN), }; -#undef TPACPI_FAN_QL -#undef TPACPI_FAN_QI -#undef TPACPI_FAN_QB - static int __init fan_init(struct ibm_init_struct *iibm) { int rc; From 3b1f99558ddc204f1ece3dc8d4996dbdc26eb18d Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Wed, 5 Dec 2018 10:12:54 -0500 Subject: [PATCH 33/41] platform/x86: intel_pmc_core: convert to DEFINE_SHOW_ATTRIBUTE Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_pmc_core.c | 49 +++++---------------------- 1 file changed, 8 insertions(+), 41 deletions(-) diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index eba6f5c27e2f..22dbf115782e 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -367,7 +367,7 @@ static void pmc_core_display_map(struct seq_file *s, int index, pf_map[index].bit_mask & pf_reg ? "Off" : "On"); } -static int pmc_core_ppfear_sts_show(struct seq_file *s, void *unused) +static int pmc_core_ppfear_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; const struct pmc_bit_map *map = pmcdev->map->pfear_sts; @@ -385,18 +385,7 @@ static int pmc_core_ppfear_sts_show(struct seq_file *s, void *unused) return 0; } - -static int pmc_core_ppfear_sts_open(struct inode *inode, struct file *file) -{ - return single_open(file, pmc_core_ppfear_sts_show, inode->i_private); -} - -static const struct file_operations pmc_core_ppfear_ops = { - .open = pmc_core_ppfear_sts_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(pmc_core_ppfear); /* This function should return link status, 0 means ready */ static int pmc_core_mtpmc_link_status(void) @@ -428,7 +417,7 @@ static int pmc_core_send_msg(u32 *addr_xram) return 0; } -static int pmc_core_mphy_pg_sts_show(struct seq_file *s, void *unused) +static int pmc_core_mphy_pg_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; const struct pmc_bit_map *map = pmcdev->map->mphy_sts; @@ -480,18 +469,7 @@ static int pmc_core_mphy_pg_sts_show(struct seq_file *s, void *unused) mutex_unlock(&pmcdev->lock); return err; } - -static int pmc_core_mphy_pg_sts_open(struct inode *inode, struct file *file) -{ - return single_open(file, pmc_core_mphy_pg_sts_show, inode->i_private); -} - -static const struct file_operations pmc_core_mphy_pg_ops = { - .open = pmc_core_mphy_pg_sts_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(pmc_core_mphy_pg); static int pmc_core_pll_show(struct seq_file *s, void *unused) { @@ -527,18 +505,7 @@ static int pmc_core_pll_show(struct seq_file *s, void *unused) mutex_unlock(&pmcdev->lock); return err; } - -static int pmc_core_pll_open(struct inode *inode, struct file *file) -{ - return single_open(file, pmc_core_pll_show, inode->i_private); -} - -static const struct file_operations pmc_core_pll_ops = { - .open = pmc_core_pll_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(pmc_core_pll); static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) @@ -729,7 +696,7 @@ static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev) &pmc_core_dev_state); debugfs_create_file("pch_ip_power_gating_status", 0444, dir, pmcdev, - &pmc_core_ppfear_ops); + &pmc_core_ppfear_fops); debugfs_create_file("ltr_ignore", 0644, dir, pmcdev, &pmc_core_ltr_ignore_ops); @@ -738,12 +705,12 @@ static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev) if (pmcdev->map->pll_sts) debugfs_create_file("pll_status", 0444, dir, pmcdev, - &pmc_core_pll_ops); + &pmc_core_pll_fops); if (pmcdev->map->mphy_sts) debugfs_create_file("mphy_core_lanes_power_gating_status", 0444, dir, pmcdev, - &pmc_core_mphy_pg_ops); + &pmc_core_mphy_pg_fops); if (pmcdev->map->slps0_dbg_maps) { debugfs_create_file("slp_s0_debug_status", 0444, From ef688fc79c5442d7115c6dffa31c5a87f95bc0d6 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Wed, 5 Dec 2018 10:12:55 -0500 Subject: [PATCH 34/41] platform/x86: intel_telemetry: convert to DEFINE_SHOW_ATTRIBUTE Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li Signed-off-by: Andy Shevchenko --- .../platform/x86/intel_telemetry_debugfs.c | 42 +++---------------- 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c index 40bce560eb30..98ba9185a27b 100644 --- a/drivers/platform/x86/intel_telemetry_debugfs.c +++ b/drivers/platform/x86/intel_telemetry_debugfs.c @@ -466,17 +466,7 @@ static int telem_pss_states_show(struct seq_file *s, void *unused) return 0; } -static int telem_pss_state_open(struct inode *inode, struct file *file) -{ - return single_open(file, telem_pss_states_show, inode->i_private); -} - -static const struct file_operations telem_pss_ops = { - .open = telem_pss_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(telem_pss_states); static int telem_ioss_states_show(struct seq_file *s, void *unused) { @@ -505,17 +495,7 @@ static int telem_ioss_states_show(struct seq_file *s, void *unused) return 0; } -static int telem_ioss_state_open(struct inode *inode, struct file *file) -{ - return single_open(file, telem_ioss_states_show, inode->i_private); -} - -static const struct file_operations telem_ioss_ops = { - .open = telem_ioss_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(telem_ioss_states); static int telem_soc_states_show(struct seq_file *s, void *unused) { @@ -664,17 +644,7 @@ static int telem_soc_states_show(struct seq_file *s, void *unused) return 0; } -static int telem_soc_state_open(struct inode *inode, struct file *file) -{ - return single_open(file, telem_soc_states_show, inode->i_private); -} - -static const struct file_operations telem_socstate_ops = { - .open = telem_soc_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(telem_soc_states); static int telem_s0ix_res_get(void *data, u64 *val) { @@ -960,7 +930,7 @@ static int __init telemetry_debugfs_init(void) f = debugfs_create_file("pss_info", S_IFREG | S_IRUGO, debugfs_conf->telemetry_dbg_dir, NULL, - &telem_pss_ops); + &telem_pss_states_fops); if (!f) { pr_err("pss_sample_info debugfs register failed\n"); goto out; @@ -968,7 +938,7 @@ static int __init telemetry_debugfs_init(void) f = debugfs_create_file("ioss_info", S_IFREG | S_IRUGO, debugfs_conf->telemetry_dbg_dir, NULL, - &telem_ioss_ops); + &telem_ioss_states_fops); if (!f) { pr_err("ioss_sample_info debugfs register failed\n"); goto out; @@ -976,7 +946,7 @@ static int __init telemetry_debugfs_init(void) f = debugfs_create_file("soc_states", S_IFREG | S_IRUGO, debugfs_conf->telemetry_dbg_dir, - NULL, &telem_socstate_ops); + NULL, &telem_soc_states_fops); if (!f) { pr_err("ioss_sample_info debugfs register failed\n"); goto out; From 59e96ec85e8e59170f6d5cba028e199a2e5dfe67 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 15 Nov 2018 17:26:54 +0000 Subject: [PATCH 35/41] platform/x86: mlx-platform: Add definitions for new registers Add definitions for new registers: - CPLD3 version - next generation systems are equipped with three CPLD; - Two reset cause registers, which store the system reset reason (like system failures, upgrade failures and so on; Signed-off-by: Vadim Pasternak Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/mlx-platform.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index c2c3a1a19879..63edab558970 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -49,7 +49,10 @@ #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 #define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00 #define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 +#define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02 #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d +#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e +#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f #define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20 #define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21 #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22 @@ -1208,7 +1211,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) switch (reg) { case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: @@ -1258,7 +1264,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) switch (reg) { case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET: case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: From 3752e5c764b4fb1abe43c78f635bf019c8e98db2 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 15 Nov 2018 17:26:55 +0000 Subject: [PATCH 36/41] platform/x86: mlx-platform: Rename new systems product names Rename product names for next generation systems QMB7, SN37, SN34 to respectively MQMB7, MSN37, MSN34. All these systems are about to be released to the customers. At the moment, none of them is at customers sites. The customers will not suffer from this change. The names have been changed due to marketing decision. Signed-off-by: Vadim Pasternak Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/mlx-platform.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 63edab558970..cdf4498579b1 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -1508,21 +1508,21 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { .callback = mlxplat_dmi_qmb7xx_matched, .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "QMB7"), + DMI_MATCH(DMI_PRODUCT_NAME, "MQM87"), }, }, { .callback = mlxplat_dmi_qmb7xx_matched, .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "SN37"), + DMI_MATCH(DMI_PRODUCT_NAME, "MSN37"), }, }, { .callback = mlxplat_dmi_qmb7xx_matched, .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"), - DMI_MATCH(DMI_PRODUCT_NAME, "SN34"), + DMI_MATCH(DMI_PRODUCT_NAME, "MSN34"), }, }, { From edd45cba5ed7f53974475ddc9a1453c2c87b3328 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 15 Nov 2018 17:26:56 +0000 Subject: [PATCH 37/41] platform/x86: mlx-platform: Fix tachometer registers Shift by one the registers for tachometers (7 - 12). This fix is relevant for the same new systems MQMB7, MSN37, MSN34, which are about to be released to the customers. At the moment, none of them is at customers sites. The customers will not suffer from this change. This fix is necessary, because register used before for tachometer 7 has been than reserved for the second PWM for newer systems, which are not supported yet in mlx-platform driver. So registers of tachometers 7-12 have been shifted by one. Fixes: 0378123c5800 ("platform/x86: mlx-platform: Add mlxreg-fan platform driver activation") Signed-off-by: Vadim Pasternak Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/mlx-platform.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index cdf4498579b1..7e9226412611 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -86,12 +86,12 @@ #define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET 0xe7 #define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET 0xe8 #define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET 0xe9 -#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xea -#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xeb -#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xec -#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xed -#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xee -#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xef +#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xeb +#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xec +#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xed +#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xee +#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xef +#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xf0 #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda From 440f343df1996302d9a3904647ff11b689bf27bc Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 15 Nov 2018 17:26:57 +0000 Subject: [PATCH 38/41] platform/x86: mlx-platform: Fix LED configuration Exchange LED configuration between msn201x and next generation systems types. Bug was introduced when LED driver activation was added to mlx-platform. LED configuration for the three new system MQMB7, MSN37, MSN34 was assigned to MSN21 and vice versa. This bug affects MSN21 only and likely requires backport to v4.19. Fixes: 1189456b1cce ("platform/x86: mlx-platform: Add LED platform driver activation") Signed-off-by: Vadim Pasternak Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/mlx-platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 7e9226412611..750b153aaddc 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -1430,7 +1430,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data; mlxplat_hotplug->deferred_nr = mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_default_ng_led_data; + mlxplat_led = &mlxplat_msn21xx_led_data; mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; return 1; @@ -1448,7 +1448,7 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data; mlxplat_hotplug->deferred_nr = mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; - mlxplat_led = &mlxplat_msn21xx_led_data; + mlxplat_led = &mlxplat_default_ng_led_data; mlxplat_fan = &mlxplat_default_fan_data; return 1; From e2883859dd0b4ee6fc70151e417fed8680efaa4b Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 15 Nov 2018 17:26:58 +0000 Subject: [PATCH 39/41] platform/x86: mlx-platform: Allow mlxreg-io driver activation for new systems Allow mlxreg-io platform driver activation for the next generation systems, in particular for MQM87xx, MSN34xx, MSN37xx types, which have: - extended reset causes bits related to ComEx reset, voltage devices firmware upgrade, system platform reset; - additional CPLD device; - JTAG select capability; Signed-off-by: Vadim Pasternak Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/mlx-platform.c | 113 ++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 750b153aaddc..af085235f87e 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -1104,6 +1104,118 @@ static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = { .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data), }; +/* Platform register access for next generation systems families data */ +static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { + { + .label = "cpld1_version", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "cpld2_version", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "cpld3_version", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "reset_long_pb", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(0), + .mode = 0444, + }, + { + .label = "reset_short_pb", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(1), + .mode = 0444, + }, + { + .label = "reset_aux_pwr_or_ref", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(2), + .mode = 0444, + }, + { + .label = "reset_from_comex", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(4), + .mode = 0444, + }, + { + .label = "reset_asic_thermal", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(7), + .mode = 0444, + }, + { + .label = "reset_comex_pwr_fail", + .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(3), + .mode = 0444, + }, + { + .label = "reset_voltmon_upgrade_fail", + .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(0), + .mode = 0444, + }, + { + .label = "reset_system", + .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(1), + .mode = 0444, + }, + { + .label = "psu1_on", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(0), + .mode = 0200, + }, + { + .label = "psu2_on", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(1), + .mode = 0200, + }, + { + .label = "pwr_cycle", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(2), + .mode = 0200, + }, + { + .label = "pwr_down", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(3), + .mode = 0200, + }, + { + .label = "jtag_enable", + .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(4), + .mode = 0644, + }, + { + .label = "asic_health", + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, + .mask = MLXPLAT_CPLD_ASIC_MASK, + .bit = 1, + .mode = 0444, + }, +}; + +static struct mlxreg_core_platform_data mlxplat_default_ng_regs_io_data = { + .data = mlxplat_mlxcpld_default_ng_regs_io_data, + .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_regs_io_data), +}; + /* Platform FAN default */ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { { @@ -1449,6 +1561,7 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) mlxplat_hotplug->deferred_nr = mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_led = &mlxplat_default_ng_led_data; + mlxplat_regs_io = &mlxplat_default_ng_regs_io_data; mlxplat_fan = &mlxplat_default_fan_data; return 1; From 52675da1d087f009b59d2808b1a7363c9ab2c6e7 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 15 Nov 2018 17:26:59 +0000 Subject: [PATCH 40/41] Documentation/ABI: Add new attribute for mlxreg-io sysfs interfaces Add documentation for the new attributes for systems of type MQM87xx, MSN34xx, MSN37xx. It includes the attributes related to ComEx resets, system platform reset, JTAG interface enabling, additional CPLD device. All the above system are equipped with ComEX board, have JTAG selector and extra CPLD. Signed-off-by: Vadim Pasternak [dvhart: Change kernel version from 5.0 to 4.21 until we know for sure] Signed-off-by: Darren Hart (VMware) --- .../ABI/stable/sysfs-driver-mlxreg-io | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/stable/sysfs-driver-mlxreg-io b/Documentation/ABI/stable/sysfs-driver-mlxreg-io index d9d117d457e1..9b642669cb16 100644 --- a/Documentation/ABI/stable/sysfs-driver-mlxreg-io +++ b/Documentation/ABI/stable/sysfs-driver-mlxreg-io @@ -12,7 +12,6 @@ Description: This file shows ASIC health status. The possible values are: What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/ cpld1_version cpld2_version - Date: June 2018 KernelVersion: 4.19 Contact: Vadim Pasternak @@ -21,6 +20,28 @@ Description: These files show with which CPLD versions have been burned The files are read only. +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/ + cpld3_version + +Date: November 2018 +KernelVersion: 4.21 +Contact: Vadim Pasternak +Description: These files show with which CPLD versions have been burned + on LED board. + + The files are read only. + +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/ + jtag_enable + +Date: November 2018 +KernelVersion: 4.21 +Contact: Vadim Pasternak +Description: These files enable and disable the access to the JTAG domain. + By default access to the JTAG domain is disabled. + + The file is read/write. + What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/select_iio Date: June 2018 KernelVersion: 4.19 @@ -76,3 +97,21 @@ Description: These files show the system reset cause, as following: power reset cause. The files are read only. + +What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/ + reset_comex_pwr_fail + reset_from_comex + reset_system + reset_voltmon_upgrade_fail + +Date: November 2018 +KernelVersion: 4.21 +Contact: Vadim Pasternak +Description: These files show the system reset cause, as following: ComEx + power fail, reset from ComEx, system platform reset, reset + due to voltage monitor devices upgrade failure, + Value 1 in file means this is reset cause, 0 - otherwise. + Only one bit could be 1 at the same time, representing only + the last reset cause. + + The files are read only. From fb7255a923115188ac134bb562d1c44f4f3a413b Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 15 Nov 2018 17:27:00 +0000 Subject: [PATCH 41/41] platform/x86: mlx-platform: Convert to use SPDX identifier Reduce size of duplicated comments by switching to use SPDX identifier. Signed-off-by: Vadim Pasternak Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/mlx-platform.c | 33 ++++------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index af085235f87e..df3fcd36776a 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -1,34 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 /* - * Copyright (c) 2016 Mellanox Technologies. All rights reserved. - * Copyright (c) 2016 Vadim Pasternak + * Mellanox platform driver * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * Copyright (C) 2016-2018 Mellanox Technologies + * Copyright (C) 2016-2018 Vadim Pasternak */ #include