[char-misc-next] mei: me: add Alder Lake P device id.

2021-04-13 Thread Tomas Winkler
Add Alder Lake P device ID.

Cc: 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me-regs.h | 1 +
 drivers/misc/mei/pci-me.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 14be76d4c2e6..cb34925e10f1 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -105,6 +105,7 @@
 
 #define MEI_DEV_ID_ADP_S  0x7AE8  /* Alder Lake Point S */
 #define MEI_DEV_ID_ADP_LP 0x7A60  /* Alder Lake Point LP */
+#define MEI_DEV_ID_ADP_P  0x51E0  /* Alder Lake Point P */
 
 /*
  * MEI HW Section
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index a7e179626b63..c3393b383e59 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -111,6 +111,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 
{MEI_PCI_DEVICE(MEI_DEV_ID_ADP_S, MEI_ME_PCH15_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_ADP_LP, MEI_ME_PCH15_CFG)},
+   {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_P, MEI_ME_PCH15_CFG)},
 
/* required last entry */
{0, }
-- 
2.26.3



[PATCH v3] mtd: intel-spi: add is_protected and is_bios_locked knobs

2021-04-11 Thread Tomas Winkler
From: Tamar Mashiah 

The manufacturing access to the PCH/SOC SPI device is traditionally
performed via user space driver accessing registers via /dev/mem
but due to security concerns /dev/mem access is being much restricted,
hence the reason for utilizing dedicated Intel PCH/SOC SPI controller
driver, which is already implemented in the Linux kernel.

Intel PCH/SOC SPI controller protects the flash storage via two
mechanisms one is the via region protection registers and second
via BIOS lock.

The device always boots with bios lock set, but during manufacturing
the bios lock has to be lifted in order to enable the write access.
So we add sysfs file (spi_bios_lock) to be able to do it on demand.
The bios lock is automatically attempted to be lifted by the driver
during initialization, this part is dropped.

Second, also the region protection status is exposed via sysfs file
as the manufacturing will need the both files in order to validate
that the device is properly sealed.

Cc: Joe Perches 
Cc: Mika Westerberg 
Signed-off-by: Tamar Mashiah 
Signed-off-by: Tomas Winkler 
Reviewed-by: Mika Westerberg 
---
V2: Add a newline to the string format in sysfs_emit() (Joe Perches 
)
V3: Resend adding new  MTD SPI-NOR maintainers

 .../ABI/testing/sysfs-devices-intel-spi   | 16 
 MAINTAINERS   |  1 +
 drivers/mfd/lpc_ich.c | 37 ++-
 .../mtd/spi-nor/controllers/intel-spi-pci.c   | 38 ++--
 drivers/mtd/spi-nor/controllers/intel-spi.c   | 96 ---
 include/linux/platform_data/x86/intel-spi.h   |  6 +-
 6 files changed, 167 insertions(+), 27 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-devices-intel-spi

diff --git a/Documentation/ABI/testing/sysfs-devices-intel-spi 
b/Documentation/ABI/testing/sysfs-devices-intel-spi
new file mode 100644
index ..515c36f8b5cf
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-intel-spi
@@ -0,0 +1,16 @@
+What:  /sys/devices/.../is_protected
+Date:  April 2021
+Contact:   Tomas Winkler 
+Description:
+   The /sys/devices/.../is_protected attribute allows the user
+   space to check if the intel spi controller is write protected
+   from the host.
+
+What:  /sys/devices/.../bios_lock
+Date:  April 2021
+Contact:   Tomas Winkler 
+Description:
+   The /sys/devices/.../bios_lock attribute allows the user
+   space to check if the intel spi controller is locked by bios
+   for writes. It is possible to unlock the bios lock by writing
+   "unlock" to the file.
diff --git a/MAINTAINERS b/MAINTAINERS
index ba561e5bc6f0..37c934f34ed7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11571,6 +11571,7 @@ Q:  
http://patchwork.ozlabs.org/project/linux-mtd/list/
 C: irc://irc.oftc.net/mtd
 T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git 
mtd/fixes
 T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
+F: Documentation/ABI/testing/sysfs-devices-intel-spi
 F: Documentation/devicetree/bindings/mtd/
 F: drivers/mtd/
 F: include/linux/mtd/
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 3bbb29a7e7a5..eceaf11bec93 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -1083,12 +1083,39 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
return ret;
 }
 
+static int lcp_ich_bios_unlock(struct device *dev)
+{
+   struct pci_dev *pdev = to_pci_dev(dev);
+   u32 bcr = 0;
+
+   pci_read_config_dword(pdev, BCR, );
+   if (!(bcr & BCR_WPD)) {
+   bcr |= BCR_WPD;
+   pci_write_config_dword(pdev, BCR, bcr);
+   pci_read_config_dword(pdev, BCR, );
+   }
+
+   if (!(bcr & BCR_WPD))
+   return -EIO;
+
+   return 0;
+}
+
+static bool lcp_ich_is_bios_locked(struct device *dev)
+{
+   struct pci_dev *pdev = to_pci_dev(dev);
+   u32 bcr = 0;
+
+   pci_read_config_dword(pdev, BCR, );
+   return !(bcr & BCR_WPD);
+}
+
 static int lpc_ich_init_spi(struct pci_dev *dev)
 {
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
struct resource *res = _spi_res[0];
struct intel_spi_boardinfo *info;
-   u32 spi_base, rcba, bcr;
+   u32 spi_base, rcba;
 
info = devm_kzalloc(>dev, sizeof(*info), GFP_KERNEL);
if (!info)
@@ -1112,8 +1139,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
res->start = spi_base + SPIBASE_LPT;
res->end = res->start + SPIBASE_LPT_SZ - 1;
 
-   pci_read_config_dword(dev, BCR, );
-   info->writeable = !!(bcr & BCR_WPD);
+   info->is_bios_locked = lcp_ich_is_bios_locked;
+   info->bios_unlock = lcp_ich_bios_unlock;
}
  

[PATCH v6] platform/x86: intel_pmc_core: export platform global reset bits via etr3 sysfs file

2021-04-11 Thread Tomas Winkler
From: Tamar Mashiah 

During PCH (platform/board) manufacturing process a global platform
reset has to be induced in order for the configuration changes take
the effect upon following platform reset. This is an internal platform
state and is not intended to be used in the regular platform resets.
The setting is exposed via ETR3 (Extended Test Mode Register 3).
After the manufacturing process is completed the register cannot be
written anymore and is hardware locked.
This setting was commonly done by accessing PMC registers via /dev/mem
but due to security concerns /dev/mem access is much more restricted,
hence the reason for exposing this setting via the dedicated sysfs
interface.
To prevent post manufacturing abuse the register is protected
by hardware locking and the file is set to read-only mode via is_visible
handler.

The register in MMIO space is defined for Cannon Lake and newer PCHs.

Cc: Hans de Goede 
Cc: David E Box 
Reviewed-by: Andy Shevchenko 
Signed-off-by: Tamar Mashiah 
Signed-off-by: Tomas Winkler 
---
V2:
1. Add locking for reading the ET3 register  (Andy)
2. Fix few style issues (Andy)
V3:
1. Resend
v4:
1. Fix return statement (Andy)
2. Specify manufacturing process (Enrico)
V5:
1. Rename sysfs file to etr3 (Hans)
2. Make file read only when register is locked (Hans)
3. Add more info to sysfs ABI documentation
V5:
1. Parentheses around arithmetic in operand of '|' [-Wparentheses] (lkp)
   656 |  return reg & ETR3_CF9LOCK ? attr->mode & SYSFS_PREALLOC | 0444 : 
attr->mode

 .../ABI/testing/sysfs-platform-intel-pmc  |  20 
 MAINTAINERS   |   1 +
 drivers/platform/x86/intel_pmc_core.c | 113 ++
 drivers/platform/x86/intel_pmc_core.h |   6 +
 4 files changed, 140 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-pmc

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-pmc 
b/Documentation/ABI/testing/sysfs-platform-intel-pmc
new file mode 100644
index ..ef199af75ab0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-pmc
@@ -0,0 +1,20 @@
+What:  /sys/devices/platform//etr3
+Date:  Apr 2021
+KernelVersion: 5.13
+Contact:   "Tomas Winkler" 
+Description:
+   The file exposes "Extended Test Mode Register 3" global
+   reset bits. The bits are used during an Intel platform
+   manufacturing process to indicate that consequent reset
+   of the platform is a "global reset". This type of reset
+   is required in order for manufacturing configurations
+   to take effect.
+
+   Display global reset setting bits for PMC.
+   * bit 31 - global reset is locked
+   * bit 20 - global reset is set
+   Writing bit 20 value to the etr3 will induce
+   a platform "global reset" upon consequent platform reset,
+   in case the register is not locked.
+   The "global reset bit" should be locked on a production
+   system and the file is in read-only mode.
diff --git a/MAINTAINERS b/MAINTAINERS
index 7dd6b67f0f51..3e898660b5b4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9145,6 +9145,7 @@ M:Rajneesh Bhardwaj 
 M: David E Box 
 L: platform-driver-...@vger.kernel.org
 S: Maintained
+F: Documentation/ABI/testing/sysfs-platform-intel-pmc
 F: drivers/platform/x86/intel_pmc_core*
 
 INTEL PMIC GPIO DRIVERS
diff --git a/drivers/platform/x86/intel_pmc_core.c 
b/drivers/platform/x86/intel_pmc_core.c
index b5888aeb4bcf..8fb4e6d1d68d 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -401,6 +401,7 @@ static const struct pmc_reg_map cnp_reg_map = {
.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,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_reg_map icl_reg_map = {
@@ -418,6 +419,7 @@ static const struct pmc_reg_map icl_reg_map = {
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_bit_map tgl_clocksource_status_map[] = {
@@ -585,6 +587,7 @@ static const struct pmc_reg_map tgl_reg_map = {
.lpm_sts = tgl_lpm_maps,
.lpm_status_offset = TGL_LPM_STATUS_OFFSET,
.lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
@@ -603,6 +606,115 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct 
pmc_dev *pmcdev, u32 value)
return (u64)value * pmcdev->map->slp_s0_res_counter_step;
 }
 
+static int set_etr3(struct p

[PATCH v5] platform/x86: intel_pmc_core: export platform global reset bits via etr3 sysfs file

2021-04-11 Thread Tomas Winkler
From: Tamar Mashiah 

During PCH (platform/board) manufacturing process a global platform
reset has to be induced in order for the configuration changes take
the effect upon following platform reset. This is an internal platform
state and is not intended to be used in the regular platform resets.
The setting is exposed via ETR3 (Extended Test Mode Register 3).
After the manufacturing process is completed the register cannot be
written anymore and is hardware locked.
This setting was commonly done by accessing PMC registers via /dev/mem
but due to security concerns /dev/mem access is much more restricted,
hence the reason for exposing this setting via the dedicated sysfs
interface.
To prevent post manufacturing abuse the register is protected
by hardware locking and the file is set to read-only mode via is_visible
handler.

The register in MMIO space is defined for Cannon Lake and newer PCHs.

Cc: Hans de Goede 
Cc: David E Box 
Reviewed-by: Andy Shevchenko 
Signed-off-by: Tamar Mashiah 
Signed-off-by: Tomas Winkler 
---

V2:
1. Add locking for reading the ET3 register  (Andy)
2. Fix few style issues (Andy)
V3:
1. Resend
v4:
1. Fix return statement (Andy)
2. Specify manufacturing process (Enrico)
V5:
1. Rename sysfs file to etr3 (Hans)
2. Make file read only when register is locked (Hans)
3. Add more info to sysfs ABI documentation 

 .../ABI/testing/sysfs-platform-intel-pmc  |  20 
 MAINTAINERS   |   1 +
 drivers/platform/x86/intel_pmc_core.c | 113 ++
 drivers/platform/x86/intel_pmc_core.h |   6 +
 4 files changed, 140 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-pmc

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-pmc 
b/Documentation/ABI/testing/sysfs-platform-intel-pmc
new file mode 100644
index ..ef199af75ab0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-pmc
@@ -0,0 +1,20 @@
+What:  /sys/devices/platform//etr3
+Date:  Apr 2021
+KernelVersion: 5.13
+Contact:   "Tomas Winkler" 
+Description:
+   The file exposes "Extended Test Mode Register 3" global
+   reset bits. The bits are used during an Intel platform
+   manufacturing process to indicate that consequent reset
+   of the platform is a "global reset". This type of reset
+   is required in order for manufacturing configurations
+   to take effect.
+
+   Display global reset setting bits for PMC.
+   * bit 31 - global reset is locked
+   * bit 20 - global reset is set
+   Writing bit 20 value to the etr3 will induce
+   a platform "global reset" upon consequent platform reset,
+   in case the register is not locked.
+   The "global reset bit" should be locked on a production
+   system and the file is in read-only mode.
diff --git a/MAINTAINERS b/MAINTAINERS
index 7dd6b67f0f51..3e898660b5b4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9145,6 +9145,7 @@ M:Rajneesh Bhardwaj 
 M: David E Box 
 L: platform-driver-...@vger.kernel.org
 S: Maintained
+F: Documentation/ABI/testing/sysfs-platform-intel-pmc
 F: drivers/platform/x86/intel_pmc_core*
 
 INTEL PMIC GPIO DRIVERS
diff --git a/drivers/platform/x86/intel_pmc_core.c 
b/drivers/platform/x86/intel_pmc_core.c
index b5888aeb4bcf..295c1891a9d5 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -401,6 +401,7 @@ static const struct pmc_reg_map cnp_reg_map = {
.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,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_reg_map icl_reg_map = {
@@ -418,6 +419,7 @@ static const struct pmc_reg_map icl_reg_map = {
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_bit_map tgl_clocksource_status_map[] = {
@@ -585,6 +587,7 @@ static const struct pmc_reg_map tgl_reg_map = {
.lpm_sts = tgl_lpm_maps,
.lpm_status_offset = TGL_LPM_STATUS_OFFSET,
.lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
@@ -603,6 +606,115 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct 
pmc_dev *pmcdev, u32 value)
return (u64)value * pmcdev->map->slp_s0_res_counter_step;
 }
 
+static int set_etr3(struct pmc_dev *pmcdev)
+{
+   const struct pmc_reg_map *map = pmcdev->map;
+   u32 reg;
+   int err;
+
+   if (!map->etr3_offset)
+   return -EOPN

[PATCH v4] platform/x86: intel_pmc_core: export platform global_reset via sysfs.

2021-04-02 Thread Tomas Winkler
From: Tamar Mashiah 

During PCH (platform/board) manufacturing process a global reset
has to be induced in order for configuration changes take the effect
upon following platform reset.
This setting was commonly done by accessing PMC registers via /dev/mem
but due to security concern /dev/mem access is much restricted, hence
the reason for exposing this setting via dedicated sysfs interface.
To prevent post manufacturing abuse the register is protected
by hardware locking.

The register in MMIO space is defined for Cannon Lake and newer PCHs.

Cc: David E Box 
Reviewed-by: Andy Shevchenko 
Signed-off-by: Tamar Mashiah 
Signed-off-by: Tomas Winkler 
---
2:
1. Add locking for reading the ET3 register  (Andy)
2. Fix few style issues (Andy)
V3:
1. Resend
v4:
1. Fix return statement (Andy) 
2. Specify manufacturing process (Enrico)

 .../ABI/testing/sysfs-platform-intel-pmc  | 11 +++
 MAINTAINERS   |  1 +
 drivers/platform/x86/intel_pmc_core.c | 97 +++
 drivers/platform/x86/intel_pmc_core.h |  6 ++
 4 files changed, 115 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-pmc

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-pmc 
b/Documentation/ABI/testing/sysfs-platform-intel-pmc
new file mode 100644
index ..7ce00e77fbcd
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-pmc
@@ -0,0 +1,11 @@
+What:  /sys/devices/platform//global_reset
+Date:  Apr 2021
+KernelVersion: 5.13
+Contact:   "Tomas Winkler" 
+Description:
+   Display global reset setting bits for PMC.
+   * bit 31 - global reset is locked
+   * bit 20 - global reset is set
+   Writing bit 20 value to the global_reset will induce
+   a platform global reset upon consequent platform reset.
+   in case the register is not locked.
diff --git a/MAINTAINERS b/MAINTAINERS
index 04f68e0cda64..618676eba8c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9166,6 +9166,7 @@ M:Rajneesh Bhardwaj 
 M: David E Box 
 L: platform-driver-...@vger.kernel.org
 S: Maintained
+F: Documentation/ABI/testing/sysfs-platform-intel-pmc
 F: drivers/platform/x86/intel_pmc_core*
 
 INTEL PMIC GPIO DRIVERS
diff --git a/drivers/platform/x86/intel_pmc_core.c 
b/drivers/platform/x86/intel_pmc_core.c
index ee2f757515b0..8afc198550a4 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -401,6 +401,7 @@ static const struct pmc_reg_map cnp_reg_map = {
.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,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_reg_map icl_reg_map = {
@@ -418,6 +419,7 @@ static const struct pmc_reg_map icl_reg_map = {
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_bit_map tgl_clocksource_status_map[] = {
@@ -585,6 +587,7 @@ static const struct pmc_reg_map tgl_reg_map = {
.lpm_sts = tgl_lpm_maps,
.lpm_status_offset = TGL_LPM_STATUS_OFFSET,
.lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
@@ -603,6 +606,99 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct 
pmc_dev *pmcdev, u32 value)
return (u64)value * pmcdev->map->slp_s0_res_counter_step;
 }
 
+static int set_global_reset(struct pmc_dev *pmcdev)
+{
+   const struct pmc_reg_map *map = pmcdev->map;
+   u32 reg;
+   int err;
+
+   if (!map->etr3_offset)
+   return -EOPNOTSUPP;
+
+   mutex_lock(>lock);
+
+   /* check if CF9 is locked */
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   if (reg & ETR3_CF9LOCK) {
+   err = -EACCES;
+   goto out_unlock;
+   }
+
+   /* write CF9 global reset bit */
+   reg |= ETR3_CF9GR;
+   pmc_core_reg_write(pmcdev, map->etr3_offset, reg);
+
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   if (!(reg & ETR3_CF9GR)) {
+   err = -EIO;
+   goto out_unlock;
+   }
+
+   err = 0;
+
+out_unlock:
+   mutex_unlock(>lock);
+   return err;
+}
+
+static ssize_t global_reset_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct pmc_dev *pmcdev = dev_get_drvdata(dev);
+   const struct pmc_reg_map *map = pmcdev->map;
+   u32 reg;
+
+   if (!map->etr3_offset)
+   return -EOPNOTSUPP;
+
+   mutex_lock(>lock);
+
+   reg = pmc_core_reg_read(pmcdev, map-&

[PATCH v3] platform/x86: intel_pmc_core: export platform global_reset via sysfs.

2021-04-02 Thread Tomas Winkler
From: Tamar Mashiah 

During PCH manufacturing a global reset has to be induced in order
for configuration changes take affect upon following platform reset.
This setting was commonly done by accessing PMC registers via /dev/mem
but due to security concern /dev/mem access is much restricted, hence
the reason for exposing this setting via dedicated sysfs interface.
To prevent post manufacturing abuse the register is protected
by hardware locking.

The register in MMIO space is defined for Cannon Lake and newer PCHs.

Cc: David E Box 
Reviewed-by: Andy Shevchenko 
Signed-off-by: Tamar Mashiah 
Signed-off-by: Tomas Winkler 
---
V2:
1. Add locking for reading the ET3 register  (Andy)
2. Fix few style issues (Andy)
V3:
1. Resend

 .../ABI/testing/sysfs-platform-intel-pmc  | 11 +++
 MAINTAINERS   |  1 +
 drivers/platform/x86/intel_pmc_core.c | 97 +++
 drivers/platform/x86/intel_pmc_core.h |  6 ++
 4 files changed, 115 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-pmc

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-pmc 
b/Documentation/ABI/testing/sysfs-platform-intel-pmc
new file mode 100644
index ..7ce00e77fbcd
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-pmc
@@ -0,0 +1,11 @@
+What:  /sys/devices/platform//global_reset
+Date:  Apr 2021
+KernelVersion: 5.13
+Contact:   "Tomas Winkler" 
+Description:
+   Display global reset setting bits for PMC.
+   * bit 31 - global reset is locked
+   * bit 20 - global reset is set
+   Writing bit 20 value to the global_reset will induce
+   a platform global reset upon consequent platform reset.
+   in case the register is not locked.
diff --git a/MAINTAINERS b/MAINTAINERS
index 04f68e0cda64..618676eba8c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9166,6 +9166,7 @@ M:Rajneesh Bhardwaj 
 M: David E Box 
 L: platform-driver-...@vger.kernel.org
 S: Maintained
+F: Documentation/ABI/testing/sysfs-platform-intel-pmc
 F: drivers/platform/x86/intel_pmc_core*
 
 INTEL PMIC GPIO DRIVERS
diff --git a/drivers/platform/x86/intel_pmc_core.c 
b/drivers/platform/x86/intel_pmc_core.c
index ee2f757515b0..951664133303 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -401,6 +401,7 @@ static const struct pmc_reg_map cnp_reg_map = {
.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,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_reg_map icl_reg_map = {
@@ -418,6 +419,7 @@ static const struct pmc_reg_map icl_reg_map = {
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_bit_map tgl_clocksource_status_map[] = {
@@ -585,6 +587,7 @@ static const struct pmc_reg_map tgl_reg_map = {
.lpm_sts = tgl_lpm_maps,
.lpm_status_offset = TGL_LPM_STATUS_OFFSET,
.lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
@@ -603,6 +606,99 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct 
pmc_dev *pmcdev, u32 value)
return (u64)value * pmcdev->map->slp_s0_res_counter_step;
 }
 
+static int set_global_reset(struct pmc_dev *pmcdev)
+{
+   const struct pmc_reg_map *map = pmcdev->map;
+   u32 reg;
+   int err;
+
+   if (!map->etr3_offset)
+   err = -EOPNOTSUPP;
+
+   mutex_lock(>lock);
+
+   /* check if CF9 is locked */
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   if (reg & ETR3_CF9LOCK) {
+   err = -EACCES;
+   goto out_unlock;
+   }
+
+   /* write CF9 global reset bit */
+   reg |= ETR3_CF9GR;
+   pmc_core_reg_write(pmcdev, map->etr3_offset, reg);
+
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   if (!(reg & ETR3_CF9GR)) {
+   err = -EIO;
+   goto out_unlock;
+   }
+
+   err = 0;
+
+out_unlock:
+   mutex_unlock(>lock);
+   return err;
+}
+
+static ssize_t global_reset_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct pmc_dev *pmcdev = dev_get_drvdata(dev);
+   const struct pmc_reg_map *map = pmcdev->map;
+   u32 reg;
+
+   if (!map->etr3_offset)
+   return -EOPNOTSUPP;
+
+   mutex_lock(>lock);
+
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   reg &= ETR3_CF9GR | ETR3_CF9LOCK;
+
+   mutex_unlock(>lock);
+
+  

[PATCH v2] platform/x86: intel_pmc_core: export platform global_reset via sysfs.

2021-04-02 Thread Tomas Winkler
From: Tamar Mashiah 

During PCH manufacturing a global reset has to be induced in order
for configuration changes take affect upon following platform reset.
This setting was commonly done by accessing PMC registers via /dev/mem
but due to security concern /dev/mem access is much restricted, hence
the reason for exposing this setting via dedicated sysfs interface.
To prevent post manufacturing abuse the register is protected
by hardware locking.

The register in MMIO space is defined for Cannon Lake and newer PCHs.

Cc: David E Box 
Reviewed-by: Andy Shevchenko 
Signed-off-by: Tamar Mashiah 
Signed-off-by: Tomas Winkler 
---
V2: 
1. Add locking for reading the ET3 register  (Andy)
2. Fix few style issues (Andy)

 .../ABI/testing/sysfs-platform-intel-pmc  | 11 +++
 MAINTAINERS   |  1 +
 drivers/platform/x86/intel_pmc_core.c | 95 +++
 drivers/platform/x86/intel_pmc_core.h |  6 ++
 4 files changed, 113 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-pmc

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-pmc 
b/Documentation/ABI/testing/sysfs-platform-intel-pmc
new file mode 100644
index ..7ce00e77fbcd
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-pmc
@@ -0,0 +1,11 @@
+What:  /sys/devices/platform//global_reset
+Date:  Apr 2021
+KernelVersion: 5.13
+Contact:   "Tomas Winkler" 
+Description:
+   Display global reset setting bits for PMC.
+   * bit 31 - global reset is locked
+   * bit 20 - global reset is set
+   Writing bit 20 value to the global_reset will induce
+   a platform global reset upon consequent platform reset.
+   in case the register is not locked.
diff --git a/MAINTAINERS b/MAINTAINERS
index 04f68e0cda64..618676eba8c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9166,6 +9166,7 @@ M:Rajneesh Bhardwaj 
 M: David E Box 
 L: platform-driver-...@vger.kernel.org
 S: Maintained
+F: Documentation/ABI/testing/sysfs-platform-intel-pmc
 F: drivers/platform/x86/intel_pmc_core*
 
 INTEL PMIC GPIO DRIVERS
diff --git a/drivers/platform/x86/intel_pmc_core.c 
b/drivers/platform/x86/intel_pmc_core.c
index ee2f757515b0..9f252d5f7ac5 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -401,6 +401,7 @@ static const struct pmc_reg_map cnp_reg_map = {
.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,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_reg_map icl_reg_map = {
@@ -418,6 +419,7 @@ static const struct pmc_reg_map icl_reg_map = {
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_bit_map tgl_clocksource_status_map[] = {
@@ -585,6 +587,7 @@ static const struct pmc_reg_map tgl_reg_map = {
.lpm_sts = tgl_lpm_maps,
.lpm_status_offset = TGL_LPM_STATUS_OFFSET,
.lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
@@ -603,6 +606,97 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct 
pmc_dev *pmcdev, u32 value)
return (u64)value * pmcdev->map->slp_s0_res_counter_step;
 }
 
+static int set_global_reset(struct pmc_dev *pmcdev)
+{
+   const struct pmc_reg_map *map = pmcdev->map;
+   u32 reg;
+   int err;
+
+   mutex_lock(>lock);
+
+   if (!map->etr3_offset) {
+   err = -EOPNOTSUPP;
+   goto out_unlock;
+   }
+
+   /* check if CF9 is locked */
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   if (reg & ETR3_CF9LOCK) {
+   err = -EACCES;
+   goto out_unlock;
+   }
+
+   /* write CF9 global reset bit */
+   reg |= ETR3_CF9GR;
+   pmc_core_reg_write(pmcdev, map->etr3_offset, reg);
+
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   if ((reg & ETR3_CF9GR) == 0) {
+   err = -EIO;
+   goto out_unlock;
+   }
+
+   err = 0;
+
+out_unlock:
+   mutex_unlock(>lock);
+   return err;
+}
+
+static ssize_t global_reset_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct pmc_dev *pmcdev = dev_get_drvdata(dev);
+   const struct pmc_reg_map *map = pmcdev->map;
+   u32 reg;
+
+   if (!map->etr3_offset)
+   return -EOPNOTSUPP;
+
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   reg &= ETR3_CF9GR | ETR3_CF9LOCK;
+
+   return sysfs_emit(buf, &quo

[PATCH] platform/x86: intel_pmc_core: export platform global_reset via sysfs.

2021-04-01 Thread Tomas Winkler
From: Tamar Mashiah 

During PCH manufacturing a global reset has to be induced in order
for configuration changes take affect upon following platform reset.
This setting was commonly done by accessing PMC registers via /dev/mem
but due to security concern /dev/mem access is much restricted, hence
the reason for exposing this setting via dedicated sysfs interface.
To prevent post manufacturing abuse the register is protected
by hardware locking.

The register in MMIO space is defined for Cannon Lake and newer PCHs.

Cc: David E Box 
Reviewed-by: Andy Shevchenko 
Signed-off-by: Tamar Mashiah 
Signed-off-by: Tomas Winkler 
---
 .../ABI/testing/sysfs-platform-intel-pmc  | 11 +++
 MAINTAINERS   |  1 +
 drivers/platform/x86/intel_pmc_core.c | 95 +++
 drivers/platform/x86/intel_pmc_core.h |  6 ++
 4 files changed, 113 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-pmc

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-pmc 
b/Documentation/ABI/testing/sysfs-platform-intel-pmc
new file mode 100644
index ..7ce00e77fbcd
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-pmc
@@ -0,0 +1,11 @@
+What:  /sys/devices/platform//global_reset
+Date:  Apr 2021
+KernelVersion: 5.13
+Contact:   "Tomas Winkler" 
+Description:
+   Display global reset setting bits for PMC.
+   * bit 31 - global reset is locked
+   * bit 20 - global reset is set
+   Writing bit 20 value to the global_reset will induce
+   a platform global reset upon consequent platform reset.
+   in case the register is not locked.
diff --git a/MAINTAINERS b/MAINTAINERS
index 04f68e0cda64..618676eba8c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9166,6 +9166,7 @@ M:Rajneesh Bhardwaj 
 M: David E Box 
 L: platform-driver-...@vger.kernel.org
 S: Maintained
+F: Documentation/ABI/testing/sysfs-platform-intel-pmc
 F: drivers/platform/x86/intel_pmc_core*
 
 INTEL PMIC GPIO DRIVERS
diff --git a/drivers/platform/x86/intel_pmc_core.c 
b/drivers/platform/x86/intel_pmc_core.c
index ee2f757515b0..9f252d5f7ac5 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -401,6 +401,7 @@ static const struct pmc_reg_map cnp_reg_map = {
.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,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_reg_map icl_reg_map = {
@@ -418,6 +419,7 @@ static const struct pmc_reg_map icl_reg_map = {
.pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET,
.pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT,
.ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static const struct pmc_bit_map tgl_clocksource_status_map[] = {
@@ -585,6 +587,7 @@ static const struct pmc_reg_map tgl_reg_map = {
.lpm_sts = tgl_lpm_maps,
.lpm_status_offset = TGL_LPM_STATUS_OFFSET,
.lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET,
+   .etr3_offset = ETR3_OFFSET,
 };
 
 static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset)
@@ -603,6 +606,97 @@ static inline u64 pmc_core_adjust_slp_s0_step(struct 
pmc_dev *pmcdev, u32 value)
return (u64)value * pmcdev->map->slp_s0_res_counter_step;
 }
 
+static int set_global_reset(struct pmc_dev *pmcdev)
+{
+   const struct pmc_reg_map *map = pmcdev->map;
+   u32 reg;
+   int err;
+
+   mutex_lock(>lock);
+
+   if (!map->etr3_offset) {
+   err = -EOPNOTSUPP;
+   goto out_unlock;
+   }
+
+   /* check if CF9 is locked */
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   if (reg & ETR3_CF9LOCK) {
+   err = -EACCES;
+   goto out_unlock;
+   }
+
+   /* write CF9 global reset bit */
+   reg |= ETR3_CF9GR;
+   pmc_core_reg_write(pmcdev, map->etr3_offset, reg);
+
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   if ((reg & ETR3_CF9GR) == 0) {
+   err = -EIO;
+   goto out_unlock;
+   }
+
+   err = 0;
+
+out_unlock:
+   mutex_unlock(>lock);
+   return err;
+}
+
+static ssize_t global_reset_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct pmc_dev *pmcdev = dev_get_drvdata(dev);
+   const struct pmc_reg_map *map = pmcdev->map;
+   u32 reg;
+
+   if (!map->etr3_offset)
+   return -EOPNOTSUPP;
+
+   reg = pmc_core_reg_read(pmcdev, map->etr3_offset);
+   reg &= ETR3_CF9GR | ETR3_CF9LOCK;
+
+   return sysfs_emit(buf, "0x%08x", reg);
+}
+
+static ssize_t global_reset_store(struct device *

[PATCH v2] mtd: intel-spi: add is_protected and is_bios_locked knobs

2021-03-31 Thread Tomas Winkler
From: Tamar Mashiah 

The manufacturing access to the PCH/SOC SPI device is traditionally
performed via user space driver accessing registers via /dev/mem
but due to security concerns /dev/mem access is being much restricted,
hence the reason for utilizing dedicated Intel PCH/SOC SPI controller
driver, which is already implemented in the Linux kernel.

Intel PCH/SOC SPI controller protects the flash storage via two
mechanisms one is the via region protection registers and second
via BIOS lock.

The device always boots with bios lock set, but during manufacturing
the bios lock has to be lifted in order to enable the write access.
So we add sysfs file (spi_bios_lock) to be able to do it on demand.
The bios lock is automatically attempted to be lifted by the driver
during initialization, this part is dropped.

Second, also the region protection status is exposed via sysfs file
as the manufacturing will need the both files in order to validate
that the device is properly sealed.

Cc: Joe Perches 
Cc: Mika Westerberg 
Signed-off-by: Tamar Mashiah 
Signed-off-by: Tomas Winkler 
Reviewed-by: Mika Westerberg 
---
V2: Add a newline to the string format in sysfs_emit() (Joe Perches 
)

 .../ABI/testing/sysfs-devices-intel-spi   | 16 
 MAINTAINERS   |  1 +
 drivers/mfd/lpc_ich.c | 37 ++-
 .../mtd/spi-nor/controllers/intel-spi-pci.c   | 38 ++--
 drivers/mtd/spi-nor/controllers/intel-spi.c   | 96 ---
 include/linux/platform_data/x86/intel-spi.h   |  6 +-
 6 files changed, 167 insertions(+), 27 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-devices-intel-spi

diff --git a/Documentation/ABI/testing/sysfs-devices-intel-spi 
b/Documentation/ABI/testing/sysfs-devices-intel-spi
new file mode 100644
index ..515c36f8b5cf
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-intel-spi
@@ -0,0 +1,16 @@
+What:  /sys/devices/.../is_protected
+Date:  April 2021
+Contact:   Tomas Winkler 
+Description:
+   The /sys/devices/.../is_protected attribute allows the user
+   space to check if the intel spi controller is write protected
+   from the host.
+
+What:  /sys/devices/.../bios_lock
+Date:  April 2021
+Contact:   Tomas Winkler 
+Description:
+   The /sys/devices/.../bios_lock attribute allows the user
+   space to check if the intel spi controller is locked by bios
+   for writes. It is possible to unlock the bios lock by writing
+   "unlock" to the file.
diff --git a/MAINTAINERS b/MAINTAINERS
index ba561e5bc6f0..37c934f34ed7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11571,6 +11571,7 @@ Q:  
http://patchwork.ozlabs.org/project/linux-mtd/list/
 C: irc://irc.oftc.net/mtd
 T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git 
mtd/fixes
 T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
+F: Documentation/ABI/testing/sysfs-devices-intel-spi
 F: Documentation/devicetree/bindings/mtd/
 F: drivers/mtd/
 F: include/linux/mtd/
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 3bbb29a7e7a5..eceaf11bec93 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -1083,12 +1083,39 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
return ret;
 }
 
+static int lcp_ich_bios_unlock(struct device *dev)
+{
+   struct pci_dev *pdev = to_pci_dev(dev);
+   u32 bcr = 0;
+
+   pci_read_config_dword(pdev, BCR, );
+   if (!(bcr & BCR_WPD)) {
+   bcr |= BCR_WPD;
+   pci_write_config_dword(pdev, BCR, bcr);
+   pci_read_config_dword(pdev, BCR, );
+   }
+
+   if (!(bcr & BCR_WPD))
+   return -EIO;
+
+   return 0;
+}
+
+static bool lcp_ich_is_bios_locked(struct device *dev)
+{
+   struct pci_dev *pdev = to_pci_dev(dev);
+   u32 bcr = 0;
+
+   pci_read_config_dword(pdev, BCR, );
+   return !(bcr & BCR_WPD);
+}
+
 static int lpc_ich_init_spi(struct pci_dev *dev)
 {
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
struct resource *res = _spi_res[0];
struct intel_spi_boardinfo *info;
-   u32 spi_base, rcba, bcr;
+   u32 spi_base, rcba;
 
info = devm_kzalloc(>dev, sizeof(*info), GFP_KERNEL);
if (!info)
@@ -1112,8 +1139,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
res->start = spi_base + SPIBASE_LPT;
res->end = res->start + SPIBASE_LPT_SZ - 1;
 
-   pci_read_config_dword(dev, BCR, );
-   info->writeable = !!(bcr & BCR_WPD);
+   info->is_bios_locked = lcp_ich_is_bios_locked;
+   info->bios_unlock = lcp_ich_bios_unlock;
}
break;
 
@@ -1134,8 +1161,8 @@ 

[PATCH] mtd: intel-spi: add is_protected and is_bios_locked knobs

2021-03-30 Thread Tomas Winkler
From: Tamar Mashiah 

The manufacturing access to the PCH/SOC SPI device is traditionally
performed via user space driver accessing registers via /dev/mem
but due to security concerns /dev/mem access is being much restricted,
hence the reason for utilizing dedicated Intel PCH/SOC SPI controller
driver, which is already implemented in the Linux kernel.

Intel PCH/SOC SPI controller protects the flash storage via two
mechanisms one is the via region protection registers and second
via BIOS lock.

The device always boots with bios lock set, but during manufacturing
the bios lock has to be lifted in order to enable the write access.
So we add sysfs file (spi_bios_lock) to be able to do it on demand.
The bios lock is automatically attempted to be lifted by the driver
during initialization, this part is dropped.

Second, also the region protection status is exposed via sysfs file
as the manufacturing will need the both files in order to validate
that the device is properly sealed.

Cc: Mika Westerberg 
Signed-off-by: Tamar Mashiah 
Signed-off-by: Tomas Winkler 
Reviewed-by: Mika Westerberg 
---
 .../ABI/testing/sysfs-devices-intel-spi   | 16 
 MAINTAINERS   |  1 +
 drivers/mfd/lpc_ich.c | 37 ++-
 .../mtd/spi-nor/controllers/intel-spi-pci.c   | 38 ++--
 drivers/mtd/spi-nor/controllers/intel-spi.c   | 96 ---
 include/linux/platform_data/x86/intel-spi.h   |  6 +-
 6 files changed, 167 insertions(+), 27 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-devices-intel-spi

diff --git a/Documentation/ABI/testing/sysfs-devices-intel-spi 
b/Documentation/ABI/testing/sysfs-devices-intel-spi
new file mode 100644
index ..515c36f8b5cf
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-intel-spi
@@ -0,0 +1,16 @@
+What:  /sys/devices/.../is_protected
+Date:  April 2021
+Contact:   Tomas Winkler 
+Description:
+   The /sys/devices/.../is_protected attribute allows the user
+   space to check if the intel spi controller is write protected
+   from the host.
+
+What:  /sys/devices/.../bios_lock
+Date:  April 2021
+Contact:   Tomas Winkler 
+Description:
+   The /sys/devices/.../bios_lock attribute allows the user
+   space to check if the intel spi controller is locked by bios
+   for writes. It is possible to unlock the bios lock by writing
+   "unlock" to the file.
diff --git a/MAINTAINERS b/MAINTAINERS
index ba561e5bc6f0..37c934f34ed7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11571,6 +11571,7 @@ Q:  
http://patchwork.ozlabs.org/project/linux-mtd/list/
 C: irc://irc.oftc.net/mtd
 T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git 
mtd/fixes
 T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
+F: Documentation/ABI/testing/sysfs-devices-intel-spi
 F: Documentation/devicetree/bindings/mtd/
 F: drivers/mtd/
 F: include/linux/mtd/
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 3bbb29a7e7a5..eceaf11bec93 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -1083,12 +1083,39 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
return ret;
 }
 
+static int lcp_ich_bios_unlock(struct device *dev)
+{
+   struct pci_dev *pdev = to_pci_dev(dev);
+   u32 bcr = 0;
+
+   pci_read_config_dword(pdev, BCR, );
+   if (!(bcr & BCR_WPD)) {
+   bcr |= BCR_WPD;
+   pci_write_config_dword(pdev, BCR, bcr);
+   pci_read_config_dword(pdev, BCR, );
+   }
+
+   if (!(bcr & BCR_WPD))
+   return -EIO;
+
+   return 0;
+}
+
+static bool lcp_ich_is_bios_locked(struct device *dev)
+{
+   struct pci_dev *pdev = to_pci_dev(dev);
+   u32 bcr = 0;
+
+   pci_read_config_dword(pdev, BCR, );
+   return !(bcr & BCR_WPD);
+}
+
 static int lpc_ich_init_spi(struct pci_dev *dev)
 {
struct lpc_ich_priv *priv = pci_get_drvdata(dev);
struct resource *res = _spi_res[0];
struct intel_spi_boardinfo *info;
-   u32 spi_base, rcba, bcr;
+   u32 spi_base, rcba;
 
info = devm_kzalloc(>dev, sizeof(*info), GFP_KERNEL);
if (!info)
@@ -1112,8 +1139,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
res->start = spi_base + SPIBASE_LPT;
res->end = res->start + SPIBASE_LPT_SZ - 1;
 
-   pci_read_config_dword(dev, BCR, );
-   info->writeable = !!(bcr & BCR_WPD);
+   info->is_bios_locked = lcp_ich_is_bios_locked;
+   info->bios_unlock = lcp_ich_bios_unlock;
}
break;
 
@@ -1134,8 +1161,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
res->start = spi_base &a

[char-misc-next] mei: allow map and unmap of client dma buffer only for disconnected client

2021-03-18 Thread Tomas Winkler
Allow map and unmap of the client dma buffer only when the client is not
connected. The functions return -EPROTO if the client is already connected.
This is to fix the race when traffic may start or stop when buffer
is not available.

Cc:  #v5.11+
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/client.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 4378a9b25848..2cc370adb238 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -2286,8 +2286,8 @@ int mei_cl_dma_alloc_and_map(struct mei_cl *cl, const 
struct file *fp,
if (buffer_id == 0)
return -EINVAL;
 
-   if (!mei_cl_is_connected(cl))
-   return -ENODEV;
+   if (mei_cl_is_connected(cl))
+   return -EPROTO;
 
if (cl->dma_mapped)
return -EPROTO;
@@ -2327,9 +2327,7 @@ int mei_cl_dma_alloc_and_map(struct mei_cl *cl, const 
struct file *fp,
 
mutex_unlock(>device_lock);
wait_event_timeout(cl->wait,
-  cl->dma_mapped ||
-  cl->status ||
-  !mei_cl_is_connected(cl),
+  cl->dma_mapped || cl->status,
   mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
mutex_lock(>device_lock);
 
@@ -2376,8 +2374,9 @@ int mei_cl_dma_unmap(struct mei_cl *cl, const struct file 
*fp)
return -EOPNOTSUPP;
}
 
-   if (!mei_cl_is_connected(cl))
-   return -ENODEV;
+   /* do not allow unmap for connected client */
+   if (mei_cl_is_connected(cl))
+   return -EPROTO;
 
if (!cl->dma_mapped)
return -EPROTO;
@@ -2405,9 +2404,7 @@ int mei_cl_dma_unmap(struct mei_cl *cl, const struct file 
*fp)
 
mutex_unlock(>device_lock);
wait_event_timeout(cl->wait,
-  !cl->dma_mapped ||
-  cl->status ||
-  !mei_cl_is_connected(cl),
+  !cl->dma_mapped || cl->status,
   mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
mutex_lock(>device_lock);
 
-- 
2.26.3



[PATCH] mtd: mtdcore: constify name param in mtd_bdi_init

2021-02-25 Thread Tomas Winkler
The bdi name is not modified by the function, it should be const.

Signed-off-by: Tomas Winkler 
---
 drivers/mtd/mtdcore.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index db5167eacaa4..80fb69453ebe 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -2177,7 +2177,7 @@ static int mtd_proc_show(struct seq_file *m, void *v)
 /**/
 /* Init code */
 
-static struct backing_dev_info * __init mtd_bdi_init(char *name)
+static struct backing_dev_info * __init mtd_bdi_init(const char *name)
 {
struct backing_dev_info *bdi;
int ret;
-- 
2.26.2



[char-misc-next 2/2] mei: use sysfs_emit() in tx_queue_limit_show sysfs

2021-02-08 Thread Tomas Winkler
Using of snprintf is discouraged in sysfs use the new sysfs_emit() API.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 9f6682033ed7..28937b6e7e0c 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -1026,7 +1026,7 @@ static ssize_t tx_queue_limit_show(struct device *device,
size = dev->tx_queue_limit;
mutex_unlock(>device_lock);
 
-   return snprintf(buf, PAGE_SIZE, "%u\n", size);
+   return sysfs_emit(buf, "%u\n", size);
 }
 
 static ssize_t tx_queue_limit_store(struct device *device,
-- 
2.26.2



[char-misc-next 1/2] mei: bus: block send with vtag on non-conformat FW

2021-02-08 Thread Tomas Winkler
From: Alexander Usyskin 

Block data send with vtag if either transport layer or
FW client are not supporting vtags.

Cc:  # v5.10+
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 34fb5e541fe5..be99bb0a16cf 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -61,6 +61,13 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t 
length, u8 vtag,
goto out;
}
 
+   if (vtag) {
+   /* Check if vtag is supported by client */
+   rets = mei_cl_vt_support_check(cl);
+   if (rets)
+   goto out;
+   }
+
if (length > mei_cl_mtu(cl)) {
rets = -EFBIG;
goto out;
-- 
2.26.2



[char-misc-next 6/6] mei: bus: add client dma interface

2021-02-06 Thread Tomas Winkler
From: Alexander Usyskin 

Expose the client dma mapping via mei client
bus interface.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c | 46 ++
 drivers/misc/mei/hw.h  |  5 +
 include/linux/mei_cl_bus.h |  3 +++
 3 files changed, 54 insertions(+)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 34fb5e541fe5..d430710a5fe5 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -636,6 +636,52 @@ static void mei_cl_bus_vtag_free(struct mei_cl_device 
*cldev)
kfree(cl_vtag);
 }
 
+void *mei_cldev_dma_map(struct mei_cl_device *cldev, u8 buffer_id, size_t size)
+{
+   struct mei_device *bus;
+   struct mei_cl *cl;
+   int ret;
+
+   if (!cldev || !buffer_id || !size)
+   return ERR_PTR(-EINVAL);
+
+   if (!IS_ALIGNED(size, MEI_FW_PAGE_SIZE)) {
+   dev_err(>dev, "Map size should be aligned to %lu\n",
+   MEI_FW_PAGE_SIZE);
+   return ERR_PTR(-EINVAL);
+   }
+
+   cl = cldev->cl;
+   bus = cldev->bus;
+
+   mutex_lock(>device_lock);
+   ret = mei_cl_dma_alloc_and_map(cl, NULL, buffer_id, size);
+   mutex_unlock(>device_lock);
+   if (ret)
+   return ERR_PTR(ret);
+   return cl->dma.vaddr;
+}
+EXPORT_SYMBOL_GPL(mei_cldev_dma_map);
+
+int mei_cldev_dma_unmap(struct mei_cl_device *cldev)
+{
+   struct mei_device *bus;
+   struct mei_cl *cl;
+   int ret;
+
+   if (!cldev)
+   return -EINVAL;
+
+   cl = cldev->cl;
+   bus = cldev->bus;
+
+   mutex_lock(>device_lock);
+   ret = mei_cl_dma_unmap(cl, NULL);
+   mutex_unlock(>device_lock);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(mei_cldev_dma_unmap);
+
 /**
  * mei_cldev_enable - enable me client device
  * create connection with me client
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index b10606550613..bc240b88abf1 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -22,6 +22,11 @@
 #define MEI_D0I3_TIMEOUT5  /* D0i3 set/unset max response time */
 #define MEI_HBM_TIMEOUT 1  /* 1 second */
 
+/*
+ * FW page size for DMA allocations
+ */
+#define MEI_FW_PAGE_SIZE 4096UL
+
 /*
  * MEI Version
  */
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
index 959ad7d850b4..53801eacfaef 100644
--- a/include/linux/mei_cl_bus.h
+++ b/include/linux/mei_cl_bus.h
@@ -116,4 +116,7 @@ int mei_cldev_enable(struct mei_cl_device *cldev);
 int mei_cldev_disable(struct mei_cl_device *cldev);
 bool mei_cldev_enabled(struct mei_cl_device *cldev);
 
+void *mei_cldev_dma_map(struct mei_cl_device *cldev, u8 buffer_id, size_t 
size);
+int mei_cldev_dma_unmap(struct mei_cl_device *cldev);
+
 #endif /* _LINUX_MEI_CL_BUS_H */
-- 
2.26.2



[char-misc-next 3/6] mei: add support for client dma capability

2021-02-06 Thread Tomas Winkler
From: Alexander Usyskin 

Client DMA capability indicates whether the firmware supports setting up
a direct DMA channel between the host and me client.
The DMA capabilities are supported from firmware HBM version 2.2
and newer.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/debugfs.c |  1 +
 drivers/misc/mei/hbm.c | 13 -
 drivers/misc/mei/hw.h  |  8 
 drivers/misc/mei/mei_dev.h |  2 ++
 4 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index 3ab1a431d810..1ce61e9e24fc 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -106,6 +106,7 @@ static int mei_dbgfs_devstate_show(struct seq_file *m, void 
*unused)
seq_printf(m, "\tDR: %01d\n", dev->hbm_f_dr_supported);
seq_printf(m, "\tVT: %01d\n", dev->hbm_f_vt_supported);
seq_printf(m, "\tCAP: %01d\n", dev->hbm_f_cap_supported);
+   seq_printf(m, "\tCD: %01d\n", dev->hbm_f_cd_supported);
}
 
seq_printf(m, "pg:  %s, %s\n",
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index df0f62de3dca..6e748da7e55d 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -339,7 +339,9 @@ static int mei_hbm_capabilities_req(struct mei_device *dev)
memset(, 0, sizeof(req));
req.hbm_cmd = MEI_HBM_CAPABILITIES_REQ_CMD;
if (dev->hbm_f_vt_supported)
-   req.capability_requested[0] = HBM_CAP_VT;
+   req.capability_requested[0] |= HBM_CAP_VT;
+   if (dev->hbm_f_cd_supported)
+   req.capability_requested[0] |= HBM_CAP_CD;
 
ret = mei_hbm_write_message(dev, _hdr, );
if (ret) {
@@ -1085,6 +1087,13 @@ static void mei_hbm_config_features(struct mei_device 
*dev)
(dev->version.major_version == HBM_MAJOR_VERSION_CAP &&
 dev->version.minor_version >= HBM_MINOR_VERSION_CAP))
dev->hbm_f_cap_supported = 1;
+
+   /* Client DMA Support */
+   dev->hbm_f_cd_supported = 0;
+   if (dev->version.major_version > HBM_MAJOR_VERSION_CD ||
+   (dev->version.major_version == HBM_MAJOR_VERSION_CD &&
+dev->version.minor_version >= HBM_MINOR_VERSION_CD))
+   dev->hbm_f_cd_supported = 1;
 }
 
 /**
@@ -1233,6 +1242,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct 
mei_msg_hdr *hdr)
capability_res = (struct hbm_capability_response *)mei_msg;
if (!(capability_res->capability_granted[0] & HBM_CAP_VT))
dev->hbm_f_vt_supported = 0;
+   if (!(capability_res->capability_granted[0] & HBM_CAP_CD))
+   dev->hbm_f_cd_supported = 0;
 
if (dev->hbm_f_dr_supported) {
if (mei_dmam_ring_alloc(dev))
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index df2fb9520dd8..9577a2cc0733 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -88,6 +88,12 @@
 #define HBM_MINOR_VERSION_CAP  2
 #define HBM_MAJOR_VERSION_CAP  2
 
+/*
+ * MEI version with client DMA support
+ */
+#define HBM_MINOR_VERSION_CD   2
+#define HBM_MAJOR_VERSION_CD   2
+
 /* Host bus message command opcode */
 #define MEI_HBM_CMD_OP_MSK  0x7f
 /* Host bus message command RESPONSE */
@@ -648,6 +654,8 @@ struct hbm_dma_ring_ctrl {
 
 /* virtual tag supported */
 #define HBM_CAP_VT BIT(0)
+/* client dma supported */
+#define HBM_CAP_CD BIT(2)
 
 /**
  * struct hbm_capability_request - capability request from host to fw
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 585a6f615bf8..8ebd32cb2075 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -451,6 +451,7 @@ struct mei_fw_version {
  * @hbm_f_dr_supported  : hbm feature dma ring supported
  * @hbm_f_vt_supported  : hbm feature vtag supported
  * @hbm_f_cap_supported : hbm feature capabilities message supported
+ * @hbm_f_cd_supported  : hbm feature client dma supported
  *
  * @fw_ver : FW versions
  *
@@ -538,6 +539,7 @@ struct mei_device {
unsigned int hbm_f_dr_supported:1;
unsigned int hbm_f_vt_supported:1;
unsigned int hbm_f_cap_supported:1;
+   unsigned int hbm_f_cd_supported:1;
 
struct mei_fw_version fw_ver[MEI_MAX_FW_VER_BLOCKS];
 
-- 
2.26.2



[char-misc-next 5/6] mei: implement client dma setup.

2021-02-06 Thread Tomas Winkler
From: Alexander Usyskin 

Implement HBM message protocol to setup and tear down
DMA buffer on behalf of an client. On top there DMA
buffer allocation and its life time management.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/client.c| 286 +++
 drivers/misc/mei/client.h|   8 +
 drivers/misc/mei/hbm.c   | 124 +++
 drivers/misc/mei/hbm.h   |   4 +-
 drivers/misc/mei/interrupt.c |  10 ++
 drivers/misc/mei/mei_dev.h   |  15 ++
 6 files changed, 446 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index d3f060dce4a6..4378a9b25848 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -2114,6 +2115,8 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb 
*cb)
case MEI_FOP_DISCONNECT:
case MEI_FOP_NOTIFY_STOP:
case MEI_FOP_NOTIFY_START:
+   case MEI_FOP_DMA_MAP:
+   case MEI_FOP_DMA_UNMAP:
if (waitqueue_active(>wait))
wake_up(>wait);
 
@@ -2140,3 +2143,286 @@ void mei_cl_all_disconnect(struct mei_device *dev)
list_for_each_entry(cl, >file_list, link)
mei_cl_set_disconnected(cl);
 }
+
+static struct mei_cl *mei_cl_dma_map_find(struct mei_device *dev, u8 buffer_id)
+{
+   struct mei_cl *cl;
+
+   list_for_each_entry(cl, >file_list, link)
+   if (cl->dma.buffer_id == buffer_id)
+   return cl;
+   return NULL;
+}
+
+/**
+ * mei_cl_irq_dma_map - send client dma map request in irq_thread context
+ *
+ * @cl: client
+ * @cb: callback block.
+ * @cmpl_list: complete list.
+ *
+ * Return: 0 on such and error otherwise.
+ */
+int mei_cl_irq_dma_map(struct mei_cl *cl, struct mei_cl_cb *cb,
+  struct list_head *cmpl_list)
+{
+   struct mei_device *dev = cl->dev;
+   u32 msg_slots;
+   int slots;
+   int ret;
+
+   msg_slots = mei_hbm2slots(sizeof(struct hbm_client_dma_map_request));
+   slots = mei_hbuf_empty_slots(dev);
+   if (slots < 0)
+   return -EOVERFLOW;
+
+   if ((u32)slots < msg_slots)
+   return -EMSGSIZE;
+
+   ret = mei_hbm_cl_dma_map_req(dev, cl);
+   if (ret) {
+   cl->status = ret;
+   list_move_tail(>list, cmpl_list);
+   return ret;
+   }
+
+   list_move_tail(>list, >ctrl_rd_list);
+   return 0;
+}
+
+/**
+ * mei_cl_irq_dma_unmap - send client dma unmap request in irq_thread context
+ *
+ * @cl: client
+ * @cb: callback block.
+ * @cmpl_list: complete list.
+ *
+ * Return: 0 on such and error otherwise.
+ */
+int mei_cl_irq_dma_unmap(struct mei_cl *cl, struct mei_cl_cb *cb,
+struct list_head *cmpl_list)
+{
+   struct mei_device *dev = cl->dev;
+   u32 msg_slots;
+   int slots;
+   int ret;
+
+   msg_slots = mei_hbm2slots(sizeof(struct hbm_client_dma_unmap_request));
+   slots = mei_hbuf_empty_slots(dev);
+   if (slots < 0)
+   return -EOVERFLOW;
+
+   if ((u32)slots < msg_slots)
+   return -EMSGSIZE;
+
+   ret = mei_hbm_cl_dma_unmap_req(dev, cl);
+   if (ret) {
+   cl->status = ret;
+   list_move_tail(>list, cmpl_list);
+   return ret;
+   }
+
+   list_move_tail(>list, >ctrl_rd_list);
+   return 0;
+}
+
+static int mei_cl_dma_alloc(struct mei_cl *cl, u8 buf_id, size_t size)
+{
+   cl->dma.vaddr = dmam_alloc_coherent(cl->dev->dev, size,
+   >dma.daddr, GFP_KERNEL);
+   if (!cl->dma.vaddr)
+   return -ENOMEM;
+
+   cl->dma.buffer_id = buf_id;
+   cl->dma.size = size;
+
+   return 0;
+}
+
+static void mei_cl_dma_free(struct mei_cl *cl)
+{
+   cl->dma.buffer_id = 0;
+   dmam_free_coherent(cl->dev->dev,
+  cl->dma.size, cl->dma.vaddr, cl->dma.daddr);
+   cl->dma.size = 0;
+   cl->dma.vaddr = NULL;
+   cl->dma.daddr = 0;
+}
+
+/**
+ * mei_cl_alloc_and_map - send client dma map request
+ *
+ * @cl: host client
+ * @fp: pointer to file structure
+ * @buffer_id: id of the mapped buffer
+ * @size: size of the buffer
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * Return:
+ * * -ENODEV
+ * * -EINVAL
+ * * -EOPNOTSUPP
+ * * -EPROTO
+ * * -ENOMEM;
+ */
+int mei_cl_dma_alloc_and_map(struct mei_cl *cl, const struct file *fp,
+u8 buffer_id, size_t size)
+{
+   struct mei_device *dev;
+   struct mei_cl_cb *cb;
+   int rets;
+
+   if (WARN_ON(!cl || !cl->dev))
+   return -ENODEV;
+
+   dev = cl->dev;
+
+   if (!dev->hbm_f_cd_supported) {
+

[char-misc-next 4/6] mei: hbm: add client dma hbm messages

2021-02-06 Thread Tomas Winkler
From: Alexander Usyskin 

Define structures for client DMA HBM protocol.
The protocol requires passing dma buffer address
and the buffer id.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw.h | 53 +++
 1 file changed, 53 insertions(+)

diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index 9577a2cc0733..b10606550613 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -142,6 +142,12 @@
 #define MEI_HBM_CAPABILITIES_REQ_CMD0x13
 #define MEI_HBM_CAPABILITIES_RES_CMD0x93
 
+#define MEI_HBM_CLIENT_DMA_MAP_REQ_CMD  0x14
+#define MEI_HBM_CLIENT_DMA_MAP_RES_CMD  0x94
+
+#define MEI_HBM_CLIENT_DMA_UNMAP_REQ_CMD0x15
+#define MEI_HBM_CLIENT_DMA_UNMAP_RES_CMD0x95
+
 /*
  * MEI Stop Reason
  * used by hbm_host_stop_request.reason
@@ -679,4 +685,51 @@ struct hbm_capability_response {
u8 capability_granted[3];
 } __packed;
 
+/**
+ * struct hbm_client_dma_map_request - client dma map request from host to fw
+ *
+ * @hbm_cmd: bus message command header
+ * @client_buffer_id: client buffer id
+ * @reserved: reserved
+ * @address_lsb: DMA address LSB
+ * @address_msb: DMA address MSB
+ * @size: DMA size
+ */
+struct hbm_client_dma_map_request {
+   u8 hbm_cmd;
+   u8 client_buffer_id;
+   u8 reserved[2];
+   u32 address_lsb;
+   u32 address_msb;
+   u32 size;
+} __packed;
+
+/**
+ * struct hbm_client_dma_unmap_request
+ *client dma unmap request from the host to the firmware
+ *
+ * @hbm_cmd: bus message command header
+ * @status: unmap status
+ * @client_buffer_id: client buffer id
+ * @reserved: reserved
+ */
+struct hbm_client_dma_unmap_request {
+   u8 hbm_cmd;
+   u8 status;
+   u8 client_buffer_id;
+   u8 reserved;
+} __packed;
+
+/**
+ * struct hbm_client_dma_response
+ *   client dma unmap response from the firmware to the host
+ *
+ * @hbm_cmd: bus message command header
+ * @status: command status
+ */
+struct hbm_client_dma_response {
+   u8 hbm_cmd;
+   u8 status;
+} __packed;
+
 #endif
-- 
2.26.2



[char-misc-next 2/6] mei: allow clients on bus to communicate in remove callback

2021-02-06 Thread Tomas Winkler
From: Alexander Usyskin 

Introduce new intermediate state to allow the clients on the bus
to communicate with the firmware from the remove handler.
This is to enable to perform a clean shutdown.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c | 6 --
 drivers/misc/mei/client.c  | 3 ++-
 drivers/misc/mei/init.c| 5 -
 drivers/misc/mei/mei_dev.h | 1 +
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 2907db260fba..34fb5e541fe5 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -44,7 +44,8 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t 
length, u8 vtag,
bus = cl->dev;
 
mutex_lock(>device_lock);
-   if (bus->dev_state != MEI_DEV_ENABLED) {
+   if (bus->dev_state != MEI_DEV_ENABLED &&
+   bus->dev_state != MEI_DEV_POWERING_DOWN) {
rets = -ENODEV;
goto out;
}
@@ -128,7 +129,8 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t 
length, u8 *vtag,
bus = cl->dev;
 
mutex_lock(>device_lock);
-   if (bus->dev_state != MEI_DEV_ENABLED) {
+   if (bus->dev_state != MEI_DEV_ENABLED &&
+   bus->dev_state != MEI_DEV_POWERING_DOWN) {
rets = -ENODEV;
goto out;
}
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index beb6cdff20fb..d3f060dce4a6 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -990,7 +990,8 @@ int mei_cl_disconnect(struct mei_cl *cl)
return 0;
}
 
-   if (dev->dev_state == MEI_DEV_POWER_DOWN) {
+   if (dev->dev_state == MEI_DEV_POWERING_DOWN ||
+   dev->dev_state == MEI_DEV_POWER_DOWN) {
cl_dbg(dev, cl, "Device is powering down, don't bother with 
disconnection\n");
mei_cl_set_disconnected(cl);
return 0;
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index bcee77768b91..5c8cb679b997 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -303,9 +303,12 @@ void mei_stop(struct mei_device *dev)
dev_dbg(dev->dev, "stopping the device.\n");
 
mutex_lock(>device_lock);
-   mei_set_devstate(dev, MEI_DEV_POWER_DOWN);
+   mei_set_devstate(dev, MEI_DEV_POWERING_DOWN);
mutex_unlock(>device_lock);
mei_cl_bus_remove_devices(dev);
+   mutex_lock(>device_lock);
+   mei_set_devstate(dev, MEI_DEV_POWER_DOWN);
+   mutex_unlock(>device_lock);
 
mei_cancel_work(dev);
 
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 8c395bfdf6f3..585a6f615bf8 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -57,6 +57,7 @@ enum mei_dev_state {
MEI_DEV_ENABLED,
MEI_DEV_RESETTING,
MEI_DEV_DISABLED,
+   MEI_DEV_POWERING_DOWN,
MEI_DEV_POWER_DOWN,
MEI_DEV_POWER_UP
 };
-- 
2.26.2



[char-misc-next 1/6] mei: use sprintf in tx_queue_limit_show sysfs

2021-02-06 Thread Tomas Winkler
Using of snprintf is discouraged in sysfs.
For simple u8 it is safe to use sprintf.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 9f6682033ed7..24a05f45b639 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -1026,7 +1026,7 @@ static ssize_t tx_queue_limit_show(struct device *device,
size = dev->tx_queue_limit;
mutex_unlock(>device_lock);
 
-   return snprintf(buf, PAGE_SIZE, "%u\n", size);
+   return sprintf(buf, "%u\n", size);
 }
 
 static ssize_t tx_queue_limit_store(struct device *device,
-- 
2.26.2



[PATCH] mtd: use refcount to prevent corruption

2021-01-27 Thread Tomas Winkler
When underlying device is removed mtd core will crash
in case user space is still holding an open handle to a mtd device node.
A proper refcounting is needed so device is release only when a
partition has no active users. The current simple counter is not
sufficient.

Signed-off-by: Tomas Winkler 
---
 drivers/mtd/mtdcore.c   | 55 ++---
 drivers/mtd/mtdcore.h   |  1 +
 drivers/mtd/mtdpart.c   | 12 -
 include/linux/mtd/mtd.h |  2 +-
 4 files changed, 38 insertions(+), 32 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 2d6423d89a17..db5167eacaa4 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -93,9 +93,29 @@ static void mtd_release(struct device *dev)
dev_t index = MTD_DEVT(mtd->index);
 
/* remove /dev/mtdXro node */
+   if (mtd_is_partition(mtd))
+   release_mtd_partition(mtd);
+
device_destroy(_class, index + 1);
 }
 
+static void mtd_device_release(struct kref *kref)
+{
+   struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt);
+
+   if (mtd->nvmem) {
+   nvmem_unregister(mtd->nvmem);
+   mtd->nvmem = NULL;
+   }
+
+   idr_remove(_idr, mtd->index);
+   of_node_put(mtd_get_of_node(mtd));
+
+   device_unregister(>dev);
+
+   module_put(THIS_MODULE);
+}
+
 static ssize_t mtd_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
 {
@@ -619,7 +639,7 @@ int add_mtd_device(struct mtd_info *mtd)
}
 
mtd->index = i;
-   mtd->usecount = 0;
+   kref_init(>refcnt);
 
/* default value if not set by driver */
if (mtd->bitflip_threshold == 0)
@@ -733,23 +753,8 @@ int del_mtd_device(struct mtd_info *mtd)
list_for_each_entry(not, _notifiers, list)
not->remove(mtd);
 
-   if (mtd->usecount) {
-   printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count 
%d\n",
-  mtd->index, mtd->name, mtd->usecount);
-   ret = -EBUSY;
-   } else {
-   /* Try to remove the NVMEM provider */
-   if (mtd->nvmem)
-   nvmem_unregister(mtd->nvmem);
-
-   device_unregister(>dev);
-
-   idr_remove(_idr, mtd->index);
-   of_node_put(mtd_get_of_node(mtd));
-
-   module_put(THIS_MODULE);
-   ret = 0;
-   }
+   kref_put(>refcnt, mtd_device_release);
+   ret = 0;
 
 out_error:
mutex_unlock(_table_mutex);
@@ -984,20 +989,21 @@ int __get_mtd_device(struct mtd_info *mtd)
if (!try_module_get(master->owner))
return -ENODEV;
 
+   kref_get(>refcnt);
+
if (master->_get_device) {
err = master->_get_device(mtd);
 
if (err) {
+   kref_put(>refcnt, mtd_device_release);
module_put(master->owner);
return err;
}
}
 
-   master->usecount++;
-
while (mtd->parent) {
-   mtd->usecount++;
mtd = mtd->parent;
+   kref_get(>refcnt);
}
 
return 0;
@@ -1055,14 +1061,13 @@ void __put_mtd_device(struct mtd_info *mtd)
 {
struct mtd_info *master = mtd_get_master(mtd);
 
+   kref_put(>refcnt, mtd_device_release);
+
while (mtd->parent) {
-   --mtd->usecount;
-   BUG_ON(mtd->usecount < 0);
mtd = mtd->parent;
+   kref_put(>refcnt, mtd_device_release);
}
 
-   master->usecount--;
-
if (master->_put_device)
master->_put_device(master);
 
diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h
index b5eefeabf310..b014861a06a6 100644
--- a/drivers/mtd/mtdcore.h
+++ b/drivers/mtd/mtdcore.h
@@ -12,6 +12,7 @@ int __must_check add_mtd_device(struct mtd_info *mtd);
 int del_mtd_device(struct mtd_info *mtd);
 int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
 int del_mtd_partitions(struct mtd_info *);
+void release_mtd_partition(struct mtd_info *mtd);
 
 struct mtd_partitions;
 
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 12ca4f19cb14..8175f6d9c790 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -31,6 +31,12 @@ static inline void free_partition(struct mtd_info *mtd)
kfree(mtd);
 }
 
+void release_mtd_partition(struct mtd_info *mtd)
+{
+   list_del_init(>part.node);
+   free_partition(mtd);
+}
+
 static struct mtd_info *allocate_partition(struct mtd_info *parent,
   const struct mtd_partition *part,
   int partno, uint64_t cur_offset)
@@ -313,9 +319,6 @@ static int __mtd_del_partition(struct mtd

[watchdog v2] watchdog: mei_wdt: request stop on unregister

2021-01-24 Thread Tomas Winkler
From: Alexander Usyskin 

The MEI bus has a special behavior on suspend it destroys
all the attached devices, this is due to the fact that also
firmware context is not persistent across power flows.

If watchdog on MEI bus is ticking before suspending the firmware
times out and reports that the OS is missing watchdog tick.
Send the stop command to the firmware on watchdog unregistered
to eliminate the false event on suspend.
This does not make the things worse from the user-space perspective
as a user-space should re-open watchdog device after
suspending before this patch.

Cc: 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
V2: Update the commit message with better explanation

 drivers/watchdog/mei_wdt.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c
index 5391bf3e6b11..c5967d8b4256 100644
--- a/drivers/watchdog/mei_wdt.c
+++ b/drivers/watchdog/mei_wdt.c
@@ -382,6 +382,7 @@ static int mei_wdt_register(struct mei_wdt *wdt)
 
watchdog_set_drvdata(>wdd, wdt);
watchdog_stop_on_reboot(>wdd);
+   watchdog_stop_on_unregister(>wdd);
 
ret = watchdog_register_device(>wdd);
if (ret)
-- 
2.26.2



[watchdog] watchdog: mei_wdt: request stop on unregister

2021-01-07 Thread Tomas Winkler
From: Alexander Usyskin 

Send the stop command to the firmware on watchdog unregister
to eleminate false event on suspend.

Cc: 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/watchdog/mei_wdt.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c
index 5391bf3e6b11..c5967d8b4256 100644
--- a/drivers/watchdog/mei_wdt.c
+++ b/drivers/watchdog/mei_wdt.c
@@ -382,6 +382,7 @@ static int mei_wdt_register(struct mei_wdt *wdt)
 
watchdog_set_drvdata(>wdd, wdt);
watchdog_stop_on_reboot(>wdd);
+   watchdog_stop_on_unregister(>wdd);
 
ret = watchdog_register_device(>wdd);
if (ret)
-- 
2.26.2



[char-misc-next 2/2] mei: bus: enable pavp device.

2020-11-16 Thread Tomas Winkler
Enable protected audio video path client on mei client
bus.

Cc: Sean Z Huang 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus-fixup.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 6cc3145bb716..d8e760b11ae3 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -33,6 +33,9 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO;
 #define MEI_UUID_HDCP UUID_LE(0xB638AB7E, 0x94E2, 0x4EA2, \
  0xA5, 0x52, 0xD1, 0xC5, 0x4B, 0x62, 0x7F, 0x04)
 
+#define MEI_UUID_PAVP UUID_LE(0xfbf6fcf1, 0x96cf, 0x4e2e, 0xA6, \
+ 0xa6, 0x1b, 0xab, 0x8c, 0xbe, 0x36, 0xb1)
+
 #define MEI_UUID_ANY NULL_UUID_LE
 
 /**
@@ -491,6 +494,7 @@ static struct mei_fixup {
MEI_FIXUP(MEI_UUID_MKHIF_FIX, mei_mkhi_fix),
MEI_FIXUP(MEI_UUID_HDCP, whitelist),
MEI_FIXUP(MEI_UUID_ANY, vt_support),
+   MEI_FIXUP(MEI_UUID_PAVP, whitelist),
 };
 
 /**
-- 
2.26.2



[char-misc-next 1/2] mei: bus: add vtag support

2020-11-16 Thread Tomas Winkler
From: Alexander Usyskin 

Add API to support vtag in communication on mei bus.

Add mei_cldev_send_vtag, mei_cldev_recv_vtag and
mei_cldev_recv_nonblock_vtag functions to allow sending a message
with vtag set and to receive vtag of an incoming message.

Cc: Sean Z Huang 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus-fixup.c |  13 +++--
 drivers/misc/mei/bus.c   | 101 +--
 drivers/misc/mei/client.c|   6 ++-
 drivers/misc/mei/mei_dev.h   |   4 +-
 include/linux/mei_cl_bus.h   |   6 +++
 5 files changed, 104 insertions(+), 26 deletions(-)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 4e30fa98fe7d..6cc3145bb716 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -148,7 +148,7 @@ static int mei_osver(struct mei_cl_device *cldev)
os_ver = (struct mei_os_ver *)fwcaps->data;
os_ver->os_type = OSTYPE_LINUX;
 
-   return __mei_cl_send(cldev->cl, buf, size, mode);
+   return __mei_cl_send(cldev->cl, buf, size, 0, mode);
 }
 
 #define MKHI_FWVER_BUF_LEN (sizeof(struct mkhi_msg_hdr) + \
@@ -169,7 +169,7 @@ static int mei_fwver(struct mei_cl_device *cldev)
req.hdr.group_id = MKHI_GEN_GROUP_ID;
req.hdr.command = MKHI_GEN_GET_FW_VERSION_CMD;
 
-   ret = __mei_cl_send(cldev->cl, (u8 *), sizeof(req),
+   ret = __mei_cl_send(cldev->cl, (u8 *), sizeof(req), 0,
MEI_CL_IO_TX_BLOCKING);
if (ret < 0) {
dev_err(>dev, "Could not send ReqFWVersion cmd\n");
@@ -177,7 +177,7 @@ static int mei_fwver(struct mei_cl_device *cldev)
}
 
ret = 0;
-   bytes_recv = __mei_cl_recv(cldev->cl, buf, sizeof(buf), 0,
+   bytes_recv = __mei_cl_recv(cldev->cl, buf, sizeof(buf), NULL, 0,
   MKHI_RCV_TIMEOUT);
if (bytes_recv < 0 || (size_t)bytes_recv < MKHI_FWVER_LEN(1)) {
/*
@@ -324,13 +324,15 @@ static int mei_nfc_if_version(struct mei_cl *cl,
};
struct mei_nfc_reply *reply = NULL;
size_t if_version_length;
+   u8 vtag;
int bytes_recv, ret;
 
bus = cl->dev;
 
WARN_ON(mutex_is_locked(>device_lock));
 
-   ret = __mei_cl_send(cl, (u8 *), sizeof(cmd), MEI_CL_IO_TX_BLOCKING);
+   ret = __mei_cl_send(cl, (u8 *), sizeof(cmd), 0,
+   MEI_CL_IO_TX_BLOCKING);
if (ret < 0) {
dev_err(bus->dev, "Could not send IF version cmd\n");
return ret;
@@ -344,7 +346,8 @@ static int mei_nfc_if_version(struct mei_cl *cl,
return -ENOMEM;
 
ret = 0;
-   bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0, 0);
+   bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, ,
+  0, 0);
if (bytes_recv < 0 || (size_t)bytes_recv < if_version_length) {
dev_err(bus->dev, "Could not read IF version\n");
ret = -EIO;
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 7fe48baa103a..2907db260fba 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -26,11 +26,12 @@
  * @cl: host client
  * @buf: buffer to send
  * @length: buffer length
+ * @vtag: virtual tag
  * @mode: sending mode
  *
  * Return: written size bytes or < 0 on error
  */
-ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
+ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, u8 vtag,
  unsigned int mode)
 {
struct mei_device *bus;
@@ -86,6 +87,7 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t 
length,
rets = -ENOMEM;
goto out;
}
+   cb->vtag = vtag;
 
cb->internal = !!(mode & MEI_CL_IO_TX_INTERNAL);
cb->blocking = !!(mode & MEI_CL_IO_TX_BLOCKING);
@@ -106,11 +108,12 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t 
length,
  * @buf: buffer to receive
  * @length: buffer length
  * @mode: io mode
+ * @vtag: virtual tag
  * @timeout: recv timeout, 0 for infinite timeout
  *
  * Return: read size in bytes of < 0 on error
  */
-ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
+ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length, u8 *vtag,
  unsigned int mode, unsigned long timeout)
 {
struct mei_device *bus;
@@ -196,6 +199,8 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t 
length,
r_length = min_t(size_t, length, cb->buf_idx);
memcpy(buf, cb->buf.data, r_length);
rets = r_length;
+   if (vtag)
+   *vtag = cb->vtag;
 
 free:
mei_cl_del_rd_completed(cl, cb);
@@ -206,40 +211,87 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t 
length,
 }
 
 /**
- * mei_cldev_send

[char-misc-next 3/3] mei: bus: deinitialize callback functions on init failure

2020-10-29 Thread Tomas Winkler
From: Alexander Usyskin 

If the initialization procedure for receive or receive callback
registration on the client bus has failed the caller can't re-run it.
Deinitilize the callback pointers and cancel the work
to allow the caller to retry.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 1a54bf3ed0c3..76aa0e93748a 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -370,8 +370,11 @@ int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, 
mei_cldev_cb_t rx_cb)
else
ret = -ENODEV;
mutex_unlock(>device_lock);
-   if (ret && ret != -EBUSY)
+   if (ret && ret != -EBUSY) {
+   cancel_work_sync(>rx_work);
+   cldev->rx_cb = NULL;
return ret;
+   }
 
return 0;
 }
@@ -405,8 +408,11 @@ int mei_cldev_register_notif_cb(struct mei_cl_device 
*cldev,
mutex_lock(>device_lock);
ret = mei_cl_notify_request(cldev->cl, NULL, 1);
mutex_unlock(>device_lock);
-   if (ret)
+   if (ret) {
+   cancel_work_sync(>notif_work);
+   cldev->notif_cb = NULL;
return ret;
+   }
 
return 0;
 }
-- 
2.25.4



[char-misc-next 0/3] mei: bus: null derefence in rx

2020-10-29 Thread Tomas Winkler
Fix race in receive callback for drivers on me client
bus, that results in null dereferencing and improve 
the error handling.
The first patch 'mei: protect mei_cl_mtu from null dereference'
itself is sufficient to prevent the failure and is intended
for stable.


Alexander Usyskin (3):
  mei: protect mei_cl_mtu from null dereference
  mei: bus: do not start a read for disconnected clients
  mei: bus: deinitialize callback functions on init failure

 drivers/misc/mei/bus.c| 18 ++
 drivers/misc/mei/client.h |  4 ++--
 2 files changed, 16 insertions(+), 6 deletions(-)

-- 
2.25.4



[char-misc-next 2/3] mei: bus: do not start a read for disconnected clients

2020-10-29 Thread Tomas Winkler
From: Alexander Usyskin 

Avoid queuing reads and registering rx callbacks in
case the client is not connected, to prevent null
dereferencing and memory leaks.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 9cdaa7f3af23..1a54bf3ed0c3 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -276,7 +276,8 @@ static void mei_cl_bus_rx_work(struct work_struct *work)
cldev->rx_cb(cldev);
 
mutex_lock(>device_lock);
-   mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+   if (mei_cl_is_connected(cldev->cl))
+   mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
mutex_unlock(>device_lock);
 }
 
@@ -364,7 +365,10 @@ int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, 
mei_cldev_cb_t rx_cb)
INIT_WORK(>rx_work, mei_cl_bus_rx_work);
 
mutex_lock(>device_lock);
-   ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+   if (mei_cl_is_connected(cldev->cl))
+   ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+   else
+   ret = -ENODEV;
mutex_unlock(>device_lock);
if (ret && ret != -EBUSY)
return ret;
-- 
2.25.4



[char-misc-next 1/3] mei: protect mei_cl_mtu from null dereference

2020-10-29 Thread Tomas Winkler
From: Alexander Usyskin 

A receive callback is queued while the client is still connected
but can still be called after the client was disconnected. Upon
disconnect cl->me_cl is set to NULL, hence we need to check
that ME client is not-NULL in mei_cl_mtu to avoid
null dereference.

Cc: 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/client.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 64143d4ec758..9e08a9843bba 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -182,11 +182,11 @@ static inline u8 mei_cl_me_id(const struct mei_cl *cl)
  *
  * @cl: host client
  *
- * Return: mtu
+ * Return: mtu or 0 if client is not connected
  */
 static inline size_t mei_cl_mtu(const struct mei_cl *cl)
 {
-   return cl->me_cl->props.max_msg_length;
+   return cl->me_cl ? cl->me_cl->props.max_msg_length : 0;
 }
 
 /**
-- 
2.25.4



[char-misc-next 08/13] mei: handle tx queue flushing for vtag connections

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

Since multiple file pointers (fp) can be associated
with a single host client, upon close() only objects
associated with the fp has to flushed from the tx queues.
The control queues should be flushed only when all
the connections are closed and the client is disconnected.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/client.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 3904fce18261..d5c3f7d54634 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -429,14 +429,16 @@ static void mei_io_list_flush_cl(struct list_head *head,
  *
  * @head: An instance of our list structure
  * @cl: host client
+ * @fp: file pointer (matching cb file object), may be NULL
  */
 static void mei_io_tx_list_free_cl(struct list_head *head,
-  const struct mei_cl *cl)
+  const struct mei_cl *cl,
+  const struct file *fp)
 {
struct mei_cl_cb *cb, *next;
 
list_for_each_entry_safe(cb, next, head, list) {
-   if (cl == cb->cl)
+   if (cl == cb->cl && (!fp || fp == cb->fp))
mei_tx_cb_dequeue(cb);
}
 }
@@ -574,13 +576,14 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct 
file *fp)
dev = cl->dev;
 
cl_dbg(dev, cl, "remove list entry belonging to cl\n");
-   mei_io_tx_list_free_cl(>dev->write_list, cl);
-   mei_io_tx_list_free_cl(>dev->write_waiting_list, cl);
-   mei_io_list_flush_cl(>dev->ctrl_wr_list, cl);
-   mei_io_list_flush_cl(>dev->ctrl_rd_list, cl);
-   /* free pending cb only in final flush */
-   if (!fp)
+   mei_io_tx_list_free_cl(>dev->write_list, cl, fp);
+   mei_io_tx_list_free_cl(>dev->write_waiting_list, cl, fp);
+   /* free pending and control cb only in final flush */
+   if (!fp) {
+   mei_io_list_flush_cl(>dev->ctrl_wr_list, cl);
+   mei_io_list_flush_cl(>dev->ctrl_rd_list, cl);
mei_cl_free_pending(cl);
+   }
spin_lock(>rd_completed_lock);
mei_io_list_free_fp(>rd_completed, fp);
spin_unlock(>rd_completed_lock);
@@ -798,8 +801,8 @@ static void mei_cl_set_disconnected(struct mei_cl *cl)
return;
 
cl->state = MEI_FILE_DISCONNECTED;
-   mei_io_tx_list_free_cl(>write_list, cl);
-   mei_io_tx_list_free_cl(>write_waiting_list, cl);
+   mei_io_tx_list_free_cl(>write_list, cl, NULL);
+   mei_io_tx_list_free_cl(>write_waiting_list, cl, NULL);
mei_io_list_flush_cl(>ctrl_rd_list, cl);
mei_io_list_flush_cl(>ctrl_wr_list, cl);
mei_cl_wake_all(cl);
-- 
2.25.4



[char-misc-next 04/13] mei: add support for mei extended header.

2020-08-18 Thread Tomas Winkler
Add an extend header beyond existing 4 bytes of the mei message header.
The extension is of variable length, starting with meta header
that contains the number of headers and the overall size of
the extended headers excluding meta header itself followed by
TLV list of extended headers. Currently only supported extension is
the vtag. From the HW perspective the extended headers is already
part of the payload.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
---
 drivers/misc/mei/client.c| 189 ---
 drivers/misc/mei/hbm.c   |  14 +--
 drivers/misc/mei/hw.h|  93 -
 drivers/misc/mei/interrupt.c | 113 ++---
 drivers/misc/mei/mei_dev.h   |  11 +-
 5 files changed, 334 insertions(+), 86 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 2572887d99b6..a52799590dc7 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -378,6 +378,8 @@ static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl,
cb->cl = cl;
cb->buf_idx = 0;
cb->fop_type = type;
+   cb->vtag = 0;
+
return cb;
 }
 
@@ -1518,21 +1520,67 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, 
const struct file *fp)
return rets;
 }
 
+static inline u8 mei_ext_hdr_set_vtag(struct mei_ext_hdr *ext, u8 vtag)
+{
+   ext->type = MEI_EXT_HDR_VTAG;
+   ext->ext_payload[0] = vtag;
+   ext->length = mei_data2slots(sizeof(*ext));
+   return ext->length;
+}
+
 /**
- * mei_msg_hdr_init - initialize mei message header
+ * mei_msg_hdr_init - allocate and initialize mei message header
  *
- * @mei_hdr: mei message header
  * @cb: message callback structure
+ *
+ * Return: a pointer to initialized header
  */
-static void mei_msg_hdr_init(struct mei_msg_hdr *mei_hdr, struct mei_cl_cb *cb)
+static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb)
 {
+   size_t hdr_len;
+   struct mei_ext_meta_hdr *meta;
+   struct mei_ext_hdr *ext;
+   struct mei_msg_hdr *mei_hdr;
+   bool is_ext, is_vtag;
+
+   if (!cb)
+   return ERR_PTR(-EINVAL);
+
+   /* Extended header for vtag is attached only on the first fragment */
+   is_vtag = (cb->vtag && cb->buf_idx == 0);
+   is_ext = is_vtag;
+
+   /* Compute extended header size */
+   hdr_len = sizeof(*mei_hdr);
+
+   if (!is_ext)
+   goto setup_hdr;
+
+   hdr_len += sizeof(*meta);
+   if (is_vtag)
+   hdr_len += sizeof(*ext);
+
+setup_hdr:
+   mei_hdr = kzalloc(hdr_len, GFP_KERNEL);
+   if (!mei_hdr)
+   return ERR_PTR(-ENOMEM);
+
mei_hdr->host_addr = mei_cl_host_addr(cb->cl);
mei_hdr->me_addr = mei_cl_me_id(cb->cl);
-   mei_hdr->length = 0;
-   mei_hdr->reserved = 0;
-   mei_hdr->msg_complete = 0;
-   mei_hdr->dma_ring = 0;
mei_hdr->internal = cb->internal;
+   mei_hdr->extended = is_ext;
+
+   if (!is_ext)
+   goto out;
+
+   meta = (struct mei_ext_meta_hdr *)mei_hdr->extension;
+   if (is_vtag) {
+   meta->count++;
+   meta->size += mei_ext_hdr_set_vtag(meta->hdrs, cb->vtag);
+   }
+out:
+   mei_hdr->length = hdr_len - sizeof(*mei_hdr);
+   return mei_hdr;
 }
 
 /**
@@ -1550,10 +1598,11 @@ int mei_cl_irq_write(struct mei_cl *cl, struct 
mei_cl_cb *cb,
 {
struct mei_device *dev;
struct mei_msg_data *buf;
-   struct mei_msg_hdr mei_hdr;
-   size_t hdr_len = sizeof(mei_hdr);
-   size_t len;
+   struct mei_msg_hdr *mei_hdr = NULL;
+   size_t hdr_len;
size_t hbuf_len, dr_len;
+   size_t buf_len;
+   size_t data_len;
int hbuf_slots;
u32 dr_slots;
u32 dma_len;
@@ -1579,7 +1628,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb 
*cb,
return 0;
}
 
-   len = buf->size - cb->buf_idx;
+   buf_len = buf->size - cb->buf_idx;
data = buf->data + cb->buf_idx;
hbuf_slots = mei_hbuf_empty_slots(dev);
if (hbuf_slots < 0) {
@@ -1591,42 +1640,54 @@ int mei_cl_irq_write(struct mei_cl *cl, struct 
mei_cl_cb *cb,
dr_slots = mei_dma_ring_empty_slots(dev);
dr_len = mei_slots2data(dr_slots);
 
-   mei_msg_hdr_init(_hdr, cb);
+   mei_hdr = mei_msg_hdr_init(cb);
+   if (IS_ERR(mei_hdr)) {
+   rets = PTR_ERR(mei_hdr);
+   mei_hdr = NULL;
+   goto err;
+   }
+
+   cl_dbg(dev, cl, "Extended Header %d vtag = %d\n",
+  mei_hdr->extended, cb->vtag);
+
+   hdr_len = sizeof(*mei_hdr) + mei_hdr->length;
 
/**
 * Split the message only if we can write the whole host buffer
 * otherwise wait for next time the host buffer is empty.
 */
-   if 

[char-misc-next 06/13] mei: add a spin lock to protect rd_completed queue

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

In order to support vtags we need to access read completed
queue out of driver big lock.
Add a spin lock to protect rd_completed queue.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c |  6 ++---
 drivers/misc/mei/client.c  | 47 +-
 drivers/misc/mei/client.h  |  7 --
 drivers/misc/mei/main.c|  6 ++---
 drivers/misc/mei/mei_dev.h |  2 ++
 5 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 2e7ac53a4152..fc20a0da5c24 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -152,7 +152,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t 
length,
if (timeout) {
rets = wait_event_interruptible_timeout
(cl->rx_wait,
-   (!list_empty(>rd_completed)) ||
+   mei_cl_read_cb(cl, NULL) ||
(!mei_cl_is_connected(cl)),
msecs_to_jiffies(timeout));
if (rets == 0)
@@ -165,7 +165,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t 
length,
} else {
if (wait_event_interruptible
(cl->rx_wait,
-   (!list_empty(>rd_completed)) ||
+   mei_cl_read_cb(cl, NULL) ||
(!mei_cl_is_connected(cl {
if (signal_pending(current))
return -EINTR;
@@ -198,7 +198,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t 
length,
rets = r_length;
 
 free:
-   mei_io_cb_free(cb);
+   mei_cl_del_rd_completed(cl, cb);
 out:
mutex_unlock(>device_lock);
 
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index a52799590dc7..276021f99666 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -507,15 +507,19 @@ struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl 
*cl, size_t length,
  *
  * Return: cb on success, NULL if cb is not found
  */
-struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file 
*fp)
+struct mei_cl_cb *mei_cl_read_cb(struct mei_cl *cl, const struct file *fp)
 {
struct mei_cl_cb *cb;
+   struct mei_cl_cb *ret_cb = NULL;
 
+   spin_lock(>rd_completed_lock);
list_for_each_entry(cb, >rd_completed, list)
-   if (!fp || fp == cb->fp)
-   return cb;
-
-   return NULL;
+   if (!fp || fp == cb->fp) {
+   ret_cb = cb;
+   break;
+   }
+   spin_unlock(>rd_completed_lock);
+   return ret_cb;
 }
 
 /**
@@ -541,7 +545,9 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct 
file *fp)
mei_io_list_flush_cl(>dev->ctrl_wr_list, cl);
mei_io_list_flush_cl(>dev->ctrl_rd_list, cl);
mei_io_list_free_fp(>rd_pending, fp);
+   spin_lock(>rd_completed_lock);
mei_io_list_free_fp(>rd_completed, fp);
+   spin_unlock(>rd_completed_lock);
 
return 0;
 }
@@ -559,6 +565,7 @@ static void mei_cl_init(struct mei_cl *cl, struct 
mei_device *dev)
init_waitqueue_head(>rx_wait);
init_waitqueue_head(>tx_wait);
init_waitqueue_head(>ev_wait);
+   spin_lock_init(>rd_completed_lock);
INIT_LIST_HEAD(>rd_completed);
INIT_LIST_HEAD(>rd_pending);
INIT_LIST_HEAD(>link);
@@ -1230,6 +1237,34 @@ static int mei_cl_tx_flow_ctrl_creds_reduce(struct 
mei_cl *cl)
return 0;
 }
 
+/**
+ * mei_cl_add_rd_completed - add read completed callback to list with lock
+ *
+ * @cl: host client
+ * @cb: callback block
+ *
+ */
+void mei_cl_add_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
+{
+   spin_lock(>rd_completed_lock);
+   list_add_tail(>list, >rd_completed);
+   spin_unlock(>rd_completed_lock);
+}
+
+/**
+ * mei_cl_del_rd_completed - free read completed callback with lock
+ *
+ * @cl: host client
+ * @cb: callback block
+ *
+ */
+void mei_cl_del_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
+{
+   spin_lock(>rd_completed_lock);
+   mei_io_cb_free(cb);
+   spin_unlock(>rd_completed_lock);
+}
+
 /**
  *  mei_cl_notify_fop2req - convert fop to proper request
  *
@@ -1897,7 +1932,7 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb 
*cb)
break;
 
case MEI_FOP_READ:
-   list_add_tail(>list, >rd_completed);
+   mei_cl_add_rd_completed(cl, cb);
if (!mei_cl_is_fixed_address(cl) &&
!WARN_ON(!cl->rx_flow_ctrl_c

[char-misc-next 10/13] mei: bus: unconditionally enable clients with vtag support

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

The list of clients is only visible via mei client bus.
Enabling vtag clients on the mei client bus allows user-space to
enumerate clients with vtag support by traversing the mei bus on sysfs.
This feature is required for ACRN device model service.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus-fixup.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 07ba16d46690..4e30fa98fe7d 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -463,6 +463,17 @@ static void mei_nfc(struct mei_cl_device *cldev)
dev_dbg(bus->dev, "end of fixup match = %d\n", cldev->do_match);
 }
 
+/**
+ * vt_support - enable on bus clients with vtag support
+ *
+ * @cldev: me clients device
+ */
+static void vt_support(struct mei_cl_device *cldev)
+{
+   if (cldev->me_cl->props.vt_supported == 1)
+   cldev->do_match = 1;
+}
+
 #define MEI_FIXUP(_uuid, _hook) { _uuid, _hook }
 
 static struct mei_fixup {
@@ -476,6 +487,7 @@ static struct mei_fixup {
MEI_FIXUP(MEI_UUID_WD, mei_wd),
MEI_FIXUP(MEI_UUID_MKHIF_FIX, mei_mkhi_fix),
MEI_FIXUP(MEI_UUID_HDCP, whitelist),
+   MEI_FIXUP(MEI_UUID_ANY, vt_support),
 };
 
 /**
-- 
2.25.4



[char-misc-next 12/13] mei: docs: add vtag ioctl documentation

2020-08-18 Thread Tomas Winkler
Add structured documenation for the new vtag ioctl

Signed-off-by: Tomas Winkler 
---
 Documentation/driver-api/mei/mei.rst | 37 
 1 file changed, 37 insertions(+)

diff --git a/Documentation/driver-api/mei/mei.rst 
b/Documentation/driver-api/mei/mei.rst
index c800d8e5f422..cea0b69ec216 100644
--- a/Documentation/driver-api/mei/mei.rst
+++ b/Documentation/driver-api/mei/mei.rst
@@ -42,6 +42,11 @@ The session is terminated calling :c:func:`close(int fd)`.
 
 A code snippet for an application communicating with Intel AMTHI client:
 
+In order to support virtualization or sandboxing a trusted supervisor
+can use :c:macro:`MEI_CONNECT_CLIENT_IOCTL_VTAG` to create
+virtual channels with an Intel ME feature. Not all features support
+virtual channels such client with answer EOPNOTSUPP.
+
 .. code-block:: C
 
struct mei_connect_client_data data;
@@ -110,6 +115,38 @@ Connect to firmware Feature/Client.
 data that can be sent or received. (e.g. if MTU=2K, can send
 requests up to bytes 2k and received responses up to 2k bytes).
 
+IOCTL_MEI_CONNECT_CLIENT_VTAG:
+--
+
+.. code-block:: none
+
+Usage:
+
+struct mei_connect_client_data_vtag client_data_vtag;
+
+ioctl(fd, IOCTL_MEI_CONNECT_CLIENT_VTAG, _data_vtag);
+
+Inputs:
+
+struct mei_connect_client_data_vtag - contain the following
+Input field:
+
+in_client_uuid -  GUID of the FW Feature that needs
+  to connect to.
+vtag - virtual tag [1, 255]
+
+ Outputs:
+out_client_properties - Client Properties: MTU and Protocol 
Version.
+
+ Error returns:
+
+ENOTTY No such client (i.e. wrong GUID) or connection is not 
allowed.
+EINVAL Wrong IOCTL Number or tag == 0
+ENODEV Device or Connection is not initialized or ready.
+ENOMEM Unable to allocate memory to client internal data.
+EFAULT Fatal Error (e.g. Unable to access user input data)
+EBUSY  Connection Already Open
+EOPNOTSUPP Vtag is not supported
 
 IOCTL_MEI_NOTIFY_SET
 -
-- 
2.25.4



[char-misc-next 09/13] mei: bus: use zero vtag for bus clients.

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

The zero vtag is required for the read flow to work also for
devices on the mei client bus.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c | 72 +-
 1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index fc20a0da5c24..9cdaa7f3af23 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -495,6 +495,68 @@ static void mei_cl_bus_module_put(struct mei_cl_device 
*cldev)
module_put(cldev->bus->dev->driver->owner);
 }
 
+/**
+ * mei_cl_bus_vtag - get bus vtag entry wrapper
+ * The tag for bus client is always first.
+ *
+ * @cl: host client
+ *
+ * Return: bus vtag or NULL
+ */
+static inline struct mei_cl_vtag *mei_cl_bus_vtag(struct mei_cl *cl)
+{
+   return list_first_entry_or_null(>vtag_map,
+   struct mei_cl_vtag, list);
+}
+
+/**
+ * mei_cl_bus_vtag_alloc - add bus client entry to vtag map
+ *
+ * @cldev: me client device
+ *
+ * Return:
+ * * 0 on success
+ * * -ENOMEM if memory allocation failed
+ */
+static int mei_cl_bus_vtag_alloc(struct mei_cl_device *cldev)
+{
+   struct mei_cl *cl = cldev->cl;
+   struct mei_cl_vtag *cl_vtag;
+
+   /*
+* Bail out if the client does not supports vtags
+* or has already allocated one
+*/
+   if (mei_cl_vt_support_check(cl) || mei_cl_bus_vtag(cl))
+   return 0;
+
+   cl_vtag = mei_cl_vtag_alloc(NULL, 0);
+   if (IS_ERR(cl_vtag))
+   return -ENOMEM;
+
+   list_add_tail(_vtag->list, >vtag_map);
+
+   return 0;
+}
+
+/**
+ * mei_cl_bus_vtag_free - remove the bus entry from vtag map
+ *
+ * @cldev: me client device
+ */
+static void mei_cl_bus_vtag_free(struct mei_cl_device *cldev)
+{
+   struct mei_cl *cl = cldev->cl;
+   struct mei_cl_vtag *cl_vtag;
+
+   cl_vtag = mei_cl_bus_vtag(cl);
+   if (!cl_vtag)
+   return;
+
+   list_del(_vtag->list);
+   kfree(cl_vtag);
+}
+
 /**
  * mei_cldev_enable - enable me client device
  * create connection with me client
@@ -531,9 +593,15 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
goto out;
}
 
+   ret = mei_cl_bus_vtag_alloc(cldev);
+   if (ret)
+   goto out;
+
ret = mei_cl_connect(cl, cldev->me_cl, NULL);
-   if (ret < 0)
+   if (ret < 0) {
dev_err(>dev, "cannot connect\n");
+   mei_cl_bus_vtag_free(cldev);
+   }
 
 out:
mutex_unlock(>device_lock);
@@ -586,6 +654,8 @@ int mei_cldev_disable(struct mei_cl_device *cldev)
 
mutex_lock(>device_lock);
 
+   mei_cl_bus_vtag_free(cldev);
+
if (!mei_cl_is_connected(cl)) {
dev_dbg(bus->dev, "Already disconnected\n");
err = 0;
-- 
2.25.4



[char-misc-next 13/13] mei: virtio: virtualization frontend driver

2020-08-18 Thread Tomas Winkler
This frontend driver implements MEI hw interface based on virtio
framework to let MEI driver work without changes under virtualization.
It requires a backend service in the ACRN device-model on the service
OS side to make it work. The backend service will emulate mei routing
and assign vtags for each mei vritio device.

The backend service is available in ACRN device-model at github.
For more information, please refer to https://projectacrn.org

The ACRN virtio sub device id for MEI is is 0x8602.

Signed-off-by: Tomas Winkler 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Wang Yu 
Signed-off-by: Liu Shuo 
---
 drivers/misc/mei/Kconfig |  10 +
 drivers/misc/mei/Makefile|   3 +
 drivers/misc/mei/hw-virtio.c | 874 +++
 3 files changed, 887 insertions(+)
 create mode 100644 drivers/misc/mei/hw-virtio.c

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index f5fd5b786607..c06581ffa7bd 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -46,4 +46,14 @@ config INTEL_MEI_TXE
  Supported SoCs:
  Intel Bay Trail
 
+config INTEL_MEI_VIRTIO
+   tristate "Intel MEI interface emulation with virtio framework"
+   select INTEL_MEI
+   depends on X86 && PCI && VIRTIO_PCI
+   help
+ This module implements mei hw emulation over virtio transport.
+ The module will be called mei_virtio.
+ Enable this if your virtual machine supports virtual mei
+ device over virtio.
+
 source "drivers/misc/mei/hdcp/Kconfig"
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index f1c76f7ee804..52aefaab5c1b 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -22,6 +22,9 @@ obj-$(CONFIG_INTEL_MEI_TXE) += mei-txe.o
 mei-txe-objs := pci-txe.o
 mei-txe-objs += hw-txe.o
 
+obj-$(CONFIG_INTEL_MEI_VIRTIO) += mei-virtio.o
+mei-virtio-objs := hw-virtio.o
+
 mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
 CFLAGS_mei-trace.o = -I$(src)
 
diff --git a/drivers/misc/mei/hw-virtio.c b/drivers/misc/mei/hw-virtio.c
new file mode 100644
index ..899dc1c5e7ca
--- /dev/null
+++ b/drivers/misc/mei/hw-virtio.c
@@ -0,0 +1,874 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2018-2020, Intel Corporation.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mei_dev.h"
+#include "hbm.h"
+#include "client.h"
+
+#define MEI_VIRTIO_RPM_TIMEOUT 500
+/* ACRN virtio device types */
+#ifndef VIRTIO_ID_MEI
+#define VIRTIO_ID_MEI 0xFFFE /* virtio mei */
+#endif
+
+/**
+ * struct mei_virtio_cfg - settings passed from the virtio backend
+ * @buf_depth: read buffer depth in slots (4bytes)
+ * @hw_ready: hw is ready for operation
+ * @host_reset: synchronize reset with virtio backend
+ * @reserved: reserved for alignment
+ * @fw_status: FW status
+ */
+struct mei_virtio_cfg {
+   u32 buf_depth;
+   u8 hw_ready;
+   u8 host_reset;
+   u8 reserved[2];
+   u32 fw_status[MEI_FW_STATUS_MAX];
+} __packed;
+
+struct mei_virtio_hw {
+   struct mei_device mdev;
+   char name[32];
+
+   struct virtqueue *in;
+   struct virtqueue *out;
+
+   bool host_ready;
+   struct work_struct intr_handler;
+
+   u32 *recv_buf;
+   u8 recv_rdy;
+   size_t recv_sz;
+   u32 recv_idx;
+   u32 recv_len;
+
+   /* send buffer */
+   atomic_t hbuf_ready;
+   const void *send_hdr;
+   const void *send_buf;
+
+   struct mei_virtio_cfg cfg;
+};
+
+#define to_virtio_hw(_dev) container_of(_dev, struct mei_virtio_hw, mdev)
+
+/**
+ * mei_virtio_fw_status() - read status register of mei
+ * @dev: mei device
+ * @fw_status: fw status register values
+ *
+ * Return: always 0
+ */
+static int mei_virtio_fw_status(struct mei_device *dev,
+   struct mei_fw_status *fw_status)
+{
+   struct virtio_device *vdev = dev_to_virtio(dev->dev);
+
+   fw_status->count = MEI_FW_STATUS_MAX;
+   virtio_cread_bytes(vdev, offsetof(struct mei_virtio_cfg, fw_status),
+  fw_status->status, sizeof(fw_status->status));
+   return 0;
+}
+
+/**
+ * mei_virtio_pg_state() - translate internal pg state
+ *   to the mei power gating state
+ *   There is no power management in ACRN mode always return OFF
+ * @dev: mei device
+ *
+ * Return:
+ * * MEI_PG_OFF - if aliveness is on (always)
+ * * MEI_PG_ON  - (never)
+ */
+static inline enum mei_pg_state mei_virtio_pg_state(struct mei_device *dev)
+{
+   return MEI_PG_OFF;
+}
+
+/**
+ * mei_virtio_hw_config() - configure hw dependent settings
+ *
+ * @dev: mei device
+ *
+ * Return: always 0
+ */
+static int mei_virtio_hw_config(struct mei_device *dev)
+{
+   return 0;
+}
+
+/**
+ * mei_virtio_hbuf_empty_slots() - counts write empty sl

[char-misc-next 11/13] mei: add connect with vtag ioctl

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

This IOCTL is used to associate the current file descriptor
with a FW Client (given by UUID), and virtual tag (vtag).
The IOCTL opens a communication channel between a host client
and a FW client on a tagged channel. From this point on,
every reader  and write will communicate with the associated
FW client on the tagged channel. Upon close() the communication
is terminated.

The IOCTL argument is a struct with a union that contains
the input parameter and the output parameter for this IOCTL.

The input parameter is UUID of the FW Client, a vtag [0,255]
The output parameter is the properties of the FW client

Clients that do not support tagged connection
will respond with -EOPNOTSUPP

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/main.c  | 210 ---
 include/uapi/linux/mei.h |  49 +
 2 files changed, 243 insertions(+), 16 deletions(-)

diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 401bf8743689..9f6682033ed7 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -395,17 +395,18 @@ static ssize_t mei_write(struct file *file, const char 
__user *ubuf,
  * mei_ioctl_connect_client - the connect to fw client IOCTL function
  *
  * @file: private data of the file object
- * @data: IOCTL connect data, input and output parameters
+ * @in_client_uuid: requested UUID for connection
+ * @client: IOCTL connect data, output parameters
  *
  * Locking: called under "dev->device_lock" lock
  *
  * Return: 0 on success, <0 on failure.
  */
 static int mei_ioctl_connect_client(struct file *file,
-   struct mei_connect_client_data *data)
+   const uuid_le *in_client_uuid,
+   struct mei_client *client)
 {
struct mei_device *dev;
-   struct mei_client *client;
struct mei_me_client *me_cl;
struct mei_cl *cl;
int rets;
@@ -413,18 +414,15 @@ static int mei_ioctl_connect_client(struct file *file,
cl = file->private_data;
dev = cl->dev;
 
-   if (dev->dev_state != MEI_DEV_ENABLED)
-   return -ENODEV;
-
if (cl->state != MEI_FILE_INITIALIZING &&
cl->state != MEI_FILE_DISCONNECTED)
return  -EBUSY;
 
/* find ME client we're trying to connect to */
-   me_cl = mei_me_cl_by_uuid(dev, >in_client_uuid);
+   me_cl = mei_me_cl_by_uuid(dev, in_client_uuid);
if (!me_cl) {
dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n",
-   >in_client_uuid);
+   in_client_uuid);
rets = -ENOTTY;
goto end;
}
@@ -434,7 +432,7 @@ static int mei_ioctl_connect_client(struct file *file,
 !dev->allow_fixed_address : !dev->hbm_f_fa_supported;
if (forbidden) {
dev_dbg(dev->dev, "Connection forbidden to FW Client 
UUID = %pUl\n",
-   >in_client_uuid);
+   in_client_uuid);
rets = -ENOTTY;
goto end;
}
@@ -448,7 +446,6 @@ static int mei_ioctl_connect_client(struct file *file,
me_cl->props.max_msg_length);
 
/* prepare the output buffer */
-   client = >out_client_properties;
client->max_msg_length = me_cl->props.max_msg_length;
client->protocol_version = me_cl->props.protocol_version;
dev_dbg(dev->dev, "Can connect?\n");
@@ -460,6 +457,135 @@ static int mei_ioctl_connect_client(struct file *file,
return rets;
 }
 
+/**
+ * mei_vt_support_check - check if client support vtags
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * @dev: mei_device
+ * @uuid: client UUID
+ *
+ * Return:
+ * 0 - supported
+ * -ENOTTY - no such client
+ * -EOPNOTSUPP - vtags are not supported by client
+ */
+static int mei_vt_support_check(struct mei_device *dev, const uuid_le *uuid)
+{
+   struct mei_me_client *me_cl;
+   int ret;
+
+   if (!dev->hbm_f_vt_supported)
+   return -EOPNOTSUPP;
+
+   me_cl = mei_me_cl_by_uuid(dev, uuid);
+   if (!me_cl) {
+   dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n",
+   uuid);
+   return -ENOTTY;
+   }
+   ret = me_cl->props.vt_supported ? 0 : -EOPNOTSUPP;
+   mei_me_cl_put(me_cl);
+
+   return ret;
+}
+
+/**
+ * mei_ioctl_connect_vtag - connect to fw client with vtag IOCTL function
+ *
+ * @file: private data of the file object
+ * @in_client_uuid: requested UUID for connection
+ * @client: IOCTL connect data, output parameters
+ * @vtag: vm tag
+ *
+ * Locki

[char-misc-next 05/13] mei: bump hbm version to 2.2

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

Bump HBM version to 2.2 to indicate vtag support.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index c3c628132b50..8bac86c4d86b 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -25,7 +25,7 @@
 /*
  * MEI Version
  */
-#define HBM_MINOR_VERSION   1
+#define HBM_MINOR_VERSION   2
 #define HBM_MAJOR_VERSION   2
 
 /*
-- 
2.25.4



[char-misc-next 03/13] mei: add vtag support bit in client properties

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

Vtag support is on a client basis, meaning not every client
supports it. The vtag capability is communicated via the client properties
structure during client enumeration process.
Export the propertiy via sysfs.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 Documentation/ABI/testing/sysfs-bus-mei |  7 +++
 drivers/misc/mei/bus.c  | 11 +++
 drivers/misc/mei/client.h   | 12 
 drivers/misc/mei/debugfs.c  |  7 ---
 drivers/misc/mei/hw.h   | 15 ++-
 5 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-mei 
b/Documentation/ABI/testing/sysfs-bus-mei
index 3d37e2796d5a..6e9a105fe5cb 100644
--- a/Documentation/ABI/testing/sysfs-bus-mei
+++ b/Documentation/ABI/testing/sysfs-bus-mei
@@ -41,6 +41,13 @@ Contact: Tomas Winkler 
 Description:   Stores mei client fixed address, if any
Format: %d
 
+What:  /sys/bus/mei/devices/.../vtag
+Date:  Nov 2020
+KernelVersion: 5.9
+Contact:   Tomas Winkler 
+Description:   Stores mei client vtag support status
+   Format: %d
+
 What:  /sys/bus/mei/devices/.../max_len
 Date:  Nov 2019
 KernelVersion: 5.5
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index a6dfc3ce1db2..2e7ac53a4152 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -810,6 +810,16 @@ static ssize_t fixed_show(struct device *dev, struct 
device_attribute *a,
 }
 static DEVICE_ATTR_RO(fixed);
 
+static ssize_t vtag_show(struct device *dev, struct device_attribute *a,
+char *buf)
+{
+   struct mei_cl_device *cldev = to_mei_cl_device(dev);
+   bool vt = mei_me_cl_vt(cldev->me_cl);
+
+   return sprintf(buf, "%d", vt);
+}
+static DEVICE_ATTR_RO(vtag);
+
 static ssize_t max_len_show(struct device *dev, struct device_attribute *a,
char *buf)
 {
@@ -827,6 +837,7 @@ static struct attribute *mei_cldev_attrs[] = {
_attr_modalias.attr,
_attr_max_conn.attr,
_attr_fixed.attr,
+   _attr_vtag.attr,
_attr_max_len.attr,
NULL,
 };
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 2f8954def591..0d0f36373a4b 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -93,6 +93,18 @@ static inline u8 mei_me_cl_fixed(const struct mei_me_client 
*me_cl)
return me_cl->props.fixed_address;
 }
 
+/**
+ * mei_me_cl_vt - return me client vtag supported status
+ *
+ * @me_cl: me client
+ *
+ * Return: true if me client supports vt tagging
+ */
+static inline bool mei_me_cl_vt(const struct mei_me_client *me_cl)
+{
+   return me_cl->props.vt_supported == 1;
+}
+
 /**
  * mei_me_cl_max_len - return me client max msg length
  *
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index b98f6f9a4896..3ab1a431d810 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -27,7 +27,7 @@ static int mei_dbgfs_meclients_show(struct seq_file *m, void 
*unused)
 
down_read(>me_clients_rwsem);
 
-   seq_puts(m, "  |id|fix| UUID   |con|msg 
len|sb|refc|\n");
+   seq_puts(m, "  |id|fix| UUID   |con|msg 
len|sb|refc|vt|\n");
 
/*  if the driver is not enabled the list won't be consistent */
if (dev->dev_state != MEI_DEV_ENABLED)
@@ -37,14 +37,15 @@ static int mei_dbgfs_meclients_show(struct seq_file *m, 
void *unused)
if (!mei_me_cl_get(me_cl))
continue;
 
-   seq_printf(m, "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d|\n",
+   seq_printf(m, "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d|%2d|\n",
   i++, me_cl->client_id,
   me_cl->props.fixed_address,
   _cl->props.protocol_name,
   me_cl->props.max_number_of_connections,
   me_cl->props.max_msg_length,
   me_cl->props.single_recv_buf,
-  kref_read(_cl->refcnt));
+  kref_read(_cl->refcnt),
+  me_cl->props.vt_supported);
mei_me_cl_put(me_cl);
}
 
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index 13e4cb68a0e6..ea0a2e459282 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -314,13 +314,26 @@ struct hbm_host_enum_response {
u8 valid_addresses[32];
 } __packed;
 
+/**
+ * struct mei_client_properties - mei client properties
+ *
+ * @protocol_name: guid of the client
+ * @protocol_version: client protocol version
+ * @max_number_of_connections: number of possible connections.
+ * @fixed_address: fixed me address (0 if the client is dynamic)
+ * @single

[char-misc-next 02/13] mei: restrict vtag support to hbm version 2.2

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

The vtag allows partitioning the mei messages into virtual groups/channels.
Vtags are supported for firmwares with HBM version 2.2 and newer
and only when a firmware confirms the support via capability handshake.
This change only define vtag restrictions in order to make
the series bisectable. Everything will be enabled when driver HBM
version is set to 2.2.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/debugfs.c |  1 +
 drivers/misc/mei/hbm.c | 15 +++
 drivers/misc/mei/hw.h  |  9 +
 drivers/misc/mei/mei_dev.h |  2 ++
 4 files changed, 27 insertions(+)

diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index 72ee572ad9b4..b98f6f9a4896 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -103,6 +103,7 @@ static int mei_dbgfs_devstate_show(struct seq_file *m, void 
*unused)
seq_printf(m, "\tFA: %01d\n", dev->hbm_f_fa_supported);
seq_printf(m, "\tOS: %01d\n", dev->hbm_f_os_supported);
seq_printf(m, "\tDR: %01d\n", dev->hbm_f_dr_supported);
+   seq_printf(m, "\tVT: %01d\n", dev->hbm_f_vt_supported);
seq_printf(m, "\tCAP: %01d\n", dev->hbm_f_cap_supported);
}
 
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 3a227d9363d5..0513b8a4ea88 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -342,6 +342,8 @@ static int mei_hbm_capabilities_req(struct mei_device *dev)
 
memset(, 0, sizeof(req));
req.hbm_cmd = MEI_HBM_CAPABILITIES_REQ_CMD;
+   if (dev->hbm_f_vt_supported)
+   req.capability_requested[0] = HBM_CAP_VT;
 
ret = mei_hbm_write_message(dev, _hdr, );
if (ret) {
@@ -1074,6 +1076,14 @@ static void mei_hbm_config_features(struct mei_device 
*dev)
 dev->version.minor_version >= HBM_MINOR_VERSION_DR))
dev->hbm_f_dr_supported = 1;
 
+   /* VTag Support */
+   dev->hbm_f_vt_supported = 0;
+   if (dev->version.major_version > HBM_MAJOR_VERSION_VT ||
+   (dev->version.major_version == HBM_MAJOR_VERSION_VT &&
+dev->version.minor_version >= HBM_MINOR_VERSION_VT))
+   dev->hbm_f_vt_supported = 1;
+
+   /* Capability message Support */
dev->hbm_f_cap_supported = 0;
if (dev->version.major_version > HBM_MAJOR_VERSION_CAP ||
(dev->version.major_version == HBM_MAJOR_VERSION_CAP &&
@@ -1112,6 +1122,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct 
mei_msg_hdr *hdr)
struct hbm_host_enum_response *enum_res;
struct hbm_dma_setup_response *dma_setup_res;
struct hbm_add_client_request *add_cl_req;
+   struct hbm_capability_response *capability_res;
int ret;
 
struct mei_hbm_cl_cmd *cl_cmd;
@@ -1214,6 +1225,10 @@ int mei_hbm_dispatch(struct mei_device *dev, struct 
mei_msg_hdr *hdr)
return -EPROTO;
}
 
+   capability_res = (struct hbm_capability_response *)mei_msg;
+   if (!(capability_res->capability_granted[0] & HBM_CAP_VT))
+   dev->hbm_f_vt_supported = 0;
+
if (dev->hbm_f_dr_supported) {
if (mei_dmam_ring_alloc(dev))
dev_info(dev->dev, "running w/o dma ring\n");
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index 539d89ba1c61..13e4cb68a0e6 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -76,6 +76,12 @@
 #define HBM_MINOR_VERSION_DR   1
 #define HBM_MAJOR_VERSION_DR   2
 
+/*
+ * MEI version with vm tag support
+ */
+#define HBM_MINOR_VERSION_VT   2
+#define HBM_MAJOR_VERSION_VT   2
+
 /*
  * MEI version with capabilities message support
  */
@@ -542,6 +548,9 @@ struct hbm_dma_ring_ctrl {
u32 reserved4;
 } __packed;
 
+/* virtual tag supported */
+#define HBM_CAP_VT BIT(0)
+
 /**
  * struct hbm_capability_request - capability request from host to fw
  *
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index e18af7dfd9ff..f80cc6463f18 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -426,6 +426,7 @@ struct mei_fw_version {
  * @hbm_f_ie_supported  : hbm feature immediate reply to enum request
  * @hbm_f_os_supported  : hbm feature support OS ver message
  * @hbm_f_dr_supported  : hbm feature dma ring supported
+ * @hbm_f_vt_supported  : hbm feature vtag supported
  * @hbm_f_cap_supported : hbm feature capabilities message supported
  *
  * @fw_ver : FW versions
@@ -511,6 +512,7 @@ struct mei_device {
unsigned int hbm_f_ie_supported:1;
unsigned int hbm_f_os_supported:1;
unsigned int hbm_f_dr_supported:1;
+   unsigned int hbm_f_vt_supported:1;
unsigned int hbm_f_cap_supported:1;
 
struct mei_fw_version fw_ver[MEI_MAX_FW_VER_BLOCKS];
-- 
2.25.4



[char-misc-next 07/13] mei: add a vtag map for each client

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

Vtag map is a list of tuples of vtag and file pointer (struct
mei_cl_vtag) associated with a particular me host client.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/client.c  | 168 -
 drivers/misc/mei/client.h  |   3 +
 drivers/misc/mei/main.c|  68 ++-
 drivers/misc/mei/mei_dev.h |  17 
 4 files changed, 251 insertions(+), 5 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 276021f99666..3904fce18261 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -354,6 +354,27 @@ static inline void mei_tx_cb_dequeue(struct mei_cl_cb *cb)
mei_io_cb_free(cb);
 }
 
+/**
+ * mei_cl_set_read_by_fp - set pending_read flag to vtag struct for given fp
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * @cl: mei client
+ * @fp: pointer to file structure
+ */
+static void mei_cl_set_read_by_fp(const struct mei_cl *cl,
+ const struct file *fp)
+{
+   struct mei_cl_vtag *cl_vtag;
+
+   list_for_each_entry(cl_vtag, >vtag_map, list) {
+   if (cl_vtag->fp == fp) {
+   cl_vtag->pending_read = true;
+   return;
+   }
+   }
+}
+
 /**
  * mei_io_cb_init - allocate and initialize io callback
  *
@@ -435,6 +456,19 @@ static void mei_io_list_free_fp(struct list_head *head, 
const struct file *fp)
mei_io_cb_free(cb);
 }
 
+/**
+ * mei_cl_free_pending - free pending cb
+ *
+ * @cl: host client
+ */
+static void mei_cl_free_pending(struct mei_cl *cl)
+{
+   struct mei_cl_cb *cb;
+
+   cb = list_first_entry_or_null(>rd_pending, struct mei_cl_cb, list);
+   mei_io_cb_free(cb);
+}
+
 /**
  * mei_cl_alloc_cb - a convenient wrapper for allocating read cb
  *
@@ -544,7 +578,9 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct 
file *fp)
mei_io_tx_list_free_cl(>dev->write_waiting_list, cl);
mei_io_list_flush_cl(>dev->ctrl_wr_list, cl);
mei_io_list_flush_cl(>dev->ctrl_rd_list, cl);
-   mei_io_list_free_fp(>rd_pending, fp);
+   /* free pending cb only in final flush */
+   if (!fp)
+   mei_cl_free_pending(cl);
spin_lock(>rd_completed_lock);
mei_io_list_free_fp(>rd_completed, fp);
spin_unlock(>rd_completed_lock);
@@ -565,6 +601,7 @@ static void mei_cl_init(struct mei_cl *cl, struct 
mei_device *dev)
init_waitqueue_head(>rx_wait);
init_waitqueue_head(>tx_wait);
init_waitqueue_head(>ev_wait);
+   INIT_LIST_HEAD(>vtag_map);
spin_lock_init(>rd_completed_lock);
INIT_LIST_HEAD(>rd_completed);
INIT_LIST_HEAD(>rd_pending);
@@ -1237,8 +1274,117 @@ static int mei_cl_tx_flow_ctrl_creds_reduce(struct 
mei_cl *cl)
return 0;
 }
 
+/**
+ * mei_cl_vtag_alloc - allocate and fill the vtag structure
+ *
+ * @fp: pointer to file structure
+ * @vtag: vm tag
+ *
+ * Return:
+ * * Pointer to allocated struct - on success
+ * * ERR_PTR(-ENOMEM) on memory allocation failure
+ */
+struct mei_cl_vtag *mei_cl_vtag_alloc(struct file *fp, u8 vtag)
+{
+   struct mei_cl_vtag *cl_vtag;
+
+   cl_vtag = kzalloc(sizeof(*cl_vtag), GFP_KERNEL);
+   if (!cl_vtag)
+   return ERR_PTR(-ENOMEM);
+
+   INIT_LIST_HEAD(_vtag->list);
+   cl_vtag->vtag = vtag;
+   cl_vtag->fp = fp;
+
+   return cl_vtag;
+}
+
+/**
+ * mei_cl_fp_by_vtag - obtain the file pointer by vtag
+ *
+ * @cl: host client
+ * @vtag: vm tag
+ *
+ * Return:
+ * * A file pointer - on success
+ * * ERR_PTR(-ENOENT) if vtag is not found in the client vtag list
+ */
+const struct file *mei_cl_fp_by_vtag(const struct mei_cl *cl, u8 vtag)
+{
+   struct mei_cl_vtag *vtag_l;
+
+   list_for_each_entry(vtag_l, >vtag_map, list)
+   if (vtag_l->vtag == vtag)
+   return vtag_l->fp;
+
+   return ERR_PTR(-ENOENT);
+}
+
+/**
+ * mei_cl_reset_read_by_vtag - reset pending_read flag by given vtag
+ *
+ * @cl: host client
+ * @vtag: vm tag
+ */
+static void mei_cl_reset_read_by_vtag(const struct mei_cl *cl, u8 vtag)
+{
+   struct mei_cl_vtag *vtag_l;
+
+   list_for_each_entry(vtag_l, >vtag_map, list) {
+   if (vtag_l->vtag == vtag) {
+   vtag_l->pending_read = false;
+   break;
+   }
+   }
+}
+
+/**
+ * mei_cl_read_vtag_add_fc - add flow control for next pending reader
+ *   in the vtag list
+ *
+ * @cl: host client
+ */
+static void mei_cl_read_vtag_add_fc(struct mei_cl *cl)
+{
+   struct mei_cl_vtag *cl_vtag;
+
+   list_for_each_entry(cl_vtag, >vtag_map, list) {
+   if (cl_vtag->pending_read) {
+   

[char-misc-next 01/13] mei: hbm: add capabilities message

2020-08-18 Thread Tomas Winkler
From: Alexander Usyskin 

The new capabilities command in HBM version 2.2 allows
performing capabilities handshake between the firmware
and the host driver. The driver requests a capability
by setting the appropriate bit in 24bit wide bitmask and
the fw responses with the bit set providing the requested
capability is supported.

Bump copyright year in affected files.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/debugfs.c |  1 +
 drivers/misc/mei/hbm.c | 72 ++
 drivers/misc/mei/hbm.h |  2 ++
 drivers/misc/mei/hw.h  | 31 
 drivers/misc/mei/mei_dev.h |  2 ++
 5 files changed, 108 insertions(+)

diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index a26c716c61a1..72ee572ad9b4 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -103,6 +103,7 @@ static int mei_dbgfs_devstate_show(struct seq_file *m, void 
*unused)
seq_printf(m, "\tFA: %01d\n", dev->hbm_f_fa_supported);
seq_printf(m, "\tOS: %01d\n", dev->hbm_f_os_supported);
seq_printf(m, "\tDR: %01d\n", dev->hbm_f_dr_supported);
+   seq_printf(m, "\tCAP: %01d\n", dev->hbm_f_cap_supported);
}
 
seq_printf(m, "pg:  %s, %s\n",
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 308caee86920..3a227d9363d5 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -325,6 +325,37 @@ static int mei_hbm_dma_setup_req(struct mei_device *dev)
return 0;
 }
 
+/**
+ * mei_hbm_capabilities_req - request capabilities
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success and < 0 on failure
+ */
+static int mei_hbm_capabilities_req(struct mei_device *dev)
+{
+   struct mei_msg_hdr mei_hdr;
+   struct hbm_capability_request req;
+   int ret;
+
+   mei_hbm_hdr(_hdr, sizeof(req));
+
+   memset(, 0, sizeof(req));
+   req.hbm_cmd = MEI_HBM_CAPABILITIES_REQ_CMD;
+
+   ret = mei_hbm_write_message(dev, _hdr, );
+   if (ret) {
+   dev_err(dev->dev,
+   "capabilities request write failed: ret = %d.\n", ret);
+   return ret;
+   }
+
+   dev->hbm_state = MEI_HBM_CAP_SETUP;
+   dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
+   mei_schedule_stall_timer(dev);
+   return 0;
+}
+
 /**
  * mei_hbm_enum_clients_req - sends enumeration client request message.
  *
@@ -1042,6 +1073,12 @@ static void mei_hbm_config_features(struct mei_device 
*dev)
(dev->version.major_version == HBM_MAJOR_VERSION_DR &&
 dev->version.minor_version >= HBM_MINOR_VERSION_DR))
dev->hbm_f_dr_supported = 1;
+
+   dev->hbm_f_cap_supported = 0;
+   if (dev->version.major_version > HBM_MAJOR_VERSION_CAP ||
+   (dev->version.major_version == HBM_MAJOR_VERSION_CAP &&
+dev->version.minor_version >= HBM_MINOR_VERSION_CAP))
+   dev->hbm_f_cap_supported = 1;
 }
 
 /**
@@ -1138,6 +1175,13 @@ int mei_hbm_dispatch(struct mei_device *dev, struct 
mei_msg_hdr *hdr)
return -EPROTO;
}
 
+   if (dev->hbm_f_cap_supported) {
+   if (mei_hbm_capabilities_req(dev))
+   return -EIO;
+   wake_up(>wait_hbm_start);
+   break;
+   }
+
if (dev->hbm_f_dr_supported) {
if (mei_dmam_ring_alloc(dev))
dev_info(dev->dev, "running w/o dma ring\n");
@@ -1159,6 +1203,34 @@ int mei_hbm_dispatch(struct mei_device *dev, struct 
mei_msg_hdr *hdr)
wake_up(>wait_hbm_start);
break;
 
+   case MEI_HBM_CAPABILITIES_RES_CMD:
+   dev_dbg(dev->dev, "hbm: capabilities response: message 
received.\n");
+
+   dev->init_clients_timer = 0;
+
+   if (dev->hbm_state != MEI_HBM_CAP_SETUP) {
+   dev_err(dev->dev, "hbm: capabilities response: state 
mismatch, [%d, %d]\n",
+   dev->dev_state, dev->hbm_state);
+   return -EPROTO;
+   }
+
+   if (dev->hbm_f_dr_supported) {
+   if (mei_dmam_ring_alloc(dev))
+   dev_info(dev->dev, "running w/o dma ring\n");
+   if (mei_dma_ring_is_allocated(dev)) {
+   if (mei_hbm_dma_setup_req(dev))
+   return -EIO;
+   break;
+   }
+   }
+
+   dev->hbm_f_dr_supported = 0;
+   mei_dmam_ring_free(dev)

[char-misc-next 00/13] mei: add support for virtual tags

2020-08-18 Thread Tomas Winkler
Add support for mei virtualization for ACRN but might be used for other 
purposes such as sandboxing.
ACRN is an open-source hypervisor maintained by The Linux Foundation.
The support for ACRN was added in kernel in v5.3.
The patches were part of the ACRN service OS kernel for a while.
https://github.com/projectacrn/acrn-kernel

Only selected platforms, notable for IoT usage, such as APL-I, have
firmware that supports vtags.


Alexander Usyskin (10):
  mei: hbm: add capabilities message
  mei: restrict vtag support to hbm version 2.2
  mei: add vtag support bit in client properties
  mei: bump hbm version to 2.2
  mei: add a spin lock to protect rd_completed queue
  mei: add a vtag map for each client
  mei: handle tx queue flushing for vtag connections
  mei: bus: use zero vtag for bus clients.
  mei: bus: unconditionally enable clients with vtag support
  mei: add connect with vtag ioctl

Tomas Winkler (3):
  mei: add support for mei extended header.
  mei: docs: add vtag ioctl documentation
  mei: virtio: virtualization frontend driver

 Documentation/ABI/testing/sysfs-bus-mei |   7 +
 Documentation/driver-api/mei/mei.rst|  37 +
 drivers/misc/mei/Kconfig|  10 +
 drivers/misc/mei/Makefile   |   3 +
 drivers/misc/mei/bus-fixup.c|  12 +
 drivers/misc/mei/bus.c  |  89 ++-
 drivers/misc/mei/client.c   | 423 ++--
 drivers/misc/mei/client.h   |  22 +-
 drivers/misc/mei/debugfs.c  |   9 +-
 drivers/misc/mei/hbm.c  | 101 ++-
 drivers/misc/mei/hbm.h  |   2 +
 drivers/misc/mei/hw-virtio.c| 874 
 drivers/misc/mei/hw.h   | 150 +++-
 drivers/misc/mei/interrupt.c| 113 ++-
 drivers/misc/mei/main.c | 284 +++-
 drivers/misc/mei/mei_dev.h  |  34 +-
 include/uapi/linux/mei.h|  49 ++
 17 files changed, 2084 insertions(+), 135 deletions(-)
 create mode 100644 drivers/misc/mei/hw-virtio.c

-- 
2.25.4



[char-misc V5] mei: hdcp: fix mei_hdcp_verify_mprime() input parameter

2020-08-18 Thread Tomas Winkler
wired_cmd_repeater_auth_stream_req_in has a variable
length array at the end. we use struct_size() overflow
macro to determine the size for the allocation and sending
size.
This also fixes bug in case number of streams is > 0 in the original
submission. This bug was not triggered as the number of streams is
always one.

Fixes: c56967d674e3 (mei: hdcp: Replace one-element array with flexible-array 
member)
Fixes: 0a1af1b5c18d (misc/mei/hdcp: Verify M_prime)
Cc:  # v5.1+: c56967d674e3 (mei: hdcp: Replace 
one-element array with flexible-array member)
Signed-off-by: Tomas Winkler 
Reviewed-by: Gustavo A. R. Silva 
---
V5:
1. Add reference to depending patch for stable
V4:
1. Fix typo in the subject. (Gustavo)
2. Fix dereferencing pointer in send. (Gustavo)
V3:
1. Fix commit message with more info and another patch it fixes 
(Gustavo) 2. Target stable. (Gustavo)
V2:
1. Check for allocation failure.

 drivers/misc/mei/hdcp/mei_hdcp.c | 40 +++-
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index d1d3e025ca0e..9ae9669e46ea 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -546,38 +546,46 @@ static int mei_hdcp_verify_mprime(struct device *dev,
  struct hdcp_port_data *data,
  struct hdcp2_rep_stream_ready *stream_ready)
 {
-   struct wired_cmd_repeater_auth_stream_req_in
-   verify_mprime_in = { { 0 } };
+   struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
struct wired_cmd_repeater_auth_stream_req_out
verify_mprime_out = { { 0 } };
struct mei_cl_device *cldev;
ssize_t byte;
+   size_t cmd_size;
 
if (!dev || !stream_ready || !data)
return -EINVAL;
 
cldev = to_mei_cl_device(dev);
 
-   verify_mprime_in.header.api_version = HDCP_API_VERSION;
-   verify_mprime_in.header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
-   verify_mprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
-   verify_mprime_in.header.buffer_len =
+   cmd_size = struct_size(verify_mprime_in, streams, data->k);
+   if (cmd_size == SIZE_MAX)
+   return -EINVAL;
+
+   verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);
+   if (!verify_mprime_in)
+   return -ENOMEM;
+
+   verify_mprime_in->header.api_version = HDCP_API_VERSION;
+   verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
+   verify_mprime_in->header.status = ME_HDCP_STATUS_SUCCESS;
+   verify_mprime_in->header.buffer_len =
WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN;
 
-   verify_mprime_in.port.integrated_port_type = data->port_type;
-   verify_mprime_in.port.physical_port = (u8)data->fw_ddi;
-   verify_mprime_in.port.attached_transcoder = (u8)data->fw_tc;
+   verify_mprime_in->port.integrated_port_type = data->port_type;
+   verify_mprime_in->port.physical_port = (u8)data->fw_ddi;
+   verify_mprime_in->port.attached_transcoder = (u8)data->fw_tc;
+
+   memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, 
HDCP_2_2_MPRIME_LEN);
+   drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);
 
-   memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
-  HDCP_2_2_MPRIME_LEN);
-   drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m);
-   memcpy(verify_mprime_in.streams, data->streams,
+   memcpy(verify_mprime_in->streams, data->streams,
   array_size(data->k, sizeof(*data->streams)));
 
-   verify_mprime_in.k = cpu_to_be16(data->k);
+   verify_mprime_in->k = cpu_to_be16(data->k);
 
-   byte = mei_cldev_send(cldev, (u8 *)_mprime_in,
- sizeof(verify_mprime_in));
+   byte = mei_cldev_send(cldev, (u8 *)verify_mprime_in, cmd_size);
+   kfree(verify_mprime_in);
if (byte < 0) {
dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
return byte;
-- 
2.25.4



[char-misc-next V4] mei: hdcp: fix mei_hdcp_verify_mprime() input parameter

2020-07-30 Thread Tomas Winkler
wired_cmd_repeater_auth_stream_req_in has a variable
length array at the end. we use struct_size() overflow
macro to determine the size for the allocation and sending
size.
This also fixes bug in case number of streams is > 0 in the original
submission. This bug was not triggered as the number of streams is
always one.

Fixes: c56967d674e3 (mei: hdcp: Replace one-element array with flexible-array 
member)
Fixes: commit 0a1af1b5c18d ("misc/mei/hdcp: Verify M_prime")
Cc: "Gustavo A. R. Silva" 
Cc: Ramalingam C 
Cc:  v5.1+
Signed-off-by: Tomas Winkler 
---
V4:
1. Fix typo in the subject. (Gustavo)
2. Fix dereferencing pointer in send. (Gustavo)
V3:
1. Fix commit message with more info and another patch it fixes (Gustavo)
2. Target stable. (Gustavo)
V2: Check for allocation failure.

 drivers/misc/mei/hdcp/mei_hdcp.c | 40 +++-
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index d1d3e025ca0e..9ae9669e46ea 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -546,38 +546,46 @@ static int mei_hdcp_verify_mprime(struct device *dev,
  struct hdcp_port_data *data,
  struct hdcp2_rep_stream_ready *stream_ready)
 {
-   struct wired_cmd_repeater_auth_stream_req_in
-   verify_mprime_in = { { 0 } };
+   struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
struct wired_cmd_repeater_auth_stream_req_out
verify_mprime_out = { { 0 } };
struct mei_cl_device *cldev;
ssize_t byte;
+   size_t cmd_size;
 
if (!dev || !stream_ready || !data)
return -EINVAL;
 
cldev = to_mei_cl_device(dev);
 
-   verify_mprime_in.header.api_version = HDCP_API_VERSION;
-   verify_mprime_in.header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
-   verify_mprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
-   verify_mprime_in.header.buffer_len =
+   cmd_size = struct_size(verify_mprime_in, streams, data->k);
+   if (cmd_size == SIZE_MAX)
+   return -EINVAL;
+
+   verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);
+   if (!verify_mprime_in)
+   return -ENOMEM;
+
+   verify_mprime_in->header.api_version = HDCP_API_VERSION;
+   verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
+   verify_mprime_in->header.status = ME_HDCP_STATUS_SUCCESS;
+   verify_mprime_in->header.buffer_len =
WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN;
 
-   verify_mprime_in.port.integrated_port_type = data->port_type;
-   verify_mprime_in.port.physical_port = (u8)data->fw_ddi;
-   verify_mprime_in.port.attached_transcoder = (u8)data->fw_tc;
+   verify_mprime_in->port.integrated_port_type = data->port_type;
+   verify_mprime_in->port.physical_port = (u8)data->fw_ddi;
+   verify_mprime_in->port.attached_transcoder = (u8)data->fw_tc;
+
+   memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, 
HDCP_2_2_MPRIME_LEN);
+   drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);
 
-   memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
-  HDCP_2_2_MPRIME_LEN);
-   drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m);
-   memcpy(verify_mprime_in.streams, data->streams,
+   memcpy(verify_mprime_in->streams, data->streams,
   array_size(data->k, sizeof(*data->streams)));
 
-   verify_mprime_in.k = cpu_to_be16(data->k);
+   verify_mprime_in->k = cpu_to_be16(data->k);
 
-   byte = mei_cldev_send(cldev, (u8 *)_mprime_in,
- sizeof(verify_mprime_in));
+   byte = mei_cldev_send(cldev, (u8 *)verify_mprime_in, cmd_size);
+   kfree(verify_mprime_in);
if (byte < 0) {
dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
return byte;
-- 
2.25.4



[char-misc-next] mei: hdcp: fix mei_hdcp_verify_mprime() input parameter

2020-07-30 Thread Tomas Winkler
wired_cmd_repeater_auth_stream_req_in has a variable
length array at the end. we use struct_size() overflow
macro to determine the size for the allocation and sending
size.
This also fixes bug in case number of streams is > 0 in the original
submission. This bug was not triggered as the number of streams is
always one.

Fixes: c56967d674e3 (mei: hdcp: Replace one-element array with flexible-array 
member)
Fixes: commit 0a1af1b5c18d ("misc/mei/hdcp: Verify M_prime")
Cc: "Gustavo A. R. Silva" 
Cc: Ramalingam C 
Cc:  v5.1+
Signed-off-by: Tomas Winkler 
---
V4:
1. Fix typo in the subject. (Gustavo)
2. Fix dereferencing pointer in send. (Gustavo)
V3:
1. Fix commit message with more info and another patch it fixes (Gustavo)
2. Target stable. (Gustavo)
V2: Check for allocation failure.

 drivers/misc/mei/hdcp/mei_hdcp.c | 40 +++-
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index d1d3e025ca0e..9ae9669e46ea 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -546,38 +546,46 @@ static int mei_hdcp_verify_mprime(struct device *dev,
  struct hdcp_port_data *data,
  struct hdcp2_rep_stream_ready *stream_ready)
 {
-   struct wired_cmd_repeater_auth_stream_req_in
-   verify_mprime_in = { { 0 } };
+   struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
struct wired_cmd_repeater_auth_stream_req_out
verify_mprime_out = { { 0 } };
struct mei_cl_device *cldev;
ssize_t byte;
+   size_t cmd_size;
 
if (!dev || !stream_ready || !data)
return -EINVAL;
 
cldev = to_mei_cl_device(dev);
 
-   verify_mprime_in.header.api_version = HDCP_API_VERSION;
-   verify_mprime_in.header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
-   verify_mprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
-   verify_mprime_in.header.buffer_len =
+   cmd_size = struct_size(verify_mprime_in, streams, data->k);
+   if (cmd_size == SIZE_MAX)
+   return -EINVAL;
+
+   verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);
+   if (!verify_mprime_in)
+   return -ENOMEM;
+
+   verify_mprime_in->header.api_version = HDCP_API_VERSION;
+   verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
+   verify_mprime_in->header.status = ME_HDCP_STATUS_SUCCESS;
+   verify_mprime_in->header.buffer_len =
WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN;
 
-   verify_mprime_in.port.integrated_port_type = data->port_type;
-   verify_mprime_in.port.physical_port = (u8)data->fw_ddi;
-   verify_mprime_in.port.attached_transcoder = (u8)data->fw_tc;
+   verify_mprime_in->port.integrated_port_type = data->port_type;
+   verify_mprime_in->port.physical_port = (u8)data->fw_ddi;
+   verify_mprime_in->port.attached_transcoder = (u8)data->fw_tc;
+
+   memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, 
HDCP_2_2_MPRIME_LEN);
+   drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);
 
-   memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
-  HDCP_2_2_MPRIME_LEN);
-   drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m);
-   memcpy(verify_mprime_in.streams, data->streams,
+   memcpy(verify_mprime_in->streams, data->streams,
   array_size(data->k, sizeof(*data->streams)));
 
-   verify_mprime_in.k = cpu_to_be16(data->k);
+   verify_mprime_in->k = cpu_to_be16(data->k);
 
-   byte = mei_cldev_send(cldev, (u8 *)_mprime_in,
- sizeof(verify_mprime_in));
+   byte = mei_cldev_send(cldev, (u8 *)verify_mprime_in, cmd_size);
+   kfree(verify_mprime_in);
if (byte < 0) {
dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
return byte;
-- 
2.25.4



[char-misc-next V3] mei: hdcp: fix mei_hdcp_verify_mprime() input paramter

2020-07-30 Thread Tomas Winkler
wired_cmd_repeater_auth_stream_req_in has a variable
length array at the end. we use struct_size() overflow
macro to determine the size for the allocation and sending
size.
This also fixes bug in case number of streams is > 0 in the original
submission. This bug was not triggered as the number of streams is
always one.

Fixes: c56967d674e3 (mei: hdcp: Replace one-element array with flexible-array 
member)
Fixes: 0a1af1b5c18d ("misc/mei/hdcp: Verify M_prime")
Cc: "Gustavo A. R. Silva" 
Cc: Ramalingam C 
Cc:  v5.1+
Signed-off-by: Tomas Winkler 
---
V3:
1. Fix commit message with more info and another patch it fixes (Gustavo)
2. Target stable. (Gustavo)
V2: Check for allocation failure.
 drivers/misc/mei/hdcp/mei_hdcp.c | 40 +++-
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index d1d3e025ca0e..f1205e0060db 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -546,38 +546,46 @@ static int mei_hdcp_verify_mprime(struct device *dev,
  struct hdcp_port_data *data,
  struct hdcp2_rep_stream_ready *stream_ready)
 {
-   struct wired_cmd_repeater_auth_stream_req_in
-   verify_mprime_in = { { 0 } };
+   struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
struct wired_cmd_repeater_auth_stream_req_out
verify_mprime_out = { { 0 } };
struct mei_cl_device *cldev;
ssize_t byte;
+   size_t cmd_size;
 
if (!dev || !stream_ready || !data)
return -EINVAL;
 
cldev = to_mei_cl_device(dev);
 
-   verify_mprime_in.header.api_version = HDCP_API_VERSION;
-   verify_mprime_in.header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
-   verify_mprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
-   verify_mprime_in.header.buffer_len =
+   cmd_size = struct_size(verify_mprime_in, streams, data->k);
+   if (cmd_size == SIZE_MAX)
+   return -EINVAL;
+
+   verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);
+   if (!verify_mprime_in)
+   return -ENOMEM;
+
+   verify_mprime_in->header.api_version = HDCP_API_VERSION;
+   verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
+   verify_mprime_in->header.status = ME_HDCP_STATUS_SUCCESS;
+   verify_mprime_in->header.buffer_len =
WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN;
 
-   verify_mprime_in.port.integrated_port_type = data->port_type;
-   verify_mprime_in.port.physical_port = (u8)data->fw_ddi;
-   verify_mprime_in.port.attached_transcoder = (u8)data->fw_tc;
+   verify_mprime_in->port.integrated_port_type = data->port_type;
+   verify_mprime_in->port.physical_port = (u8)data->fw_ddi;
+   verify_mprime_in->port.attached_transcoder = (u8)data->fw_tc;
+
+   memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, 
HDCP_2_2_MPRIME_LEN);
+   drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);
 
-   memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
-  HDCP_2_2_MPRIME_LEN);
-   drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m);
-   memcpy(verify_mprime_in.streams, data->streams,
+   memcpy(verify_mprime_in->streams, data->streams,
   array_size(data->k, sizeof(*data->streams)));
 
-   verify_mprime_in.k = cpu_to_be16(data->k);
+   verify_mprime_in->k = cpu_to_be16(data->k);
 
-   byte = mei_cldev_send(cldev, (u8 *)_mprime_in,
- sizeof(verify_mprime_in));
+   byte = mei_cldev_send(cldev, (u8 *)_mprime_in, cmd_size);
+   kfree(verify_mprime_in);
if (byte < 0) {
dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
return byte;
-- 
2.25.4



[char-misc-next V2] mei: hdcp: fix mei_hdcp_verify_mprime() input paramter

2020-07-30 Thread Tomas Winkler
wired_cmd_repeater_auth_stream_req_in has a variable
length array at the end. we use struct_size() overflow
macro to determine the size for the allocation and sending
size.

Fixes: c56967d674e3 (mei: hdcp: Replace one-element array with flexible-array 
member)
Fixes: c56967d674e3 (mei: hdcp: Replace one-element array with flexible-array 
member)
Cc: Ramalingam C 
Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
V2: Check for allocation failure.
 drivers/misc/mei/hdcp/mei_hdcp.c | 40 +++-
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index d1d3e025ca0e..f1205e0060db 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -546,38 +546,46 @@ static int mei_hdcp_verify_mprime(struct device *dev,
  struct hdcp_port_data *data,
  struct hdcp2_rep_stream_ready *stream_ready)
 {
-   struct wired_cmd_repeater_auth_stream_req_in
-   verify_mprime_in = { { 0 } };
+   struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
struct wired_cmd_repeater_auth_stream_req_out
verify_mprime_out = { { 0 } };
struct mei_cl_device *cldev;
ssize_t byte;
+   size_t cmd_size;
 
if (!dev || !stream_ready || !data)
return -EINVAL;
 
cldev = to_mei_cl_device(dev);
 
-   verify_mprime_in.header.api_version = HDCP_API_VERSION;
-   verify_mprime_in.header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
-   verify_mprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
-   verify_mprime_in.header.buffer_len =
+   cmd_size = struct_size(verify_mprime_in, streams, data->k);
+   if (cmd_size == SIZE_MAX)
+   return -EINVAL;
+
+   verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);
+   if (!verify_mprime_in)
+   return -ENOMEM;
+
+   verify_mprime_in->header.api_version = HDCP_API_VERSION;
+   verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
+   verify_mprime_in->header.status = ME_HDCP_STATUS_SUCCESS;
+   verify_mprime_in->header.buffer_len =
WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN;
 
-   verify_mprime_in.port.integrated_port_type = data->port_type;
-   verify_mprime_in.port.physical_port = (u8)data->fw_ddi;
-   verify_mprime_in.port.attached_transcoder = (u8)data->fw_tc;
+   verify_mprime_in->port.integrated_port_type = data->port_type;
+   verify_mprime_in->port.physical_port = (u8)data->fw_ddi;
+   verify_mprime_in->port.attached_transcoder = (u8)data->fw_tc;
+
+   memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, 
HDCP_2_2_MPRIME_LEN);
+   drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);
 
-   memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
-  HDCP_2_2_MPRIME_LEN);
-   drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m);
-   memcpy(verify_mprime_in.streams, data->streams,
+   memcpy(verify_mprime_in->streams, data->streams,
   array_size(data->k, sizeof(*data->streams)));
 
-   verify_mprime_in.k = cpu_to_be16(data->k);
+   verify_mprime_in->k = cpu_to_be16(data->k);
 
-   byte = mei_cldev_send(cldev, (u8 *)_mprime_in,
- sizeof(verify_mprime_in));
+   byte = mei_cldev_send(cldev, (u8 *)_mprime_in, cmd_size);
+   kfree(verify_mprime_in);
if (byte < 0) {
dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
return byte;
-- 
2.25.4



[char-misc-next] mei: hdcp: fix mei_hdcp_verify_mprime() input paramter

2020-07-29 Thread Tomas Winkler
wired_cmd_repeater_auth_stream_req_in has a variable
length array at the end. we use struct_size() overflow
macro to determine the size for the allocation and sending
size.

Fixes: c56967d674e3 (mei: hdcp: Replace one-element array with flexible-array 
member)
Cc: Ramalingam C 
Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 38 ++--
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index d1d3e025ca0e..0e8f12e38494 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -546,38 +546,44 @@ static int mei_hdcp_verify_mprime(struct device *dev,
  struct hdcp_port_data *data,
  struct hdcp2_rep_stream_ready *stream_ready)
 {
-   struct wired_cmd_repeater_auth_stream_req_in
-   verify_mprime_in = { { 0 } };
+   struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
struct wired_cmd_repeater_auth_stream_req_out
verify_mprime_out = { { 0 } };
struct mei_cl_device *cldev;
ssize_t byte;
+   size_t cmd_size;
 
if (!dev || !stream_ready || !data)
return -EINVAL;
 
cldev = to_mei_cl_device(dev);
 
-   verify_mprime_in.header.api_version = HDCP_API_VERSION;
-   verify_mprime_in.header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
-   verify_mprime_in.header.status = ME_HDCP_STATUS_SUCCESS;
-   verify_mprime_in.header.buffer_len =
+   cmd_size = struct_size(verify_mprime_in, streams, data->k);
+   if (cmd_size == SIZE_MAX)
+   return -EINVAL;
+
+   verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);
+
+   verify_mprime_in->header.api_version = HDCP_API_VERSION;
+   verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
+   verify_mprime_in->header.status = ME_HDCP_STATUS_SUCCESS;
+   verify_mprime_in->header.buffer_len =
WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN;
 
-   verify_mprime_in.port.integrated_port_type = data->port_type;
-   verify_mprime_in.port.physical_port = (u8)data->fw_ddi;
-   verify_mprime_in.port.attached_transcoder = (u8)data->fw_tc;
+   verify_mprime_in->port.integrated_port_type = data->port_type;
+   verify_mprime_in->port.physical_port = (u8)data->fw_ddi;
+   verify_mprime_in->port.attached_transcoder = (u8)data->fw_tc;
+
+   memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, 
HDCP_2_2_MPRIME_LEN);
+   drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);
 
-   memcpy(verify_mprime_in.m_prime, stream_ready->m_prime,
-  HDCP_2_2_MPRIME_LEN);
-   drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m);
-   memcpy(verify_mprime_in.streams, data->streams,
+   memcpy(verify_mprime_in->streams, data->streams,
   array_size(data->k, sizeof(*data->streams)));
 
-   verify_mprime_in.k = cpu_to_be16(data->k);
+   verify_mprime_in->k = cpu_to_be16(data->k);
 
-   byte = mei_cldev_send(cldev, (u8 *)_mprime_in,
- sizeof(verify_mprime_in));
+   byte = mei_cldev_send(cldev, (u8 *)_mprime_in, cmd_size);
+   kfree(verify_mprime_in);
if (byte < 0) {
dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
return byte;
-- 
2.25.4



[char-misc-next] MAINTAINERS: Fix maintainer entry for mei driver

2020-07-29 Thread Tomas Winkler
mei driver has sub modules, those are not
listed via scripts/get_maintainer.pl when using asterisk:
drivers/misc/mei/*
The correct notation is:
drivers/misc/mei/

Cc: Joe Perches 
Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 86994c35d56e..dbe6a71eb6f2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8789,7 +8789,7 @@ M:Tomas Winkler 
 L: linux-kernel@vger.kernel.org
 S: Supported
 F: Documentation/driver-api/mei/*
-F: drivers/misc/mei/*
+F: drivers/misc/mei/
 F: drivers/watchdog/mei_wdt.c
 F: include/linux/mei_cl_bus.h
 F: include/uapi/linux/mei.h
-- 
2.25.4



[char-misc-next] Revert "mei: hdcp: Replace one-element array with flexible-array member"

2020-07-28 Thread Tomas Winkler
Greg please revert, this commit it changes size of
struct wired_cmd_repeater_auth_stream_req_in, this is
not what firmware is expecting.
I really do not appreciate that the code is bypassing
driver maintaner review, I think this is a minimum
we can ask for, this is not for a first time.

This reverts commit c56967d674e361ebe716e66992e3c5332b25ac1f.

Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 2 +-
 drivers/misc/mei/hdcp/mei_hdcp.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index d1d3e025ca0e..e6c3dc595617 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -572,7 +572,7 @@ static int mei_hdcp_verify_mprime(struct device *dev,
   HDCP_2_2_MPRIME_LEN);
drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m);
memcpy(verify_mprime_in.streams, data->streams,
-  array_size(data->k, sizeof(*data->streams)));
+  (data->k * sizeof(struct hdcp2_streamid_type)));
 
verify_mprime_in.k = cpu_to_be16(data->k);
 
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h b/drivers/misc/mei/hdcp/mei_hdcp.h
index 834757f5e072..18ffc773fa18 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.h
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -358,7 +358,7 @@ struct wired_cmd_repeater_auth_stream_req_in {
u8  seq_num_m[HDCP_2_2_SEQ_NUM_LEN];
u8  m_prime[HDCP_2_2_MPRIME_LEN];
__be16  k;
-   struct hdcp2_streamid_type  streams[];
+   struct hdcp2_streamid_type  streams[1];
 } __packed;
 
 struct wired_cmd_repeater_auth_stream_req_out {
-- 
2.25.4



[char-misc-next V3] mei: add device kind to sysfs

2020-07-28 Thread Tomas Winkler
From: Alexander Usyskin 

Some of the mei device heads are not generic and have
a specific purpose, we need to announce it to the user space
so it is possible to detect the correct device node via
matching attributes.

Generic heads are marked as 'mei' while special purpose heads
have their own names. Currently we are adding 'itouch' string
for Intel IPTS 1.0, 2.0 devices.

This is done via new sysfs attribute 'kind'.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
V2:
1. Send the correct patch.
V3:
1. Remove redundant lock from kind_show(). (Greg)
2. Don't initialize ret variable. (Greg)

 Documentation/ABI/testing/sysfs-class-mei | 13 
 drivers/misc/mei/hw-me.c  | 22 
 drivers/misc/mei/hw-me.h  |  7 ++-
 drivers/misc/mei/main.c   | 25 +++
 drivers/misc/mei/mei_dev.h|  4 
 drivers/misc/mei/pci-me.c | 10 -
 6 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-mei 
b/Documentation/ABI/testing/sysfs-class-mei
index e9dc110650ae..5c52372b43cb 100644
--- a/Documentation/ABI/testing/sysfs-class-mei
+++ b/Documentation/ABI/testing/sysfs-class-mei
@@ -90,3 +90,16 @@ Description: Display trc status register content
The ME FW writes Glitch Detection HW (TRC)
status information into trc status register
for BIOS and OS to monitor fw health.
+
+What:  /sys/class/mei/meiN/kind
+Date:  Jul 2020
+KernelVersion: 5.8
+Contact:   Tomas Winkler 
+Description:   Display kind of the device
+
+   Generic devices are marked as "mei"
+   while special purpose have their own
+   names.
+   Available options:
+   - mei:  generic mei device.
+   - itouch:  itouch (ipts) mei device.
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 7692b69abcb5..cda0829ac589 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1430,6 +1430,9 @@ static bool mei_me_fw_type_sps(const struct pci_dev *pdev)
return fw_type == PCI_CFG_HFS_3_FW_SKU_SPS;
 }
 
+#define MEI_CFG_KIND_ITOUCH \
+   .kind = "itouch"
+
 #define MEI_CFG_FW_SPS  \
.quirk_probe = mei_me_fw_type_sps
 
@@ -1499,6 +1502,13 @@ static const struct mei_cfg mei_me_pch8_cfg = {
MEI_CFG_FW_VER_SUPP,
 };
 
+/* PCH8 Lynx Point and newer devices - iTouch */
+static const struct mei_cfg mei_me_pch8_itouch_cfg = {
+   MEI_CFG_KIND_ITOUCH,
+   MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
+};
+
 /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */
 static const struct mei_cfg mei_me_pch8_sps_4_cfg = {
MEI_CFG_PCH8_HFS,
@@ -1528,10 +1538,11 @@ static const struct mei_cfg mei_me_pch12_sps_cfg = {
MEI_CFG_FW_SPS,
 };
 
-/* Cannon Lake with quirk for SPS 5.0 and newer Firmware exclusion
- * w/o DMA support
+/* Cannon Lake itouch with quirk for SPS 5.0 and newer Firmware exclusion
+ * w/o DMA support.
  */
-static const struct mei_cfg mei_me_pch12_nodma_sps_cfg = {
+static const struct mei_cfg mei_me_pch12_itouch_sps_cfg = {
+   MEI_CFG_KIND_ITOUCH,
MEI_CFG_PCH8_HFS,
MEI_CFG_FW_VER_SUPP,
MEI_CFG_FW_SPS,
@@ -1566,11 +1577,12 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_PCH7_CFG] = _me_pch7_cfg,
[MEI_ME_PCH_CPT_PBG_CFG] = _me_pch_cpt_pbg_cfg,
[MEI_ME_PCH8_CFG] = _me_pch8_cfg,
+   [MEI_ME_PCH8_ITOUCH_CFG] = _me_pch8_itouch_cfg,
[MEI_ME_PCH8_SPS_4_CFG] = _me_pch8_sps_4_cfg,
[MEI_ME_PCH12_CFG] = _me_pch12_cfg,
[MEI_ME_PCH12_SPS_4_CFG] = _me_pch12_sps_4_cfg,
[MEI_ME_PCH12_SPS_CFG] = _me_pch12_sps_cfg,
-   [MEI_ME_PCH12_SPS_NODMA_CFG] = _me_pch12_nodma_sps_cfg,
+   [MEI_ME_PCH12_SPS_ITOUCH_CFG] = _me_pch12_itouch_sps_cfg,
[MEI_ME_PCH15_CFG] = _me_pch15_cfg,
[MEI_ME_PCH15_SPS_CFG] = _me_pch15_sps_cfg,
 };
@@ -1614,6 +1626,8 @@ struct mei_device *mei_me_dev_init(struct device *parent,
 
dev->fw_f_fw_ver_supported = cfg->fw_ver_supported;
 
+   dev->kind = cfg->kind;
+
return dev;
 }
 
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 560c8ebb17be..00a7132ac7a2 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -19,6 +19,7 @@
  *
  * @fw_status: FW status
  * @quirk_probe: device exclusion quirk
+ * @kind: MEI head kind
  * @dma_size: device DMA buffers size
  * @fw_ver_supported: is fw version retrievable from FW
  * @hw_trc_supported: does the hw support trc register
@@ -26,6 +27,7 @@
 struct mei_cfg {
const struct mei_fw_status fw_status;
bool (*quirk_probe)(const struct pci_dev *pdev);
+   const char *kind;
size_t dma_size[DMA_DSCR_NUM];
u32 fw_ver_supported

[char-misc-next V2] mei: add device kind to sysfs

2020-07-28 Thread Tomas Winkler
From: Alexander Usyskin 

Some of the mei device heads are not generic and have
a specific purpose, we need to announce it to the user space
so it is possible to detect the correct device node via
matching attributes.

Generic heads are marked as 'mei' while special purpose heads
have their own names. Currently we are adding 'itouch' string
for Intel IPTS 1.0, 2.0 devices.

This is done via new sysfs attribute 'kind'.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
V2: Correct version of the patch.

 Documentation/ABI/testing/sysfs-class-mei | 13 +++
 drivers/misc/mei/hw-me.c  | 22 ++
 drivers/misc/mei/hw-me.h  |  7 +-
 drivers/misc/mei/main.c   | 27 +++
 drivers/misc/mei/mei_dev.h|  4 
 drivers/misc/mei/pci-me.c | 10 -
 6 files changed, 73 insertions(+), 10 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-mei 
b/Documentation/ABI/testing/sysfs-class-mei
index e9dc110650ae..5c52372b43cb 100644
--- a/Documentation/ABI/testing/sysfs-class-mei
+++ b/Documentation/ABI/testing/sysfs-class-mei
@@ -90,3 +90,16 @@ Description: Display trc status register content
The ME FW writes Glitch Detection HW (TRC)
status information into trc status register
for BIOS and OS to monitor fw health.
+
+What:  /sys/class/mei/meiN/kind
+Date:  Jul 2020
+KernelVersion: 5.8
+Contact:   Tomas Winkler 
+Description:   Display kind of the device
+
+   Generic devices are marked as "mei"
+   while special purpose have their own
+   names.
+   Available options:
+   - mei:  generic mei device.
+   - itouch:  itouch (ipts) mei device.
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 7692b69abcb5..cda0829ac589 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1430,6 +1430,9 @@ static bool mei_me_fw_type_sps(const struct pci_dev *pdev)
return fw_type == PCI_CFG_HFS_3_FW_SKU_SPS;
 }
 
+#define MEI_CFG_KIND_ITOUCH \
+   .kind = "itouch"
+
 #define MEI_CFG_FW_SPS  \
.quirk_probe = mei_me_fw_type_sps
 
@@ -1499,6 +1502,13 @@ static const struct mei_cfg mei_me_pch8_cfg = {
MEI_CFG_FW_VER_SUPP,
 };
 
+/* PCH8 Lynx Point and newer devices - iTouch */
+static const struct mei_cfg mei_me_pch8_itouch_cfg = {
+   MEI_CFG_KIND_ITOUCH,
+   MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
+};
+
 /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */
 static const struct mei_cfg mei_me_pch8_sps_4_cfg = {
MEI_CFG_PCH8_HFS,
@@ -1528,10 +1538,11 @@ static const struct mei_cfg mei_me_pch12_sps_cfg = {
MEI_CFG_FW_SPS,
 };
 
-/* Cannon Lake with quirk for SPS 5.0 and newer Firmware exclusion
- * w/o DMA support
+/* Cannon Lake itouch with quirk for SPS 5.0 and newer Firmware exclusion
+ * w/o DMA support.
  */
-static const struct mei_cfg mei_me_pch12_nodma_sps_cfg = {
+static const struct mei_cfg mei_me_pch12_itouch_sps_cfg = {
+   MEI_CFG_KIND_ITOUCH,
MEI_CFG_PCH8_HFS,
MEI_CFG_FW_VER_SUPP,
MEI_CFG_FW_SPS,
@@ -1566,11 +1577,12 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_PCH7_CFG] = _me_pch7_cfg,
[MEI_ME_PCH_CPT_PBG_CFG] = _me_pch_cpt_pbg_cfg,
[MEI_ME_PCH8_CFG] = _me_pch8_cfg,
+   [MEI_ME_PCH8_ITOUCH_CFG] = _me_pch8_itouch_cfg,
[MEI_ME_PCH8_SPS_4_CFG] = _me_pch8_sps_4_cfg,
[MEI_ME_PCH12_CFG] = _me_pch12_cfg,
[MEI_ME_PCH12_SPS_4_CFG] = _me_pch12_sps_4_cfg,
[MEI_ME_PCH12_SPS_CFG] = _me_pch12_sps_cfg,
-   [MEI_ME_PCH12_SPS_NODMA_CFG] = _me_pch12_nodma_sps_cfg,
+   [MEI_ME_PCH12_SPS_ITOUCH_CFG] = _me_pch12_itouch_sps_cfg,
[MEI_ME_PCH15_CFG] = _me_pch15_cfg,
[MEI_ME_PCH15_SPS_CFG] = _me_pch15_sps_cfg,
 };
@@ -1614,6 +1626,8 @@ struct mei_device *mei_me_dev_init(struct device *parent,
 
dev->fw_f_fw_ver_supported = cfg->fw_ver_supported;
 
+   dev->kind = cfg->kind;
+
return dev;
 }
 
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 560c8ebb17be..00a7132ac7a2 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -19,6 +19,7 @@
  *
  * @fw_status: FW status
  * @quirk_probe: device exclusion quirk
+ * @kind: MEI head kind
  * @dma_size: device DMA buffers size
  * @fw_ver_supported: is fw version retrievable from FW
  * @hw_trc_supported: does the hw support trc register
@@ -26,6 +27,7 @@
 struct mei_cfg {
const struct mei_fw_status fw_status;
bool (*quirk_probe)(const struct pci_dev *pdev);
+   const char *kind;
size_t dma_size[DMA_DSCR_NUM];
u32 fw_ver_supported:1;
u32 hw_trc_supported:1;
@@ -76,6 +78,8 @@ struct mei_me_hw {
  *

[char-misc-next] mei: add device type

2020-07-28 Thread Tomas Winkler
From: Alexander Usyskin 

Some of the device heads are not generic and have
specific purpose, we need to announce it to the user space
so it can detect and correct device node via matching
attributes.

Generic devices are marked as 'mei' while special
purpose their own names. Currently we are adding
'itouch' string for Intel IPTS devices.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me.c   | 12 
 drivers/misc/mei/hw-me.h   |  5 +
 drivers/misc/mei/hw-txe.c  |  1 +
 drivers/misc/mei/main.c| 27 +++
 drivers/misc/mei/mei_dev.h |  4 
 drivers/misc/mei/pci-me.c  |  8 
 6 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 7692b69abcb5..5c3aa35ba3f4 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1430,6 +1430,9 @@ static bool mei_me_fw_type_sps(const struct pci_dev *pdev)
return fw_type == PCI_CFG_HFS_3_FW_SKU_SPS;
 }
 
+#define MEI_CFG_TYPE_ITOUCH \
+   .type = "itouch"
+
 #define MEI_CFG_FW_SPS  \
.quirk_probe = mei_me_fw_type_sps
 
@@ -1499,6 +1502,13 @@ static const struct mei_cfg mei_me_pch8_cfg = {
MEI_CFG_FW_VER_SUPP,
 };
 
+/* PCH8 Lynx Point and newer devices - iTouch */
+static const struct mei_cfg mei_me_pch8_itouch_cfg = {
+   MEI_CFG_TYPE_ITOUCH,
+   MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
+};
+
 /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */
 static const struct mei_cfg mei_me_pch8_sps_4_cfg = {
MEI_CFG_PCH8_HFS,
@@ -1566,6 +1576,7 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_PCH7_CFG] = _me_pch7_cfg,
[MEI_ME_PCH_CPT_PBG_CFG] = _me_pch_cpt_pbg_cfg,
[MEI_ME_PCH8_CFG] = _me_pch8_cfg,
+   [MEI_ME_PCH8_ITOUCH_CFG] = _me_pch8_itouch_cfg,
[MEI_ME_PCH8_SPS_4_CFG] = _me_pch8_sps_4_cfg,
[MEI_ME_PCH12_CFG] = _me_pch12_cfg,
[MEI_ME_PCH12_SPS_4_CFG] = _me_pch12_sps_4_cfg,
@@ -1613,6 +1624,7 @@ struct mei_device *mei_me_dev_init(struct device *parent,
hw->cfg = cfg;
 
dev->fw_f_fw_ver_supported = cfg->fw_ver_supported;
+   dev->type = cfg->type;
 
return dev;
 }
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 560c8ebb17be..fe231b06c449 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -19,6 +19,7 @@
  *
  * @fw_status: FW status
  * @quirk_probe: device exclusion quirk
+ * @type: MEI head type
  * @dma_size: device DMA buffers size
  * @fw_ver_supported: is fw version retrievable from FW
  * @hw_trc_supported: does the hw support trc register
@@ -26,6 +27,7 @@
 struct mei_cfg {
const struct mei_fw_status fw_status;
bool (*quirk_probe)(const struct pci_dev *pdev);
+   const char *type;
size_t dma_size[DMA_DSCR_NUM];
u32 fw_ver_supported:1;
u32 hw_trc_supported:1;
@@ -76,6 +78,8 @@ struct mei_me_hw {
  * with quirk for Node Manager exclusion.
  * @MEI_ME_PCH8_CFG:   Platform Controller Hub Gen8 and newer
  * client platforms.
+ * @MEI_ME_PCH8_ITOUCH_CFG:Platform Controller Hub Gen8 and newer
+ * client platforms (iTouch).
  * @MEI_ME_PCH8_SPS_4_CFG: Platform Controller Hub Gen8 and newer
  * servers platforms with quirk for
  * SPS firmware exclusion.
@@ -100,6 +104,7 @@ enum mei_cfg_idx {
MEI_ME_PCH7_CFG,
MEI_ME_PCH_CPT_PBG_CFG,
MEI_ME_PCH8_CFG,
+   MEI_ME_PCH8_ITOUCH_CFG,
MEI_ME_PCH8_SPS_4_CFG,
MEI_ME_PCH12_CFG,
MEI_ME_PCH12_SPS_4_CFG,
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index a4e854b9b9e6..6fe2810b2d43 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -1206,6 +1206,7 @@ struct mei_device *mei_txe_dev_init(struct pci_dev *pdev)
return NULL;
 
mei_device_init(dev, >dev, _txe_hw_ops);
+   dev->type = "txe";
 
hw = to_txe_hw(dev);
 
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 05e6ad6d4d54..fc34c19c618d 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -885,6 +885,32 @@ void mei_set_devstate(struct mei_device *dev, enum 
mei_dev_state state)
}
 }
 
+/**
+ * type_show - display device type
+ *
+ * @device: device pointer
+ * @attr: attribute pointer
+ * @buf: char out buffer
+ *
+ * Return: number of the bytes printed into buf or error
+ */
+static ssize_t type_show(struct device *device,
+struct device_attribute *attr, char *buf)
+{
+   struct mei_device *dev = dev_get_drvdata(device);
+   ssize_t ret = 0;
+
+   mutex_lock(>device_lock);
+   if (dev->type)
+   ret = sprintf(buf, "%s\n", dev->type);

[char-misc-next 6/6] mei: hw: don't use one element arrays

2020-07-23 Thread Tomas Winkler
Replace the single element arrays with a simple value type u8 reserved,
even thought is is not used for dynamically sized trailing elements
it confuses the effort of replacing one-element arrays with
flexible arrays for that purpose.

Link: https://github.com/KSPP/linux/issues/79
Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index b1a8d5ec88b3..26fa92cb7f7a 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (c) 2003-2018, Intel Corporation. All rights reserved
+ * Copyright (c) 2003-2020, Intel Corporation. All rights reserved
  * Intel Management Engine Interface (Intel MEI) Linux driver
  */
 
@@ -319,7 +319,7 @@ struct hbm_props_response {
u8 hbm_cmd;
u8 me_addr;
u8 status;
-   u8 reserved[1];
+   u8 reserved;
struct mei_client_properties client_properties;
 } __packed;
 
@@ -352,7 +352,7 @@ struct hbm_add_client_response {
u8 hbm_cmd;
u8 me_addr;
u8 status;
-   u8 reserved[1];
+   u8 reserved;
 } __packed;
 
 /**
@@ -461,7 +461,7 @@ struct hbm_notification {
u8 hbm_cmd;
u8 me_addr;
u8 host_addr;
-   u8 reserved[1];
+   u8 reserved;
 } __packed;
 
 /**
-- 
2.25.4



[char-misc-next 5/6] mei: hw: use sizeof of variable instead of struct type

2020-07-23 Thread Tomas Winkler
Use sizeof(*dev) + sizeof(*hw) instead of
sizeof(struct mei_device) + sizeof(struct mei_me_hw)

There is a possibility of bug when variable type has changed but
corresponding struct passed to the sizeof has not.

Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me.c  | 5 ++---
 drivers/misc/mei/hw-txe.c | 5 ++---
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index c51d3da8f333..7692b69abcb5 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2003-2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2003-2020, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
  */
 
@@ -1600,8 +1600,7 @@ struct mei_device *mei_me_dev_init(struct device *parent,
struct mei_me_hw *hw;
int i;
 
-   dev = devm_kzalloc(parent, sizeof(struct mei_device) +
-  sizeof(struct mei_me_hw), GFP_KERNEL);
+   dev = devm_kzalloc(parent, sizeof(*dev) + sizeof(*hw), GFP_KERNEL);
if (!dev)
return NULL;
 
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index 785b260b3ae9..a4e854b9b9e6 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2013-2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2013-2020, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
  */
 
@@ -1201,8 +1201,7 @@ struct mei_device *mei_txe_dev_init(struct pci_dev *pdev)
struct mei_device *dev;
struct mei_txe_hw *hw;
 
-   dev = devm_kzalloc(>dev, sizeof(struct mei_device) +
-  sizeof(struct mei_txe_hw), GFP_KERNEL);
+   dev = devm_kzalloc(>dev, sizeof(*dev) + sizeof(*hw), GFP_KERNEL);
if (!dev)
return NULL;
 
-- 
2.25.4



[char-misc-next 2/6] mei: ioctl: use sizeof of variable instead of struct type

2020-07-23 Thread Tomas Winkler
Use sizeof(connect_data))) instead of
sizeof(struct mei_connect_client_data) when copying data
between user space and kernel.

There is a possibility of bug when variable type has changed but
corresponding struct passed to the sizeof has not.

Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/main.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index f17297f2943d..05e6ad6d4d54 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2003-2018, Intel Corporation. All rights reserved.
+ * Copyright (c) 2003-2020, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
  */
 
@@ -476,7 +476,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, 
unsigned long data)
case IOCTL_MEI_CONNECT_CLIENT:
dev_dbg(dev->dev, ": IOCTL_MEI_CONNECT_CLIENT.\n");
if (copy_from_user(_data, (char __user *)data,
-   sizeof(struct mei_connect_client_data))) {
+  sizeof(connect_data))) {
dev_dbg(dev->dev, "failed to copy data from 
userland\n");
rets = -EFAULT;
goto out;
@@ -488,7 +488,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, 
unsigned long data)
 
/* if all is ok, copying the data back to user. */
if (copy_to_user((char __user *)data, _data,
-   sizeof(struct mei_connect_client_data))) {
+sizeof(connect_data))) {
dev_dbg(dev->dev, "failed to copy data to userland\n");
rets = -EFAULT;
goto out;
-- 
2.25.4



[char-misc-next 4/6] mei: client: use sizeof of variable instead of struct type

2020-07-23 Thread Tomas Winkler
There is a possibility of bug when variable type has changed but
corresponding struct passed to the sizeof has not.

Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/client.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index b32c825a0945..2572887d99b6 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2003-2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2003-2020, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
  */
 
@@ -369,7 +369,7 @@ static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl,
 {
struct mei_cl_cb *cb;
 
-   cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+   cb = kzalloc(sizeof(*cb), GFP_KERNEL);
if (!cb)
return NULL;
 
@@ -552,7 +552,7 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct 
file *fp)
  */
 static void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
 {
-   memset(cl, 0, sizeof(struct mei_cl));
+   memset(cl, 0, sizeof(*cl));
init_waitqueue_head(>wait);
init_waitqueue_head(>rx_wait);
init_waitqueue_head(>tx_wait);
@@ -575,7 +575,7 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
 {
struct mei_cl *cl;
 
-   cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
+   cl = kmalloc(sizeof(*cl), GFP_KERNEL);
if (!cl)
return NULL;
 
-- 
2.25.4



[char-misc-next 3/6] mei: bus: use sizeof of variable instead of struct type

2020-07-23 Thread Tomas Winkler
There is a possibility of bug when variable type has changed but
corresponding struct passed to the sizeof has not.

Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus-fixup.c | 23 +++
 drivers/misc/mei/bus.c   |  2 +-
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 910f059b3384..07ba16d46690 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2013-2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2013-2020, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
  */
 
@@ -159,17 +159,17 @@ static int mei_osver(struct mei_cl_device *cldev)
 static int mei_fwver(struct mei_cl_device *cldev)
 {
char buf[MKHI_FWVER_BUF_LEN];
-   struct mkhi_msg *req;
+   struct mkhi_msg req;
+   struct mkhi_msg *rsp;
struct mkhi_fw_ver *fwver;
int bytes_recv, ret, i;
 
memset(buf, 0, sizeof(buf));
 
-   req = (struct mkhi_msg *)buf;
-   req->hdr.group_id = MKHI_GEN_GROUP_ID;
-   req->hdr.command = MKHI_GEN_GET_FW_VERSION_CMD;
+   req.hdr.group_id = MKHI_GEN_GROUP_ID;
+   req.hdr.command = MKHI_GEN_GET_FW_VERSION_CMD;
 
-   ret = __mei_cl_send(cldev->cl, buf, sizeof(struct mkhi_msg_hdr),
+   ret = __mei_cl_send(cldev->cl, (u8 *), sizeof(req),
MEI_CL_IO_TX_BLOCKING);
if (ret < 0) {
dev_err(>dev, "Could not send ReqFWVersion cmd\n");
@@ -188,7 +188,8 @@ static int mei_fwver(struct mei_cl_device *cldev)
return -EIO;
}
 
-   fwver = (struct mkhi_fw_ver *)req->data;
+   rsp = (struct mkhi_msg *)buf;
+   fwver = (struct mkhi_fw_ver *)rsp->data;
memset(cldev->bus->fw_ver, 0, sizeof(cldev->bus->fw_ver));
for (i = 0; i < MEI_MAX_FW_VER_BLOCKS; i++) {
if ((size_t)bytes_recv < MKHI_FWVER_LEN(i + 1))
@@ -329,16 +330,14 @@ static int mei_nfc_if_version(struct mei_cl *cl,
 
WARN_ON(mutex_is_locked(>device_lock));
 
-   ret = __mei_cl_send(cl, (u8 *), sizeof(struct mei_nfc_cmd),
-   MEI_CL_IO_TX_BLOCKING);
+   ret = __mei_cl_send(cl, (u8 *), sizeof(cmd), MEI_CL_IO_TX_BLOCKING);
if (ret < 0) {
dev_err(bus->dev, "Could not send IF version cmd\n");
return ret;
}
 
/* to be sure on the stack we alloc memory */
-   if_version_length = sizeof(struct mei_nfc_reply) +
-   sizeof(struct mei_nfc_if_version);
+   if_version_length = sizeof(*reply) + sizeof(*ver);
 
reply = kzalloc(if_version_length, GFP_KERNEL);
if (!reply)
@@ -352,7 +351,7 @@ static int mei_nfc_if_version(struct mei_cl *cl,
goto err;
}
 
-   memcpy(ver, reply->data, sizeof(struct mei_nfc_if_version));
+   memcpy(ver, reply->data, sizeof(*ver));
 
dev_info(bus->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 
0x%x\n",
ver->fw_ivn, ver->vendor_id, ver->radio_type);
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index f476dbc7252b..a6dfc3ce1db2 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -931,7 +931,7 @@ static struct mei_cl_device *mei_cl_bus_dev_alloc(struct 
mei_device *bus,
struct mei_cl_device *cldev;
struct mei_cl *cl;
 
-   cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
+   cldev = kzalloc(sizeof(*cldev), GFP_KERNEL);
if (!cldev)
return NULL;
 
-- 
2.25.4



[char-misc-next 0/6] mei: remove one-element arrays

2020-07-23 Thread Tomas Winkler


1. Remove one-element arrays from hw.h
2. Adjust to preferred method of getting size of structure
from memory allocation and movement. sizeof(*var) 
instead of sizeof(struct some_struct)


Tomas Winkler (6):
  mei: hbm: use sizeof of variable instead of struct type
  mei: ioctl: use sizeof of variable instead of struct type
  mei: bus: use sizeof of variable instead of struct type
  mei: client: use sizeof of variable instead of struct type
  mei: hw: use sizeof of variable instead of struct type
  mei: hw: don't use one element arrays

 drivers/misc/mei/bus-fixup.c | 23 ++-
 drivers/misc/mei/bus.c   |  2 +-
 drivers/misc/mei/client.c|  8 ++--
 drivers/misc/mei/hbm.c   | 74 
 drivers/misc/mei/hw-me.c |  5 +--
 drivers/misc/mei/hw-txe.c|  5 +--
 drivers/misc/mei/hw.h|  8 ++--
 drivers/misc/mei/main.c  |  6 +--
 8 files changed, 59 insertions(+), 72 deletions(-)

-- 
2.25.4



[char-misc-next 1/6] mei: hbm: use sizeof of variable instead of struct type

2020-07-23 Thread Tomas Winkler
There is a possibility of bug when variable type has changed but
corresponding struct passed to the sizeof has not.

Cc: Gustavo A. R. Silva 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hbm.c | 74 ++
 1 file changed, 32 insertions(+), 42 deletions(-)

diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index a44094cdbc36..308caee86920 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2003-2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2003-2020, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
  */
 #include 
@@ -257,22 +257,21 @@ int mei_hbm_start_wait(struct mei_device *dev)
 int mei_hbm_start_req(struct mei_device *dev)
 {
struct mei_msg_hdr mei_hdr;
-   struct hbm_host_version_request start_req;
-   const size_t len = sizeof(struct hbm_host_version_request);
+   struct hbm_host_version_request req;
int ret;
 
mei_hbm_reset(dev);
 
-   mei_hbm_hdr(_hdr, len);
+   mei_hbm_hdr(_hdr, sizeof(req));
 
/* host start message */
-   memset(_req, 0, len);
-   start_req.hbm_cmd = HOST_START_REQ_CMD;
-   start_req.host_version.major_version = HBM_MAJOR_VERSION;
-   start_req.host_version.minor_version = HBM_MINOR_VERSION;
+   memset(, 0, sizeof(req));
+   req.hbm_cmd = HOST_START_REQ_CMD;
+   req.host_version.major_version = HBM_MAJOR_VERSION;
+   req.host_version.minor_version = HBM_MINOR_VERSION;
 
dev->hbm_state = MEI_HBM_IDLE;
-   ret = mei_hbm_write_message(dev, _hdr, _req);
+   ret = mei_hbm_write_message(dev, _hdr, );
if (ret) {
dev_err(dev->dev, "version message write failed: ret = %d\n",
ret);
@@ -295,13 +294,12 @@ static int mei_hbm_dma_setup_req(struct mei_device *dev)
 {
struct mei_msg_hdr mei_hdr;
struct hbm_dma_setup_request req;
-   const size_t len = sizeof(struct hbm_dma_setup_request);
unsigned int i;
int ret;
 
-   mei_hbm_hdr(_hdr, len);
+   mei_hbm_hdr(_hdr, sizeof(req));
 
-   memset(, 0, len);
+   memset(, 0, sizeof(req));
req.hbm_cmd = MEI_HBM_DMA_SETUP_REQ_CMD;
for (i = 0; i < DMA_DSCR_NUM; i++) {
phys_addr_t paddr;
@@ -337,21 +335,19 @@ static int mei_hbm_dma_setup_req(struct mei_device *dev)
 static int mei_hbm_enum_clients_req(struct mei_device *dev)
 {
struct mei_msg_hdr mei_hdr;
-   struct hbm_host_enum_request enum_req;
-   const size_t len = sizeof(struct hbm_host_enum_request);
+   struct hbm_host_enum_request req;
int ret;
 
/* enumerate clients */
-   mei_hbm_hdr(_hdr, len);
+   mei_hbm_hdr(_hdr, sizeof(req));
 
-   memset(_req, 0, len);
-   enum_req.hbm_cmd = HOST_ENUM_REQ_CMD;
-   enum_req.flags |= dev->hbm_f_dc_supported ?
- MEI_HBM_ENUM_F_ALLOW_ADD : 0;
-   enum_req.flags |= dev->hbm_f_ie_supported ?
+   memset(, 0, sizeof(req));
+   req.hbm_cmd = HOST_ENUM_REQ_CMD;
+   req.flags |= dev->hbm_f_dc_supported ? MEI_HBM_ENUM_F_ALLOW_ADD : 0;
+   req.flags |= dev->hbm_f_ie_supported ?
  MEI_HBM_ENUM_F_IMMEDIATE_ENUM : 0;
 
-   ret = mei_hbm_write_message(dev, _hdr, _req);
+   ret = mei_hbm_write_message(dev, _hdr, );
if (ret) {
dev_err(dev->dev, "enumeration request write failed: ret = 
%d.\n",
ret);
@@ -380,7 +376,7 @@ static int mei_hbm_me_cl_add(struct mei_device *dev,
 
mei_me_cl_rm_by_uuid(dev, uuid);
 
-   me_cl = kzalloc(sizeof(struct mei_me_client), GFP_KERNEL);
+   me_cl = kzalloc(sizeof(*me_cl), GFP_KERNEL);
if (!me_cl)
return -ENOMEM;
 
@@ -408,14 +404,13 @@ static int mei_hbm_add_cl_resp(struct mei_device *dev, u8 
addr, u8 status)
 {
struct mei_msg_hdr mei_hdr;
struct hbm_add_client_response resp;
-   const size_t len = sizeof(struct hbm_add_client_response);
int ret;
 
dev_dbg(dev->dev, "adding client response\n");
 
-   mei_hbm_hdr(_hdr, len);
+   mei_hbm_hdr(_hdr, sizeof(resp));
 
-   memset(, 0, sizeof(struct hbm_add_client_response));
+   memset(, 0, sizeof(resp));
resp.hbm_cmd = MEI_HBM_ADD_CLIENT_RES_CMD;
resp.me_addr = addr;
resp.status  = status;
@@ -469,11 +464,10 @@ int mei_hbm_cl_notify_req(struct mei_device *dev,
 
struct mei_msg_hdr mei_hdr;
struct hbm_notification_request req;
-   const size_t len = sizeof(struct hbm_notification_request);
int ret;
 
-   mei_hbm_hdr(_hdr, len);
-   mei_hbm_cl_hdr(cl, MEI_HBM_NOTIFY_REQ_CMD, , len);
+   mei_hbm_hdr(_hdr, sizeof(req));
+   mei_hbm_cl_hdr(cl, MEI_HBM_NOTIFY_REQ_CMD, , size

[char-misc-next] mei: bus: don't clean driver pointer

2020-06-28 Thread Tomas Winkler
From: Alexander Usyskin 

It's not needed to set driver to NULL in mei_cl_device_remove()
which is bus_type remove() handler as this is done anyway
in __device_release_driver().

Actually this is causing an endless loop in driver_detach()
on ubuntu patched kernel, while removing (rmmod) the mei_hdcp module.
The reason list_empty(>p->klist_devices.k_list) is always not-empty.
as the check is always true in  __device_release_driver()
if (dev->driver != drv)
return;

The non upstream patch is causing this behavior, titled:
'vfio -- release device lock before userspace requests'

Nevertheless the fix is correct also for the upstream.

Link: 
https://patchwork.ozlabs.org/project/ubuntu-kernel/patch/20180912085046.3401-2-...@canonical.com/
Cc: 
Cc: Andy Whitcroft 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 8d468e0a950a..f476dbc7252b 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -745,9 +745,8 @@ static int mei_cl_device_remove(struct device *dev)
 
mei_cl_bus_module_put(cldev);
module_put(THIS_MODULE);
-   dev->driver = NULL;
-   return ret;
 
+   return ret;
 }
 
 static ssize_t name_show(struct device *dev, struct device_attribute *a,
-- 
2.25.4



[char-misc-next 1/7] mei: me: disable mei interface on Mehlow server platforms

2020-06-19 Thread Tomas Winkler
For SPS firmware versions 5.0 and newer the way detection has changed.
The detection is done now via PCI_CFG_HFS_3 register.
To prevent conflict the previous method will get sps_4 suffix
Disable both CNP_H and CNP_H_3 interfaces. CNP_H_3 requires
a separate configuration as it doesn't support DMA.

Cc: 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me-regs.h |  2 ++
 drivers/misc/mei/hw-me.c  | 60 +++
 drivers/misc/mei/hw-me.h  | 13 +---
 drivers/misc/mei/pci-me.c | 16 +-
 4 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 9392934e3a06..01b1bf74f262 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -107,6 +107,8 @@
 #  define PCI_CFG_HFS_1_D0I3_MSK 0x8000
 #define PCI_CFG_HFS_2 0x48
 #define PCI_CFG_HFS_3 0x60
+#  define PCI_CFG_HFS_3_FW_SKU_MSK   0x0070
+#  define PCI_CFG_HFS_3_FW_SKU_SPS   0x0060
 #define PCI_CFG_HFS_4 0x64
 #define PCI_CFG_HFS_5 0x68
 #define PCI_CFG_HFS_6 0x6C
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index f620442addf5..f8155c1e811d 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1366,7 +1366,7 @@ static bool mei_me_fw_type_nm(struct pci_dev *pdev)
 #define MEI_CFG_FW_NM   \
.quirk_probe = mei_me_fw_type_nm
 
-static bool mei_me_fw_type_sps(struct pci_dev *pdev)
+static bool mei_me_fw_type_sps_4(struct pci_dev *pdev)
 {
u32 reg;
unsigned int devfn;
@@ -1382,7 +1382,36 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev)
return (reg & 0xf) == 0xf;
 }
 
-#define MEI_CFG_FW_SPS   \
+#define MEI_CFG_FW_SPS_4  \
+   .quirk_probe = mei_me_fw_type_sps_4
+
+/**
+ * mei_me_fw_sku_sps() - check for sps sku
+ *
+ * Read ME FW Status register to check for SPS Firmware.
+ * The SPS FW is only signaled in pci function 0
+ *
+ * @pdev: pci device
+ *
+ * Return: true in case of SPS firmware
+ */
+static bool mei_me_fw_type_sps(struct pci_dev *pdev)
+{
+   u32 reg;
+   u32 fw_type;
+   unsigned int devfn;
+
+   devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+   pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_3, );
+   trace_mei_pci_cfg_read(>dev, "PCI_CFG_HFS_3", PCI_CFG_HFS_3, reg);
+   fw_type = (reg & PCI_CFG_HFS_3_FW_SKU_MSK);
+
+   dev_dbg(>dev, "fw type is %d\n", fw_type);
+
+   return fw_type == PCI_CFG_HFS_3_FW_SKU_SPS;
+}
+
+#define MEI_CFG_FW_SPS  \
.quirk_probe = mei_me_fw_type_sps
 
 #define MEI_CFG_FW_VER_SUPP \
@@ -1452,10 +1481,17 @@ static const struct mei_cfg mei_me_pch8_cfg = {
 };
 
 /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */
-static const struct mei_cfg mei_me_pch8_sps_cfg = {
+static const struct mei_cfg mei_me_pch8_sps_4_cfg = {
MEI_CFG_PCH8_HFS,
MEI_CFG_FW_VER_SUPP,
-   MEI_CFG_FW_SPS,
+   MEI_CFG_FW_SPS_4,
+};
+
+/* LBG with quirk for SPS (4.0) Firmware exclusion */
+static const struct mei_cfg mei_me_pch12_sps_4_cfg = {
+   MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
+   MEI_CFG_FW_SPS_4,
 };
 
 /* Cannon Lake and newer devices */
@@ -1465,8 +1501,18 @@ static const struct mei_cfg mei_me_pch12_cfg = {
MEI_CFG_DMA_128,
 };
 
-/* LBG with quirk for SPS Firmware exclusion */
+/* Cannon Lake with quirk for SPS 5.0 and newer Firmware exclusion */
 static const struct mei_cfg mei_me_pch12_sps_cfg = {
+   MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
+   MEI_CFG_DMA_128,
+   MEI_CFG_FW_SPS,
+};
+
+/* Cannon Lake with quirk for SPS 5.0 and newer Firmware exclusion
+ * w/o DMA support
+ */
+static const struct mei_cfg mei_me_pch12_nodma_sps_cfg = {
MEI_CFG_PCH8_HFS,
MEI_CFG_FW_VER_SUPP,
MEI_CFG_FW_SPS,
@@ -1492,9 +1538,11 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_PCH7_CFG] = _me_pch7_cfg,
[MEI_ME_PCH_CPT_PBG_CFG] = _me_pch_cpt_pbg_cfg,
[MEI_ME_PCH8_CFG] = _me_pch8_cfg,
-   [MEI_ME_PCH8_SPS_CFG] = _me_pch8_sps_cfg,
+   [MEI_ME_PCH8_SPS_4_CFG] = _me_pch8_sps_4_cfg,
[MEI_ME_PCH12_CFG] = _me_pch12_cfg,
+   [MEI_ME_PCH12_SPS_4_CFG] = _me_pch12_sps_4_cfg,
[MEI_ME_PCH12_SPS_CFG] = _me_pch12_sps_cfg,
+   [MEI_ME_PCH12_SPS_NODMA_CFG] = _me_pch12_nodma_sps_cfg,
[MEI_ME_PCH15_CFG] = _me_pch15_cfg,
 };
 
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index b6b94e211464..52e0c6d578f2 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (c) 2012-2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2012-2020, Intel Corporation. All rights reserved.
  * Intel Management E

[char-misc-next 3/7] mei: me: make mei_me_fw_sku_sps_4() less cryptic

2020-06-19 Thread Tomas Winkler
Last add mei_me_fw_sku_sps_4() kdoc and add descriptive defines
for register name and values.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me-regs.h |  2 ++
 drivers/misc/mei/hw-me.c  | 18 --
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 01b1bf74f262..64823bdde6af 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -105,6 +105,8 @@
 /* Host Firmware Status Registers in PCI Config Space */
 #define PCI_CFG_HFS_1 0x40
 #  define PCI_CFG_HFS_1_D0I3_MSK 0x8000
+#  define PCI_CFG_HFS_1_OPMODE_MSK 0xf /* OP MODE Mask: SPS <= 4.0 */
+#  define PCI_CFG_HFS_1_OPMODE_SPS 0xf /* SPS SKU : SPS <= 4.0 */
 #define PCI_CFG_HFS_2 0x48
 #define PCI_CFG_HFS_3 0x60
 #  define PCI_CFG_HFS_3_FW_SKU_MSK   0x0070
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index b45143510912..6aa522c0d910 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1366,20 +1366,26 @@ static bool mei_me_fw_type_nm(const struct pci_dev 
*pdev)
 #define MEI_CFG_FW_NM   \
.quirk_probe = mei_me_fw_type_nm
 
+/**
+ * mei_me_fw_sku_sps_4() - check for sps 4.0 sku
+ *
+ * Read ME FW Status register to check for SPS Firmware.
+ * The SPS FW is only signaled in the PCI function 0.
+ * __Note__: Deprecated by SPS 5.0 and newer.
+ *
+ * @pdev: pci device
+ *
+ * Return: true in case of SPS firmware
+ */
 static bool mei_me_fw_type_sps_4(const struct pci_dev *pdev)
 {
u32 reg;
unsigned int devfn;
 
-   /*
-* Read ME FW Status register to check for SPS Firmware
-* The SPS FW is only signaled in pci function 0
-*/
devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_1, );
trace_mei_pci_cfg_read(>dev, "PCI_CFG_HFS_1", PCI_CFG_HFS_1, reg);
-   /* if bits [19:16] = 15, running SPS Firmware */
-   return (reg & 0xf) == 0xf;
+   return (reg & PCI_CFG_HFS_1_OPMODE_MSK) == PCI_CFG_HFS_1_OPMODE_SPS;
 }
 
 #define MEI_CFG_FW_SPS_4  \
-- 
2.25.4



[char-misc-next 5/7] mei: me: add MEI device for SPT with ITPS capability

2020-06-19 Thread Tomas Winkler
Add device ID for Intel Sunrise Point PCH (Skylake) which has
Intel Precise Touch & Stylus IPTS (iTouch).

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me-regs.h | 1 +
 drivers/misc/mei/pci-me.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 64823bdde6af..bf230c5b5eec 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -59,6 +59,7 @@
 
 #define MEI_DEV_ID_SPT0x9D3A  /* Sunrise Point */
 #define MEI_DEV_ID_SPT_2  0x9D3B  /* Sunrise Point 2 */
+#define MEI_DEV_ID_SPT_3  0x9D3E  /* Sunrise Point 3 (iToutch) */
 #define MEI_DEV_ID_SPT_H  0xA13A  /* Sunrise Point H */
 #define MEI_DEV_ID_SPT_H_20xA13B  /* Sunrise Point H 2 */
 
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 1bcc724a18aa..e97abebc949c 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -68,6 +68,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
+   {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_3, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_4_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_4_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_SPS_4_CFG)},
-- 
2.25.4



[char-misc-next 7/7] mei: me: add tiger lake point device ids for H platforms.

2020-06-19 Thread Tomas Winkler
From: Alexander Usyskin 

Add Tiger Lake device ids H for HECI1.
TGH_H is also used in Tatlow SPS platform we need to
disable the mei interface there.

Cc: 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me-regs.h |  1 +
 drivers/misc/mei/hw-me.c  | 10 ++
 drivers/misc/mei/hw-me.h  |  4 
 drivers/misc/mei/pci-me.c |  1 +
 4 files changed, 16 insertions(+)

diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index b86ce504fdd3..9cf8d8f60cfe 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -96,6 +96,7 @@
 #define MEI_DEV_ID_JSP_N  0x4DE0  /* Jasper Lake Point N */
 
 #define MEI_DEV_ID_TGP_LP 0xA0E0  /* Tiger Lake Point LP */
+#define MEI_DEV_ID_TGP_H  0x43E0  /* Tiger Lake Point H */
 
 #define MEI_DEV_ID_MCC0x4B70  /* Mule Creek Canyon (EHL) */
 #define MEI_DEV_ID_MCC_4  0x4B75  /* Mule Creek Canyon 4 (EHL) */
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index e476995e4c56..c51d3da8f333 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1545,6 +1545,15 @@ static const struct mei_cfg mei_me_pch15_cfg = {
MEI_CFG_TRC,
 };
 
+/* Tiger Lake with quirk for SPS 5.0 and newer Firmware exclusion */
+static const struct mei_cfg mei_me_pch15_sps_cfg = {
+   MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
+   MEI_CFG_DMA_128,
+   MEI_CFG_TRC,
+   MEI_CFG_FW_SPS,
+};
+
 /*
  * mei_cfg_list - A list of platform platform specific configurations.
  * Note: has to be synchronized with  enum mei_cfg_idx.
@@ -1563,6 +1572,7 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_PCH12_SPS_CFG] = _me_pch12_sps_cfg,
[MEI_ME_PCH12_SPS_NODMA_CFG] = _me_pch12_nodma_sps_cfg,
[MEI_ME_PCH15_CFG] = _me_pch15_cfg,
+   [MEI_ME_PCH15_SPS_CFG] = _me_pch15_sps_cfg,
 };
 
 const struct mei_cfg *mei_me_get_cfg(kernel_ulong_t idx)
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 4df51cb8fa4b..560c8ebb17be 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -87,6 +87,9 @@ struct mei_me_hw {
  * servers platforms with quirk for
  * SPS firmware exclusion.
  * @MEI_ME_PCH15_CFG:  Platform Controller Hub Gen15 and newer
+ * @MEI_ME_PCH15_SPS_CFG:  Platform Controller Hub Gen15 and newer
+ * servers platforms with quirk for
+ * SPS firmware exclusion.
  * @MEI_ME_NUM_CFG:Upper Sentinel.
  */
 enum mei_cfg_idx {
@@ -103,6 +106,7 @@ enum mei_cfg_idx {
MEI_ME_PCH12_SPS_CFG,
MEI_ME_PCH12_SPS_NODMA_CFG,
MEI_ME_PCH15_CFG,
+   MEI_ME_PCH15_SPS_CFG,
MEI_ME_NUM_CFG,
 };
 
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 188f59a94118..159e40a2505d 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -98,6 +98,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
 
{MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH15_CFG)},
+   {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_H, MEI_ME_PCH15_SPS_CFG)},
 
{MEI_PCI_DEVICE(MEI_DEV_ID_JSP_N, MEI_ME_PCH15_CFG)},
 
-- 
2.25.4



[char-misc-next 2/7] mei: me: constify the device parameter to the probe quirk

2020-06-19 Thread Tomas Winkler
The quirk_probe there is no writing to pci device hence
we can constify the passed pci_dev pointer.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me.c | 6 +++---
 drivers/misc/mei/hw-me.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index f8155c1e811d..b45143510912 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1353,7 +1353,7 @@ static const struct mei_hw_ops mei_me_hw_ops = {
.read = mei_me_read_slots
 };
 
-static bool mei_me_fw_type_nm(struct pci_dev *pdev)
+static bool mei_me_fw_type_nm(const struct pci_dev *pdev)
 {
u32 reg;
 
@@ -1366,7 +1366,7 @@ static bool mei_me_fw_type_nm(struct pci_dev *pdev)
 #define MEI_CFG_FW_NM   \
.quirk_probe = mei_me_fw_type_nm
 
-static bool mei_me_fw_type_sps_4(struct pci_dev *pdev)
+static bool mei_me_fw_type_sps_4(const struct pci_dev *pdev)
 {
u32 reg;
unsigned int devfn;
@@ -1395,7 +1395,7 @@ static bool mei_me_fw_type_sps_4(struct pci_dev *pdev)
  *
  * Return: true in case of SPS firmware
  */
-static bool mei_me_fw_type_sps(struct pci_dev *pdev)
+static bool mei_me_fw_type_sps(const struct pci_dev *pdev)
 {
u32 reg;
u32 fw_type;
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 52e0c6d578f2..4df51cb8fa4b 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -25,7 +25,7 @@
  */
 struct mei_cfg {
const struct mei_fw_status fw_status;
-   bool (*quirk_probe)(struct pci_dev *pdev);
+   bool (*quirk_probe)(const struct pci_dev *pdev);
size_t dma_size[DMA_DSCR_NUM];
u32 fw_ver_supported:1;
u32 hw_trc_supported:1;
-- 
2.25.4



[char-misc-next 4/7] mei: me: add kdoc for mei_me_fw_type_nm()

2020-06-19 Thread Tomas Winkler
Add kdoc for mei_me_fw_type_nm() function.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 6aa522c0d910..e476995e4c56 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1353,11 +1353,24 @@ static const struct mei_hw_ops mei_me_hw_ops = {
.read = mei_me_read_slots
 };
 
+/**
+ * mei_me_fw_type_nm() - check for nm sku
+ *
+ * Read ME FW Status register to check for the Node Manager (NM) Firmware.
+ * The NM FW is only signaled in PCI function 0.
+ * __Note__: Deprecated by PCH8 and newer.
+ *
+ * @pdev: pci device
+ *
+ * Return: true in case of NM firmware
+ */
 static bool mei_me_fw_type_nm(const struct pci_dev *pdev)
 {
u32 reg;
+   unsigned int devfn;
 
-   pci_read_config_dword(pdev, PCI_CFG_HFS_2, );
+   devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
+   pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_2, );
trace_mei_pci_cfg_read(>dev, "PCI_CFG_HFS_2", PCI_CFG_HFS_2, reg);
/* make sure that bit 9 (NM) is up and bit 10 (DM) is down */
return (reg & 0x600) == 0x200;
-- 
2.25.4



[char-misc-next 6/7] mei: me: add MEI device for KBP with ITPS capability

2020-06-19 Thread Tomas Winkler
Add device ID for Intel Kaby Point PCH (Kabylake) which has
Intel Precise Touch & Stylus IPTS (iTouch).

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me-regs.h | 1 +
 drivers/misc/mei/pci-me.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index bf230c5b5eec..b86ce504fdd3 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -74,6 +74,7 @@
 
 #define MEI_DEV_ID_KBP0xA2BA  /* Kaby Point */
 #define MEI_DEV_ID_KBP_2  0xA2BB  /* Kaby Point 2 */
+#define MEI_DEV_ID_KBP_3  0xA2BE  /* Kaby Point 3 (iTouch) */
 
 #define MEI_DEV_ID_CNP_LP 0x9DE0  /* Cannon Point LP */
 #define MEI_DEV_ID_CNP_LP_3   0x9DE4  /* Cannon Point LP 3 (iTouch) */
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index e97abebc949c..188f59a94118 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -82,6 +82,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 
{MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, MEI_ME_PCH8_CFG)},
+   {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_3, MEI_ME_PCH8_CFG)},
 
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP_3, MEI_ME_PCH8_CFG)},
-- 
2.25.4



[PATCH 2/2] mfd: mfd_cell: constify platform_data

2020-05-16 Thread Tomas Winkler
platform_data is duplicated into platform_device platform_data
via platform_device_add_data() and is not modified.

Signed-off-by: Tomas Winkler 
---
 include/linux/mfd/core.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 7e5ac3c00891..6919aaee33dc 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -66,7 +66,7 @@ struct mfd_cell {
int (*resume)(struct platform_device *dev);
 
/* platform data passed to the sub devices drivers */
-   void*platform_data;
+   const void  *platform_data;
size_t  pdata_size;
 
/* device properties passed to the sub devices drivers */
-- 
2.21.3



[PATCH 0/2] mfd: constify pointers

2020-05-16 Thread Tomas Winkler
Constify properties and platform_data in mfd cells

Tomas Winkler (2):
  mfd: constify properties in mfd_cell
  mfd: mfd_cell: constify platform_data

 include/linux/mfd/core.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

-- 
2.21.3



[PATCH 1/2] mfd: constify properties in mfd_cell

2020-05-16 Thread Tomas Winkler
Constify 'struct property_entry *properties' in
mfd_cell It is always passed
around as a pointer const struct.

Signed-off-by: Tomas Winkler 
---
 include/linux/mfd/core.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index d01d1299e49d..7e5ac3c00891 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -70,7 +70,7 @@ struct mfd_cell {
size_t  pdata_size;
 
/* device properties passed to the sub devices drivers */
-   struct property_entry *properties;
+   const struct property_entry *properties;
 
/*
 * Device Tree compatible string
-- 
2.21.3



[char-misc-next] mei: release me_cl object reference

2020-05-12 Thread Tomas Winkler
From: Alexander Usyskin 

Allow me_cl object to be freed by releasing the reference
that was acquired  by one of the search functions:
__mei_me_cl_by_uuid_id() or __mei_me_cl_by_uuid()

Cc: 
Reported-by: 亿一 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/client.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 204d807e755b..b32c825a0945 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -266,6 +266,7 @@ void mei_me_cl_rm_by_uuid(struct mei_device *dev, const 
uuid_le *uuid)
down_write(>me_clients_rwsem);
me_cl = __mei_me_cl_by_uuid(dev, uuid);
__mei_me_cl_del(dev, me_cl);
+   mei_me_cl_put(me_cl);
up_write(>me_clients_rwsem);
 }
 
@@ -287,6 +288,7 @@ void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, const 
uuid_le *uuid, u8 id)
down_write(>me_clients_rwsem);
me_cl = __mei_me_cl_by_uuid_id(dev, uuid, id);
__mei_me_cl_del(dev, me_cl);
+   mei_me_cl_put(me_cl);
up_write(>me_clients_rwsem);
 }
 
-- 
2.21.3



[char-misc] mei: me: disable mei interface on LBG servers.

2020-04-28 Thread Tomas Winkler
Disable the MEI driver on LBG SPS (server) platforms, some corner
flows such as recovery mode does not work, and the driver
doesn't have working use cases.

Cc: 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me.c  | 8 
 drivers/misc/mei/hw-me.h  | 4 
 drivers/misc/mei/pci-me.c | 2 +-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 668418d7ea77..f620442addf5 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1465,6 +1465,13 @@ static const struct mei_cfg mei_me_pch12_cfg = {
MEI_CFG_DMA_128,
 };
 
+/* LBG with quirk for SPS Firmware exclusion */
+static const struct mei_cfg mei_me_pch12_sps_cfg = {
+   MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
+   MEI_CFG_FW_SPS,
+};
+
 /* Tiger Lake and newer devices */
 static const struct mei_cfg mei_me_pch15_cfg = {
MEI_CFG_PCH8_HFS,
@@ -1487,6 +1494,7 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_PCH8_CFG] = _me_pch8_cfg,
[MEI_ME_PCH8_SPS_CFG] = _me_pch8_sps_cfg,
[MEI_ME_PCH12_CFG] = _me_pch12_cfg,
+   [MEI_ME_PCH12_SPS_CFG] = _me_pch12_sps_cfg,
[MEI_ME_PCH15_CFG] = _me_pch15_cfg,
 };
 
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 4a8d4dcd5a91..b6b94e211464 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -80,6 +80,9 @@ struct mei_me_hw {
  * servers platforms with quirk for
  * SPS firmware exclusion.
  * @MEI_ME_PCH12_CFG:  Platform Controller Hub Gen12 and newer
+ * @MEI_ME_PCH12_SPS_CFG:  Platform Controller Hub Gen12 and newer
+ * servers platforms with quirk for
+ * SPS firmware exclusion.
  * @MEI_ME_PCH15_CFG:  Platform Controller Hub Gen15 and newer
  * @MEI_ME_NUM_CFG:Upper Sentinel.
  */
@@ -93,6 +96,7 @@ enum mei_cfg_idx {
MEI_ME_PCH8_CFG,
MEI_ME_PCH8_SPS_CFG,
MEI_ME_PCH12_CFG,
+   MEI_ME_PCH12_SPS_CFG,
MEI_ME_PCH15_CFG,
MEI_ME_NUM_CFG,
 };
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 3d21c38e2dbb..d4899a430e9d 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -70,7 +70,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
-   {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_CFG)},
+   {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_SPS_CFG)},
 
{MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)},
-- 
2.21.1



[char-misc-next] samples: mei: use hostprogs kbuild constructs

2019-10-10 Thread Tomas Winkler
Use hostprogs kbuild constructs to compile
mei sample program mei-amt-version

Add CONFIG_SAMPLE_INTEL_MEI option to enable/disable
the feature.

Signed-off-by: Tomas Winkler 
---
 samples/Kconfig  |  7 +++
 samples/Makefile |  1 +
 samples/mei/Makefile | 12 ++--
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/samples/Kconfig b/samples/Kconfig
index c8dacb4dda80..b663d9d24114 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -169,4 +169,11 @@ config SAMPLE_VFS
  as mount API and statx().  Note that this is restricted to the x86
  arch whilst it accesses system calls that aren't yet in all arches.
 
+config SAMPLE_INTEL_MEI
+   bool "Build example program working with intel mei driver"
+   depends on INTEL_MEI
+   help
+ Build a sample program to work with mei device.
+
+
 endif # SAMPLES
diff --git a/samples/Makefile b/samples/Makefile
index 7d6e4ca28d69..d6062ab25347 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_SAMPLE_TRACE_PRINTK) += trace_printk/
 obj-$(CONFIG_VIDEO_PCI_SKELETON)   += v4l/
 obj-y  += vfio-mdev/
 subdir-$(CONFIG_SAMPLE_VFS)+= vfs
+obj-$(CONFIG_SAMPLE_INTEL_MEI) += mei/
diff --git a/samples/mei/Makefile b/samples/mei/Makefile
index c7e52e9e92ca..27f37efdadb4 100644
--- a/samples/mei/Makefile
+++ b/samples/mei/Makefile
@@ -1,10 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0
-CC := $(CROSS_COMPILE)gcc
-CFLAGS := -I../../usr/include
+# Copyright (c) 2012-2019, Intel Corporation. All rights reserved.
 
-PROGS := mei-amt-version
+hostprogs-y := mei-amt-version
 
-all: $(PROGS)
+HOSTCFLAGS_mei-amt-version.o += -I$(objtree)/usr/include
 
-clean:
-   rm -fr $(PROGS)
+always := $(hostprogs-y)
+
+all: mei-amt-version
-- 
2.21.0



[char-misc-next 2/2] mei: me: fix me_intr_clear function name in KDoc

2019-10-07 Thread Tomas Winkler
From: Alexander Usyskin 

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index c4f6991d3028..5ef30c7c92b3 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -269,7 +269,7 @@ static inline void me_intr_disable(struct mei_device *dev, 
u32 hcsr)
 }
 
 /**
- * mei_me_intr_clear - clear and stop interrupts
+ * me_intr_clear - clear and stop interrupts
  *
  * @dev: the device structure
  * @hcsr: supplied hcsr register value
-- 
2.21.0



[char-misc-next 1/2] mei: fix modalias documentation

2019-10-07 Thread Tomas Winkler
From: Alexander Usyskin 

mei client bus added the client protocol version to the device alias,
but ABI documentation was not updated.

Fixes: b26864cad1c9 (mei: bus: add client protocol version to the device alias)
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 Documentation/ABI/testing/sysfs-bus-mei | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-mei 
b/Documentation/ABI/testing/sysfs-bus-mei
index 6bd45346ac7e..3f8701e8fa24 100644
--- a/Documentation/ABI/testing/sysfs-bus-mei
+++ b/Documentation/ABI/testing/sysfs-bus-mei
@@ -4,7 +4,7 @@ KernelVersion:  3.10
 Contact:   Samuel Ortiz 
linux-...@linux.intel.com
 Description:   Stores the same MODALIAS value emitted by uevent
-   Format: mei:::
+   Format: mei:::
 
 What:  /sys/bus/mei/devices/.../name
 Date:  May 2015
-- 
2.21.0



[char-misc-next] mei: buf: drop 'running hook' debug messages.

2019-10-04 Thread Tomas Winkler
Drop 'running hook' debug messages, as this info
can be already retrieved via ftrace.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus-fixup.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 0a2b99e1af45..9ad9c01ddf41 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -46,8 +46,6 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO;
  */
 static void number_of_connections(struct mei_cl_device *cldev)
 {
-   dev_dbg(>dev, "running hook %s\n", __func__);
-
if (cldev->me_cl->props.max_number_of_connections > 1)
cldev->do_match = 0;
 }
@@ -59,8 +57,6 @@ static void number_of_connections(struct mei_cl_device *cldev)
  */
 static void blacklist(struct mei_cl_device *cldev)
 {
-   dev_dbg(>dev, "running hook %s\n", __func__);
-
cldev->do_match = 0;
 }
 
@@ -71,8 +67,6 @@ static void blacklist(struct mei_cl_device *cldev)
  */
 static void whitelist(struct mei_cl_device *cldev)
 {
-   dev_dbg(>dev, "running hook %s\n", __func__);
-
cldev->do_match = 1;
 }
 
@@ -256,7 +250,6 @@ static void mei_wd(struct mei_cl_device *cldev)
 {
struct pci_dev *pdev = to_pci_dev(cldev->dev.parent);
 
-   dev_dbg(>dev, "running hook %s\n", __func__);
if (pdev->device == MEI_DEV_ID_WPT_LP ||
pdev->device == MEI_DEV_ID_SPT ||
pdev->device == MEI_DEV_ID_SPT_H)
@@ -410,8 +403,6 @@ static void mei_nfc(struct mei_cl_device *cldev)
 
bus = cldev->bus;
 
-   dev_dbg(>dev, "running hook %s\n", __func__);
-
mutex_lock(>device_lock);
/* we need to connect to INFO GUID */
cl = mei_cl_alloc_linked(bus);
-- 
2.21.0



[char-misc for v4.5-rc2 2/2 V2] mei: avoid FW version request on Ibex Peak and earlier

2019-10-04 Thread Tomas Winkler
From: Alexander Usyskin 

The fixed MKHI client on PCH 6 gen platforms
does not support fw version retrieval.
The error is not fatal, but it fills up the kernel logs and
slows down the driver start.
This patch disables requesting FW version on GEN6 and earlier platforms.

Fixes warning:
[   15.964298] mei mei::55213584-9a29-4916-badf-0fb7ed682aeb:01: Could not read 
FW version
[   15.964301] mei mei::55213584-9a29-4916-badf-0fb7ed682aeb:01: version 
command failed -5

Cc:  +v4.18
Cc: Paul Menzel 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
V2: Drop offending debug message
 drivers/misc/mei/bus-fixup.c | 14 +++---
 drivers/misc/mei/hw-me.c | 21 ++---
 drivers/misc/mei/hw-me.h |  8 ++--
 drivers/misc/mei/mei_dev.h   |  4 
 drivers/misc/mei/pci-me.c| 10 +-
 5 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 32e9b1aed2ca..0a2b99e1af45 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -218,13 +218,21 @@ static void mei_mkhi_fix(struct mei_cl_device *cldev)
 {
int ret;
 
+   /* No need to enable the client if nothing is needed from it */
+   if (!cldev->bus->fw_f_fw_ver_supported &&
+   !cldev->bus->hbm_f_os_supported)
+   return;
+
ret = mei_cldev_enable(cldev);
if (ret)
return;
 
-   ret = mei_fwver(cldev);
-   if (ret < 0)
-   dev_err(>dev, "FW version command failed %d\n", ret);
+   if (cldev->bus->fw_f_fw_ver_supported) {
+   ret = mei_fwver(cldev);
+   if (ret < 0)
+   dev_err(>dev, "FW version command failed %d\n",
+   ret);
+   }
 
if (cldev->bus->hbm_f_os_supported) {
ret = mei_osver(cldev);
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index abe1b1f4362f..c4f6991d3028 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1355,6 +1355,8 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev)
 #define MEI_CFG_FW_SPS   \
.quirk_probe = mei_me_fw_type_sps
 
+#define MEI_CFG_FW_VER_SUPP \
+   .fw_ver_supported = 1
 
 #define MEI_CFG_ICH_HFS  \
.fw_status.count = 0
@@ -1392,31 +1394,41 @@ static const struct mei_cfg mei_me_ich10_cfg = {
MEI_CFG_ICH10_HFS,
 };
 
-/* PCH devices */
-static const struct mei_cfg mei_me_pch_cfg = {
+/* PCH6 devices */
+static const struct mei_cfg mei_me_pch6_cfg = {
MEI_CFG_PCH_HFS,
 };
 
+/* PCH7 devices */
+static const struct mei_cfg mei_me_pch7_cfg = {
+   MEI_CFG_PCH_HFS,
+   MEI_CFG_FW_VER_SUPP,
+};
+
 /* PCH Cougar Point and Patsburg with quirk for Node Manager exclusion */
 static const struct mei_cfg mei_me_pch_cpt_pbg_cfg = {
MEI_CFG_PCH_HFS,
+   MEI_CFG_FW_VER_SUPP,
MEI_CFG_FW_NM,
 };
 
 /* PCH8 Lynx Point and newer devices */
 static const struct mei_cfg mei_me_pch8_cfg = {
MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
 };
 
 /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */
 static const struct mei_cfg mei_me_pch8_sps_cfg = {
MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
MEI_CFG_FW_SPS,
 };
 
 /* Cannon Lake and newer devices */
 static const struct mei_cfg mei_me_pch12_cfg = {
MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
MEI_CFG_DMA_128,
 };
 
@@ -1428,7 +1440,8 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_UNDEF_CFG] = NULL,
[MEI_ME_ICH_CFG] = _me_ich_cfg,
[MEI_ME_ICH10_CFG] = _me_ich10_cfg,
-   [MEI_ME_PCH_CFG] = _me_pch_cfg,
+   [MEI_ME_PCH6_CFG] = _me_pch6_cfg,
+   [MEI_ME_PCH7_CFG] = _me_pch7_cfg,
[MEI_ME_PCH_CPT_PBG_CFG] = _me_pch_cpt_pbg_cfg,
[MEI_ME_PCH8_CFG] = _me_pch8_cfg,
[MEI_ME_PCH8_SPS_CFG] = _me_pch8_sps_cfg,
@@ -1473,6 +1486,8 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
mei_device_init(dev, >dev, _me_hw_ops);
hw->cfg = cfg;
 
+   dev->fw_f_fw_ver_supported = cfg->fw_ver_supported;
+
return dev;
 }
 
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 08c84a0de4a8..1d8794828cbc 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -20,11 +20,13 @@
  * @fw_status: FW status
  * @quirk_probe: device exclusion quirk
  * @dma_size: device DMA buffers size
+ * @fw_ver_supported: is fw version retrievable from FW
  */
 struct mei_cfg {
const struct mei_fw_status fw_status;
bool (*quirk_probe)(struct pci_dev *pdev);
size_t dma_size[DMA_DSCR_NUM];
+   u32 fw_ver_supported:1;
 };
 
 
@@ -62,7 +64,8 @@ struct mei_me_hw {
  * @MEI_ME_UNDEF_CFG:  Lower sentinel.
  * @MEI_ME_ICH_CFG:I/O Controller Hub le

[char-misc for 4.5-rc2 1/2] mei: me: add comet point (lake) LP device ids

2019-10-01 Thread Tomas Winkler
Add Comet Point devices IDs for Comet Lake U platforms.

Cc: 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me-regs.h | 3 +++
 drivers/misc/mei/pci-me.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 77f7dff7098d..c09f8bb49495 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -79,6 +79,9 @@
 #define MEI_DEV_ID_CNP_H  0xA360  /* Cannon Point H */
 #define MEI_DEV_ID_CNP_H_40xA364  /* Cannon Point H 4 (iTouch) */
 
+#define MEI_DEV_ID_CMP_LP 0x02e0  /* Comet Point LP */
+#define MEI_DEV_ID_CMP_LP_3   0x02e4  /* Comet Point LP 3 (iTouch) */
+
 #define MEI_DEV_ID_ICP_LP 0x34E0  /* Ice Lake Point LP */
 
 #define MEI_DEV_ID_TGP_LP 0xA0E0  /* Tiger Lake Point LP */
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index d5a92c6eadb3..775a2090c2ac 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -96,6 +96,9 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_4, MEI_ME_PCH8_CFG)},
 
+   {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP, MEI_ME_PCH12_CFG)},
+   {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP_3, MEI_ME_PCH8_CFG)},
+
{MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
 
{MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH12_CFG)},
-- 
2.21.0



[char-misc for v4.5-rc2 2/2] mei: avoid FW version request on Ibex Peak and earlier

2019-10-01 Thread Tomas Winkler
From: Alexander Usyskin 

The fixed MKHI client on PCH 6 gen platforms
does not support fw version retrieval.
The error is not fatal, but it fills up the kernel logs and
slows down the driver start.
This patch disables requesting FW version on GEN6 and earlier platforms.

Fixes warning:
[   15.964298] mei mei::55213584-9a29-4916-badf-0fb7ed682aeb:01: Could not read 
FW version
[   15.964301] mei mei::55213584-9a29-4916-badf-0fb7ed682aeb:01: version 
command failed -5

Cc:  +v4.18
Cc: Paul Menzel 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus-fixup.c | 16 +---
 drivers/misc/mei/hw-me.c | 21 ++---
 drivers/misc/mei/hw-me.h |  8 ++--
 drivers/misc/mei/mei_dev.h   |  4 
 drivers/misc/mei/pci-me.c| 10 +-
 5 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 32e9b1aed2ca..5ac679ac9b19 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -218,13 +218,23 @@ static void mei_mkhi_fix(struct mei_cl_device *cldev)
 {
int ret;
 
+   dev_dbg(>dev, "running hook %s\n", __func__);
+
+   /* No need to enable the client if nothing is needed from it */
+   if (!cldev->bus->fw_f_fw_ver_supported &&
+   !cldev->bus->hbm_f_os_supported)
+   return;
+
ret = mei_cldev_enable(cldev);
if (ret)
return;
 
-   ret = mei_fwver(cldev);
-   if (ret < 0)
-   dev_err(>dev, "FW version command failed %d\n", ret);
+   if (cldev->bus->fw_f_fw_ver_supported) {
+   ret = mei_fwver(cldev);
+   if (ret < 0)
+   dev_err(>dev, "FW version command failed %d\n",
+   ret);
+   }
 
if (cldev->bus->hbm_f_os_supported) {
ret = mei_osver(cldev);
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index abe1b1f4362f..c4f6991d3028 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -1355,6 +1355,8 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev)
 #define MEI_CFG_FW_SPS   \
.quirk_probe = mei_me_fw_type_sps
 
+#define MEI_CFG_FW_VER_SUPP \
+   .fw_ver_supported = 1
 
 #define MEI_CFG_ICH_HFS  \
.fw_status.count = 0
@@ -1392,31 +1394,41 @@ static const struct mei_cfg mei_me_ich10_cfg = {
MEI_CFG_ICH10_HFS,
 };
 
-/* PCH devices */
-static const struct mei_cfg mei_me_pch_cfg = {
+/* PCH6 devices */
+static const struct mei_cfg mei_me_pch6_cfg = {
MEI_CFG_PCH_HFS,
 };
 
+/* PCH7 devices */
+static const struct mei_cfg mei_me_pch7_cfg = {
+   MEI_CFG_PCH_HFS,
+   MEI_CFG_FW_VER_SUPP,
+};
+
 /* PCH Cougar Point and Patsburg with quirk for Node Manager exclusion */
 static const struct mei_cfg mei_me_pch_cpt_pbg_cfg = {
MEI_CFG_PCH_HFS,
+   MEI_CFG_FW_VER_SUPP,
MEI_CFG_FW_NM,
 };
 
 /* PCH8 Lynx Point and newer devices */
 static const struct mei_cfg mei_me_pch8_cfg = {
MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
 };
 
 /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */
 static const struct mei_cfg mei_me_pch8_sps_cfg = {
MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
MEI_CFG_FW_SPS,
 };
 
 /* Cannon Lake and newer devices */
 static const struct mei_cfg mei_me_pch12_cfg = {
MEI_CFG_PCH8_HFS,
+   MEI_CFG_FW_VER_SUPP,
MEI_CFG_DMA_128,
 };
 
@@ -1428,7 +1440,8 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_UNDEF_CFG] = NULL,
[MEI_ME_ICH_CFG] = _me_ich_cfg,
[MEI_ME_ICH10_CFG] = _me_ich10_cfg,
-   [MEI_ME_PCH_CFG] = _me_pch_cfg,
+   [MEI_ME_PCH6_CFG] = _me_pch6_cfg,
+   [MEI_ME_PCH7_CFG] = _me_pch7_cfg,
[MEI_ME_PCH_CPT_PBG_CFG] = _me_pch_cpt_pbg_cfg,
[MEI_ME_PCH8_CFG] = _me_pch8_cfg,
[MEI_ME_PCH8_SPS_CFG] = _me_pch8_sps_cfg,
@@ -1473,6 +1486,8 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
mei_device_init(dev, >dev, _me_hw_ops);
hw->cfg = cfg;
 
+   dev->fw_f_fw_ver_supported = cfg->fw_ver_supported;
+
return dev;
 }
 
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 08c84a0de4a8..1d8794828cbc 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -20,11 +20,13 @@
  * @fw_status: FW status
  * @quirk_probe: device exclusion quirk
  * @dma_size: device DMA buffers size
+ * @fw_ver_supported: is fw version retrievable from FW
  */
 struct mei_cfg {
const struct mei_fw_status fw_status;
bool (*quirk_probe)(struct pci_dev *pdev);
size_t dma_size[DMA_DSCR_NUM];
+   u32 fw_ver_supported:1;
 };
 
 
@@ -62,7 +64,8 @@ struct mei_me_hw {
  * @MEI_ME_UNDEF_CFG:  Lower sentinel.
  * @

[char-misc-next] mei: me: add Tiger Lake point LP device ID

2019-08-19 Thread Tomas Winkler
Add Tiger Lake Point device ID for TGP LP.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me-regs.h | 2 ++
 drivers/misc/mei/pci-me.c | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 6c0173772162..77f7dff7098d 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -81,6 +81,8 @@
 
 #define MEI_DEV_ID_ICP_LP 0x34E0  /* Ice Lake Point LP */
 
+#define MEI_DEV_ID_TGP_LP 0xA0E0  /* Tiger Lake Point LP */
+
 #define MEI_DEV_ID_MCC0x4B70  /* Mule Creek Canyon (EHL) */
 #define MEI_DEV_ID_MCC_4  0x4B75  /* Mule Creek Canyon 4 (EHL) */
 
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 563ebd56c3e5..d5a92c6eadb3 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -98,6 +98,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 
{MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
 
+   {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH12_CFG)},
+
{MEI_PCI_DEVICE(MEI_DEV_ID_MCC, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)},
 
-- 
2.20.1



[PATCH V2] scsi: ufs: revamp string descriptor reading

2019-07-30 Thread Tomas Winkler
Define new a type: uc_string_id for easier string
handling and less casting. Reduce number or string
copies in price of a dynamic allocation.

Signed-off-by: Tomas Winkler 
Tested-by: Avri Altman 
---
V2:
   a. Use u8 instead of char as result string is utf8
   b. In ufshcd_read_desc_param() keep buffer typed u8*

 drivers/scsi/ufs/ufs-sysfs.c |  18 ++--
 drivers/scsi/ufs/ufs.h   |   2 +-
 drivers/scsi/ufs/ufshcd.c| 162 +--
 drivers/scsi/ufs/ufshcd.h|   7 +-
 4 files changed, 112 insertions(+), 77 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index f478685122ff..969a36b15897 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -571,9 +571,10 @@ static ssize_t _name##_show(struct device *dev,
\
int ret;\
int desc_len = QUERY_DESC_MAX_SIZE; \
u8 *desc_buf;   \
+   \
desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC);\
-   if (!desc_buf)  \
-   return -ENOMEM; \
+   if (!desc_buf)  \
+   return -ENOMEM; \
ret = ufshcd_query_descriptor_retry(hba,\
UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \
0, 0, desc_buf, _len); \
@@ -582,14 +583,13 @@ static ssize_t _name##_show(struct device *dev,   
\
goto out;   \
}   \
index = desc_buf[DEVICE_DESC_PARAM##_pname];\
-   memset(desc_buf, 0, QUERY_DESC_MAX_SIZE);   \
-   if (ufshcd_read_string_desc(hba, index, desc_buf,   \
-   QUERY_DESC_MAX_SIZE, true)) {   \
-   ret = -EINVAL;  \
+   kfree(desc_buf);\
+   desc_buf = NULL;\
+   ret = ufshcd_read_string_desc(hba, index, _buf,\
+ SD_ASCII_STD);\
+   if (ret < 0)\
goto out;   \
-   }   \
-   ret = snprintf(buf, PAGE_SIZE, "%s\n",  \
-   desc_buf + QUERY_DESC_HDR_SIZE);\
+   ret = snprintf(buf, PAGE_SIZE, "%s\n", desc_buf);   \
 out:   \
kfree(desc_buf);\
return ret; \
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 99a9c4d16f6b..3327981ef894 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -541,7 +541,7 @@ struct ufs_dev_info {
  */
 struct ufs_dev_desc {
u16 wmanufacturerid;
-   char model[MAX_MODEL_LEN + 1];
+   u8 *model;
 };
 
 /**
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a383d0f54f5d..507fd51e8039 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -299,16 +299,6 @@ static void ufshcd_scsi_block_requests(struct ufs_hba *hba)
scsi_block_requests(hba->host);
 }
 
-/* replace non-printable or non-ASCII characters with spaces */
-static inline void ufshcd_remove_non_printable(char *val)
-{
-   if (!val)
-   return;
-
-   if (*val < 0x20 || *val > 0x7e)
-   *val = ' ';
-}
-
 static void ufshcd_add_cmd_upiu_trace(struct ufs_hba *hba, unsigned int tag,
const char *str)
 {
@@ -3211,7 +3201,7 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
 static inline int ufshcd_read_desc(struct ufs_hba *hba,
   enum desc_idn desc_id,
   int desc_index,
-  u8 *buf,
+  void *buf,
   u32 size)
 {
return ufshcd_read_desc_param(hba, desc_id, desc_index, 0, buf, size);
@@ -3229,49 +3219,78 @@ static int ufshcd_read_device_desc(struct ufs_hba *hba, 
u8 *buf, u32 size)
return ufshcd_read_desc(hba, QUERY_DESC_IDN_DEVICE, 0, buf, size);
 }
 
+/**
+ * struct uc_string_id - u

[PATCH RESEND] scsi: ufs: revamp string descriptor reading

2019-07-21 Thread Tomas Winkler
Define new a type: uc_string_id for easier string
handling and less casting. Reduce number or string
copies in price of a dynamic allocation.

Signed-off-by: Tomas Winkler 
Tested-by: Avri Altman 
---

Resend: It was reviewed by not merged.

 drivers/scsi/ufs/ufs-sysfs.c |  20 ++---
 drivers/scsi/ufs/ufs.h   |   2 +-
 drivers/scsi/ufs/ufshcd.c| 164 +--
 drivers/scsi/ufs/ufshcd.h|   9 +-
 4 files changed, 115 insertions(+), 80 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index f478685122ff..13e357f01025 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -570,10 +570,11 @@ static ssize_t _name##_show(struct device *dev,   
\
struct ufs_hba *hba = dev_get_drvdata(dev); \
int ret;\
int desc_len = QUERY_DESC_MAX_SIZE; \
-   u8 *desc_buf;   \
+   char *desc_buf; \
+   \
desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC);\
-   if (!desc_buf)  \
-   return -ENOMEM; \
+   if (!desc_buf)  \
+   return -ENOMEM; \
ret = ufshcd_query_descriptor_retry(hba,\
UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \
0, 0, desc_buf, _len); \
@@ -582,14 +583,13 @@ static ssize_t _name##_show(struct device *dev,   
\
goto out;   \
}   \
index = desc_buf[DEVICE_DESC_PARAM##_pname];\
-   memset(desc_buf, 0, QUERY_DESC_MAX_SIZE);   \
-   if (ufshcd_read_string_desc(hba, index, desc_buf,   \
-   QUERY_DESC_MAX_SIZE, true)) {   \
-   ret = -EINVAL;  \
+   kfree(desc_buf);\
+   desc_buf = NULL;\
+   ret = ufshcd_read_string_desc(hba, index, _buf,\
+ SD_ASCII_STD);\
+   if (ret < 0)\
goto out;   \
-   }   \
-   ret = snprintf(buf, PAGE_SIZE, "%s\n",  \
-   desc_buf + QUERY_DESC_HDR_SIZE);\
+   ret = snprintf(buf, PAGE_SIZE, "%s\n", desc_buf);   \
 out:   \
kfree(desc_buf);\
return ret; \
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 99a9c4d16f6b..b3e1b2a0f463 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -541,7 +541,7 @@ struct ufs_dev_info {
  */
 struct ufs_dev_desc {
u16 wmanufacturerid;
-   char model[MAX_MODEL_LEN + 1];
+   char *model;
 };
 
 /**
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a3b6cd1a623d..e2740353332a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -299,16 +299,6 @@ static void ufshcd_scsi_block_requests(struct ufs_hba *hba)
scsi_block_requests(hba->host);
 }
 
-/* replace non-printable or non-ASCII characters with spaces */
-static inline void ufshcd_remove_non_printable(char *val)
-{
-   if (!val)
-   return;
-
-   if (*val < 0x20 || *val > 0x7e)
-   *val = ' ';
-}
-
 static void ufshcd_add_cmd_upiu_trace(struct ufs_hba *hba, unsigned int tag,
const char *str)
 {
@@ -3130,7 +3120,7 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
   enum desc_idn desc_id,
   int desc_index,
   u8 param_offset,
-  u8 *param_read_buf,
+  void *param_read_buf,
   u8 param_size)
 {
int ret;
@@ -3198,7 +3188,7 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
 static inline int ufshcd_read_desc(struct ufs_hba *hba,
   enum desc_idn desc_id,
 

[char-misc] mei: me: add mule creek canyon (EHL) device ids

2019-07-12 Thread Tomas Winkler
From: Alexander Usyskin 

Add Mule Creek Canyon (PCH) MEI device ids for Elkhart Lake (EHL) Platform.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hw-me-regs.h | 3 +++
 drivers/misc/mei/pci-me.c | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index d74b182e19f3..6c0173772162 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -81,6 +81,9 @@
 
 #define MEI_DEV_ID_ICP_LP 0x34E0  /* Ice Lake Point LP */
 
+#define MEI_DEV_ID_MCC0x4B70  /* Mule Creek Canyon (EHL) */
+#define MEI_DEV_ID_MCC_4  0x4B75  /* Mule Creek Canyon 4 (EHL) */
+
 /*
  * MEI HW Section
  */
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 7a2b3545a7f9..57cb68f5cc64 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -98,6 +98,9 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 
{MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
 
+   {MEI_PCI_DEVICE(MEI_DEV_ID_MCC, MEI_ME_PCH12_CFG)},
+   {MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)},
+
/* required last entry */
{0, }
 };
-- 
2.20.1



[char-misc-next] mei: Convert to use DEFINE_SHOW_ATTRIBUTE macro

2019-05-20 Thread Tomas Winkler
From: Vitaly Lubart 

Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code.

Signed-off-by: Vitaly Lubart 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/debugfs.c | 184 +++--
 1 file changed, 52 insertions(+), 132 deletions(-)

diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index 0970142bcace..47cfd5005e1b 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -15,104 +16,56 @@
 #include "client.h"
 #include "hw.h"
 
-static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
-   size_t cnt, loff_t *ppos)
+static int mei_dbgfs_meclients_show(struct seq_file *m, void *unused)
 {
-   struct mei_device *dev = fp->private_data;
+   struct mei_device *dev = m->private;
struct mei_me_client *me_cl;
-   size_t bufsz = 1;
-   char *buf;
int i = 0;
-   int pos = 0;
-   int ret;
 
-#define HDR \
-"  |id|fix| UUID   |con|msg len|sb|refc|\n"
+   if (!dev)
+   return -ENODEV;
 
down_read(>me_clients_rwsem);
-   list_for_each_entry(me_cl, >me_clients, list)
-   bufsz++;
 
-   bufsz *= sizeof(HDR) + 1;
-   buf = kzalloc(bufsz, GFP_KERNEL);
-   if (!buf) {
-   up_read(>me_clients_rwsem);
-   return -ENOMEM;
-   }
-
-   pos += scnprintf(buf + pos, bufsz - pos, HDR);
-#undef HDR
+   seq_puts(m, "  |id|fix| UUID   |con|msg 
len|sb|refc|\n");
 
/*  if the driver is not enabled the list won't be consistent */
if (dev->dev_state != MEI_DEV_ENABLED)
goto out;
 
list_for_each_entry(me_cl, >me_clients, list) {
-
-   if (mei_me_cl_get(me_cl)) {
-   pos += scnprintf(buf + pos, bufsz - pos,
-   "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d|\n",
-   i++, me_cl->client_id,
-   me_cl->props.fixed_address,
-   _cl->props.protocol_name,
-   me_cl->props.max_number_of_connections,
-   me_cl->props.max_msg_length,
-   me_cl->props.single_recv_buf,
-   kref_read(_cl->refcnt));
-
-   mei_me_cl_put(me_cl);
-   }
+   if (!mei_me_cl_get(me_cl))
+   continue;
+
+   seq_printf(m, "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d|\n",
+  i++, me_cl->client_id,
+  me_cl->props.fixed_address,
+  _cl->props.protocol_name,
+  me_cl->props.max_number_of_connections,
+  me_cl->props.max_msg_length,
+  me_cl->props.single_recv_buf,
+  kref_read(_cl->refcnt));
+   mei_me_cl_put(me_cl);
}
 
 out:
up_read(>me_clients_rwsem);
-   ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos);
-   kfree(buf);
-   return ret;
+   return 0;
 }
+DEFINE_SHOW_ATTRIBUTE(mei_dbgfs_meclients);
 
-static const struct file_operations mei_dbgfs_fops_meclients = {
-   .open = simple_open,
-   .read = mei_dbgfs_read_meclients,
-   .llseek = generic_file_llseek,
-};
-
-static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf,
-   size_t cnt, loff_t *ppos)
+static int mei_dbgfs_active_show(struct seq_file *m, void *unused)
 {
-   struct mei_device *dev = fp->private_data;
+   struct mei_device *dev = m->private;
struct mei_cl *cl;
-   size_t bufsz = 1;
-   char *buf;
int i = 0;
-   int pos = 0;
-   int ret;
-
-#define HDR "   |me|host|state|rd|wr|wrq\n"
 
if (!dev)
return -ENODEV;
 
mutex_lock(>device_lock);
 
-   /*
-* if the driver is not enabled the list won't be consistent,
-* we output empty table
-*/
-   if (dev->dev_state == MEI_DEV_ENABLED)
-   list_for_each_entry(cl, >file_list, link)
-   bufsz++;
-
-   bufsz *= sizeof(HDR) + 1;
-
-   buf = kzalloc(bufsz, GFP_KERNEL);
-   if  (!buf) {
-   mutex_unlock(>device_lock);
-   return -ENOMEM;
-   }
-
-   pos += scnprintf(buf + pos, bufsz - pos, HDR);
-#undef HDR
+   seq_puts(m, "   |me|host|state|rd|wr|wrq\n");
 
/*  if the driver is not enabled the list won't be consistent */
if (dev->dev_state != MEI_DEV_ENABLED)
@@ -120,76 +73,44 @@ static ssize_t mei

[char-misc-next 1/2] mei: hdcp: use own Kconfig file

2019-04-22 Thread Tomas Winkler
The mei/hdcp module have its own Makefile
so naturally it should have associated Kconfig
in the same directory.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/Kconfig  | 10 +-
 drivers/misc/mei/hdcp/Kconfig | 13 +
 2 files changed, 14 insertions(+), 9 deletions(-)
 create mode 100644 drivers/misc/mei/hdcp/Kconfig

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index 132b07151f42..9d7b3719bfa0 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -46,12 +46,4 @@ config INTEL_MEI_TXE
  Supported SoCs:
  Intel Bay Trail
 
-config INTEL_MEI_HDCP
-   tristate "Intel HDCP2.2 services of ME Interface"
-   select INTEL_MEI_ME
-   depends on DRM_I915
-   help
- MEI Support for HDCP2.2 Services on Intel platforms.
-
- Enables the ME FW services required for HDCP2.2 support through
- I915 display driver of Intel.
+source "drivers/misc/mei/hdcp/Kconfig"
diff --git a/drivers/misc/mei/hdcp/Kconfig b/drivers/misc/mei/hdcp/Kconfig
new file mode 100644
index ..95b2d6d37f10
--- /dev/null
+++ b/drivers/misc/mei/hdcp/Kconfig
@@ -0,0 +1,13 @@
+
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2019, Intel Corporation. All rights reserved.
+#
+config INTEL_MEI_HDCP
+   tristate "Intel HDCP2.2 services of ME Interface"
+   select INTEL_MEI_ME
+   depends on DRM_I915
+   help
+ MEI Support for HDCP2.2 Services on Intel platforms.
+
+ Enables the ME FW services required for HDCP2.2 support through
+ I915 display driver of Intel.
-- 
2.20.1



[char-misc-next 2/2] mei: expose device state in sysfs

2019-04-22 Thread Tomas Winkler
From: Alexander Usyskin 

Expose mei device state to user-space through sysfs.
This gives indication to applications that driver is in transition,
usefully mostly to detect link reset state.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 Documentation/ABI/testing/sysfs-class-mei | 15 ++
 drivers/misc/mei/client.c |  2 +-
 drivers/misc/mei/init.c   | 20 +++
 drivers/misc/mei/main.c   | 65 ---
 drivers/misc/mei/mei_dev.h|  3 +-
 5 files changed, 87 insertions(+), 18 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-mei 
b/Documentation/ABI/testing/sysfs-class-mei
index 17d7444a2397..a92d844f806e 100644
--- a/Documentation/ABI/testing/sysfs-class-mei
+++ b/Documentation/ABI/testing/sysfs-class-mei
@@ -65,3 +65,18 @@ Description: Display the ME firmware version.
:
There can be up to three such blocks for different
FW components.
+
+What:  /sys/class/mei/meiN/dev_state
+Date:  Mar 2019
+KernelVersion: 5.1
+Contact:   Tomas Winkler 
+Description:   Display the ME device state.
+
+   The device state can have following values:
+   INITIALIZING
+   INIT_CLIENTS
+   ENABLED
+   RESETTING
+   DISABLED
+   POWER_DOWN
+   POWER_UP
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 88b83c4bc5b7..1e3edbbacb1e 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -669,7 +669,7 @@ int mei_cl_unlink(struct mei_cl *cl)
 
 void mei_host_client_init(struct mei_device *dev)
 {
-   dev->dev_state = MEI_DEV_ENABLED;
+   mei_set_devstate(dev, MEI_DEV_ENABLED);
dev->reset_count = 0;
 
schedule_work(>bus_rescan_work);
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index cc359ae968ce..b9fef773e71b 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -123,12 +123,12 @@ int mei_reset(struct mei_device *dev)
 
/* enter reset flow */
interrupts_enabled = state != MEI_DEV_POWER_DOWN;
-   dev->dev_state = MEI_DEV_RESETTING;
+   mei_set_devstate(dev, MEI_DEV_RESETTING);
 
dev->reset_count++;
if (dev->reset_count > MEI_MAX_CONSEC_RESET) {
dev_err(dev->dev, "reset: reached maximal consecutive resets: 
disabling the device\n");
-   dev->dev_state = MEI_DEV_DISABLED;
+   mei_set_devstate(dev, MEI_DEV_DISABLED);
return -ENODEV;
}
 
@@ -150,7 +150,7 @@ int mei_reset(struct mei_device *dev)
 
if (state == MEI_DEV_POWER_DOWN) {
dev_dbg(dev->dev, "powering down: end of reset\n");
-   dev->dev_state = MEI_DEV_DISABLED;
+   mei_set_devstate(dev, MEI_DEV_DISABLED);
return 0;
}
 
@@ -162,11 +162,11 @@ int mei_reset(struct mei_device *dev)
 
dev_dbg(dev->dev, "link is established start sending messages.\n");
 
-   dev->dev_state = MEI_DEV_INIT_CLIENTS;
+   mei_set_devstate(dev, MEI_DEV_INIT_CLIENTS);
ret = mei_hbm_start_req(dev);
if (ret) {
dev_err(dev->dev, "hbm_start failed ret = %d\n", ret);
-   dev->dev_state = MEI_DEV_RESETTING;
+   mei_set_devstate(dev, MEI_DEV_RESETTING);
return ret;
}
 
@@ -196,7 +196,7 @@ int mei_start(struct mei_device *dev)
 
dev->reset_count = 0;
do {
-   dev->dev_state = MEI_DEV_INITIALIZING;
+   mei_set_devstate(dev, MEI_DEV_INITIALIZING);
ret = mei_reset(dev);
 
if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
@@ -231,7 +231,7 @@ int mei_start(struct mei_device *dev)
return 0;
 err:
dev_err(dev->dev, "link layer initialization failed.\n");
-   dev->dev_state = MEI_DEV_DISABLED;
+   mei_set_devstate(dev, MEI_DEV_DISABLED);
mutex_unlock(>device_lock);
return -ENODEV;
 }
@@ -250,7 +250,7 @@ int mei_restart(struct mei_device *dev)
 
mutex_lock(>device_lock);
 
-   dev->dev_state = MEI_DEV_POWER_UP;
+   mei_set_devstate(dev, MEI_DEV_POWER_UP);
dev->reset_count = 0;
 
err = mei_reset(dev);
@@ -301,7 +301,7 @@ void mei_stop(struct mei_device *dev)
dev_dbg(dev->dev, "stopping the device.\n");
 
mutex_lock(>device_lock);
-   dev->dev_state = MEI_DEV_POWER_DOWN;
+   mei_set_devstate(dev, MEI_DEV_POWER_DOWN);
mutex_unlock(>device_lock);
mei_cl_bus_remove_devices(dev);
 
@@ -314,7 +314,7 @@ void mei_stop(struct mei_device *dev)
 
mei_reset(dev);
/* move device to disabled state unconditionally */
-   dev->dev_state =

[char-misc-next] mei: hdcp: use own Kconfig file

2019-04-04 Thread Tomas Winkler
The mei/hdcp module have its own Makefile
so naturally it should have associated Kconfig
in the same directory.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/Kconfig  | 10 +-
 drivers/misc/mei/hdcp/Kconfig | 13 +
 2 files changed, 14 insertions(+), 9 deletions(-)
 create mode 100644 drivers/misc/mei/hdcp/Kconfig

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index 132b07151f42..9d7b3719bfa0 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -46,12 +46,4 @@ config INTEL_MEI_TXE
  Supported SoCs:
  Intel Bay Trail
 
-config INTEL_MEI_HDCP
-   tristate "Intel HDCP2.2 services of ME Interface"
-   select INTEL_MEI_ME
-   depends on DRM_I915
-   help
- MEI Support for HDCP2.2 Services on Intel platforms.
-
- Enables the ME FW services required for HDCP2.2 support through
- I915 display driver of Intel.
+source "drivers/misc/mei/hdcp/Kconfig"
diff --git a/drivers/misc/mei/hdcp/Kconfig b/drivers/misc/mei/hdcp/Kconfig
new file mode 100644
index ..95b2d6d37f10
--- /dev/null
+++ b/drivers/misc/mei/hdcp/Kconfig
@@ -0,0 +1,13 @@
+
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2019, Intel Corporation. All rights reserved.
+#
+config INTEL_MEI_HDCP
+   tristate "Intel HDCP2.2 services of ME Interface"
+   select INTEL_MEI_ME
+   depends on DRM_I915
+   help
+ MEI Support for HDCP2.2 Services on Intel platforms.
+
+ Enables the ME FW services required for HDCP2.2 support through
+ I915 display driver of Intel.
-- 
2.20.1



[char-misc 5/5] mei: adjust the copyright notice in the files.

2019-03-11 Thread Tomas Winkler
Use unified version of the copyright notice in the files
Update copyright years according the year the files
were touched, except this patch and SPDX conversions.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/Kconfig   | 1 +
 drivers/misc/mei/Makefile  | 2 +-
 drivers/misc/mei/bus-fixup.c   | 2 +-
 drivers/misc/mei/bus.c | 2 +-
 drivers/misc/mei/client.c  | 2 +-
 drivers/misc/mei/client.h  | 2 +-
 drivers/misc/mei/debugfs.c | 2 +-
 drivers/misc/mei/dma-ring.c| 2 +-
 drivers/misc/mei/hbm.c | 2 +-
 drivers/misc/mei/hbm.h | 2 +-
 drivers/misc/mei/hdcp/Makefile | 2 +-
 drivers/misc/mei/hw-me-regs.h  | 2 +-
 drivers/misc/mei/hw-me.c   | 2 +-
 drivers/misc/mei/hw-me.h   | 2 +-
 drivers/misc/mei/hw-txe-regs.h | 2 +-
 drivers/misc/mei/hw-txe.c  | 2 +-
 drivers/misc/mei/hw-txe.h  | 2 +-
 drivers/misc/mei/hw.h  | 2 +-
 drivers/misc/mei/init.c| 2 +-
 drivers/misc/mei/interrupt.c   | 2 +-
 drivers/misc/mei/main.c| 2 +-
 drivers/misc/mei/mei-trace.c   | 2 +-
 drivers/misc/mei/mei-trace.h   | 2 +-
 drivers/misc/mei/mei_dev.h | 2 +-
 drivers/misc/mei/pci-me.c  | 2 +-
 drivers/misc/mei/pci-txe.c | 2 +-
 include/linux/mei_cl_bus.h | 3 +++
 include/uapi/linux/mei.h   | 2 +-
 28 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index 998fb4ae9791..132b07151f42 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2003-2019, Intel Corporation. All rights reserved.
 config INTEL_MEI
tristate "Intel Management Engine Interface"
depends on X86 && PCI
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 8c2d9565a4cb..f1c76f7ee804 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 #
+# Copyright (c) 2010-2019, Intel Corporation. All rights reserved.
 # Makefile - Intel Management Engine Interface (Intel MEI) Linux driver
-# Copyright (c) 2010-2014, Intel Corporation.
 #
 obj-$(CONFIG_INTEL_MEI) += mei.o
 mei-objs := init.o
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index c839bdf453d8..32e9b1aed2ca 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2013-2019, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2018, Intel Corporation.
  */
 
 #include 
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index e6788fbd611c..985bd4fd3328 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2012-2019, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2012-2013, Intel Corporation.
  */
 
 #include 
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 306b5fdeaf9c..88b83c4bc5b7 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2003-2019, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2012, Intel Corporation.
  */
 
 #include 
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index a0e2ec2ed7ab..c1f9e810cf81 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
+ * Copyright (c) 2003-2018, Intel Corporation. All rights reserved.
  * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2012, Intel Corporation.
  */
 
 #ifndef _MEI_CLIENT_H_
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index 3b2dd5a1be06..0970142bcace 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright (c) 2012-2016, Intel Corporation. All rights reserved
  * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2012-2013, Intel Corporation.
  */
 
 #include 
diff --git a/drivers/misc/mei/dma-ring.c b/drivers/misc/mei/dma-ring.c
index 795641b82181..ef56f849b251 100644
--- a/drivers/misc/mei/dma-ring.c
+++ b/drivers/misc/mei/dma-ring.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
+ * Copyright(c) 2016-2018 Intel Corporation. All rights reserved.
  */
 #include 
 #include 
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index dfc21787d978..a44094cdbc36 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyr

[char-misc 3/5] nfc/mei: convert to SPDX license tags

2019-03-11 Thread Tomas Winkler
Replace boiler plate licenses texts with the SPDX license
identifiers in the mei nfc files header.

Signed-off-by: Tomas Winkler 
---
 drivers/nfc/mei_phy.c   | 18 +++---
 drivers/nfc/microread/mei.c | 17 +++--
 drivers/nfc/pn544/mei.c | 15 ++-
 3 files changed, 8 insertions(+), 42 deletions(-)

diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c
index 8a04c5e02999..0f43bb389566 100644
--- a/drivers/nfc/mei_phy.c
+++ b/drivers/nfc/mei_phy.c
@@ -1,21 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * MEI Library for mei bus nfc device access
- *
- * Copyright (C) 2013  Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
+ * Copyright (c) 2013, Intel Corporation.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * MEI Library for mei bus nfc device access
  */
-
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c
index eb5eddf1794e..5dad8847a9b3 100644
--- a/drivers/nfc/microread/mei.c
+++ b/drivers/nfc/microread/mei.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * HCI based Driver for Inside Secure microread NFC Chip
- *
- * Copyright (C) 2013  Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * HCI based Driver for Inside Secure microread NFC Chip
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c
index ad57a8ec00d6..579bc599f545 100644
--- a/drivers/nfc/pn544/mei.c
+++ b/drivers/nfc/pn544/mei.c
@@ -1,19 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * HCI based Driver for NXP pn544 NFC Chip
- *
  * Copyright (C) 2013  Intel Corporation. All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * HCI based Driver for NXP pn544 NFC Chip
  */
 
 #include 
-- 
2.20.1



[char-misc 4/5] mei/hdcp: Fix SPDX identifiers

2019-03-11 Thread Tomas Winkler
1. Remove redundant parentheses around single license
2. Fix the license to GPL-2.0 and not GPL-2.0+ in mei_hdcp.h

Cc: Ramalingam C 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hdcp/mei_hdcp.c | 2 +-
 drivers/misc/mei/hdcp/mei_hdcp.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c
index 90b6ae8e9dae..b07000202d4a 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.c
+++ b/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0)
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright © 2019 Intel Corporation
  *
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.h b/drivers/misc/mei/hdcp/mei_hdcp.h
index 5f74b908e486..e4b1cd54c853 100644
--- a/drivers/misc/mei/hdcp/mei_hdcp.h
+++ b/drivers/misc/mei/hdcp/mei_hdcp.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0+) */
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright © 2019 Intel Corporation
  *
-- 
2.20.1



[char-misc 1/5] mei: add missing SPDX tag to mei Kconfig

2019-03-11 Thread Tomas Winkler
Add SPDX tag with GPLv2 license to mei Kconfig.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index 74e2c667dce0..998fb4ae9791 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 config INTEL_MEI
tristate "Intel Management Engine Interface"
depends on X86 && PCI
-- 
2.20.1



[char-misc 2/5] mei: convert to SPDX license tags

2019-03-11 Thread Tomas Winkler
Replace boiler plate licenses texts with the SPDX license
identifiers in the mei files header.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus-fixup.c   | 12 +--
 drivers/misc/mei/bus.c | 11 +-
 drivers/misc/mei/client.c  | 12 +--
 drivers/misc/mei/client.h  | 12 +--
 drivers/misc/mei/debugfs.c | 13 ++-
 drivers/misc/mei/hbm.c | 13 +--
 drivers/misc/mei/hbm.h | 12 +--
 drivers/misc/mei/hw-me-regs.h  | 66 ++
 drivers/misc/mei/hw-me.c   | 12 +--
 drivers/misc/mei/hw-me.h   | 14 +---
 drivers/misc/mei/hw-txe-regs.h | 61 ++-
 drivers/misc/mei/hw-txe.c  | 12 +--
 drivers/misc/mei/hw-txe.h  | 12 +--
 drivers/misc/mei/hw.h  | 12 +--
 drivers/misc/mei/init.c| 12 +--
 drivers/misc/mei/interrupt.c   | 13 +--
 drivers/misc/mei/main.c| 13 ++-
 drivers/misc/mei/mei-trace.c   | 12 +--
 drivers/misc/mei/mei-trace.h   | 12 +--
 drivers/misc/mei/mei_dev.h | 12 +--
 drivers/misc/mei/pci-me.c  | 13 ++-
 drivers/misc/mei/pci-txe.c | 12 +--
 include/uapi/linux/mei.h   | 65 ++---
 23 files changed, 31 insertions(+), 407 deletions(-)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 5fcac02233af..c839bdf453d8 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -1,17 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- *
  * Intel Management Engine Interface (Intel MEI) Linux driver
  * Copyright (c) 2003-2018, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  */
 
 #include 
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 65bec998eb6e..e6788fbd611c 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel Management Engine Interface (Intel MEI) Linux driver
  * Copyright (c) 2012-2013, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  */
 
 #include 
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index ca4c9cc218a2..306b5fdeaf9c 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -1,17 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- *
  * Intel Management Engine Interface (Intel MEI) Linux driver
  * Copyright (c) 2003-2012, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  */
 
 #include 
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 64e318f589b4..a0e2ec2ed7ab 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -1,17 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
- *
  * Intel Management Engine Interface (Intel MEI) Linux driver
  * Copyright (c) 2003-2012, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  */
 
 #ifndef _MEI_CLIENT_H_
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index 7b5df8fd6c5a..3b2dd5a1be06 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- *
  * Intel Management Engine Interface (Intel MEI) Linux driver
  * Copyright (c) 2012-2013, Intel Corporation.
- *
- * This program is free software

[char-misc 0/5] mei: spdx and copyright adjustments

2019-03-11 Thread Tomas Winkler
Replace boiler plate licenses texts with the SPDX license
identifiers, and fix minor mistakes in HDCP2.0 code SPDX identifiers.

This includes also code under the NFC subsystem, this can be merged via
char-misc as this code is unlikely to change, so no conflicts are expected.

Use the same format for copyright notice in the all files
and update the copyright notice according file modification date.

Tomas Winkler (5):
  mei: add missing SPDX tag to mei Kconfig
  mei: convert to SPDX license tags
  nfc/mei: convert to SPDX license tags
  mei/hdcp: Fix SPDX identifiers
  mei: adjust the copyright notice in the files.

 drivers/misc/mei/Kconfig |  2 +
 drivers/misc/mei/Makefile|  2 +-
 drivers/misc/mei/bus-fixup.c | 14 +--
 drivers/misc/mei/bus.c   | 13 +-
 drivers/misc/mei/client.c| 14 +--
 drivers/misc/mei/client.h| 14 +--
 drivers/misc/mei/debugfs.c   | 15 ++-
 drivers/misc/mei/dma-ring.c  |  2 +-
 drivers/misc/mei/hbm.c   | 15 +--
 drivers/misc/mei/hbm.h   | 14 +--
 drivers/misc/mei/hdcp/Makefile   |  2 +-
 drivers/misc/mei/hdcp/mei_hdcp.c |  2 +-
 drivers/misc/mei/hdcp/mei_hdcp.h |  2 +-
 drivers/misc/mei/hw-me-regs.h| 68 ++--
 drivers/misc/mei/hw-me.c | 14 +--
 drivers/misc/mei/hw-me.h | 16 +---
 drivers/misc/mei/hw-txe-regs.h   | 63 ++---
 drivers/misc/mei/hw-txe.c| 14 +--
 drivers/misc/mei/hw-txe.h| 14 +--
 drivers/misc/mei/hw.h| 14 +--
 drivers/misc/mei/init.c  | 14 +--
 drivers/misc/mei/interrupt.c | 15 +--
 drivers/misc/mei/main.c  | 15 ++-
 drivers/misc/mei/mei-trace.c | 14 +--
 drivers/misc/mei/mei-trace.h | 14 +--
 drivers/misc/mei/mei_dev.h   | 14 +--
 drivers/misc/mei/pci-me.c| 15 ++-
 drivers/misc/mei/pci-txe.c   | 14 +--
 drivers/nfc/mei_phy.c| 18 ++---
 drivers/nfc/microread/mei.c  | 17 ++--
 drivers/nfc/pn544/mei.c  | 15 +--
 include/linux/mei_cl_bus.h   |  3 ++
 include/uapi/linux/mei.h | 67 ++-
 33 files changed, 72 insertions(+), 477 deletions(-)

-- 
2.20.1



[char-misc] mei: convert to SPDX license tags

2019-03-10 Thread Tomas Winkler
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/Kconfig |  1 +
 drivers/misc/mei/Makefile|  2 +-
 drivers/misc/mei/bus-fixup.c | 13 +-
 drivers/misc/mei/bus.c   | 14 ++-
 drivers/misc/mei/client.c| 13 +-
 drivers/misc/mei/client.h| 13 +-
 drivers/misc/mei/debugfs.c   | 14 ++-
 drivers/misc/mei/dma-ring.c  |  5 ++-
 drivers/misc/mei/hbm.c   | 13 +-
 drivers/misc/mei/hbm.h   | 13 +-
 drivers/misc/mei/hdcp/mei_hdcp.c |  2 +-
 drivers/misc/mei/hdcp/mei_hdcp.h |  2 +-
 drivers/misc/mei/hw-me-regs.h| 70 +++-
 drivers/misc/mei/hw-me.c | 13 +-
 drivers/misc/mei/hw-me.h | 15 +--
 drivers/misc/mei/hw-txe-regs.h   | 65 +++--
 drivers/misc/mei/hw-txe.c| 13 +-
 drivers/misc/mei/hw-txe.h| 13 +-
 drivers/misc/mei/hw.h| 13 +-
 drivers/misc/mei/init.c  | 13 +-
 drivers/misc/mei/interrupt.c | 14 +--
 drivers/misc/mei/main.c  | 14 ++-
 drivers/misc/mei/mei-trace.c | 14 ++-
 drivers/misc/mei/mei-trace.h | 13 +-
 drivers/misc/mei/mei_dev.h   | 14 ++-
 drivers/misc/mei/pci-me.c| 14 ++-
 drivers/misc/mei/pci-txe.c   | 13 +-
 include/linux/mei_cl_bus.h   |  6 +++
 include/uapi/linux/mei.h | 70 ++--
 29 files changed, 75 insertions(+), 417 deletions(-)

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index 74e2c667dce0..998fb4ae9791 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 config INTEL_MEI
tristate "Intel Management Engine Interface"
depends on X86 && PCI
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 8c2d9565a4cb..68b6e72c777f 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 #
 # Makefile - Intel Management Engine Interface (Intel MEI) Linux driver
-# Copyright (c) 2010-2014, Intel Corporation.
+# Copyright (c) 2010-2019, Intel Corporation.
 #
 obj-$(CONFIG_INTEL_MEI) += mei.o
 mei-objs := init.o
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 5fcac02233af..465612fea5bb 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright(c) 2003-2019, Intel Corporation. All rights reserved.
  *
  * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2018, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  */
 
 #include 
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 65bec998eb6e..bbdb0e4f48de 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2012-2013, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
+ * Copyright(c) 2012-2019, Intel Corporation. All rights reserved.
  *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
  */
 
 #include 
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index ca4c9cc218a2..81db5a536d06 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
+ * Copyright(c) 2003-2019, Intel Corporation. All rights reserved.
  *
  * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2012, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  */

[char-misc-next] mei: bus: move hw module get/put to probe/release

2019-02-25 Thread Tomas Winkler
From: Alexander Usyskin 

Fix unbalanced module reference counting during internal reset, which
prevents the drivers unloading.
Tracking mei_me/txe modules on mei client bus via
mei_cldev_enable/disable is error prone due to possible internal
reset flow, where clients are disconnected underneath.
Moving reference counting to probe and release of mei bus client
driver solves this issue in simplest way, as each client provides only
a single connection to a client bus driver.

Cc: 
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c | 21 ++---
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index e5456faf00e6..65bec998eb6e 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -540,17 +540,9 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
goto out;
}
 
-   if (!mei_cl_bus_module_get(cldev)) {
-   dev_err(>dev, "get hw module failed");
-   ret = -ENODEV;
-   goto out;
-   }
-
ret = mei_cl_connect(cl, cldev->me_cl, NULL);
-   if (ret < 0) {
+   if (ret < 0)
dev_err(>dev, "cannot connect\n");
-   mei_cl_bus_module_put(cldev);
-   }
 
 out:
mutex_unlock(>device_lock);
@@ -613,7 +605,6 @@ int mei_cldev_disable(struct mei_cl_device *cldev)
if (err < 0)
dev_err(bus->dev, "Could not disconnect from the ME client\n");
 
-   mei_cl_bus_module_put(cldev);
 out:
/* Flush queues and remove any pending read */
mei_cl_flush_queues(cl, NULL);
@@ -724,9 +715,16 @@ static int mei_cl_device_probe(struct device *dev)
if (!id)
return -ENODEV;
 
+   if (!mei_cl_bus_module_get(cldev)) {
+   dev_err(>dev, "get hw module failed");
+   return -ENODEV;
+   }
+
ret = cldrv->probe(cldev, id);
-   if (ret)
+   if (ret) {
+   mei_cl_bus_module_put(cldev);
return ret;
+   }
 
__module_get(THIS_MODULE);
return 0;
@@ -754,6 +752,7 @@ static int mei_cl_device_remove(struct device *dev)
 
mei_cldev_unregister_callbacks(cldev);
 
+   mei_cl_bus_module_put(cldev);
module_put(THIS_MODULE);
dev->driver = NULL;
return ret;
-- 
2.20.1



[char-misc] mei: hbm: clean the feature flags on link reset

2019-02-20 Thread Tomas Winkler
From: Alexander Usyskin 

The list of supported functions can be altered upon link reset,
clean the flags to allow correct selections of supported
features.

Cc:  v4.19+
Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/hbm.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 8f7616557c97..e6207f614816 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -1029,29 +1029,36 @@ static void mei_hbm_config_features(struct mei_device 
*dev)
dev->version.minor_version >= HBM_MINOR_VERSION_PGI)
dev->hbm_f_pg_supported = 1;
 
+   dev->hbm_f_dc_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_DC)
dev->hbm_f_dc_supported = 1;
 
+   dev->hbm_f_ie_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_IE)
dev->hbm_f_ie_supported = 1;
 
/* disconnect on connect timeout instead of link reset */
+   dev->hbm_f_dot_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT)
dev->hbm_f_dot_supported = 1;
 
/* Notification Event Support */
+   dev->hbm_f_ev_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_EV)
dev->hbm_f_ev_supported = 1;
 
/* Fixed Address Client Support */
+   dev->hbm_f_fa_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_FA)
dev->hbm_f_fa_supported = 1;
 
/* OS ver message Support */
+   dev->hbm_f_os_supported = 0;
if (dev->version.major_version >= HBM_MAJOR_VERSION_OS)
dev->hbm_f_os_supported = 1;
 
/* DMA Ring Support */
+   dev->hbm_f_dr_supported = 0;
if (dev->version.major_version > HBM_MAJOR_VERSION_DR ||
(dev->version.major_version == HBM_MAJOR_VERSION_DR &&
 dev->version.minor_version >= HBM_MINOR_VERSION_DR))
-- 
2.20.1



[char-misc-next] mei: bus: export to_mei_cl_device for mei client devices drivers

2019-02-09 Thread Tomas Winkler
Export to_mei_cl_device macro, as it is needed also
in the mei client drivers.

Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/bus.c | 1 -
 include/linux/mei_cl_bus.h | 2 ++
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index fc3872fe7b25..e5456faf00e6 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -28,7 +28,6 @@
 #include "client.h"
 
 #define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
-#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
 
 /**
  * __mei_cl_send - internal client send (write)
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
index 7fde40e17c8b..03b6ba2a63f8 100644
--- a/include/linux/mei_cl_bus.h
+++ b/include/linux/mei_cl_bus.h
@@ -55,6 +55,8 @@ struct mei_cl_device {
void *priv_data;
 };
 
+#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
+
 struct mei_cl_driver {
struct device_driver driver;
const char *name;
-- 
2.20.1



[char-misc for v5.0] mei: free read cb on ctrl_wr list flush

2019-01-29 Thread Tomas Winkler
From: Alexander Usyskin 

There is a little window during disconnection flow
when read cb is moved between lists and may be not freed.
Remove moving read cbs explicitly during flash fixes this memory
leak.

Signed-off-by: Alexander Usyskin 
Signed-off-by: Tomas Winkler 
---
 drivers/misc/mei/client.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 1fc8ea0f519b..ca4c9cc218a2 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -401,8 +401,11 @@ static void mei_io_list_flush_cl(struct list_head *head,
struct mei_cl_cb *cb, *next;
 
list_for_each_entry_safe(cb, next, head, list) {
-   if (cl == cb->cl)
+   if (cl == cb->cl) {
list_del_init(>list);
+   if (cb->fop_type == MEI_FOP_READ)
+   mei_io_cb_free(cb);
+   }
}
 }
 
-- 
2.20.1



  1   2   3   4   5   6   7   8   9   10   >