Răsfoiți Sursa

Merge tag 'char-misc-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver updates from Greg KH:
 "Here's the big set of driver patches for char/misc drivers.  Nothing
  major in here, the shortlog goes into the details.  All have been in
  the linux-next tree for a while with no issues"

* tag 'char-misc-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (80 commits)
  mei: mei_txe_fw_sts can be static
  mei: fix kernel-doc warnings
  mei: fix KDoc documentation formatting
  mei: drop me_client_presentation_num
  mei: trivial: fix errors in prints in comments
  mei: remove include to pci header from mei module files
  mei: push pci cfg structure me hw
  mei: remove the reference to pdev from mei_device
  mei: move fw_status back to hw ops handlers
  mei: get rid of most of the pci dependencies in mei
  mei: push all standard settings into mei_device_init
  mei: move mei_hbm_hdr function from hbm.h the hbm.c
  mei: kill error message for allocation failure
  mei: nfc: fix style warning
  mei: fix style warning: Missing a blank line after declarations
  mei: pg: fix cat and paste error in comments
  mei: debugfs: add single buffer indicator
  mei: debugfs: adjust print buffer
  mei: add hbm and pg state in devstate debugfs print
  Drivers: hv: vmbus: Enable interrupt driven flow control
  ...
Linus Torvalds 10 ani în urmă
părinte
comite
ef0625b70d
63 a modificat fișierele cu 2794 adăugiri și 1345 ștergeri
  1. 25 0
      Documentation/devicetree/bindings/extcon/extcon-rt8973a.txt
  2. 1 0
      Documentation/devicetree/bindings/vendor-prefixes.txt
  3. 13 0
      drivers/char/i8k.c
  4. 0 1
      drivers/char/xilinx_hwicap/xilinx_hwicap.c
  5. 13 0
      drivers/extcon/Kconfig
  6. 1 0
      drivers/extcon/Makefile
  7. 5 5
      drivers/extcon/extcon-gpio.c
  8. 15 22
      drivers/extcon/extcon-max77693.c
  9. 740 0
      drivers/extcon/extcon-rt8973a.c
  10. 203 0
      drivers/extcon/extcon-rt8973a.h
  11. 7 13
      drivers/extcon/extcon-sm5502.c
  12. 0 5
      drivers/extcon/extcon-sm5502.h
  13. 38 18
      drivers/hv/channel.c
  14. 15 6
      drivers/hv/channel_mgmt.c
  15. 14 3
      drivers/hv/connection.c
  16. 15 12
      drivers/hv/hv.c
  17. 4 0
      drivers/hv/hyperv_vmbus.h
  18. 5 0
      drivers/hv/ring_buffer.c
  19. 2 1
      drivers/ipack/carriers/tpci200.c
  20. 44 25
      drivers/ipack/devices/ipoctal.c
  21. 1 1
      drivers/ipack/devices/ipoctal.h
  22. 3 1
      drivers/ipack/ipack.c
  23. 6 17
      drivers/misc/eeprom/eeprom.c
  24. 24 14
      drivers/misc/genwqe/card_base.c
  25. 13 8
      drivers/misc/genwqe/card_base.h
  26. 48 29
      drivers/misc/genwqe/card_ddcb.c
  27. 1 1
      drivers/misc/genwqe/card_ddcb.h
  28. 6 4
      drivers/misc/genwqe/card_debugfs.c
  29. 13 8
      drivers/misc/genwqe/card_dev.c
  30. 1 10
      drivers/misc/genwqe/card_sysfs.c
  31. 4 3
      drivers/misc/genwqe/card_utils.c
  32. 2 2
      drivers/misc/genwqe/genwqe_driver.h
  33. 1 0
      drivers/misc/lattice-ecp3-config.c
  34. 75 92
      drivers/misc/mei/amthif.c
  35. 12 13
      drivers/misc/mei/bus.c
  36. 141 96
      drivers/misc/mei/client.c
  37. 13 4
      drivers/misc/mei/client.h
  38. 44 26
      drivers/misc/mei/debugfs.c
  39. 323 244
      drivers/misc/mei/hbm.c
  40. 6 11
      drivers/misc/mei/hbm.h
  41. 126 68
      drivers/misc/mei/hw-me.c
  42. 31 1
      drivers/misc/mei/hw-me.h
  43. 162 90
      drivers/misc/mei/hw-txe.c
  44. 2 4
      drivers/misc/mei/hw-txe.h
  45. 51 23
      drivers/misc/mei/hw.h
  46. 55 52
      drivers/misc/mei/init.c
  47. 43 53
      drivers/misc/mei/interrupt.c
  48. 66 77
      drivers/misc/mei/main.c
  49. 179 100
      drivers/misc/mei/mei_dev.h
  50. 39 38
      drivers/misc/mei/nfc.c
  51. 7 7
      drivers/misc/mei/pci-me.c
  52. 7 6
      drivers/misc/mei/pci-txe.c
  53. 27 32
      drivers/misc/mei/wd.c
  54. 23 75
      drivers/misc/spear13xx_pcie_gadget.c
  55. 5 6
      drivers/misc/ti-st/st_core.c
  56. 2 1
      drivers/misc/vmw_vmci/vmci_datagram.c
  57. 42 12
      drivers/parport/parport_pc.c
  58. 3 1
      include/linux/extcon/extcon-gpio.h
  59. 23 1
      include/linux/ipack.h
  60. 1 0
      include/linux/mei_cl_bus.h
  61. 1 1
      include/linux/ti_wilink_st.h
  62. 1 1
      include/uapi/linux/genwqe/genwqe_card.h
  63. 1 1
      include/uapi/linux/hyperv.h

+ 25 - 0
Documentation/devicetree/bindings/extcon/extcon-rt8973a.txt

@@ -0,0 +1,25 @@
+
+* Richtek RT8973A - Micro USB Switch device
+
+The Richtek RT8973A is Micro USB Switch with OVP and I2C interface. The RT8973A
+is a USB port accessory detector and switch that is optimized to protect low
+voltage system from abnormal high input voltage (up to 28V) and supports high
+speed USB operation. Also, RT8973A support 'auto-configuration' mode.
+If auto-configuration mode is enabled, RT8973A would control internal h/w patch
+for USB D-/D+ switching.
+
+Required properties:
+- compatible: Should be "richtek,rt8973a-muic"
+- reg: Specifies the I2C slave address of the MUIC block. It should be 0x14
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from rt8973a are delivered to.
+- interrupts: Interrupt specifiers for detection interrupt sources.
+
+Example:
+
+	rt8973a@14 {
+		compatible = "richtek,rt8973a-muic";
+		interrupt-parent = <&gpx1>;
+		interrupts = <5 0>;
+		reg = <0x14>;
+	};

+ 1 - 0
Documentation/devicetree/bindings/vendor-prefixes.txt

@@ -150,6 +150,7 @@ winbond Winbond Electronics corp.
 wlf	Wolfson Microelectronics
 wlf	Wolfson Microelectronics
 wm	Wondermedia Technologies, Inc.
 wm	Wondermedia Technologies, Inc.
 xes	Extreme Engineering Solutions (X-ES)
 xes	Extreme Engineering Solutions (X-ES)
+xillybus	Xillybus Ltd.
 xlnx	Xilinx
 xlnx	Xilinx
 zyxel	ZyXEL Communications Corp.
 zyxel	ZyXEL Communications Corp.
 zarlink	Zarlink Semiconductor
 zarlink	Zarlink Semiconductor

+ 13 - 0
drivers/char/i8k.c

@@ -651,6 +651,7 @@ struct i8k_config_data {
 
 
 enum i8k_configs {
 enum i8k_configs {
 	DELL_LATITUDE_D520,
 	DELL_LATITUDE_D520,
+	DELL_LATITUDE_E6540,
 	DELL_PRECISION_490,
 	DELL_PRECISION_490,
 	DELL_STUDIO,
 	DELL_STUDIO,
 	DELL_XPS_M140,
 	DELL_XPS_M140,
@@ -661,6 +662,10 @@ static const struct i8k_config_data i8k_config_data[] = {
 		.fan_mult = 1,
 		.fan_mult = 1,
 		.fan_max = I8K_FAN_TURBO,
 		.fan_max = I8K_FAN_TURBO,
 	},
 	},
+	[DELL_LATITUDE_E6540] = {
+		.fan_mult = 1,
+		.fan_max = I8K_FAN_HIGH,
+	},
 	[DELL_PRECISION_490] = {
 	[DELL_PRECISION_490] = {
 		.fan_mult = 1,
 		.fan_mult = 1,
 		.fan_max = I8K_FAN_TURBO,
 		.fan_max = I8K_FAN_TURBO,
@@ -705,6 +710,14 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
 		},
 		},
 		.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],
 		.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],
 	},
 	},
+	{
+		.ident = "Dell Latitude E6540",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6540"),
+		},
+		.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_E6540],
+	},
 	{
 	{
 		.ident = "Dell Latitude 2",
 		.ident = "Dell Latitude 2",
 		.matches = {
 		.matches = {

+ 0 - 1
drivers/char/xilinx_hwicap/xilinx_hwicap.c

@@ -843,7 +843,6 @@ static struct platform_driver hwicap_platform_driver = {
 	.probe = hwicap_drv_probe,
 	.probe = hwicap_drv_probe,
 	.remove = hwicap_drv_remove,
 	.remove = hwicap_drv_remove,
 	.driver = {
 	.driver = {
-		.owner = THIS_MODULE,
 		.name = DRIVER_NAME,
 		.name = DRIVER_NAME,
 		.of_match_table = hwicap_of_match,
 		.of_match_table = hwicap_of_match,
 	},
 	},

+ 13 - 0
drivers/extcon/Kconfig

@@ -70,8 +70,21 @@ config EXTCON_PALMAS
 	  Say Y here to enable support for USB peripheral and USB host
 	  Say Y here to enable support for USB peripheral and USB host
 	  detection by palmas usb.
 	  detection by palmas usb.
 
 
+config EXTCON_RT8973A
+	tristate "RT8973A EXTCON support"
+	depends on I2C
+	select IRQ_DOMAIN
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	help
+	  If you say yes here you get support for the MUIC device of
+	  Richtek RT8973A. The RT8973A is a USB port accessory detector
+	  and switch that is optimized to protect low voltage system
+	  from abnormal high input voltage (up to 28V).
+
 config EXTCON_SM5502
 config EXTCON_SM5502
 	tristate "SM5502 EXTCON support"
 	tristate "SM5502 EXTCON support"
+	depends on I2C
 	select IRQ_DOMAIN
 	select IRQ_DOMAIN
 	select REGMAP_I2C
 	select REGMAP_I2C
 	select REGMAP_IRQ
 	select REGMAP_IRQ

+ 1 - 0
drivers/extcon/Makefile

@@ -10,4 +10,5 @@ obj-$(CONFIG_EXTCON_MAX14577)	+= extcon-max14577.o
 obj-$(CONFIG_EXTCON_MAX77693)	+= extcon-max77693.o
 obj-$(CONFIG_EXTCON_MAX77693)	+= extcon-max77693.o
 obj-$(CONFIG_EXTCON_MAX8997)	+= extcon-max8997.o
 obj-$(CONFIG_EXTCON_MAX8997)	+= extcon-max8997.o
 obj-$(CONFIG_EXTCON_PALMAS)	+= extcon-palmas.o
 obj-$(CONFIG_EXTCON_PALMAS)	+= extcon-palmas.o
+obj-$(CONFIG_EXTCON_RT8973A)	+= extcon-rt8973a.o
 obj-$(CONFIG_EXTCON_SM5502)	+= extcon-sm5502.o
 obj-$(CONFIG_EXTCON_SM5502)	+= extcon-sm5502.o

+ 5 - 5
drivers/extcon/extcon-gpio.c

@@ -20,16 +20,16 @@
  *
  *
 */
 */
 
 
-#include <linux/module.h>
-#include <linux/kernel.h>
+#include <linux/extcon.h>
+#include <linux/extcon/extcon-gpio.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
-#include <linux/gpio.h>
-#include <linux/extcon.h>
-#include <linux/extcon/extcon-gpio.h>
 
 
 struct gpio_extcon_data {
 struct gpio_extcon_data {
 	struct extcon_dev *edev;
 	struct extcon_dev *edev;

+ 15 - 22
drivers/extcon/extcon-max77693.c

@@ -255,10 +255,14 @@ static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
 	case ADC_DEBOUNCE_TIME_10MS:
 	case ADC_DEBOUNCE_TIME_10MS:
 	case ADC_DEBOUNCE_TIME_25MS:
 	case ADC_DEBOUNCE_TIME_25MS:
 	case ADC_DEBOUNCE_TIME_38_62MS:
 	case ADC_DEBOUNCE_TIME_38_62MS:
-		ret = regmap_update_bits(info->max77693->regmap_muic,
-					  MAX77693_MUIC_REG_CTRL3,
-					  CONTROL3_ADCDBSET_MASK,
-					  time << CONTROL3_ADCDBSET_SHIFT);
+		/*
+		 * Don't touch BTLDset, JIGset when you want to change adc
+		 * debounce time. If it writes other than 0 to BTLDset, JIGset
+		 * muic device will be reset and loose current state.
+		 */
+		ret = regmap_write(info->max77693->regmap_muic,
+				  MAX77693_MUIC_REG_CTRL3,
+				  time << CONTROL3_ADCDBSET_SHIFT);
 		if (ret) {
 		if (ret) {
 			dev_err(info->dev, "failed to set ADC debounce time\n");
 			dev_err(info->dev, "failed to set ADC debounce time\n");
 			return ret;
 			return ret;
@@ -1155,13 +1159,11 @@ static int max77693_muic_probe(struct platform_device *pdev)
 
 
 		virq = regmap_irq_get_virq(max77693->irq_data_muic,
 		virq = regmap_irq_get_virq(max77693->irq_data_muic,
 					muic_irq->irq);
 					muic_irq->irq);
-		if (!virq) {
-			ret = -EINVAL;
-			goto err_irq;
-		}
+		if (!virq)
+			return -EINVAL;
 		muic_irq->virq = virq;
 		muic_irq->virq = virq;
 
 
-		ret = request_threaded_irq(virq, NULL,
+		ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
 				max77693_muic_irq_handler,
 				max77693_muic_irq_handler,
 				IRQF_NO_SUSPEND,
 				IRQF_NO_SUSPEND,
 				muic_irq->name, info);
 				muic_irq->name, info);
@@ -1170,7 +1172,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
 				"failed: irq request (IRQ: %d,"
 				"failed: irq request (IRQ: %d,"
 				" error :%d)\n",
 				" error :%d)\n",
 				muic_irq->irq, ret);
 				muic_irq->irq, ret);
-			goto err_irq;
+			return ret;
 		}
 		}
 	}
 	}
 
 
@@ -1179,15 +1181,14 @@ static int max77693_muic_probe(struct platform_device *pdev)
 					      max77693_extcon_cable);
 					      max77693_extcon_cable);
 	if (IS_ERR(info->edev)) {
 	if (IS_ERR(info->edev)) {
 		dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
 		dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
-		ret = -ENOMEM;
-		goto err_irq;
+		return -ENOMEM;
 	}
 	}
 	info->edev->name = DEV_NAME;
 	info->edev->name = DEV_NAME;
 
 
 	ret = devm_extcon_dev_register(&pdev->dev, info->edev);
 	ret = devm_extcon_dev_register(&pdev->dev, info->edev);
 	if (ret) {
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register extcon device\n");
 		dev_err(&pdev->dev, "failed to register extcon device\n");
-		goto err_irq;
+		return ret;
 	}
 	}
 
 
 	/* Initialize MUIC register by using platform data or default data */
 	/* Initialize MUIC register by using platform data or default data */
@@ -1265,7 +1266,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
 			MAX77693_MUIC_REG_ID, &id);
 			MAX77693_MUIC_REG_ID, &id);
 	if (ret < 0) {
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to read revision number\n");
 		dev_err(&pdev->dev, "failed to read revision number\n");
-		goto err_irq;
+		return ret;
 	}
 	}
 	dev_info(info->dev, "device ID : 0x%x\n", id);
 	dev_info(info->dev, "device ID : 0x%x\n", id);
 
 
@@ -1285,20 +1286,12 @@ static int max77693_muic_probe(struct platform_device *pdev)
 			delay_jiffies);
 			delay_jiffies);
 
 
 	return ret;
 	return ret;
-
-err_irq:
-	while (--i >= 0)
-		free_irq(muic_irqs[i].virq, info);
-	return ret;
 }
 }
 
 
 static int max77693_muic_remove(struct platform_device *pdev)
 static int max77693_muic_remove(struct platform_device *pdev)
 {
 {
 	struct max77693_muic_info *info = platform_get_drvdata(pdev);
 	struct max77693_muic_info *info = platform_get_drvdata(pdev);
-	int i;
 
 
-	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
-		free_irq(muic_irqs[i].virq, info);
 	cancel_work_sync(&info->irq_work);
 	cancel_work_sync(&info->irq_work);
 	input_unregister_device(info->dock);
 	input_unregister_device(info->dock);
 
 

+ 740 - 0
drivers/extcon/extcon-rt8973a.c

@@ -0,0 +1,740 @@
+/*
+ * extcon-rt8973a.c - Richtek RT8973A extcon driver to support USB switches
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ * Author: Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/extcon.h>
+
+#include "extcon-rt8973a.h"
+
+#define	DELAY_MS_DEFAULT		20000	/* unit: millisecond */
+
+struct muic_irq {
+	unsigned int irq;
+	const char *name;
+	unsigned int virq;
+};
+
+struct reg_data {
+	u8 reg;
+	u8 mask;
+	u8 val;
+	bool invert;
+};
+
+struct rt8973a_muic_info {
+	struct device *dev;
+	struct extcon_dev *edev;
+
+	struct i2c_client *i2c;
+	struct regmap *regmap;
+
+	struct regmap_irq_chip_data *irq_data;
+	struct muic_irq *muic_irqs;
+	unsigned int num_muic_irqs;
+	int irq;
+	bool irq_attach;
+	bool irq_detach;
+	bool irq_ovp;
+	bool irq_otp;
+	struct work_struct irq_work;
+
+	struct reg_data *reg_data;
+	unsigned int num_reg_data;
+	bool auto_config;
+
+	struct mutex mutex;
+
+	/*
+	 * Use delayed workqueue to detect cable state and then
+	 * notify cable state to notifiee/platform through uevent.
+	 * After completing the booting of platform, the extcon provider
+	 * driver should notify cable state to upper layer.
+	 */
+	struct delayed_work wq_detcable;
+};
+
+/* Default value of RT8973A register to bring up MUIC device. */
+static struct reg_data rt8973a_reg_data[] = {
+	{
+		.reg = RT8973A_REG_CONTROL1,
+		.mask = RT8973A_REG_CONTROL1_ADC_EN_MASK
+			| RT8973A_REG_CONTROL1_USB_CHD_EN_MASK
+			| RT8973A_REG_CONTROL1_CHGTYP_MASK
+			| RT8973A_REG_CONTROL1_SWITCH_OPEN_MASK
+			| RT8973A_REG_CONTROL1_AUTO_CONFIG_MASK
+			| RT8973A_REG_CONTROL1_INTM_MASK,
+		.val = RT8973A_REG_CONTROL1_ADC_EN_MASK
+			| RT8973A_REG_CONTROL1_USB_CHD_EN_MASK
+			| RT8973A_REG_CONTROL1_CHGTYP_MASK,
+		.invert = false,
+	},
+	{ /* sentinel */ }
+};
+
+/* List of detectable cables */
+enum {
+	EXTCON_CABLE_USB = 0,
+	EXTCON_CABLE_USB_HOST,
+	EXTCON_CABLE_TA,
+	EXTCON_CABLE_JIG_OFF_USB,
+	EXTCON_CABLE_JIG_ON_USB,
+	EXTCON_CABLE_JIG_OFF_UART,
+	EXTCON_CABLE_JIG_ON_UART,
+
+	EXTCON_CABLE_END,
+};
+
+static const char *rt8973a_extcon_cable[] = {
+	[EXTCON_CABLE_USB]		= "USB",
+	[EXTCON_CABLE_USB_HOST]		= "USB-Host",
+	[EXTCON_CABLE_TA]		= "TA",
+	[EXTCON_CABLE_JIG_OFF_USB]	= "JIG-USB-OFF",
+	[EXTCON_CABLE_JIG_ON_USB]	= "JIG-USB-ON",
+	[EXTCON_CABLE_JIG_OFF_UART]	= "JIG-UART-OFF",
+	[EXTCON_CABLE_JIG_ON_UART]	= "JIG-UART-ON",
+	NULL,
+};
+
+/* Define OVP (Over Voltage Protection), OTP (Over Temperature Protection) */
+enum rt8973a_event_type {
+	RT8973A_EVENT_ATTACH = 1,
+	RT8973A_EVENT_DETACH,
+	RT8973A_EVENT_OVP,
+	RT8973A_EVENT_OTP,
+};
+
+/* Define supported accessory type */
+enum rt8973a_muic_acc_type {
+	RT8973A_MUIC_ADC_OTG = 0x0,
+	RT8973A_MUIC_ADC_AUDIO_SEND_END_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S1_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S2_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S3_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S4_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S5_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S6_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S7_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S8_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S9_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S10_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S11_BUTTON,
+	RT8973A_MUIC_ADC_AUDIO_REMOTE_S12_BUTTON,
+	RT8973A_MUIC_ADC_RESERVED_ACC_1,
+	RT8973A_MUIC_ADC_RESERVED_ACC_2,
+	RT8973A_MUIC_ADC_RESERVED_ACC_3,
+	RT8973A_MUIC_ADC_RESERVED_ACC_4,
+	RT8973A_MUIC_ADC_RESERVED_ACC_5,
+	RT8973A_MUIC_ADC_AUDIO_TYPE2,
+	RT8973A_MUIC_ADC_PHONE_POWERED_DEV,
+	RT8973A_MUIC_ADC_UNKNOWN_ACC_1,
+	RT8973A_MUIC_ADC_UNKNOWN_ACC_2,
+	RT8973A_MUIC_ADC_TA,
+	RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB,
+	RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB,
+	RT8973A_MUIC_ADC_UNKNOWN_ACC_3,
+	RT8973A_MUIC_ADC_UNKNOWN_ACC_4,
+	RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART,
+	RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART,
+	RT8973A_MUIC_ADC_UNKNOWN_ACC_5,
+	RT8973A_MUIC_ADC_OPEN = 0x1f,
+
+	/* The below accessories has same ADC value (0x1f).
+	   So, Device type1 is used to separate specific accessory. */
+					/* |---------|--ADC| */
+					/* |    [7:5]|[4:0]| */
+	RT8973A_MUIC_ADC_USB = 0x3f,	/* |      001|11111| */
+};
+
+/* List of supported interrupt for RT8973A */
+static struct muic_irq rt8973a_muic_irqs[] = {
+	{ RT8973A_INT1_ATTACH,		"muic-attach" },
+	{ RT8973A_INT1_DETACH,		"muic-detach" },
+	{ RT8973A_INT1_CHGDET,		"muic-chgdet" },
+	{ RT8973A_INT1_DCD_T,		"muic-dcd-t" },
+	{ RT8973A_INT1_OVP,		"muic-ovp" },
+	{ RT8973A_INT1_CONNECT,		"muic-connect" },
+	{ RT8973A_INT1_ADC_CHG,		"muic-adc-chg" },
+	{ RT8973A_INT1_OTP,		"muic-otp" },
+	{ RT8973A_INT2_UVLO,		"muic-uvlo" },
+	{ RT8973A_INT2_POR,		"muic-por" },
+	{ RT8973A_INT2_OTP_FET,		"muic-otp-fet" },
+	{ RT8973A_INT2_OVP_FET,		"muic-ovp-fet" },
+	{ RT8973A_INT2_OCP_LATCH,	"muic-ocp-latch" },
+	{ RT8973A_INT2_OCP,		"muic-ocp" },
+	{ RT8973A_INT2_OVP_OCP,		"muic-ovp-ocp" },
+};
+
+/* Define interrupt list of RT8973A to register regmap_irq */
+static const struct regmap_irq rt8973a_irqs[] = {
+	/* INT1 interrupts */
+	{ .reg_offset = 0, .mask = RT8973A_INT1_ATTACH_MASK, },
+	{ .reg_offset = 0, .mask = RT8973A_INT1_DETACH_MASK, },
+	{ .reg_offset = 0, .mask = RT8973A_INT1_CHGDET_MASK, },
+	{ .reg_offset = 0, .mask = RT8973A_INT1_DCD_T_MASK, },
+	{ .reg_offset = 0, .mask = RT8973A_INT1_OVP_MASK, },
+	{ .reg_offset = 0, .mask = RT8973A_INT1_CONNECT_MASK, },
+	{ .reg_offset = 0, .mask = RT8973A_INT1_ADC_CHG_MASK, },
+	{ .reg_offset = 0, .mask = RT8973A_INT1_OTP_MASK, },
+
+	/* INT2 interrupts */
+	{ .reg_offset = 1, .mask = RT8973A_INT2_UVLOT_MASK,},
+	{ .reg_offset = 1, .mask = RT8973A_INT2_POR_MASK, },
+	{ .reg_offset = 1, .mask = RT8973A_INT2_OTP_FET_MASK, },
+	{ .reg_offset = 1, .mask = RT8973A_INT2_OVP_FET_MASK, },
+	{ .reg_offset = 1, .mask = RT8973A_INT2_OCP_LATCH_MASK, },
+	{ .reg_offset = 1, .mask = RT8973A_INT2_OCP_MASK, },
+	{ .reg_offset = 1, .mask = RT8973A_INT2_OVP_OCP_MASK, },
+};
+
+static const struct regmap_irq_chip rt8973a_muic_irq_chip = {
+	.name			= "rt8973a",
+	.status_base		= RT8973A_REG_INT1,
+	.mask_base		= RT8973A_REG_INTM1,
+	.mask_invert		= false,
+	.num_regs		= 2,
+	.irqs			= rt8973a_irqs,
+	.num_irqs		= ARRAY_SIZE(rt8973a_irqs),
+};
+
+/* Define regmap configuration of RT8973A for I2C communication  */
+static bool rt8973a_muic_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case RT8973A_REG_INTM1:
+	case RT8973A_REG_INTM2:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static const struct regmap_config rt8973a_muic_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.volatile_reg	= rt8973a_muic_volatile_reg,
+	.max_register	= RT8973A_REG_END,
+};
+
+/* Change DM_CON/DP_CON/VBUSIN switch according to cable type */
+static int rt8973a_muic_set_path(struct rt8973a_muic_info *info,
+				unsigned int con_sw, bool attached)
+{
+	int ret;
+
+	/*
+	 * Don't need to set h/w path according to cable type
+	 * if Auto-configuration mode of CONTROL1 register is true.
+	 */
+	if (info->auto_config)
+		return 0;
+
+	if (!attached)
+		con_sw	= DM_DP_SWITCH_UART;
+
+	switch (con_sw) {
+	case DM_DP_SWITCH_OPEN:
+	case DM_DP_SWITCH_USB:
+	case DM_DP_SWITCH_UART:
+		ret = regmap_update_bits(info->regmap, RT8973A_REG_MANUAL_SW1,
+					RT8973A_REG_MANUAL_SW1_DP_MASK |
+					RT8973A_REG_MANUAL_SW1_DM_MASK,
+					con_sw);
+		if (ret < 0) {
+			dev_err(info->dev,
+				"cannot update DM_CON/DP_CON switch\n");
+			return ret;
+		}
+		break;
+	default:
+		dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n",
+				con_sw);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rt8973a_muic_get_cable_type(struct rt8973a_muic_info *info)
+{
+	unsigned int adc, dev1;
+	int ret, cable_type;
+
+	/* Read ADC value according to external cable or button */
+	ret = regmap_read(info->regmap, RT8973A_REG_ADC, &adc);
+	if (ret) {
+		dev_err(info->dev, "failed to read ADC register\n");
+		return ret;
+	}
+	cable_type = adc & RT8973A_REG_ADC_MASK;
+
+	/* Read Device 1 reigster to identify correct cable type */
+	ret = regmap_read(info->regmap, RT8973A_REG_DEV1, &dev1);
+	if (ret) {
+		dev_err(info->dev, "failed to read DEV1 register\n");
+		return ret;
+	}
+
+	switch (adc) {
+	case RT8973A_MUIC_ADC_OPEN:
+		if (dev1 & RT8973A_REG_DEV1_USB_MASK)
+			cable_type = RT8973A_MUIC_ADC_USB;
+		else if (dev1 & RT8973A_REG_DEV1_DCPORT_MASK)
+			cable_type = RT8973A_MUIC_ADC_TA;
+		else
+			cable_type = RT8973A_MUIC_ADC_OPEN;
+		break;
+	default:
+		break;
+	}
+
+	return cable_type;
+}
+
+static int rt8973a_muic_cable_handler(struct rt8973a_muic_info *info,
+					enum rt8973a_event_type event)
+{
+	static unsigned int prev_cable_type;
+	const char **cable_names = info->edev->supported_cable;
+	unsigned int con_sw = DM_DP_SWITCH_UART;
+	int ret, idx = 0, cable_type;
+	bool attached = false;
+
+	if (!cable_names)
+		return 0;
+
+	switch (event) {
+	case RT8973A_EVENT_ATTACH:
+		cable_type = rt8973a_muic_get_cable_type(info);
+		attached = true;
+		break;
+	case RT8973A_EVENT_DETACH:
+		cable_type = prev_cable_type;
+		attached = false;
+		break;
+	case RT8973A_EVENT_OVP:
+	case RT8973A_EVENT_OTP:
+		dev_warn(info->dev,
+			"happen Over %s issue. Need to disconnect all cables\n",
+			event == RT8973A_EVENT_OVP ? "Voltage" : "Temperature");
+		cable_type = prev_cable_type;
+		attached = false;
+		break;
+	default:
+		dev_err(info->dev,
+			"Cannot handle this event (event:%d)\n", event);
+		return -EINVAL;
+	}
+	prev_cable_type = cable_type;
+
+	switch (cable_type) {
+	case RT8973A_MUIC_ADC_OTG:
+		idx = EXTCON_CABLE_USB_HOST;
+		con_sw = DM_DP_SWITCH_USB;
+		break;
+	case RT8973A_MUIC_ADC_TA:
+		idx = EXTCON_CABLE_TA;
+		con_sw = DM_DP_SWITCH_OPEN;
+		break;
+	case RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB:
+		idx = EXTCON_CABLE_JIG_OFF_USB;
+		con_sw = DM_DP_SWITCH_UART;
+		break;
+	case RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB:
+		idx = EXTCON_CABLE_JIG_ON_USB;
+		con_sw = DM_DP_SWITCH_UART;
+		break;
+	case RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART:
+		idx = EXTCON_CABLE_JIG_OFF_UART;
+		con_sw = DM_DP_SWITCH_UART;
+		break;
+	case RT8973A_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART:
+		idx = EXTCON_CABLE_JIG_ON_UART;
+		con_sw = DM_DP_SWITCH_UART;
+		break;
+	case RT8973A_MUIC_ADC_USB:
+		idx = EXTCON_CABLE_USB;
+		con_sw = DM_DP_SWITCH_USB;
+		break;
+	case RT8973A_MUIC_ADC_OPEN:
+		return 0;
+	case RT8973A_MUIC_ADC_UNKNOWN_ACC_1:
+	case RT8973A_MUIC_ADC_UNKNOWN_ACC_2:
+	case RT8973A_MUIC_ADC_UNKNOWN_ACC_3:
+	case RT8973A_MUIC_ADC_UNKNOWN_ACC_4:
+	case RT8973A_MUIC_ADC_UNKNOWN_ACC_5:
+		dev_warn(info->dev,
+			"Unknown accessory type (adc:0x%x)\n", cable_type);
+		return 0;
+	case RT8973A_MUIC_ADC_AUDIO_SEND_END_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S1_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S2_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S3_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S4_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S5_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S6_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S7_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S8_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S9_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S10_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S11_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_REMOTE_S12_BUTTON:
+	case RT8973A_MUIC_ADC_AUDIO_TYPE2:
+		dev_warn(info->dev,
+			"Audio device/button type (adc:0x%x)\n", cable_type);
+		return 0;
+	case RT8973A_MUIC_ADC_RESERVED_ACC_1:
+	case RT8973A_MUIC_ADC_RESERVED_ACC_2:
+	case RT8973A_MUIC_ADC_RESERVED_ACC_3:
+	case RT8973A_MUIC_ADC_RESERVED_ACC_4:
+	case RT8973A_MUIC_ADC_RESERVED_ACC_5:
+	case RT8973A_MUIC_ADC_PHONE_POWERED_DEV:
+		return 0;
+	default:
+		dev_err(info->dev,
+			"Cannot handle this cable_type (adc:0x%x)\n",
+			cable_type);
+		return -EINVAL;
+	}
+
+	/* Change internal hardware path(DM_CON/DP_CON) */
+	ret = rt8973a_muic_set_path(info, con_sw, attached);
+	if (ret < 0)
+		return ret;
+
+	/* Change the state of external accessory */
+	extcon_set_cable_state(info->edev, cable_names[idx], attached);
+
+	return 0;
+}
+
+static void rt8973a_muic_irq_work(struct work_struct *work)
+{
+	struct rt8973a_muic_info *info = container_of(work,
+			struct rt8973a_muic_info, irq_work);
+	int ret = 0;
+
+	if (!info->edev)
+		return;
+
+	mutex_lock(&info->mutex);
+
+	/* Detect attached or detached cables */
+	if (info->irq_attach) {
+		ret = rt8973a_muic_cable_handler(info, RT8973A_EVENT_ATTACH);
+		info->irq_attach = false;
+	}
+
+	if (info->irq_detach) {
+		ret = rt8973a_muic_cable_handler(info, RT8973A_EVENT_DETACH);
+		info->irq_detach = false;
+	}
+
+	if (info->irq_ovp) {
+		ret = rt8973a_muic_cable_handler(info, RT8973A_EVENT_OVP);
+		info->irq_ovp = false;
+	}
+
+	if (info->irq_otp) {
+		ret = rt8973a_muic_cable_handler(info, RT8973A_EVENT_OTP);
+		info->irq_otp = false;
+	}
+
+	if (ret < 0)
+		dev_err(info->dev, "failed to handle MUIC interrupt\n");
+
+	mutex_unlock(&info->mutex);
+}
+
+static irqreturn_t rt8973a_muic_irq_handler(int irq, void *data)
+{
+	struct rt8973a_muic_info *info = data;
+	int i, irq_type = -1;
+
+	for (i = 0; i < info->num_muic_irqs; i++)
+		if (irq == info->muic_irqs[i].virq)
+			irq_type = info->muic_irqs[i].irq;
+
+	switch (irq_type) {
+	case RT8973A_INT1_ATTACH:
+		info->irq_attach = true;
+		break;
+	case RT8973A_INT1_DETACH:
+		info->irq_detach = true;
+		break;
+	case RT8973A_INT1_OVP:
+		info->irq_ovp = true;
+		break;
+	case RT8973A_INT1_OTP:
+		info->irq_otp = true;
+		break;
+	case RT8973A_INT1_CHGDET:
+	case RT8973A_INT1_DCD_T:
+	case RT8973A_INT1_CONNECT:
+	case RT8973A_INT1_ADC_CHG:
+	case RT8973A_INT2_UVLO:
+	case RT8973A_INT2_POR:
+	case RT8973A_INT2_OTP_FET:
+	case RT8973A_INT2_OVP_FET:
+	case RT8973A_INT2_OCP_LATCH:
+	case RT8973A_INT2_OCP:
+	case RT8973A_INT2_OVP_OCP:
+	default:
+		dev_dbg(info->dev,
+			"Cannot handle this interrupt (%d)\n", irq_type);
+		break;
+	}
+
+	schedule_work(&info->irq_work);
+
+	return IRQ_HANDLED;
+}
+
+static void rt8973a_muic_detect_cable_wq(struct work_struct *work)
+{
+	struct rt8973a_muic_info *info = container_of(to_delayed_work(work),
+				struct rt8973a_muic_info, wq_detcable);
+	int ret;
+
+	/* Notify the state of connector cable or not  */
+	ret = rt8973a_muic_cable_handler(info, RT8973A_EVENT_ATTACH);
+	if (ret < 0)
+		dev_warn(info->dev, "failed to detect cable state\n");
+}
+
+static void rt8973a_init_dev_type(struct rt8973a_muic_info *info)
+{
+	unsigned int data, vendor_id, version_id;
+	int i, ret;
+
+	/* To test I2C, Print version_id and vendor_id of RT8973A */
+	ret = regmap_read(info->regmap, RT8973A_REG_DEVICE_ID, &data);
+	if (ret) {
+		dev_err(info->dev,
+			"failed to read DEVICE_ID register: %d\n", ret);
+		return;
+	}
+
+	vendor_id = ((data & RT8973A_REG_DEVICE_ID_VENDOR_MASK) >>
+				RT8973A_REG_DEVICE_ID_VENDOR_SHIFT);
+	version_id = ((data & RT8973A_REG_DEVICE_ID_VERSION_MASK) >>
+				RT8973A_REG_DEVICE_ID_VERSION_SHIFT);
+
+	dev_info(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n",
+			    version_id, vendor_id);
+
+	/* Initiazle the register of RT8973A device to bring-up */
+	for (i = 0; i < info->num_reg_data; i++) {
+		u8 reg = info->reg_data[i].reg;
+		u8 mask = info->reg_data[i].mask;
+		u8 val = 0;
+
+		if (info->reg_data[i].invert)
+			val = ~info->reg_data[i].val;
+		else
+			val = info->reg_data[i].val;
+
+		regmap_update_bits(info->regmap, reg, mask, val);
+	}
+
+	/* Check whether RT8973A is auto swithcing mode or not */
+	ret = regmap_read(info->regmap, RT8973A_REG_CONTROL1, &data);
+	if (ret) {
+		dev_err(info->dev,
+			"failed to read CONTROL1 register: %d\n", ret);
+		return;
+	}
+
+	data &= RT8973A_REG_CONTROL1_AUTO_CONFIG_MASK;
+	if (data) {
+		info->auto_config = true;
+		dev_info(info->dev,
+			"Enable Auto-configuration for internal path\n");
+	}
+}
+
+static int rt8973a_muic_i2c_probe(struct i2c_client *i2c,
+				 const struct i2c_device_id *id)
+{
+	struct device_node *np = i2c->dev.of_node;
+	struct rt8973a_muic_info *info;
+	int i, ret, irq_flags;
+
+	if (!np)
+		return -EINVAL;
+
+	info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&i2c->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(i2c, info);
+
+	info->dev = &i2c->dev;
+	info->i2c = i2c;
+	info->irq = i2c->irq;
+	info->muic_irqs = rt8973a_muic_irqs;
+	info->num_muic_irqs = ARRAY_SIZE(rt8973a_muic_irqs);
+	info->reg_data = rt8973a_reg_data;
+	info->num_reg_data = ARRAY_SIZE(rt8973a_reg_data);
+
+	mutex_init(&info->mutex);
+
+	INIT_WORK(&info->irq_work, rt8973a_muic_irq_work);
+
+	info->regmap = devm_regmap_init_i2c(i2c, &rt8973a_muic_regmap_config);
+	if (IS_ERR(info->regmap)) {
+		ret = PTR_ERR(info->regmap);
+		dev_err(info->dev, "failed to allocate register map: %d\n",
+				   ret);
+		return ret;
+	}
+
+	/* Support irq domain for RT8973A MUIC device */
+	irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED;
+	ret = regmap_add_irq_chip(info->regmap, info->irq, irq_flags, 0,
+				  &rt8973a_muic_irq_chip, &info->irq_data);
+	if (ret != 0) {
+		dev_err(info->dev, "failed to add irq_chip (irq:%d, err:%d)\n",
+				    info->irq, ret);
+		return ret;
+	}
+
+	for (i = 0; i < info->num_muic_irqs; i++) {
+		struct muic_irq *muic_irq = &info->muic_irqs[i];
+		unsigned int virq = 0;
+
+		virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
+		if (virq <= 0)
+			return -EINVAL;
+		muic_irq->virq = virq;
+
+		ret = devm_request_threaded_irq(info->dev, virq, NULL,
+						rt8973a_muic_irq_handler,
+						IRQF_NO_SUSPEND,
+						muic_irq->name, info);
+		if (ret) {
+			dev_err(info->dev,
+				"failed: irq request (IRQ: %d, error :%d)\n",
+				muic_irq->irq, ret);
+			return ret;
+		}
+	}
+
+	/* Allocate extcon device */
+	info->edev = devm_extcon_dev_allocate(info->dev, rt8973a_extcon_cable);
+	if (IS_ERR(info->edev)) {
+		dev_err(info->dev, "failed to allocate memory for extcon\n");
+		return -ENOMEM;
+	}
+	info->edev->name = np->name;
+
+	/* Register extcon device */
+	ret = devm_extcon_dev_register(info->dev, info->edev);
+	if (ret) {
+		dev_err(info->dev, "failed to register extcon device\n");
+		return ret;
+	}
+
+	/*
+	 * Detect accessory after completing the initialization of platform
+	 *
+	 * - Use delayed workqueue to detect cable state and then
+	 * notify cable state to notifiee/platform through uevent.
+	 * After completing the booting of platform, the extcon provider
+	 * driver should notify cable state to upper layer.
+	 */
+	INIT_DELAYED_WORK(&info->wq_detcable, rt8973a_muic_detect_cable_wq);
+	queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
+			msecs_to_jiffies(DELAY_MS_DEFAULT));
+
+	/* Initialize RT8973A device and print vendor id and version id */
+	rt8973a_init_dev_type(info);
+
+	return 0;
+}
+
+static int rt8973a_muic_i2c_remove(struct i2c_client *i2c)
+{
+	struct rt8973a_muic_info *info = i2c_get_clientdata(i2c);
+
+	regmap_del_irq_chip(info->irq, info->irq_data);
+
+	return 0;
+}
+
+static struct of_device_id rt8973a_dt_match[] = {
+	{ .compatible = "richtek,rt8973a-muic" },
+	{ },
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int rt8973a_muic_suspend(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct rt8973a_muic_info *info = i2c_get_clientdata(i2c);
+
+	enable_irq_wake(info->irq);
+
+	return 0;
+}
+
+static int rt8973a_muic_resume(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct rt8973a_muic_info *info = i2c_get_clientdata(i2c);
+
+	disable_irq_wake(info->irq);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(rt8973a_muic_pm_ops,
+			 rt8973a_muic_suspend, rt8973a_muic_resume);
+
+static const struct i2c_device_id rt8973a_i2c_id[] = {
+	{ "rt8973a", TYPE_RT8973A },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rt8973a_i2c_id);
+
+static struct i2c_driver rt8973a_muic_i2c_driver = {
+	.driver		= {
+		.name	= "rt8973a",
+		.owner	= THIS_MODULE,
+		.pm	= &rt8973a_muic_pm_ops,
+		.of_match_table = rt8973a_dt_match,
+	},
+	.probe	= rt8973a_muic_i2c_probe,
+	.remove	= rt8973a_muic_i2c_remove,
+	.id_table = rt8973a_i2c_id,
+};
+
+static int __init rt8973a_muic_i2c_init(void)
+{
+	return i2c_add_driver(&rt8973a_muic_i2c_driver);
+}
+subsys_initcall(rt8973a_muic_i2c_init);
+
+MODULE_DESCRIPTION("Richtek RT8973A Extcon driver");
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_LICENSE("GPL");

+ 203 - 0
drivers/extcon/extcon-rt8973a.h

@@ -0,0 +1,203 @@
+/*
+ * rt8973a.h
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __LINUX_EXTCON_RT8973A_H
+#define __LINUX_EXTCON_RT8973A_H
+
+enum rt8973a_types {
+	TYPE_RT8973A,
+};
+
+/* RT8973A registers */
+enum rt8973A_reg {
+	RT8973A_REG_DEVICE_ID = 0x1,
+	RT8973A_REG_CONTROL1,
+	RT8973A_REG_INT1,
+	RT8973A_REG_INT2,
+	RT8973A_REG_INTM1,
+	RT8973A_REG_INTM2,
+	RT8973A_REG_ADC,
+	RT8973A_REG_RSVD_1,
+	RT8973A_REG_RSVD_2,
+	RT8973A_REG_DEV1,
+	RT8973A_REG_DEV2,
+	RT8973A_REG_RSVD_3,
+	RT8973A_REG_RSVD_4,
+	RT8973A_REG_RSVD_5,
+	RT8973A_REG_RSVD_6,
+	RT8973A_REG_RSVD_7,
+	RT8973A_REG_RSVD_8,
+	RT8973A_REG_RSVD_9,
+	RT8973A_REG_MANUAL_SW1,
+	RT8973A_REG_MANUAL_SW2,
+	RT8973A_REG_RSVD_10,
+	RT8973A_REG_RSVD_11,
+	RT8973A_REG_RSVD_12,
+	RT8973A_REG_RSVD_13,
+	RT8973A_REG_RSVD_14,
+	RT8973A_REG_RSVD_15,
+	RT8973A_REG_RESET,
+
+	RT8973A_REG_END,
+};
+
+/* Define RT8973A MASK/SHIFT constant */
+#define RT8973A_REG_DEVICE_ID_VENDOR_SHIFT	0
+#define RT8973A_REG_DEVICE_ID_VERSION_SHIFT	3
+#define RT8973A_REG_DEVICE_ID_VENDOR_MASK	(0x7 << RT8973A_REG_DEVICE_ID_VENDOR_SHIFT)
+#define RT8973A_REG_DEVICE_ID_VERSION_MASK	(0x1f << RT8973A_REG_DEVICE_ID_VERSION_SHIFT)
+
+#define RT8973A_REG_CONTROL1_INTM_SHIFT	0
+#define RT8973A_REG_CONTROL1_AUTO_CONFIG_SHIFT	2
+#define RT8973A_REG_CONTROL1_I2C_RST_EN_SHIFT	3
+#define RT8973A_REG_CONTROL1_SWITCH_OPEN_SHIFT	4
+#define RT8973A_REG_CONTROL1_CHGTYP_SHIFT	5
+#define RT8973A_REG_CONTROL1_USB_CHD_EN_SHIFT	6
+#define RT8973A_REG_CONTROL1_ADC_EN_SHIFT	7
+#define RT8973A_REG_CONTROL1_INTM_MASK		(0x1 << RT8973A_REG_CONTROL1_INTM_SHIFT)
+#define RT8973A_REG_CONTROL1_AUTO_CONFIG_MASK	(0x1 << RT8973A_REG_CONTROL1_AUTO_CONFIG_SHIFT)
+#define RT8973A_REG_CONTROL1_I2C_RST_EN_MASK	(0x1 << RT8973A_REG_CONTROL1_I2C_RST_EN_SHIFT)
+#define RT8973A_REG_CONTROL1_SWITCH_OPEN_MASK	(0x1 << RT8973A_REG_CONTROL1_SWITCH_OPEN_SHIFT)
+#define RT8973A_REG_CONTROL1_CHGTYP_MASK	(0x1 << RT8973A_REG_CONTROL1_CHGTYP_SHIFT)
+#define RT8973A_REG_CONTROL1_USB_CHD_EN_MASK	(0x1 << RT8973A_REG_CONTROL1_USB_CHD_EN_SHIFT)
+#define RT8973A_REG_CONTROL1_ADC_EN_MASK	(0x1 << RT8973A_REG_CONTROL1_ADC_EN_SHIFT)
+
+#define RT9873A_REG_INTM1_ATTACH_SHIFT		0
+#define RT9873A_REG_INTM1_DETACH_SHIFT		1
+#define RT9873A_REG_INTM1_CHGDET_SHIFT		2
+#define RT9873A_REG_INTM1_DCD_T_SHIFT		3
+#define RT9873A_REG_INTM1_OVP_SHIFT		4
+#define RT9873A_REG_INTM1_CONNECT_SHIFT		5
+#define RT9873A_REG_INTM1_ADC_CHG_SHIFT		6
+#define RT9873A_REG_INTM1_OTP_SHIFT		7
+#define RT9873A_REG_INTM1_ATTACH_MASK		(0x1 << RT9873A_REG_INTM1_ATTACH_SHIFT)
+#define RT9873A_REG_INTM1_DETACH_MASK		(0x1 <<  RT9873A_REG_INTM1_DETACH_SHIFT)
+#define RT9873A_REG_INTM1_CHGDET_MASK		(0x1 <<  RT9873A_REG_INTM1_CHGDET_SHIFT)
+#define RT9873A_REG_INTM1_DCD_T_MASK		(0x1 <<  RT9873A_REG_INTM1_DCD_T_SHIFT)
+#define RT9873A_REG_INTM1_OVP_MASK		(0x1 <<  RT9873A_REG_INTM1_OVP_SHIFT)
+#define RT9873A_REG_INTM1_CONNECT_MASK		(0x1 <<  RT9873A_REG_INTM1_CONNECT_SHIFT)
+#define RT9873A_REG_INTM1_ADC_CHG_MASK		(0x1 <<  RT9873A_REG_INTM1_ADC_CHG_SHIFT)
+#define RT9873A_REG_INTM1_OTP_MASK		(0x1 <<  RT9873A_REG_INTM1_OTP_SHIFT)
+
+#define RT9873A_REG_INTM2_UVLO_SHIFT		1
+#define RT9873A_REG_INTM2_POR_SHIFT		2
+#define RT9873A_REG_INTM2_OTP_FET_SHIFT		3
+#define RT9873A_REG_INTM2_OVP_FET_SHIFT		4
+#define RT9873A_REG_INTM2_OCP_LATCH_SHIFT	5
+#define RT9873A_REG_INTM2_OCP_SHIFT		6
+#define RT9873A_REG_INTM2_OVP_OCP_SHIFT		7
+#define RT9873A_REG_INTM2_UVLO_MASK		(0x1 << RT9873A_REG_INTM2_UVLO_SHIFT)
+#define RT9873A_REG_INTM2_POR_MASK		(0x1 <<  RT9873A_REG_INTM2_POR_SHIFT)
+#define RT9873A_REG_INTM2_OTP_FET_MASK		(0x1 <<  RT9873A_REG_INTM2_OTP_FET_SHIFT)
+#define RT9873A_REG_INTM2_OVP_FET_MASK		(0x1 <<  RT9873A_REG_INTM2_OVP_FET_SHIFT)
+#define RT9873A_REG_INTM2_OCP_LATCH_MASK	(0x1 <<  RT9873A_REG_INTM2_OCP_LATCH_SHIFT)
+#define RT9873A_REG_INTM2_OCP_MASK		(0x1 <<  RT9873A_REG_INTM2_OCP_SHIFT)
+#define RT9873A_REG_INTM2_OVP_OCP_MASK		(0x1 <<  RT9873A_REG_INTM2_OVP_OCP_SHIFT)
+
+#define RT8973A_REG_ADC_SHIFT			0
+#define RT8973A_REG_ADC_MASK			(0x1f << RT8973A_REG_ADC_SHIFT)
+
+#define RT8973A_REG_DEV1_OTG_SHIFT		0
+#define RT8973A_REG_DEV1_SDP_SHIFT		2
+#define RT8973A_REG_DEV1_UART_SHIFT		3
+#define RT8973A_REG_DEV1_CAR_KIT_TYPE1_SHIFT	4
+#define RT8973A_REG_DEV1_CDPORT_SHIFT		5
+#define RT8973A_REG_DEV1_DCPORT_SHIFT		6
+#define RT8973A_REG_DEV1_OTG_MASK		(0x1 << RT8973A_REG_DEV1_OTG_SHIFT)
+#define RT8973A_REG_DEV1_SDP_MASK		(0x1 << RT8973A_REG_DEV1_SDP_SHIFT)
+#define RT8973A_REG_DEV1_UART_MASK		(0x1 << RT8973A_REG_DEV1_UART_SHIFT)
+#define RT8973A_REG_DEV1_CAR_KIT_TYPE1_MASK	(0x1 << RT8973A_REG_DEV1_CAR_KIT_TYPE1_SHIFT)
+#define RT8973A_REG_DEV1_CDPORT_MASK		(0x1 << RT8973A_REG_DEV1_CDPORT_SHIFT)
+#define RT8973A_REG_DEV1_DCPORT_MASK		(0x1 << RT8973A_REG_DEV1_DCPORT_SHIFT)
+#define RT8973A_REG_DEV1_USB_MASK		(RT8973A_REG_DEV1_SDP_MASK \
+						| RT8973A_REG_DEV1_CDPORT_MASK)
+
+#define RT8973A_REG_DEV2_JIG_USB_ON_SHIFT	0
+#define RT8973A_REG_DEV2_JIG_USB_OFF_SHIFT	1
+#define RT8973A_REG_DEV2_JIG_UART_ON_SHIFT	2
+#define RT8973A_REG_DEV2_JIG_UART_OFF_SHIFT	3
+#define RT8973A_REG_DEV2_JIG_USB_ON_MASK	(0x1 << RT8973A_REG_DEV2_JIG_USB_ON_SHIFT)
+#define RT8973A_REG_DEV2_JIG_USB_OFF_MASK	(0x1 << RT8973A_REG_DEV2_JIG_USB_OFF_SHIFT)
+#define RT8973A_REG_DEV2_JIG_UART_ON_MASK	(0x1 << RT8973A_REG_DEV2_JIG_UART_ON_SHIFT)
+#define RT8973A_REG_DEV2_JIG_UART_OFF_MASK	(0x1 << RT8973A_REG_DEV2_JIG_UART_OFF_SHIFT)
+
+#define RT8973A_REG_MANUAL_SW1_DP_SHIFT		2
+#define RT8973A_REG_MANUAL_SW1_DM_SHIFT		5
+#define RT8973A_REG_MANUAL_SW1_DP_MASK		(0x7 << RT8973A_REG_MANUAL_SW1_DP_SHIFT)
+#define RT8973A_REG_MANUAL_SW1_DM_MASK		(0x7 << RT8973A_REG_MANUAL_SW1_DM_SHIFT)
+#define DM_DP_CON_SWITCH_OPEN			0x0
+#define DM_DP_CON_SWITCH_USB			0x1
+#define DM_DP_CON_SWITCH_UART			0x3
+#define DM_DP_SWITCH_OPEN			((DM_DP_CON_SWITCH_OPEN << RT8973A_REG_MANUAL_SW1_DP_SHIFT) \
+						| (DM_DP_CON_SWITCH_OPEN << RT8973A_REG_MANUAL_SW1_DM_SHIFT))
+#define DM_DP_SWITCH_USB			((DM_DP_CON_SWITCH_USB << RT8973A_REG_MANUAL_SW1_DP_SHIFT) \
+						| (DM_DP_CON_SWITCH_USB << RT8973A_REG_MANUAL_SW1_DM_SHIFT))
+#define DM_DP_SWITCH_UART			((DM_DP_CON_SWITCH_UART << RT8973A_REG_MANUAL_SW1_DP_SHIFT) \
+						| (DM_DP_CON_SWITCH_UART << RT8973A_REG_MANUAL_SW1_DM_SHIFT))
+
+#define RT8973A_REG_MANUAL_SW2_FET_ON_SHIFT	0
+#define RT8973A_REG_MANUAL_SW2_JIG_ON_SHIFT	2
+#define RT8973A_REG_MANUAL_SW2_BOOT_SW_SHIFT	3
+#define RT8973A_REG_MANUAL_SW2_FET_ON_MASK	(0x1 << RT8973A_REG_MANUAL_SW2_FET_ON_SHIFT)
+#define RT8973A_REG_MANUAL_SW2_JIG_ON_MASK	(0x1 << RT8973A_REG_MANUAL_SW2_JIG_ON_SHIFT)
+#define RT8973A_REG_MANUAL_SW2_BOOT_SW_MASK	(0x1 << RT8973A_REG_MANUAL_SW2_BOOT_SW_SHIFT)
+#define RT8973A_REG_MANUAL_SW2_FET_ON		0
+#define RT8973A_REG_MANUAL_SW2_FET_OFF		0x1
+#define RT8973A_REG_MANUAL_SW2_JIG_OFF		0
+#define RT8973A_REG_MANUAL_SW2_JIG_ON		0x1
+#define RT8973A_REG_MANUAL_SW2_BOOT_SW_ON	0
+#define RT8973A_REG_MANUAL_SW2_BOOT_SW_OFF	0x1
+
+#define RT8973A_REG_RESET_SHIFT			0
+#define RT8973A_REG_RESET_MASK			(0x1 << RT8973A_REG_RESET_SHIFT)
+#define RT8973A_REG_RESET			0x1
+
+/* RT8973A Interrupts */
+enum rt8973a_irq {
+	/* Interrupt1*/
+	RT8973A_INT1_ATTACH,
+	RT8973A_INT1_DETACH,
+	RT8973A_INT1_CHGDET,
+	RT8973A_INT1_DCD_T,
+	RT8973A_INT1_OVP,
+	RT8973A_INT1_CONNECT,
+	RT8973A_INT1_ADC_CHG,
+	RT8973A_INT1_OTP,
+
+	/* Interrupt2*/
+	RT8973A_INT2_UVLO,
+	RT8973A_INT2_POR,
+	RT8973A_INT2_OTP_FET,
+	RT8973A_INT2_OVP_FET,
+	RT8973A_INT2_OCP_LATCH,
+	RT8973A_INT2_OCP,
+	RT8973A_INT2_OVP_OCP,
+
+	RT8973A_NUM,
+};
+
+#define RT8973A_INT1_ATTACH_MASK		BIT(0)
+#define RT8973A_INT1_DETACH_MASK		BIT(1)
+#define RT8973A_INT1_CHGDET_MASK		BIT(2)
+#define RT8973A_INT1_DCD_T_MASK			BIT(3)
+#define RT8973A_INT1_OVP_MASK			BIT(4)
+#define RT8973A_INT1_CONNECT_MASK		BIT(5)
+#define RT8973A_INT1_ADC_CHG_MASK		BIT(6)
+#define RT8973A_INT1_OTP_MASK			BIT(7)
+#define RT8973A_INT2_UVLOT_MASK			BIT(0)
+#define RT8973A_INT2_POR_MASK			BIT(1)
+#define RT8973A_INT2_OTP_FET_MASK		BIT(2)
+#define RT8973A_INT2_OVP_FET_MASK		BIT(3)
+#define RT8973A_INT2_OCP_LATCH_MASK		BIT(4)
+#define RT8973A_INT2_OCP_MASK			BIT(5)
+#define RT8973A_INT2_OVP_OCP_MASK		BIT(6)
+
+#endif /*  __LINUX_EXTCON_RT8973A_H */

+ 7 - 13
drivers/extcon/extcon-sm5502.c

@@ -8,16 +8,10 @@
  * under  the terms of  the GNU General  Public License as published by the
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  * option) any later version.
- *
- * 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.
  */
  */
 
 
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
-#include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
@@ -26,7 +20,8 @@
 #include <linux/regmap.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/extcon.h>
 #include <linux/extcon.h>
-#include <linux/extcon/sm5502.h>
+
+#include "extcon-sm5502.h"
 
 
 #define	DELAY_MS_DEFAULT		17000	/* unit: millisecond */
 #define	DELAY_MS_DEFAULT		17000	/* unit: millisecond */
 
 
@@ -300,7 +295,7 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
 	 * If ADC is SM5502_MUIC_ADC_GROUND(0x0), external cable hasn't
 	 * If ADC is SM5502_MUIC_ADC_GROUND(0x0), external cable hasn't
 	 * connected with to MUIC device.
 	 * connected with to MUIC device.
 	 */
 	 */
-	cable_type &= SM5502_REG_ADC_MASK;
+	cable_type = adc & SM5502_REG_ADC_MASK;
 	if (cable_type == SM5502_MUIC_ADC_GROUND)
 	if (cable_type == SM5502_MUIC_ADC_GROUND)
 		return SM5502_MUIC_ADC_GROUND;
 		return SM5502_MUIC_ADC_GROUND;
 
 
@@ -395,7 +390,7 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
 	/* Get the type of attached or detached cable */
 	/* Get the type of attached or detached cable */
 	if (attached)
 	if (attached)
 		cable_type = sm5502_muic_get_cable_type(info);
 		cable_type = sm5502_muic_get_cable_type(info);
-	else if (!attached)
+	else
 		cable_type = prev_cable_type;
 		cable_type = prev_cable_type;
 	prev_cable_type = cable_type;
 	prev_cable_type = cable_type;
 
 
@@ -457,8 +452,6 @@ static void sm5502_muic_irq_work(struct work_struct *work)
 		dev_err(info->dev, "failed to handle MUIC interrupt\n");
 		dev_err(info->dev, "failed to handle MUIC interrupt\n");
 
 
 	mutex_unlock(&info->mutex);
 	mutex_unlock(&info->mutex);
-
-	return;
 }
 }
 
 
 /*
 /*
@@ -617,8 +610,9 @@ static int sm5022_muic_i2c_probe(struct i2c_client *i2c,
 						IRQF_NO_SUSPEND,
 						IRQF_NO_SUSPEND,
 						muic_irq->name, info);
 						muic_irq->name, info);
 		if (ret) {
 		if (ret) {
-			dev_err(info->dev, "failed: irq request (IRQ: %d,"
-				" error :%d)\n", muic_irq->irq, ret);
+			dev_err(info->dev,
+				"failed: irq request (IRQ: %d, error :%d)\n",
+				muic_irq->irq, ret);
 			return ret;
 			return ret;
 		}
 		}
 	}
 	}

+ 0 - 5
include/linux/extcon/sm5502.h → drivers/extcon/extcon-sm5502.h

@@ -7,11 +7,6 @@
  * under  the terms of  the GNU General  Public License as published by the
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  * option) any later version.
- *
- * 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.
  */
  */
 
 
 #ifndef __LINUX_EXTCON_SM5502_H
 #ifndef __LINUX_EXTCON_SM5502_H

+ 38 - 18
drivers/hv/channel.c

@@ -165,8 +165,10 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 	ret = vmbus_post_msg(open_msg,
 	ret = vmbus_post_msg(open_msg,
 			       sizeof(struct vmbus_channel_open_channel));
 			       sizeof(struct vmbus_channel_open_channel));
 
 
-	if (ret != 0)
+	if (ret != 0) {
+		err = ret;
 		goto error1;
 		goto error1;
+	}
 
 
 	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
 	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
 	if (t == 0) {
 	if (t == 0) {
@@ -363,7 +365,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 	u32 next_gpadl_handle;
 	u32 next_gpadl_handle;
 	unsigned long flags;
 	unsigned long flags;
 	int ret = 0;
 	int ret = 0;
-	int t;
 
 
 	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
 	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
 	atomic_inc(&vmbus_connection.next_gpadl_handle);
 	atomic_inc(&vmbus_connection.next_gpadl_handle);
@@ -410,9 +411,7 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 
 
 		}
 		}
 	}
 	}
-	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
-	BUG_ON(t == 0);
-
+	wait_for_completion(&msginfo->waitevent);
 
 
 	/* At this point, we received the gpadl created msg */
 	/* At this point, we received the gpadl created msg */
 	*gpadl_handle = gpadlmsg->gpadl;
 	*gpadl_handle = gpadlmsg->gpadl;
@@ -435,7 +434,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
 	struct vmbus_channel_gpadl_teardown *msg;
 	struct vmbus_channel_gpadl_teardown *msg;
 	struct vmbus_channel_msginfo *info;
 	struct vmbus_channel_msginfo *info;
 	unsigned long flags;
 	unsigned long flags;
-	int ret, t;
+	int ret;
 
 
 	info = kmalloc(sizeof(*info) +
 	info = kmalloc(sizeof(*info) +
 		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
 		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
@@ -457,11 +456,12 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
 	ret = vmbus_post_msg(msg,
 	ret = vmbus_post_msg(msg,
 			       sizeof(struct vmbus_channel_gpadl_teardown));
 			       sizeof(struct vmbus_channel_gpadl_teardown));
 
 
-	BUG_ON(ret != 0);
-	t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
-	BUG_ON(t == 0);
+	if (ret)
+		goto post_msg_err;
+
+	wait_for_completion(&info->waitevent);
 
 
-	/* Received a torndown response */
+post_msg_err:
 	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_del(&info->msglistentry);
 	list_del(&info->msglistentry);
 	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -478,7 +478,7 @@ static void reset_channel_cb(void *arg)
 	channel->onchannel_callback = NULL;
 	channel->onchannel_callback = NULL;
 }
 }
 
 
-static void vmbus_close_internal(struct vmbus_channel *channel)
+static int vmbus_close_internal(struct vmbus_channel *channel)
 {
 {
 	struct vmbus_channel_close_channel *msg;
 	struct vmbus_channel_close_channel *msg;
 	int ret;
 	int ret;
@@ -486,11 +486,14 @@ static void vmbus_close_internal(struct vmbus_channel *channel)
 	channel->state = CHANNEL_OPEN_STATE;
 	channel->state = CHANNEL_OPEN_STATE;
 	channel->sc_creation_callback = NULL;
 	channel->sc_creation_callback = NULL;
 	/* Stop callback and cancel the timer asap */
 	/* Stop callback and cancel the timer asap */
-	if (channel->target_cpu != smp_processor_id())
+	if (channel->target_cpu != get_cpu()) {
+		put_cpu();
 		smp_call_function_single(channel->target_cpu, reset_channel_cb,
 		smp_call_function_single(channel->target_cpu, reset_channel_cb,
 					 channel, true);
 					 channel, true);
-	else
+	} else {
 		reset_channel_cb(channel);
 		reset_channel_cb(channel);
+		put_cpu();
+	}
 
 
 	/* Send a closing message */
 	/* Send a closing message */
 
 
@@ -501,11 +504,28 @@ static void vmbus_close_internal(struct vmbus_channel *channel)
 
 
 	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
 	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
 
 
-	BUG_ON(ret != 0);
+	if (ret) {
+		pr_err("Close failed: close post msg return is %d\n", ret);
+		/*
+		 * If we failed to post the close msg,
+		 * it is perhaps better to leak memory.
+		 */
+		return ret;
+	}
+
 	/* Tear down the gpadl for the channel's ring buffer */
 	/* Tear down the gpadl for the channel's ring buffer */
-	if (channel->ringbuffer_gpadlhandle)
-		vmbus_teardown_gpadl(channel,
-					  channel->ringbuffer_gpadlhandle);
+	if (channel->ringbuffer_gpadlhandle) {
+		ret = vmbus_teardown_gpadl(channel,
+					   channel->ringbuffer_gpadlhandle);
+		if (ret) {
+			pr_err("Close failed: teardown gpadl return %d\n", ret);
+			/*
+			 * If we failed to teardown gpadl,
+			 * it is perhaps better to leak memory.
+			 */
+			return ret;
+		}
+	}
 
 
 	/* Cleanup the ring buffers for this channel */
 	/* Cleanup the ring buffers for this channel */
 	hv_ringbuffer_cleanup(&channel->outbound);
 	hv_ringbuffer_cleanup(&channel->outbound);
@@ -514,7 +534,7 @@ static void vmbus_close_internal(struct vmbus_channel *channel)
 	free_pages((unsigned long)channel->ringbuffer_pages,
 	free_pages((unsigned long)channel->ringbuffer_pages,
 		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
 		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
 
 
-
+	return ret;
 }
 }
 
 
 /*
 /*

+ 15 - 6
drivers/hv/channel_mgmt.c

@@ -224,11 +224,14 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
 	msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
 	msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
 	vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released));
 	vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released));
 
 
-	if (channel->target_cpu != smp_processor_id())
+	if (channel->target_cpu != get_cpu()) {
+		put_cpu();
 		smp_call_function_single(channel->target_cpu,
 		smp_call_function_single(channel->target_cpu,
 					 percpu_channel_deq, channel, true);
 					 percpu_channel_deq, channel, true);
-	else
+	} else {
 		percpu_channel_deq(channel);
 		percpu_channel_deq(channel);
+		put_cpu();
+	}
 
 
 	if (channel->primary_channel == NULL) {
 	if (channel->primary_channel == NULL) {
 		spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
 		spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
@@ -294,12 +297,15 @@ static void vmbus_process_offer(struct work_struct *work)
 	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
 	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
 
 
 	if (enq) {
 	if (enq) {
-		if (newchannel->target_cpu != smp_processor_id())
+		if (newchannel->target_cpu != get_cpu()) {
+			put_cpu();
 			smp_call_function_single(newchannel->target_cpu,
 			smp_call_function_single(newchannel->target_cpu,
 						 percpu_channel_enq,
 						 percpu_channel_enq,
 						 newchannel, true);
 						 newchannel, true);
-		else
+		} else {
 			percpu_channel_enq(newchannel);
 			percpu_channel_enq(newchannel);
+			put_cpu();
+		}
 	}
 	}
 	if (!fnew) {
 	if (!fnew) {
 		/*
 		/*
@@ -314,12 +320,15 @@ static void vmbus_process_offer(struct work_struct *work)
 			list_add_tail(&newchannel->sc_list, &channel->sc_list);
 			list_add_tail(&newchannel->sc_list, &channel->sc_list);
 			spin_unlock_irqrestore(&channel->sc_lock, flags);
 			spin_unlock_irqrestore(&channel->sc_lock, flags);
 
 
-			if (newchannel->target_cpu != smp_processor_id())
+			if (newchannel->target_cpu != get_cpu()) {
+				put_cpu();
 				smp_call_function_single(newchannel->target_cpu,
 				smp_call_function_single(newchannel->target_cpu,
 							 percpu_channel_enq,
 							 percpu_channel_enq,
 							 newchannel, true);
 							 newchannel, true);
-			else
+			} else {
 				percpu_channel_enq(newchannel);
 				percpu_channel_enq(newchannel);
+				put_cpu();
+			}
 
 
 			newchannel->state = CHANNEL_OPEN_STATE;
 			newchannel->state = CHANNEL_OPEN_STATE;
 			if (channel->sc_creation_callback != NULL)
 			if (channel->sc_creation_callback != NULL)

+ 14 - 3
drivers/hv/connection.c

@@ -427,10 +427,21 @@ int vmbus_post_msg(void *buffer, size_t buflen)
 	 * insufficient resources. Retry the operation a couple of
 	 * insufficient resources. Retry the operation a couple of
 	 * times before giving up.
 	 * times before giving up.
 	 */
 	 */
-	while (retries < 3) {
-		ret =  hv_post_message(conn_id, 1, buffer, buflen);
-		if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
+	while (retries < 10) {
+		ret = hv_post_message(conn_id, 1, buffer, buflen);
+
+		switch (ret) {
+		case HV_STATUS_INSUFFICIENT_BUFFERS:
+			ret = -ENOMEM;
+		case -ENOMEM:
+			break;
+		case HV_STATUS_SUCCESS:
 			return ret;
 			return ret;
+		default:
+			pr_err("hv_post_msg() failed; error code:%d\n", ret);
+			return -EINVAL;
+		}
+
 		retries++;
 		retries++;
 		msleep(100);
 		msleep(100);
 	}
 	}

+ 15 - 12
drivers/hv/hv.c

@@ -138,6 +138,8 @@ int hv_init(void)
 	memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
 	memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
 	memset(hv_context.synic_message_page, 0,
 	memset(hv_context.synic_message_page, 0,
 	       sizeof(void *) * NR_CPUS);
 	       sizeof(void *) * NR_CPUS);
+	memset(hv_context.post_msg_page, 0,
+	       sizeof(void *) * NR_CPUS);
 	memset(hv_context.vp_index, 0,
 	memset(hv_context.vp_index, 0,
 	       sizeof(int) * NR_CPUS);
 	       sizeof(int) * NR_CPUS);
 	memset(hv_context.event_dpc, 0,
 	memset(hv_context.event_dpc, 0,
@@ -217,26 +219,18 @@ int hv_post_message(union hv_connection_id connection_id,
 		  enum hv_message_type message_type,
 		  enum hv_message_type message_type,
 		  void *payload, size_t payload_size)
 		  void *payload, size_t payload_size)
 {
 {
-	struct aligned_input {
-		u64 alignment8;
-		struct hv_input_post_message msg;
-	};
 
 
 	struct hv_input_post_message *aligned_msg;
 	struct hv_input_post_message *aligned_msg;
 	u16 status;
 	u16 status;
-	unsigned long addr;
 
 
 	if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
 	if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
 		return -EMSGSIZE;
 		return -EMSGSIZE;
 
 
-	addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC);
-	if (!addr)
-		return -ENOMEM;
-
 	aligned_msg = (struct hv_input_post_message *)
 	aligned_msg = (struct hv_input_post_message *)
-			(ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN));
+			hv_context.post_msg_page[get_cpu()];
 
 
 	aligned_msg->connectionid = connection_id;
 	aligned_msg->connectionid = connection_id;
+	aligned_msg->reserved = 0;
 	aligned_msg->message_type = message_type;
 	aligned_msg->message_type = message_type;
 	aligned_msg->payload_size = payload_size;
 	aligned_msg->payload_size = payload_size;
 	memcpy((void *)aligned_msg->payload, payload, payload_size);
 	memcpy((void *)aligned_msg->payload, payload, payload_size);
@@ -244,8 +238,7 @@ int hv_post_message(union hv_connection_id connection_id,
 	status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL)
 	status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL)
 		& 0xFFFF;
 		& 0xFFFF;
 
 
-	kfree((void *)addr);
-
+	put_cpu();
 	return status;
 	return status;
 }
 }
 
 
@@ -294,6 +287,14 @@ int hv_synic_alloc(void)
 			pr_err("Unable to allocate SYNIC event page\n");
 			pr_err("Unable to allocate SYNIC event page\n");
 			goto err;
 			goto err;
 		}
 		}
+
+		hv_context.post_msg_page[cpu] =
+			(void *)get_zeroed_page(GFP_ATOMIC);
+
+		if (hv_context.post_msg_page[cpu] == NULL) {
+			pr_err("Unable to allocate post msg page\n");
+			goto err;
+		}
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -308,6 +309,8 @@ static void hv_synic_free_cpu(int cpu)
 		free_page((unsigned long)hv_context.synic_event_page[cpu]);
 		free_page((unsigned long)hv_context.synic_event_page[cpu]);
 	if (hv_context.synic_message_page[cpu])
 	if (hv_context.synic_message_page[cpu])
 		free_page((unsigned long)hv_context.synic_message_page[cpu]);
 		free_page((unsigned long)hv_context.synic_message_page[cpu]);
+	if (hv_context.post_msg_page[cpu])
+		free_page((unsigned long)hv_context.post_msg_page[cpu]);
 }
 }
 
 
 void hv_synic_free(void)
 void hv_synic_free(void)

+ 4 - 0
drivers/hv/hyperv_vmbus.h

@@ -515,6 +515,10 @@ struct hv_context {
 	 * per-cpu list of the channels based on their CPU affinity.
 	 * per-cpu list of the channels based on their CPU affinity.
 	 */
 	 */
 	struct list_head percpu_list[NR_CPUS];
 	struct list_head percpu_list[NR_CPUS];
+	/*
+	 * buffer to post messages to the host.
+	 */
+	void *post_msg_page[NR_CPUS];
 };
 };
 
 
 extern struct hv_context hv_context;
 extern struct hv_context hv_context;

+ 5 - 0
drivers/hv/ring_buffer.c

@@ -361,6 +361,11 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
 	ring_info->ring_buffer->read_index =
 	ring_info->ring_buffer->read_index =
 		ring_info->ring_buffer->write_index = 0;
 		ring_info->ring_buffer->write_index = 0;
 
 
+	/*
+	 * Set the feature bit for enabling flow control.
+	 */
+	ring_info->ring_buffer->feature_bits.value = 1;
+
 	ring_info->ring_size = buflen;
 	ring_info->ring_size = buflen;
 	ring_info->ring_datasize = buflen - sizeof(struct hv_ring_buffer);
 	ring_info->ring_datasize = buflen - sizeof(struct hv_ring_buffer);
 
 

+ 2 - 1
drivers/ipack/carriers/tpci200.c

@@ -572,7 +572,8 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
 	/* Register the carrier in the industry pack bus driver */
 	/* Register the carrier in the industry pack bus driver */
 	tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
 	tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
 						      TPCI200_NB_SLOT,
 						      TPCI200_NB_SLOT,
-						      &tpci200_bus_ops);
+						      &tpci200_bus_ops,
+						      THIS_MODULE);
 	if (!tpci200->info->ipack_bus) {
 	if (!tpci200->info->ipack_bus) {
 		dev_err(&pdev->dev,
 		dev_err(&pdev->dev,
 			"error registering the carrier on ipack driver\n");
 			"error registering the carrier on ipack driver\n");

+ 44 - 25
drivers/ipack/devices/ipoctal.c

@@ -55,6 +55,22 @@ struct ipoctal {
 	u8 __iomem			*int_space;
 	u8 __iomem			*int_space;
 };
 };
 
 
+static inline struct ipoctal *chan_to_ipoctal(struct ipoctal_channel *chan,
+					      unsigned int index)
+{
+	return container_of(chan, struct ipoctal, channel[index]);
+}
+
+static void ipoctal_reset_channel(struct ipoctal_channel *channel)
+{
+	iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
+	channel->rx_enable = 0;
+	iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
+	iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr);
+}
+
 static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
 static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
 {
 {
 	struct ipoctal_channel *channel;
 	struct ipoctal_channel *channel;
@@ -72,12 +88,20 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
 
 
 static int ipoctal_open(struct tty_struct *tty, struct file *file)
 static int ipoctal_open(struct tty_struct *tty, struct file *file)
 {
 {
-	struct ipoctal_channel *channel;
+	struct ipoctal_channel *channel = dev_get_drvdata(tty->dev);
+	struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index);
+	int err;
 
 
-	channel = dev_get_drvdata(tty->dev);
 	tty->driver_data = channel;
 	tty->driver_data = channel;
 
 
-	return tty_port_open(&channel->tty_port, tty, file);
+	if (!ipack_get_carrier(ipoctal->dev))
+		return -EBUSY;
+
+	err = tty_port_open(&channel->tty_port, tty, file);
+	if (err)
+		ipack_put_carrier(ipoctal->dev);
+
+	return err;
 }
 }
 
 
 static void ipoctal_reset_stats(struct ipoctal_stats *stats)
 static void ipoctal_reset_stats(struct ipoctal_stats *stats)
@@ -151,7 +175,6 @@ static void ipoctal_irq_rx(struct ipoctal_channel *channel, u8 sr)
 				flag = TTY_FRAME;
 				flag = TTY_FRAME;
 			}
 			}
 			if (sr & SR_RECEIVED_BREAK) {
 			if (sr & SR_RECEIVED_BREAK) {
-				iowrite8(CR_CMD_RESET_BREAK_CHANGE, &channel->regs->w.cr);
 				channel->stats.rcv_break++;
 				channel->stats.rcv_break++;
 				flag = TTY_BREAK;
 				flag = TTY_BREAK;
 			}
 			}
@@ -196,6 +219,9 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel)
 	isr = ioread8(&channel->block_regs->r.isr);
 	isr = ioread8(&channel->block_regs->r.isr);
 	sr = ioread8(&channel->regs->r.sr);
 	sr = ioread8(&channel->regs->r.sr);
 
 
+	if (isr & (IMR_DELTA_BREAK_A | IMR_DELTA_BREAK_B))
+		iowrite8(CR_CMD_RESET_BREAK_CHANGE, &channel->regs->w.cr);
+
 	if ((sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) {
 	if ((sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) {
 		iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
 		iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
 		/* In case of RS-485, change from TX to RX when finishing TX.
 		/* In case of RS-485, change from TX to RX when finishing TX.
@@ -304,10 +330,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
 			channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_A;
 			channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_A;
 		}
 		}
 
 
-		iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
-		channel->rx_enable = 0;
-		iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
-		iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
+		ipoctal_reset_channel(channel);
 		iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY,
 		iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY,
 			 &channel->regs->w.mr); /* mr1 */
 			 &channel->regs->w.mr); /* mr1 */
 		iowrite8(0, &channel->regs->w.mr); /* mr2 */
 		iowrite8(0, &channel->regs->w.mr); /* mr2 */
@@ -467,11 +490,7 @@ static void ipoctal_set_termios(struct tty_struct *tty,
 	cflag = tty->termios.c_cflag;
 	cflag = tty->termios.c_cflag;
 
 
 	/* Disable and reset everything before change the setup */
 	/* Disable and reset everything before change the setup */
-	iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr);
+	ipoctal_reset_channel(channel);
 
 
 	/* Set Bits per chars */
 	/* Set Bits per chars */
 	switch (cflag & CSIZE) {
 	switch (cflag & CSIZE) {
@@ -609,12 +628,7 @@ static void ipoctal_hangup(struct tty_struct *tty)
 
 
 	tty_port_hangup(&channel->tty_port);
 	tty_port_hangup(&channel->tty_port);
 
 
-	iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
-	channel->rx_enable = 0;
-	iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr);
+	ipoctal_reset_channel(channel);
 
 
 	clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags);
 	clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags);
 	wake_up_interruptible(&channel->tty_port.open_wait);
 	wake_up_interruptible(&channel->tty_port.open_wait);
@@ -627,15 +641,19 @@ static void ipoctal_shutdown(struct tty_struct *tty)
 	if (channel == NULL)
 	if (channel == NULL)
 		return;
 		return;
 
 
-	iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
-	channel->rx_enable = 0;
-	iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
-	iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr);
+	ipoctal_reset_channel(channel);
 	clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags);
 	clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags);
 }
 }
 
 
+static void ipoctal_cleanup(struct tty_struct *tty)
+{
+	struct ipoctal_channel *channel = tty->driver_data;
+	struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index);
+
+	/* release the carrier driver */
+	ipack_put_carrier(ipoctal->dev);
+}
+
 static const struct tty_operations ipoctal_fops = {
 static const struct tty_operations ipoctal_fops = {
 	.ioctl =		NULL,
 	.ioctl =		NULL,
 	.open =			ipoctal_open,
 	.open =			ipoctal_open,
@@ -647,6 +665,7 @@ static const struct tty_operations ipoctal_fops = {
 	.get_icount =		ipoctal_get_icount,
 	.get_icount =		ipoctal_get_icount,
 	.hangup =		ipoctal_hangup,
 	.hangup =		ipoctal_hangup,
 	.shutdown =		ipoctal_shutdown,
 	.shutdown =		ipoctal_shutdown,
+	.cleanup =              ipoctal_cleanup,
 };
 };
 
 
 static int ipoctal_probe(struct ipack_device *dev)
 static int ipoctal_probe(struct ipack_device *dev)

+ 1 - 1
drivers/ipack/devices/ipoctal.h

@@ -12,7 +12,7 @@
  * Software Foundation; version 2 of the License.
  * Software Foundation; version 2 of the License.
  */
  */
 
 
-#ifndef _IPOCTAL_H
+#ifndef _IPOCTAL_H_
 #define _IPOCTAL_H_
 #define _IPOCTAL_H_
 
 
 #define NR_CHANNELS		8
 #define NR_CHANNELS		8

+ 3 - 1
drivers/ipack/ipack.c

@@ -206,7 +206,8 @@ static struct bus_type ipack_bus_type = {
 };
 };
 
 
 struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
 struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
-					    const struct ipack_bus_ops *ops)
+					    const struct ipack_bus_ops *ops,
+					    struct module *owner)
 {
 {
 	int bus_nr;
 	int bus_nr;
 	struct ipack_bus_device *bus;
 	struct ipack_bus_device *bus;
@@ -225,6 +226,7 @@ struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
 	bus->parent = parent;
 	bus->parent = parent;
 	bus->slots = slots;
 	bus->slots = slots;
 	bus->ops = ops;
 	bus->ops = ops;
+	bus->owner = owner;
 	return bus;
 	return bus;
 }
 }
 EXPORT_SYMBOL_GPL(ipack_bus_register);
 EXPORT_SYMBOL_GPL(ipack_bus_register);

+ 6 - 17
drivers/misc/eeprom/eeprom.c

@@ -18,7 +18,7 @@
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/device.h>
 #include <linux/jiffies.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
@@ -159,12 +159,11 @@ static int eeprom_probe(struct i2c_client *client,
 {
 {
 	struct i2c_adapter *adapter = client->adapter;
 	struct i2c_adapter *adapter = client->adapter;
 	struct eeprom_data *data;
 	struct eeprom_data *data;
-	int err;
 
 
-	if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct eeprom_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 
 	memset(data->data, 0xff, EEPROM_SIZE);
 	memset(data->data, 0xff, EEPROM_SIZE);
 	i2c_set_clientdata(client, data);
 	i2c_set_clientdata(client, data);
@@ -190,22 +189,12 @@ static int eeprom_probe(struct i2c_client *client,
 	}
 	}
 
 
 	/* create the sysfs eeprom file */
 	/* create the sysfs eeprom file */
-	err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr);
-	if (err)
-		goto exit_kfree;
-
-	return 0;
-
-exit_kfree:
-	kfree(data);
-exit:
-	return err;
+	return sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr);
 }
 }
 
 
 static int eeprom_remove(struct i2c_client *client)
 static int eeprom_remove(struct i2c_client *client)
 {
 {
 	sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
 	sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
-	kfree(i2c_get_clientdata(client));
 
 
 	return 0;
 	return 0;
 }
 }

+ 24 - 14
drivers/misc/genwqe/card_base.c

@@ -5,7 +5,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -45,10 +45,10 @@
 MODULE_AUTHOR("Frank Haverkamp <haver@linux.vnet.ibm.com>");
 MODULE_AUTHOR("Frank Haverkamp <haver@linux.vnet.ibm.com>");
 MODULE_AUTHOR("Michael Ruettger <michael@ibmra.de>");
 MODULE_AUTHOR("Michael Ruettger <michael@ibmra.de>");
 MODULE_AUTHOR("Joerg-Stephan Vogt <jsvogt@de.ibm.com>");
 MODULE_AUTHOR("Joerg-Stephan Vogt <jsvogt@de.ibm.com>");
-MODULE_AUTHOR("Michal Jung <mijung@de.ibm.com>");
+MODULE_AUTHOR("Michael Jung <mijung@gmx.net>");
 
 
 MODULE_DESCRIPTION("GenWQE Card");
 MODULE_DESCRIPTION("GenWQE Card");
-MODULE_VERSION(DRV_VERS_STRING);
+MODULE_VERSION(DRV_VERSION);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 
 static char genwqe_driver_name[] = GENWQE_DEVNAME;
 static char genwqe_driver_name[] = GENWQE_DEVNAME;
@@ -346,8 +346,13 @@ static bool genwqe_setup_vf_jtimer(struct genwqe_dev *cd)
 	unsigned int vf;
 	unsigned int vf;
 	u32 T = genwqe_T_psec(cd);
 	u32 T = genwqe_T_psec(cd);
 	u64 x;
 	u64 x;
+	int totalvfs;
 
 
-	for (vf = 0; vf < pci_sriov_get_totalvfs(pci_dev); vf++) {
+	totalvfs = pci_sriov_get_totalvfs(pci_dev);
+	if (totalvfs <= 0)
+		return false;
+
+	for (vf = 0; vf < totalvfs; vf++) {
 
 
 		if (cd->vf_jobtimeout_msec[vf] == 0)
 		if (cd->vf_jobtimeout_msec[vf] == 0)
 			continue;
 			continue;
@@ -383,8 +388,9 @@ static int genwqe_ffdc_buffs_alloc(struct genwqe_dev *cd)
 
 
 		/* currently support only the debug units mentioned here */
 		/* currently support only the debug units mentioned here */
 		cd->ffdc[type].entries = e;
 		cd->ffdc[type].entries = e;
-		cd->ffdc[type].regs = kmalloc(e * sizeof(struct genwqe_reg),
-					      GFP_KERNEL);
+		cd->ffdc[type].regs =
+			kmalloc_array(e, sizeof(struct genwqe_reg),
+				      GFP_KERNEL);
 		/*
 		/*
 		 * regs == NULL is ok, the using code treats this as no regs,
 		 * regs == NULL is ok, the using code treats this as no regs,
 		 * Printing warning is ok in this case.
 		 * Printing warning is ok in this case.
@@ -723,8 +729,8 @@ static u64 genwqe_fir_checking(struct genwqe_dev *cd)
 				__genwqe_writeq(cd, sfir_addr, sfir);
 				__genwqe_writeq(cd, sfir_addr, sfir);
 
 
 				dev_dbg(&pci_dev->dev,
 				dev_dbg(&pci_dev->dev,
-					"[HM] Clearing  2ndary FIR 0x%08x "
-					"with 0x%016llx\n", sfir_addr, sfir);
+					"[HM] Clearing  2ndary FIR 0x%08x with 0x%016llx\n",
+					sfir_addr, sfir);
 
 
 				/*
 				/*
 				 * note, these cannot be error-Firs
 				 * note, these cannot be error-Firs
@@ -740,9 +746,8 @@ static u64 genwqe_fir_checking(struct genwqe_dev *cd)
 				__genwqe_writeq(cd, fir_clr_addr, mask);
 				__genwqe_writeq(cd, fir_clr_addr, mask);
 
 
 				dev_dbg(&pci_dev->dev,
 				dev_dbg(&pci_dev->dev,
-					"[HM] Clearing primary FIR 0x%08x "
-					"with 0x%016llx\n", fir_clr_addr,
-					mask);
+					"[HM] Clearing primary FIR 0x%08x with 0x%016llx\n",
+					fir_clr_addr, mask);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -1125,6 +1130,8 @@ static int genwqe_pci_setup(struct genwqe_dev *cd)
 	}
 	}
 
 
 	cd->num_vfs = pci_sriov_get_totalvfs(pci_dev);
 	cd->num_vfs = pci_sriov_get_totalvfs(pci_dev);
+	if (cd->num_vfs < 0)
+		cd->num_vfs = 0;
 
 
 	err = genwqe_read_ids(cd);
 	err = genwqe_read_ids(cd);
 	if (err)
 	if (err)
@@ -1202,8 +1209,8 @@ static int genwqe_probe(struct pci_dev *pci_dev,
 		err = genwqe_health_check_start(cd);
 		err = genwqe_health_check_start(cd);
 		if (err < 0) {
 		if (err < 0) {
 			dev_err(&pci_dev->dev,
 			dev_err(&pci_dev->dev,
-				"err: cannot start health checking! "
-				"(err=%d)\n", err);
+				"err: cannot start health checking! (err=%d)\n",
+				err);
 			goto out_stop_services;
 			goto out_stop_services;
 		}
 		}
 	}
 	}
@@ -1313,11 +1320,14 @@ static void genwqe_err_resume(struct pci_dev *pci_dev)
 
 
 static int genwqe_sriov_configure(struct pci_dev *dev, int numvfs)
 static int genwqe_sriov_configure(struct pci_dev *dev, int numvfs)
 {
 {
+	int rc;
 	struct genwqe_dev *cd = dev_get_drvdata(&dev->dev);
 	struct genwqe_dev *cd = dev_get_drvdata(&dev->dev);
 
 
 	if (numvfs > 0) {
 	if (numvfs > 0) {
 		genwqe_setup_vf_jtimer(cd);
 		genwqe_setup_vf_jtimer(cd);
-		pci_enable_sriov(dev, numvfs);
+		rc = pci_enable_sriov(dev, numvfs);
+		if (rc < 0)
+			return rc;
 		return numvfs;
 		return numvfs;
 	}
 	}
 	if (numvfs == 0) {
 	if (numvfs == 0) {

+ 13 - 8
drivers/misc/genwqe/card_base.h

@@ -8,7 +8,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -201,7 +201,8 @@ static inline void genwqe_mapping_init(struct dma_mapping *m,
  * @ddcb_seq:          Sequence number of last DDCB
  * @ddcb_seq:          Sequence number of last DDCB
  * @ddcbs_in_flight:   Currently enqueued DDCBs
  * @ddcbs_in_flight:   Currently enqueued DDCBs
  * @ddcbs_completed:   Number of already completed DDCBs
  * @ddcbs_completed:   Number of already completed DDCBs
- * @busy:              Number of -EBUSY returns
+ * @return_on_busy:    Number of -EBUSY returns on full queue
+ * @wait_on_busy:      Number of waits on full queue
  * @ddcb_daddr:        DMA address of first DDCB in the queue
  * @ddcb_daddr:        DMA address of first DDCB in the queue
  * @ddcb_vaddr:        Kernel virtual address of first DDCB in the queue
  * @ddcb_vaddr:        Kernel virtual address of first DDCB in the queue
  * @ddcb_req:          Associated requests (one per DDCB)
  * @ddcb_req:          Associated requests (one per DDCB)
@@ -218,7 +219,8 @@ struct ddcb_queue {
 	unsigned int ddcbs_in_flight;	/* number of ddcbs in processing */
 	unsigned int ddcbs_in_flight;	/* number of ddcbs in processing */
 	unsigned int ddcbs_completed;
 	unsigned int ddcbs_completed;
 	unsigned int ddcbs_max_in_flight;
 	unsigned int ddcbs_max_in_flight;
-	unsigned int busy;		/* how many times -EBUSY? */
+	unsigned int return_on_busy;    /* how many times -EBUSY? */
+	unsigned int wait_on_busy;
 
 
 	dma_addr_t ddcb_daddr;		/* DMA address */
 	dma_addr_t ddcb_daddr;		/* DMA address */
 	struct ddcb *ddcb_vaddr;	/* kernel virtual addr for DDCBs */
 	struct ddcb *ddcb_vaddr;	/* kernel virtual addr for DDCBs */
@@ -226,7 +228,7 @@ struct ddcb_queue {
 	wait_queue_head_t *ddcb_waitqs; /* waitqueue per ddcb */
 	wait_queue_head_t *ddcb_waitqs; /* waitqueue per ddcb */
 
 
 	spinlock_t ddcb_lock;		/* exclusive access to queue */
 	spinlock_t ddcb_lock;		/* exclusive access to queue */
-	wait_queue_head_t ddcb_waitq;	/* wait for ddcb processing */
+	wait_queue_head_t busy_waitq;   /* wait for ddcb processing */
 
 
 	/* registers or the respective queue to be used */
 	/* registers or the respective queue to be used */
 	u32 IO_QUEUE_CONFIG;
 	u32 IO_QUEUE_CONFIG;
@@ -306,7 +308,7 @@ struct genwqe_dev {
 	struct pci_dev *pci_dev;	/* PCI device */
 	struct pci_dev *pci_dev;	/* PCI device */
 	void __iomem *mmio;		/* BAR-0 MMIO start */
 	void __iomem *mmio;		/* BAR-0 MMIO start */
 	unsigned long mmio_len;
 	unsigned long mmio_len;
-	u16 num_vfs;
+	int num_vfs;
 	u32 vf_jobtimeout_msec[GENWQE_MAX_VFS];
 	u32 vf_jobtimeout_msec[GENWQE_MAX_VFS];
 	int is_privileged;		/* access to all regs possible */
 	int is_privileged;		/* access to all regs possible */
 
 
@@ -508,7 +510,7 @@ static inline bool dma_mapping_used(struct dma_mapping *m)
  * buildup and teardown.
  * buildup and teardown.
  */
  */
 int  __genwqe_execute_ddcb(struct genwqe_dev *cd,
 int  __genwqe_execute_ddcb(struct genwqe_dev *cd,
-			   struct genwqe_ddcb_cmd *cmd);
+			   struct genwqe_ddcb_cmd *cmd, unsigned int f_flags);
 
 
 /**
 /**
  * __genwqe_execute_raw_ddcb() - Execute DDCB request without addr translation
  * __genwqe_execute_raw_ddcb() - Execute DDCB request without addr translation
@@ -520,9 +522,12 @@ int  __genwqe_execute_ddcb(struct genwqe_dev *cd,
  * modification.
  * modification.
  */
  */
 int  __genwqe_execute_raw_ddcb(struct genwqe_dev *cd,
 int  __genwqe_execute_raw_ddcb(struct genwqe_dev *cd,
-			       struct genwqe_ddcb_cmd *cmd);
+			       struct genwqe_ddcb_cmd *cmd,
+			       unsigned int f_flags);
+int  __genwqe_enqueue_ddcb(struct genwqe_dev *cd,
+			   struct ddcb_requ *req,
+			   unsigned int f_flags);
 
 
-int  __genwqe_enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req);
 int  __genwqe_wait_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req);
 int  __genwqe_wait_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req);
 int  __genwqe_purge_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req);
 int  __genwqe_purge_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req);
 
 

+ 48 - 29
drivers/misc/genwqe/card_ddcb.c

@@ -5,7 +5,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -185,8 +185,7 @@ static void print_ddcb_info(struct genwqe_dev *cd, struct ddcb_queue *queue)
 	pddcb = queue->ddcb_vaddr;
 	pddcb = queue->ddcb_vaddr;
 	for (i = 0; i < queue->ddcb_max; i++) {
 	for (i = 0; i < queue->ddcb_max; i++) {
 		dev_err(&pci_dev->dev,
 		dev_err(&pci_dev->dev,
-			"  %c %-3d: RETC=%03x SEQ=%04x "
-			"HSI=%02X SHI=%02x PRIV=%06llx CMD=%03x\n",
+			"  %c %-3d: RETC=%03x SEQ=%04x HSI=%02X SHI=%02x PRIV=%06llx CMD=%03x\n",
 			i == queue->ddcb_act ? '>' : ' ',
 			i == queue->ddcb_act ? '>' : ' ',
 			i,
 			i,
 			be16_to_cpu(pddcb->retc_16),
 			be16_to_cpu(pddcb->retc_16),
@@ -214,6 +213,7 @@ struct genwqe_ddcb_cmd *ddcb_requ_alloc(void)
 void ddcb_requ_free(struct genwqe_ddcb_cmd *cmd)
 void ddcb_requ_free(struct genwqe_ddcb_cmd *cmd)
 {
 {
 	struct ddcb_requ *req = container_of(cmd, struct ddcb_requ, cmd);
 	struct ddcb_requ *req = container_of(cmd, struct ddcb_requ, cmd);
+
 	kfree(req);
 	kfree(req);
 }
 }
 
 
@@ -306,7 +306,7 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue,
 
 
 		new = (old | DDCB_NEXT_BE32);
 		new = (old | DDCB_NEXT_BE32);
 
 
-		wmb();
+		wmb();		/* need to ensure write ordering */
 		icrc_hsi_shi = cmpxchg(&prev_ddcb->icrc_hsi_shi_32, old, new);
 		icrc_hsi_shi = cmpxchg(&prev_ddcb->icrc_hsi_shi_32, old, new);
 
 
 		if (icrc_hsi_shi == old)
 		if (icrc_hsi_shi == old)
@@ -317,7 +317,7 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue,
 	ddcb_mark_tapped(pddcb);
 	ddcb_mark_tapped(pddcb);
 	num = (u64)ddcb_no << 8;
 	num = (u64)ddcb_no << 8;
 
 
-	wmb();
+	wmb();			/* need to ensure write ordering */
 	__genwqe_writeq(cd, queue->IO_QUEUE_OFFSET, num); /* start queue */
 	__genwqe_writeq(cd, queue->IO_QUEUE_OFFSET, num); /* start queue */
 
 
 	return RET_DDCB_TAPPED;
 	return RET_DDCB_TAPPED;
@@ -390,8 +390,9 @@ static int genwqe_check_ddcb_queue(struct genwqe_dev *cd,
 		    0x00000000)
 		    0x00000000)
 			goto go_home; /* not completed, continue waiting */
 			goto go_home; /* not completed, continue waiting */
 
 
-		/* Note: DDCB could be purged */
+		wmb();  /*  Add sync to decouple prev. read operations */
 
 
+		/* Note: DDCB could be purged */
 		req = queue->ddcb_req[queue->ddcb_act];
 		req = queue->ddcb_req[queue->ddcb_act];
 		if (req == NULL) {
 		if (req == NULL) {
 			/* this occurs if DDCB is purged, not an error */
 			/* this occurs if DDCB is purged, not an error */
@@ -416,9 +417,7 @@ static int genwqe_check_ddcb_queue(struct genwqe_dev *cd,
 			status  = __genwqe_readq(cd, queue->IO_QUEUE_STATUS);
 			status  = __genwqe_readq(cd, queue->IO_QUEUE_STATUS);
 
 
 			dev_err(&pci_dev->dev,
 			dev_err(&pci_dev->dev,
-				"[%s] SEQN=%04x HSI=%02x RETC=%03x "
-				" Q_ERRCNTS=%016llx Q_STATUS=%016llx\n"
-				" DDCB_DMA_ADDR=%016llx\n",
+				"[%s] SEQN=%04x HSI=%02x RETC=%03x Q_ERRCNTS=%016llx Q_STATUS=%016llx DDCB_DMA_ADDR=%016llx\n",
 				__func__, be16_to_cpu(pddcb->seqnum_16),
 				__func__, be16_to_cpu(pddcb->seqnum_16),
 				pddcb->hsi, retc_16, errcnts, status,
 				pddcb->hsi, retc_16, errcnts, status,
 				queue->ddcb_daddr + ddcb_offs);
 				queue->ddcb_daddr + ddcb_offs);
@@ -439,8 +438,7 @@ static int genwqe_check_ddcb_queue(struct genwqe_dev *cd,
 		vcrc_16 = be16_to_cpu(pddcb->vcrc_16);
 		vcrc_16 = be16_to_cpu(pddcb->vcrc_16);
 		if (vcrc != vcrc_16) {
 		if (vcrc != vcrc_16) {
 			printk_ratelimited(KERN_ERR
 			printk_ratelimited(KERN_ERR
-				"%s %s: err: wrong VCRC pre=%02x vcrc_len=%d "
-				"bytes vcrc_data=%04x is not vcrc_card=%04x\n",
+				"%s %s: err: wrong VCRC pre=%02x vcrc_len=%d bytes vcrc_data=%04x is not vcrc_card=%04x\n",
 				GENWQE_DEVNAME, dev_name(&pci_dev->dev),
 				GENWQE_DEVNAME, dev_name(&pci_dev->dev),
 				pddcb->pre, VCRC_LENGTH(req->cmd.asv_length),
 				pddcb->pre, VCRC_LENGTH(req->cmd.asv_length),
 				vcrc, vcrc_16);
 				vcrc, vcrc_16);
@@ -450,8 +448,10 @@ static int genwqe_check_ddcb_queue(struct genwqe_dev *cd,
 		queue->ddcbs_completed++;
 		queue->ddcbs_completed++;
 		queue->ddcbs_in_flight--;
 		queue->ddcbs_in_flight--;
 
 
-		/* wake up process waiting for this DDCB */
+		/* wake up process waiting for this DDCB, and
+                   processes on the busy queue */
 		wake_up_interruptible(&queue->ddcb_waitqs[queue->ddcb_act]);
 		wake_up_interruptible(&queue->ddcb_waitqs[queue->ddcb_act]);
+		wake_up_interruptible(&queue->busy_waitq);
 
 
 pick_next_one:
 pick_next_one:
 		queue->ddcb_act = (queue->ddcb_act + 1) % queue->ddcb_max;
 		queue->ddcb_act = (queue->ddcb_act + 1) % queue->ddcb_max;
@@ -717,8 +717,7 @@ go_home:
 	genwqe_hexdump(pci_dev, pddcb, sizeof(*pddcb));
 	genwqe_hexdump(pci_dev, pddcb, sizeof(*pddcb));
 
 
 	dev_err(&pci_dev->dev,
 	dev_err(&pci_dev->dev,
-		"[%s] err: DDCB#%d not purged and not completed "
-		"after %d seconds QSTAT=%016llx!!\n",
+		"[%s] err: DDCB#%d not purged and not completed after %d seconds QSTAT=%016llx!!\n",
 		__func__, req->num, genwqe_ddcb_software_timeout,
 		__func__, req->num, genwqe_ddcb_software_timeout,
 		queue_status);
 		queue_status);
 
 
@@ -740,7 +739,7 @@ int genwqe_init_debug_data(struct genwqe_dev *cd, struct genwqe_debug_data *d)
 	}
 	}
 
 
 	len  = sizeof(d->driver_version);
 	len  = sizeof(d->driver_version);
-	snprintf(d->driver_version, len, "%s", DRV_VERS_STRING);
+	snprintf(d->driver_version, len, "%s", DRV_VERSION);
 	d->slu_unitcfg = cd->slu_unitcfg;
 	d->slu_unitcfg = cd->slu_unitcfg;
 	d->app_unitcfg = cd->app_unitcfg;
 	d->app_unitcfg = cd->app_unitcfg;
 	return 0;
 	return 0;
@@ -748,14 +747,16 @@ int genwqe_init_debug_data(struct genwqe_dev *cd, struct genwqe_debug_data *d)
 
 
 /**
 /**
  * __genwqe_enqueue_ddcb() - Enqueue a DDCB
  * __genwqe_enqueue_ddcb() - Enqueue a DDCB
- * @cd:          pointer to genwqe device descriptor
- * @req:         pointer to DDCB execution request
+ * @cd:         pointer to genwqe device descriptor
+ * @req:        pointer to DDCB execution request
+ * @f_flags:    file mode: blocking, non-blocking
  *
  *
  * Return: 0 if enqueuing succeeded
  * Return: 0 if enqueuing succeeded
  *         -EIO if card is unusable/PCIe problems
  *         -EIO if card is unusable/PCIe problems
  *         -EBUSY if enqueuing failed
  *         -EBUSY if enqueuing failed
  */
  */
-int __genwqe_enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req)
+int __genwqe_enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req,
+			  unsigned int f_flags)
 {
 {
 	struct ddcb *pddcb;
 	struct ddcb *pddcb;
 	unsigned long flags;
 	unsigned long flags;
@@ -763,6 +764,7 @@ int __genwqe_enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req)
 	struct pci_dev *pci_dev = cd->pci_dev;
 	struct pci_dev *pci_dev = cd->pci_dev;
 	u16 icrc;
 	u16 icrc;
 
 
+ retry:
 	if (cd->card_state != GENWQE_CARD_USED) {
 	if (cd->card_state != GENWQE_CARD_USED) {
 		printk_ratelimited(KERN_ERR
 		printk_ratelimited(KERN_ERR
 			"%s %s: [%s] Card is unusable/PCIe problem Req#%d\n",
 			"%s %s: [%s] Card is unusable/PCIe problem Req#%d\n",
@@ -788,9 +790,24 @@ int __genwqe_enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req)
 
 
 	pddcb = get_next_ddcb(cd, queue, &req->num);	/* get ptr and num */
 	pddcb = get_next_ddcb(cd, queue, &req->num);	/* get ptr and num */
 	if (pddcb == NULL) {
 	if (pddcb == NULL) {
+		int rc;
+
 		spin_unlock_irqrestore(&queue->ddcb_lock, flags);
 		spin_unlock_irqrestore(&queue->ddcb_lock, flags);
-		queue->busy++;
-		return -EBUSY;
+
+		if (f_flags & O_NONBLOCK) {
+			queue->return_on_busy++;
+			return -EBUSY;
+		}
+
+		queue->wait_on_busy++;
+		rc = wait_event_interruptible(queue->busy_waitq,
+					      queue_free_ddcbs(queue) != 0);
+		dev_dbg(&pci_dev->dev, "[%s] waiting for free DDCB: rc=%d\n",
+			__func__, rc);
+		if (rc == -ERESTARTSYS)
+			return rc;  /* interrupted by a signal */
+
+		goto retry;
 	}
 	}
 
 
 	if (queue->ddcb_req[req->num] != NULL) {
 	if (queue->ddcb_req[req->num] != NULL) {
@@ -893,9 +910,11 @@ int __genwqe_enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req)
  * __genwqe_execute_raw_ddcb() - Setup and execute DDCB
  * __genwqe_execute_raw_ddcb() - Setup and execute DDCB
  * @cd:         pointer to genwqe device descriptor
  * @cd:         pointer to genwqe device descriptor
  * @req:        user provided DDCB request
  * @req:        user provided DDCB request
+ * @f_flags:    file mode: blocking, non-blocking
  */
  */
 int __genwqe_execute_raw_ddcb(struct genwqe_dev *cd,
 int __genwqe_execute_raw_ddcb(struct genwqe_dev *cd,
-			     struct genwqe_ddcb_cmd *cmd)
+			      struct genwqe_ddcb_cmd *cmd,
+			      unsigned int f_flags)
 {
 {
 	int rc = 0;
 	int rc = 0;
 	struct pci_dev *pci_dev = cd->pci_dev;
 	struct pci_dev *pci_dev = cd->pci_dev;
@@ -911,7 +930,7 @@ int __genwqe_execute_raw_ddcb(struct genwqe_dev *cd,
 			__func__, cmd->asiv_length);
 			__func__, cmd->asiv_length);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
-	rc = __genwqe_enqueue_ddcb(cd, req);
+	rc = __genwqe_enqueue_ddcb(cd, req, f_flags);
 	if (rc != 0)
 	if (rc != 0)
 		return rc;
 		return rc;
 
 
@@ -1017,7 +1036,8 @@ static int setup_ddcb_queue(struct genwqe_dev *cd, struct ddcb_queue *queue)
 	queue->ddcbs_in_flight = 0;  /* statistics */
 	queue->ddcbs_in_flight = 0;  /* statistics */
 	queue->ddcbs_max_in_flight = 0;
 	queue->ddcbs_max_in_flight = 0;
 	queue->ddcbs_completed = 0;
 	queue->ddcbs_completed = 0;
-	queue->busy = 0;
+	queue->return_on_busy = 0;
+	queue->wait_on_busy = 0;
 
 
 	queue->ddcb_seq	  = 0x100; /* start sequence number */
 	queue->ddcb_seq	  = 0x100; /* start sequence number */
 	queue->ddcb_max	  = genwqe_ddcb_max; /* module parameter */
 	queue->ddcb_max	  = genwqe_ddcb_max; /* module parameter */
@@ -1057,7 +1077,7 @@ static int setup_ddcb_queue(struct genwqe_dev *cd, struct ddcb_queue *queue)
 	queue->ddcb_next = 0;	/* queue is empty */
 	queue->ddcb_next = 0;	/* queue is empty */
 
 
 	spin_lock_init(&queue->ddcb_lock);
 	spin_lock_init(&queue->ddcb_lock);
-	init_waitqueue_head(&queue->ddcb_waitq);
+	init_waitqueue_head(&queue->busy_waitq);
 
 
 	val64 = ((u64)(queue->ddcb_max - 1) <<  8); /* lastptr */
 	val64 = ((u64)(queue->ddcb_max - 1) <<  8); /* lastptr */
 	__genwqe_writeq(cd, queue->IO_QUEUE_CONFIG,  0x07);  /* iCRC/vCRC */
 	__genwqe_writeq(cd, queue->IO_QUEUE_CONFIG,  0x07);  /* iCRC/vCRC */
@@ -1251,10 +1271,8 @@ int genwqe_setup_service_layer(struct genwqe_dev *cd)
 	}
 	}
 
 
 	rc = genwqe_set_interrupt_capability(cd, GENWQE_MSI_IRQS);
 	rc = genwqe_set_interrupt_capability(cd, GENWQE_MSI_IRQS);
-	if (rc) {
-		rc = -ENODEV;
+	if (rc)
 		goto stop_kthread;
 		goto stop_kthread;
-	}
 
 
 	/*
 	/*
 	 * We must have all wait-queues initialized when we enable the
 	 * We must have all wait-queues initialized when we enable the
@@ -1307,6 +1325,7 @@ static int queue_wake_up_all(struct genwqe_dev *cd)
 	for (i = 0; i < queue->ddcb_max; i++)
 	for (i = 0; i < queue->ddcb_max; i++)
 		wake_up_interruptible(&queue->ddcb_waitqs[queue->ddcb_act]);
 		wake_up_interruptible(&queue->ddcb_waitqs[queue->ddcb_act]);
 
 
+	wake_up_interruptible(&queue->busy_waitq);
 	spin_unlock_irqrestore(&queue->ddcb_lock, flags);
 	spin_unlock_irqrestore(&queue->ddcb_lock, flags);
 
 
 	return 0;
 	return 0;
@@ -1346,8 +1365,8 @@ int genwqe_finish_queue(struct genwqe_dev *cd)
 			break;
 			break;
 
 
 		dev_dbg(&pci_dev->dev,
 		dev_dbg(&pci_dev->dev,
-			"  DEBUG [%d/%d] waiting for queue to get empty: "
-			"%d requests!\n", i, waitmax, in_flight);
+			"  DEBUG [%d/%d] waiting for queue to get empty: %d requests!\n",
+			i, waitmax, in_flight);
 
 
 		/*
 		/*
 		 * Severe severe error situation: The card itself has
 		 * Severe severe error situation: The card itself has

+ 1 - 1
drivers/misc/genwqe/card_ddcb.h

@@ -8,7 +8,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify

+ 6 - 4
drivers/misc/genwqe/card_debugfs.c

@@ -5,7 +5,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -244,14 +244,16 @@ static int genwqe_ddcb_info_show(struct seq_file *s, void *unused)
 		   "  ddcbs_in_flight:     %u\n"
 		   "  ddcbs_in_flight:     %u\n"
 		   "  ddcbs_max_in_flight: %u\n"
 		   "  ddcbs_max_in_flight: %u\n"
 		   "  ddcbs_completed:     %u\n"
 		   "  ddcbs_completed:     %u\n"
-		   "  busy:                %u\n"
+		   "  return_on_busy:      %u\n"
+		   "  wait_on_busy:        %u\n"
 		   "  irqs_processed:      %u\n",
 		   "  irqs_processed:      %u\n",
 		   queue->ddcb_max, (long long)queue->ddcb_daddr,
 		   queue->ddcb_max, (long long)queue->ddcb_daddr,
 		   (long long)queue->ddcb_daddr +
 		   (long long)queue->ddcb_daddr +
 		   (queue->ddcb_max * DDCB_LENGTH),
 		   (queue->ddcb_max * DDCB_LENGTH),
 		   (long long)queue->ddcb_vaddr, queue->ddcbs_in_flight,
 		   (long long)queue->ddcb_vaddr, queue->ddcbs_in_flight,
 		   queue->ddcbs_max_in_flight, queue->ddcbs_completed,
 		   queue->ddcbs_max_in_flight, queue->ddcbs_completed,
-		   queue->busy, cd->irqs_processed);
+		   queue->return_on_busy, queue->wait_on_busy,
+		   cd->irqs_processed);
 
 
 	/* Hardware State */
 	/* Hardware State */
 	seq_printf(s, "  0x%08x 0x%016llx IO_QUEUE_CONFIG\n"
 	seq_printf(s, "  0x%08x 0x%016llx IO_QUEUE_CONFIG\n"
@@ -323,7 +325,7 @@ static int genwqe_info_show(struct seq_file *s, void *unused)
 		   "    Base Clock      : %u MHz\n"
 		   "    Base Clock      : %u MHz\n"
 		   "    Arch/SVN Release: %u/%llx\n"
 		   "    Arch/SVN Release: %u/%llx\n"
 		   "    Bitstream       : %llx\n",
 		   "    Bitstream       : %llx\n",
-		   GENWQE_DEVNAME, DRV_VERS_STRING, dev_name(&pci_dev->dev),
+		   GENWQE_DEVNAME, DRV_VERSION, dev_name(&pci_dev->dev),
 		   genwqe_is_privileged(cd) ?
 		   genwqe_is_privileged(cd) ?
 		   "Physical" : "Virtual or no SR-IOV",
 		   "Physical" : "Virtual or no SR-IOV",
 		   cd->card_idx, slu_id, app_id,
 		   cd->card_idx, slu_id, app_id,

+ 13 - 8
drivers/misc/genwqe/card_dev.c

@@ -5,7 +5,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -213,9 +213,9 @@ static void genwqe_remove_mappings(struct genwqe_file *cfile)
 		 * GENWQE_MAPPING_SGL_TEMP should be removed by tidy up code.
 		 * GENWQE_MAPPING_SGL_TEMP should be removed by tidy up code.
 		 */
 		 */
 		dev_err(&pci_dev->dev,
 		dev_err(&pci_dev->dev,
-			"[%s] %d. cleanup mapping: u_vaddr=%p "
-			"u_kaddr=%016lx dma_addr=%lx\n", __func__, i++,
-			dma_map->u_vaddr, (unsigned long)dma_map->k_vaddr,
+			"[%s] %d. cleanup mapping: u_vaddr=%p u_kaddr=%016lx dma_addr=%lx\n",
+			__func__, i++, dma_map->u_vaddr,
+			(unsigned long)dma_map->k_vaddr,
 			(unsigned long)dma_map->dma_addr);
 			(unsigned long)dma_map->dma_addr);
 
 
 		if (dma_map->type == GENWQE_MAPPING_RAW) {
 		if (dma_map->type == GENWQE_MAPPING_RAW) {
@@ -346,6 +346,7 @@ static int genwqe_open(struct inode *inode, struct file *filp)
 static int genwqe_fasync(int fd, struct file *filp, int mode)
 static int genwqe_fasync(int fd, struct file *filp, int mode)
 {
 {
 	struct genwqe_file *cdev = (struct genwqe_file *)filp->private_data;
 	struct genwqe_file *cdev = (struct genwqe_file *)filp->private_data;
+
 	return fasync_helper(fd, filp, mode, &cdev->async_queue);
 	return fasync_helper(fd, filp, mode, &cdev->async_queue);
 }
 }
 
 
@@ -515,6 +516,7 @@ static int do_flash_update(struct genwqe_file *cfile,
 	u32 crc;
 	u32 crc;
 	u8 cmdopts;
 	u8 cmdopts;
 	struct genwqe_dev *cd = cfile->cd;
 	struct genwqe_dev *cd = cfile->cd;
+	struct file *filp = cfile->filp;
 	struct pci_dev *pci_dev = cd->pci_dev;
 	struct pci_dev *pci_dev = cd->pci_dev;
 
 
 	if ((load->size & 0x3) != 0)
 	if ((load->size & 0x3) != 0)
@@ -609,7 +611,7 @@ static int do_flash_update(struct genwqe_file *cfile,
 		/* For Genwqe5 we get back the calculated CRC */
 		/* For Genwqe5 we get back the calculated CRC */
 		*(u64 *)&req->asv[0] = 0ULL;			/* 0x80 */
 		*(u64 *)&req->asv[0] = 0ULL;			/* 0x80 */
 
 
-		rc = __genwqe_execute_raw_ddcb(cd, req);
+		rc = __genwqe_execute_raw_ddcb(cd, req, filp->f_flags);
 
 
 		load->retc = req->retc;
 		load->retc = req->retc;
 		load->attn = req->attn;
 		load->attn = req->attn;
@@ -649,6 +651,7 @@ static int do_flash_read(struct genwqe_file *cfile,
 	u8 *xbuf;
 	u8 *xbuf;
 	u8 cmdopts;
 	u8 cmdopts;
 	struct genwqe_dev *cd = cfile->cd;
 	struct genwqe_dev *cd = cfile->cd;
+	struct file *filp = cfile->filp;
 	struct pci_dev *pci_dev = cd->pci_dev;
 	struct pci_dev *pci_dev = cd->pci_dev;
 	struct genwqe_ddcb_cmd *cmd;
 	struct genwqe_ddcb_cmd *cmd;
 
 
@@ -726,7 +729,7 @@ static int do_flash_read(struct genwqe_file *cfile,
 		/* we only get back the calculated CRC */
 		/* we only get back the calculated CRC */
 		*(u64 *)&cmd->asv[0] = 0ULL;	/* 0x80 */
 		*(u64 *)&cmd->asv[0] = 0ULL;	/* 0x80 */
 
 
-		rc = __genwqe_execute_raw_ddcb(cd, cmd);
+		rc = __genwqe_execute_raw_ddcb(cd, cmd, filp->f_flags);
 
 
 		load->retc = cmd->retc;
 		load->retc = cmd->retc;
 		load->attn = cmd->attn;
 		load->attn = cmd->attn;
@@ -987,13 +990,14 @@ static int genwqe_execute_ddcb(struct genwqe_file *cfile,
 {
 {
 	int rc;
 	int rc;
 	struct genwqe_dev *cd = cfile->cd;
 	struct genwqe_dev *cd = cfile->cd;
+	struct file *filp = cfile->filp;
 	struct ddcb_requ *req = container_of(cmd, struct ddcb_requ, cmd);
 	struct ddcb_requ *req = container_of(cmd, struct ddcb_requ, cmd);
 
 
 	rc = ddcb_cmd_fixups(cfile, req);
 	rc = ddcb_cmd_fixups(cfile, req);
 	if (rc != 0)
 	if (rc != 0)
 		return rc;
 		return rc;
 
 
-	rc = __genwqe_execute_raw_ddcb(cd, cmd);
+	rc = __genwqe_execute_raw_ddcb(cd, cmd, filp->f_flags);
 	ddcb_cmd_cleanup(cfile, req);
 	ddcb_cmd_cleanup(cfile, req);
 	return rc;
 	return rc;
 }
 }
@@ -1005,6 +1009,7 @@ static int do_execute_ddcb(struct genwqe_file *cfile,
 	struct genwqe_ddcb_cmd *cmd;
 	struct genwqe_ddcb_cmd *cmd;
 	struct ddcb_requ *req;
 	struct ddcb_requ *req;
 	struct genwqe_dev *cd = cfile->cd;
 	struct genwqe_dev *cd = cfile->cd;
+	struct file *filp = cfile->filp;
 
 
 	cmd = ddcb_requ_alloc();
 	cmd = ddcb_requ_alloc();
 	if (cmd == NULL)
 	if (cmd == NULL)
@@ -1020,7 +1025,7 @@ static int do_execute_ddcb(struct genwqe_file *cfile,
 	if (!raw)
 	if (!raw)
 		rc = genwqe_execute_ddcb(cfile, cmd);
 		rc = genwqe_execute_ddcb(cfile, cmd);
 	else
 	else
-		rc = __genwqe_execute_raw_ddcb(cd, cmd);
+		rc = __genwqe_execute_raw_ddcb(cd, cmd, filp->f_flags);
 
 
 	/* Copy back only the modifed fields. Do not copy ASIV
 	/* Copy back only the modifed fields. Do not copy ASIV
 	   back since the copy got modified by the driver. */
 	   back since the copy got modified by the driver. */

+ 1 - 10
drivers/misc/genwqe/card_sysfs.c

@@ -5,7 +5,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -91,13 +91,6 @@ static ssize_t type_show(struct device *dev, struct device_attribute *attr,
 }
 }
 static DEVICE_ATTR_RO(type);
 static DEVICE_ATTR_RO(type);
 
 
-static ssize_t driver_show(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	return sprintf(buf, "%s\n", DRV_VERS_STRING);
-}
-static DEVICE_ATTR_RO(driver);
-
 static ssize_t tempsens_show(struct device *dev, struct device_attribute *attr,
 static ssize_t tempsens_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 			     char *buf)
 {
 {
@@ -256,7 +249,6 @@ static struct attribute *genwqe_attributes[] = {
 	&dev_attr_next_bitstream.attr,
 	&dev_attr_next_bitstream.attr,
 	&dev_attr_curr_bitstream.attr,
 	&dev_attr_curr_bitstream.attr,
 	&dev_attr_base_clock.attr,
 	&dev_attr_base_clock.attr,
-	&dev_attr_driver.attr,
 	&dev_attr_type.attr,
 	&dev_attr_type.attr,
 	&dev_attr_version.attr,
 	&dev_attr_version.attr,
 	&dev_attr_appid.attr,
 	&dev_attr_appid.attr,
@@ -268,7 +260,6 @@ static struct attribute *genwqe_attributes[] = {
 };
 };
 
 
 static struct attribute *genwqe_normal_attributes[] = {
 static struct attribute *genwqe_normal_attributes[] = {
-	&dev_attr_driver.attr,
 	&dev_attr_type.attr,
 	&dev_attr_type.attr,
 	&dev_attr_version.attr,
 	&dev_attr_version.attr,
 	&dev_attr_appid.attr,
 	&dev_attr_appid.attr,

+ 4 - 3
drivers/misc/genwqe/card_utils.c

@@ -5,7 +5,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -150,6 +150,7 @@ int genwqe_read_app_id(struct genwqe_dev *cd, char *app_name, int len)
 	memset(app_name, 0, len);
 	memset(app_name, 0, len);
 	for (i = 0, j = 0; j < min(len, 4); j++) {
 	for (i = 0, j = 0; j < min(len, 4); j++) {
 		char ch = (char)((app_id >> (24 - j*8)) & 0xff);
 		char ch = (char)((app_id >> (24 - j*8)) & 0xff);
+
 		if (ch == ' ')
 		if (ch == ' ')
 			continue;
 			continue;
 		app_name[i++] = isprint(ch) ? ch : 'X';
 		app_name[i++] = isprint(ch) ? ch : 'X';
@@ -304,8 +305,7 @@ int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
 	sgl->nr_pages = DIV_ROUND_UP(sgl->fpage_offs + user_size, PAGE_SIZE);
 	sgl->nr_pages = DIV_ROUND_UP(sgl->fpage_offs + user_size, PAGE_SIZE);
 	sgl->lpage_size = (user_size - sgl->fpage_size) % PAGE_SIZE;
 	sgl->lpage_size = (user_size - sgl->fpage_size) % PAGE_SIZE;
 
 
-	dev_dbg(&pci_dev->dev, "[%s] uaddr=%p usize=%8ld nr_pages=%ld "
-		"fpage_offs=%lx fpage_size=%ld lpage_size=%ld\n",
+	dev_dbg(&pci_dev->dev, "[%s] uaddr=%p usize=%8ld nr_pages=%ld fpage_offs=%lx fpage_size=%ld lpage_size=%ld\n",
 		__func__, user_addr, user_size, sgl->nr_pages,
 		__func__, user_addr, user_size, sgl->nr_pages,
 		sgl->fpage_offs, sgl->fpage_size, sgl->lpage_size);
 		sgl->fpage_offs, sgl->fpage_size, sgl->lpage_size);
 
 
@@ -662,6 +662,7 @@ int genwqe_user_vunmap(struct genwqe_dev *cd, struct dma_mapping *m,
 u8 genwqe_card_type(struct genwqe_dev *cd)
 u8 genwqe_card_type(struct genwqe_dev *cd)
 {
 {
 	u64 card_type = cd->slu_unitcfg;
 	u64 card_type = cd->slu_unitcfg;
+
 	return (u8)((card_type & IO_SLU_UNITCFG_TYPE_MASK) >> 20);
 	return (u8)((card_type & IO_SLU_UNITCFG_TYPE_MASK) >> 20);
 }
 }
 
 

+ 2 - 2
drivers/misc/genwqe/genwqe_driver.h

@@ -8,7 +8,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -36,7 +36,7 @@
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
 #include <linux/genwqe/genwqe_card.h>
 #include <linux/genwqe/genwqe_card.h>
 
 
-#define DRV_VERS_STRING		"2.0.21"
+#define DRV_VERSION		"2.0.25"
 
 
 /*
 /*
  * Static minor number assignement, until we decide/implement
  * Static minor number assignement, until we decide/implement

+ 1 - 0
drivers/misc/lattice-ecp3-config.c

@@ -247,3 +247,4 @@ module_spi_driver(lattice_ecp3_driver);
 MODULE_AUTHOR("Stefan Roese <sr@denx.de>");
 MODULE_AUTHOR("Stefan Roese <sr@denx.de>");
 MODULE_DESCRIPTION("Lattice ECP3 FPGA configuration via SPI");
 MODULE_DESCRIPTION("Lattice ECP3 FPGA configuration via SPI");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(FIRMWARE_NAME);

+ 75 - 92
drivers/misc/mei/amthif.c

@@ -20,7 +20,6 @@
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/fcntl.h>
 #include <linux/aio.h>
 #include <linux/aio.h>
-#include <linux/pci.h>
 #include <linux/ioctl.h>
 #include <linux/ioctl.h>
 #include <linux/cdev.h>
 #include <linux/cdev.h>
 #include <linux/list.h>
 #include <linux/list.h>
@@ -29,6 +28,7 @@
 #include <linux/uuid.h>
 #include <linux/uuid.h>
 #include <linux/jiffies.h>
 #include <linux/jiffies.h>
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>
+#include <linux/slab.h>
 
 
 #include <linux/mei.h>
 #include <linux/mei.h>
 
 
@@ -64,31 +64,32 @@ void mei_amthif_reset_params(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
+ * Return: 0 on success, <0 on failure.
  */
  */
 int mei_amthif_host_init(struct mei_device *dev)
 int mei_amthif_host_init(struct mei_device *dev)
 {
 {
 	struct mei_cl *cl = &dev->iamthif_cl;
 	struct mei_cl *cl = &dev->iamthif_cl;
+	struct mei_me_client *me_cl;
 	unsigned char *msg_buf;
 	unsigned char *msg_buf;
-	int ret, i;
+	int ret;
 
 
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
 
 
 	mei_cl_init(cl, dev);
 	mei_cl_init(cl, dev);
 
 
-	i = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
-	if (i < 0) {
-		dev_info(&dev->pdev->dev,
-			"amthif: failed to find the client %d\n", i);
+	me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
+	if (!me_cl) {
+		dev_info(dev->dev, "amthif: failed to find the client");
 		return -ENOTTY;
 		return -ENOTTY;
 	}
 	}
 
 
-	cl->me_client_id = dev->me_clients[i].client_id;
+	cl->me_client_id = me_cl->client_id;
+	cl->cl_uuid = me_cl->props.protocol_name;
 
 
 	/* Assign iamthif_mtu to the value received from ME  */
 	/* Assign iamthif_mtu to the value received from ME  */
 
 
-	dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
-	dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
-			dev->me_clients[i].props.max_msg_length);
+	dev->iamthif_mtu = me_cl->props.max_msg_length;
+	dev_dbg(dev->dev, "IAMTHIF_MTU = %d\n", dev->iamthif_mtu);
 
 
 	kfree(dev->iamthif_msg_buf);
 	kfree(dev->iamthif_msg_buf);
 	dev->iamthif_msg_buf = NULL;
 	dev->iamthif_msg_buf = NULL;
@@ -96,17 +97,15 @@ int mei_amthif_host_init(struct mei_device *dev)
 	/* allocate storage for ME message buffer */
 	/* allocate storage for ME message buffer */
 	msg_buf = kcalloc(dev->iamthif_mtu,
 	msg_buf = kcalloc(dev->iamthif_mtu,
 			sizeof(unsigned char), GFP_KERNEL);
 			sizeof(unsigned char), GFP_KERNEL);
-	if (!msg_buf) {
-		dev_err(&dev->pdev->dev, "amthif: memory allocation for ME message buffer failed.\n");
+	if (!msg_buf)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	dev->iamthif_msg_buf = msg_buf;
 	dev->iamthif_msg_buf = msg_buf;
 
 
 	ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID);
 	ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID);
 
 
 	if (ret < 0) {
 	if (ret < 0) {
-		dev_err(&dev->pdev->dev,
+		dev_err(dev->dev,
 			"amthif: failed link client %d\n", ret);
 			"amthif: failed link client %d\n", ret);
 		return ret;
 		return ret;
 	}
 	}
@@ -124,18 +123,16 @@ int mei_amthif_host_init(struct mei_device *dev)
  * @dev: the device structure
  * @dev: the device structure
  * @file: pointer to file object
  * @file: pointer to file object
  *
  *
- * returns   returned a list entry on success, NULL on failure.
+ * Return:   returned a list entry on success, NULL on failure.
  */
  */
 struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
 struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
 						struct file *file)
 						struct file *file)
 {
 {
 	struct mei_cl_cb *cb;
 	struct mei_cl_cb *cb;
 
 
-	list_for_each_entry(cb, &dev->amthif_rd_complete_list.list, list) {
-		if (cb->cl && cb->cl == &dev->iamthif_cl &&
-			cb->file_object == file)
+	list_for_each_entry(cb, &dev->amthif_rd_complete_list.list, list)
+		if (cb->file_object == file)
 			return cb;
 			return cb;
-	}
 	return NULL;
 	return NULL;
 }
 }
 
 
@@ -144,15 +141,14 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
  * mei_amthif_read - read data from AMTHIF client
  * mei_amthif_read - read data from AMTHIF client
  *
  *
  * @dev: the device structure
  * @dev: the device structure
- * @if_num:  minor number
  * @file: pointer to file object
  * @file: pointer to file object
- * @*ubuf: pointer to user data in user space
+ * @ubuf: pointer to user data in user space
  * @length: data length to read
  * @length: data length to read
  * @offset: data read offset
  * @offset: data read offset
  *
  *
  * Locking: called under "dev->device_lock" lock
  * Locking: called under "dev->device_lock" lock
  *
  *
- * returns
+ * Return:
  *  returned data length on success,
  *  returned data length on success,
  *  zero if no data to read,
  *  zero if no data to read,
  *  negative on failure.
  *  negative on failure.
@@ -160,25 +156,19 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
 int mei_amthif_read(struct mei_device *dev, struct file *file,
 int mei_amthif_read(struct mei_device *dev, struct file *file,
 	       char __user *ubuf, size_t length, loff_t *offset)
 	       char __user *ubuf, size_t length, loff_t *offset)
 {
 {
-	int rets;
-	int wait_ret;
-	struct mei_cl_cb *cb = NULL;
 	struct mei_cl *cl = file->private_data;
 	struct mei_cl *cl = file->private_data;
+	struct mei_cl_cb *cb;
 	unsigned long timeout;
 	unsigned long timeout;
-	int i;
+	int rets;
+	int wait_ret;
 
 
 	/* Only possible if we are in timeout */
 	/* Only possible if we are in timeout */
-	if (!cl || cl != &dev->iamthif_cl) {
-		dev_dbg(&dev->pdev->dev, "bad file ext.\n");
+	if (!cl) {
+		dev_err(dev->dev, "bad file ext.\n");
 		return -ETIME;
 		return -ETIME;
 	}
 	}
 
 
-	i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
-	if (i < 0) {
-		dev_dbg(&dev->pdev->dev, "amthif client not found.\n");
-		return -ENOTTY;
-	}
-	dev_dbg(&dev->pdev->dev, "checking amthif data\n");
+	dev_dbg(dev->dev, "checking amthif data\n");
 	cb = mei_amthif_find_read_list_entry(dev, file);
 	cb = mei_amthif_find_read_list_entry(dev, file);
 
 
 	/* Check for if we can block or not*/
 	/* Check for if we can block or not*/
@@ -186,7 +176,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 		return -EAGAIN;
 		return -EAGAIN;
 
 
 
 
-	dev_dbg(&dev->pdev->dev, "waiting for amthif data\n");
+	dev_dbg(dev->dev, "waiting for amthif data\n");
 	while (cb == NULL) {
 	while (cb == NULL) {
 		/* unlock the Mutex */
 		/* unlock the Mutex */
 		mutex_unlock(&dev->device_lock);
 		mutex_unlock(&dev->device_lock);
@@ -200,21 +190,21 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 		if (wait_ret)
 		if (wait_ret)
 			return -ERESTARTSYS;
 			return -ERESTARTSYS;
 
 
-		dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
+		dev_dbg(dev->dev, "woke up from sleep\n");
 	}
 	}
 
 
 
 
-	dev_dbg(&dev->pdev->dev, "Got amthif data\n");
+	dev_dbg(dev->dev, "Got amthif data\n");
 	dev->iamthif_timer = 0;
 	dev->iamthif_timer = 0;
 
 
 	if (cb) {
 	if (cb) {
 		timeout = cb->read_time +
 		timeout = cb->read_time +
 			mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
 			mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
-		dev_dbg(&dev->pdev->dev, "amthif timeout = %lud\n",
+		dev_dbg(dev->dev, "amthif timeout = %lud\n",
 				timeout);
 				timeout);
 
 
 		if  (time_after(jiffies, timeout)) {
 		if  (time_after(jiffies, timeout)) {
-			dev_dbg(&dev->pdev->dev, "amthif Time out\n");
+			dev_dbg(dev->dev, "amthif Time out\n");
 			/* 15 sec for the message has expired */
 			/* 15 sec for the message has expired */
 			list_del(&cb->list);
 			list_del(&cb->list);
 			rets = -ETIME;
 			rets = -ETIME;
@@ -234,16 +224,16 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 		 * remove message from deletion list
 		 * remove message from deletion list
 		 */
 		 */
 
 
-	dev_dbg(&dev->pdev->dev, "amthif cb->response_buffer size - %d\n",
+	dev_dbg(dev->dev, "amthif cb->response_buffer size - %d\n",
 	    cb->response_buffer.size);
 	    cb->response_buffer.size);
-	dev_dbg(&dev->pdev->dev, "amthif cb->buf_idx - %lu\n", cb->buf_idx);
+	dev_dbg(dev->dev, "amthif cb->buf_idx - %lu\n", cb->buf_idx);
 
 
 	/* length is being truncated to PAGE_SIZE, however,
 	/* length is being truncated to PAGE_SIZE, however,
 	 * the buf_idx may point beyond */
 	 * the buf_idx may point beyond */
 	length = min_t(size_t, length, (cb->buf_idx - *offset));
 	length = min_t(size_t, length, (cb->buf_idx - *offset));
 
 
 	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
 	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
-		dev_dbg(&dev->pdev->dev, "failed to copy data to userland\n");
+		dev_dbg(dev->dev, "failed to copy data to userland\n");
 		rets = -EFAULT;
 		rets = -EFAULT;
 	} else {
 	} else {
 		rets = length;
 		rets = length;
@@ -253,7 +243,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 		}
 		}
 	}
 	}
 free:
 free:
-	dev_dbg(&dev->pdev->dev, "free amthif cb memory.\n");
+	dev_dbg(dev->dev, "free amthif cb memory.\n");
 	*offset = 0;
 	*offset = 0;
 	mei_io_cb_free(cb);
 	mei_io_cb_free(cb);
 out:
 out:
@@ -266,7 +256,7 @@ out:
  * @dev: the device structure
  * @dev: the device structure
  * @cb: mei call back struct
  * @cb: mei call back struct
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  *
  *
  */
  */
 static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
@@ -277,7 +267,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 	if (!dev || !cb)
 	if (!dev || !cb)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	dev_dbg(&dev->pdev->dev, "write data to amthif client.\n");
+	dev_dbg(dev->dev, "write data to amthif client.\n");
 
 
 	dev->iamthif_state = MEI_IAMTHIF_WRITING;
 	dev->iamthif_state = MEI_IAMTHIF_WRITING;
 	dev->iamthif_current_cb = cb;
 	dev->iamthif_current_cb = cb;
@@ -316,12 +306,12 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 				return -EIO;
 				return -EIO;
 			dev->iamthif_flow_control_pending = true;
 			dev->iamthif_flow_control_pending = true;
 			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
 			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
-			dev_dbg(&dev->pdev->dev, "add amthif cb to write waiting list\n");
+			dev_dbg(dev->dev, "add amthif cb to write waiting list\n");
 			dev->iamthif_current_cb = cb;
 			dev->iamthif_current_cb = cb;
 			dev->iamthif_file_object = cb->file_object;
 			dev->iamthif_file_object = cb->file_object;
 			list_add_tail(&cb->list, &dev->write_waiting_list.list);
 			list_add_tail(&cb->list, &dev->write_waiting_list.list);
 		} else {
 		} else {
-			dev_dbg(&dev->pdev->dev, "message does not complete, so add amthif cb to write list.\n");
+			dev_dbg(dev->dev, "message does not complete, so add amthif cb to write list.\n");
 			list_add_tail(&cb->list, &dev->write_list.list);
 			list_add_tail(&cb->list, &dev->write_list.list);
 		}
 		}
 	} else {
 	} else {
@@ -336,7 +326,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
  * @dev: the device structure
  * @dev: the device structure
  * @cb: mei call back struct
  * @cb: mei call back struct
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  *
  *
  */
  */
 int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
 int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
@@ -354,25 +344,23 @@ int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
 
 
 	if (!list_empty(&dev->amthif_cmd_list.list) ||
 	if (!list_empty(&dev->amthif_cmd_list.list) ||
 	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
 	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
-		dev_dbg(&dev->pdev->dev,
+		dev_dbg(dev->dev,
 			"amthif state = %d\n", dev->iamthif_state);
 			"amthif state = %d\n", dev->iamthif_state);
-		dev_dbg(&dev->pdev->dev, "AMTHIF: add cb to the wait list\n");
+		dev_dbg(dev->dev, "AMTHIF: add cb to the wait list\n");
 		list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
 		list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
 		return 0;
 		return 0;
 	}
 	}
 	return mei_amthif_send_cmd(dev, cb);
 	return mei_amthif_send_cmd(dev, cb);
 }
 }
 /**
 /**
- * mei_amthif_run_next_cmd
+ * mei_amthif_run_next_cmd - send next amt command from queue
  *
  *
  * @dev: the device structure
  * @dev: the device structure
- *
- * returns 0 on success, <0 on failure.
  */
  */
 void mei_amthif_run_next_cmd(struct mei_device *dev)
 void mei_amthif_run_next_cmd(struct mei_device *dev)
 {
 {
-	struct mei_cl_cb *pos = NULL;
-	struct mei_cl_cb *next = NULL;
+	struct mei_cl_cb *cb;
+	struct mei_cl_cb *next;
 	int status;
 	int status;
 
 
 	if (!dev)
 	if (!dev)
@@ -386,21 +374,17 @@ void mei_amthif_run_next_cmd(struct mei_device *dev)
 	dev->iamthif_timer = 0;
 	dev->iamthif_timer = 0;
 	dev->iamthif_file_object = NULL;
 	dev->iamthif_file_object = NULL;
 
 
-	dev_dbg(&dev->pdev->dev, "complete amthif cmd_list cb.\n");
-
-	list_for_each_entry_safe(pos, next, &dev->amthif_cmd_list.list, list) {
-		list_del(&pos->list);
+	dev_dbg(dev->dev, "complete amthif cmd_list cb.\n");
 
 
-		if (pos->cl && pos->cl == &dev->iamthif_cl) {
-			status = mei_amthif_send_cmd(dev, pos);
-			if (status) {
-				dev_dbg(&dev->pdev->dev,
-					"amthif write failed status = %d\n",
+	list_for_each_entry_safe(cb, next, &dev->amthif_cmd_list.list, list) {
+		list_del(&cb->list);
+		if (!cb->cl)
+			continue;
+		status = mei_amthif_send_cmd(dev, cb);
+		if (status)
+			dev_warn(dev->dev, "amthif write failed status = %d\n",
 						status);
 						status);
-				return;
-			}
-			break;
-		}
+		break;
 	}
 	}
 }
 }
 
 
@@ -421,7 +405,7 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
 		   dev->iamthif_file_object == file) {
 		   dev->iamthif_file_object == file) {
 
 
 		mask |= (POLLIN | POLLRDNORM);
 		mask |= (POLLIN | POLLRDNORM);
-		dev_dbg(&dev->pdev->dev, "run next amthif cb\n");
+		dev_dbg(dev->dev, "run next amthif cb\n");
 		mei_amthif_run_next_cmd(dev);
 		mei_amthif_run_next_cmd(dev);
 	}
 	}
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
@@ -434,12 +418,11 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
 /**
 /**
  * mei_amthif_irq_write - write iamthif command in irq thread context.
  * mei_amthif_irq_write - write iamthif command in irq thread context.
  *
  *
- * @dev: the device structure.
- * @cb_pos: callback block.
  * @cl: private data of the file object.
  * @cl: private data of the file object.
+ * @cb: callback block.
  * @cmpl_list: complete list.
  * @cmpl_list: complete list.
  *
  *
- * returns 0, OK; otherwise, error.
+ * Return: 0, OK; otherwise, error.
  */
  */
 int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 			 struct mei_cl_cb *cmpl_list)
 			 struct mei_cl_cb *cmpl_list)
@@ -481,7 +464,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 		return 0;
 		return 0;
 	}
 	}
 
 
-	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
+	dev_dbg(dev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
 
 
 	rets = mei_write_message(dev, &mei_hdr,
 	rets = mei_write_message(dev, &mei_hdr,
 			dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
 			dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
@@ -514,14 +497,14 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 }
 }
 
 
 /**
 /**
- * mei_amthif_irq_read_message - read routine after ISR to
+ * mei_amthif_irq_read_msg - read routine after ISR to
  *			handle the read amthif message
  *			handle the read amthif message
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  * @mei_hdr: header of amthif message
  * @mei_hdr: header of amthif message
  * @complete_list: An instance of our list structure
  * @complete_list: An instance of our list structure
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 int mei_amthif_irq_read_msg(struct mei_device *dev,
 int mei_amthif_irq_read_msg(struct mei_device *dev,
 			    struct mei_msg_hdr *mei_hdr,
 			    struct mei_msg_hdr *mei_hdr,
@@ -543,10 +526,10 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
 	if (!mei_hdr->msg_complete)
 	if (!mei_hdr->msg_complete)
 		return 0;
 		return 0;
 
 
-	dev_dbg(&dev->pdev->dev, "amthif_message_buffer_index =%d\n",
+	dev_dbg(dev->dev, "amthif_message_buffer_index =%d\n",
 			mei_hdr->length);
 			mei_hdr->length);
 
 
-	dev_dbg(&dev->pdev->dev, "completed amthif read.\n ");
+	dev_dbg(dev->dev, "completed amthif read.\n ");
 	if (!dev->iamthif_current_cb)
 	if (!dev->iamthif_current_cb)
 		return -ENODEV;
 		return -ENODEV;
 
 
@@ -559,10 +542,10 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
 	dev->iamthif_stall_timer = 0;
 	dev->iamthif_stall_timer = 0;
 	cb->buf_idx = dev->iamthif_msg_buf_index;
 	cb->buf_idx = dev->iamthif_msg_buf_index;
 	cb->read_time = jiffies;
 	cb->read_time = jiffies;
-	if (dev->iamthif_ioctl && cb->cl == &dev->iamthif_cl) {
+	if (dev->iamthif_ioctl) {
 		/* found the iamthif cb */
 		/* found the iamthif cb */
-		dev_dbg(&dev->pdev->dev, "complete the amthif read cb.\n ");
-		dev_dbg(&dev->pdev->dev, "add the amthif read cb to complete.\n ");
+		dev_dbg(dev->dev, "complete the amthif read cb.\n ");
+		dev_dbg(dev->dev, "add the amthif read cb to complete.\n ");
 		list_add_tail(&cb->list, &complete_list->list);
 		list_add_tail(&cb->list, &complete_list->list);
 	}
 	}
 	return 0;
 	return 0;
@@ -574,7 +557,7 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
  * @dev: the device structure.
  * @dev: the device structure.
  * @slots: free slots.
  * @slots: free slots.
  *
  *
- * returns 0, OK; otherwise, error.
+ * Return: 0, OK; otherwise, error.
  */
  */
 int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
 int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
 {
 {
@@ -586,11 +569,11 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
 	*slots -= msg_slots;
 	*slots -= msg_slots;
 
 
 	if (mei_hbm_cl_flow_control_req(dev, &dev->iamthif_cl)) {
 	if (mei_hbm_cl_flow_control_req(dev, &dev->iamthif_cl)) {
-		dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
+		dev_dbg(dev->dev, "iamthif flow control failed\n");
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
-	dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
+	dev_dbg(dev->dev, "iamthif flow control success\n");
 	dev->iamthif_state = MEI_IAMTHIF_READING;
 	dev->iamthif_state = MEI_IAMTHIF_READING;
 	dev->iamthif_flow_control_pending = false;
 	dev->iamthif_flow_control_pending = false;
 	dev->iamthif_msg_buf_index = 0;
 	dev->iamthif_msg_buf_index = 0;
@@ -604,7 +587,7 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
  * mei_amthif_complete - complete amthif callback.
  * mei_amthif_complete - complete amthif callback.
  *
  *
  * @dev: the device structure.
  * @dev: the device structure.
- * @cb_pos: callback block.
+ * @cb: callback block.
  */
  */
 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
 {
 {
@@ -615,15 +598,15 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
 				dev->iamthif_msg_buf,
 				dev->iamthif_msg_buf,
 				dev->iamthif_msg_buf_index);
 				dev->iamthif_msg_buf_index);
 		list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
 		list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
-		dev_dbg(&dev->pdev->dev, "amthif read completed\n");
+		dev_dbg(dev->dev, "amthif read completed\n");
 		dev->iamthif_timer = jiffies;
 		dev->iamthif_timer = jiffies;
-		dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
+		dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n",
 				dev->iamthif_timer);
 				dev->iamthif_timer);
 	} else {
 	} else {
 		mei_amthif_run_next_cmd(dev);
 		mei_amthif_run_next_cmd(dev);
 	}
 	}
 
 
-	dev_dbg(&dev->pdev->dev, "completing amthif call back.\n");
+	dev_dbg(dev->dev, "completing amthif call back.\n");
 	wake_up_interruptible(&dev->iamthif_cl.wait);
 	wake_up_interruptible(&dev->iamthif_cl.wait);
 }
 }
 
 
@@ -638,7 +621,7 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
  * mei_clear_list is called to clear resources associated with file
  * mei_clear_list is called to clear resources associated with file
  * when application calls close function or Ctrl-C was pressed
  * when application calls close function or Ctrl-C was pressed
  *
  *
- * returns true if callback removed from the list, false otherwise
+ * Return: true if callback removed from the list, false otherwise
  */
  */
 static bool mei_clear_list(struct mei_device *dev,
 static bool mei_clear_list(struct mei_device *dev,
 		const struct file *file, struct list_head *mei_cb_list)
 		const struct file *file, struct list_head *mei_cb_list)
@@ -678,7 +661,7 @@ static bool mei_clear_list(struct mei_device *dev,
  * mei_clear_lists is called to clear resources associated with file
  * mei_clear_lists is called to clear resources associated with file
  * when application calls close function or Ctrl-C was pressed
  * when application calls close function or Ctrl-C was pressed
  *
  *
- * returns true if callback removed from the list, false otherwise
+ * Return: true if callback removed from the list, false otherwise
  */
  */
 static bool mei_clear_lists(struct mei_device *dev, struct file *file)
 static bool mei_clear_lists(struct mei_device *dev, struct file *file)
 {
 {
@@ -719,7 +702,7 @@ static bool mei_clear_lists(struct mei_device *dev, struct file *file)
 *  @dev: device structure
 *  @dev: device structure
 *  @file: pointer to file structure
 *  @file: pointer to file structure
 *
 *
-*  returns 0 on success, <0 on error
+*  Return: 0 on success, <0 on error
 */
 */
 int mei_amthif_release(struct mei_device *dev, struct file *file)
 int mei_amthif_release(struct mei_device *dev, struct file *file)
 {
 {
@@ -729,11 +712,11 @@ int mei_amthif_release(struct mei_device *dev, struct file *file)
 	if (dev->iamthif_file_object == file &&
 	if (dev->iamthif_file_object == file &&
 	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
 	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
 
 
-		dev_dbg(&dev->pdev->dev, "amthif canceled iamthif state %d\n",
+		dev_dbg(dev->dev, "amthif canceled iamthif state %d\n",
 		    dev->iamthif_state);
 		    dev->iamthif_state);
 		dev->iamthif_canceled = true;
 		dev->iamthif_canceled = true;
 		if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
 		if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
-			dev_dbg(&dev->pdev->dev, "run next amthif iamthif cb\n");
+			dev_dbg(dev->dev, "run next amthif iamthif cb\n");
 			mei_amthif_run_next_cmd(dev);
 			mei_amthif_run_next_cmd(dev);
 		}
 		}
 	}
 	}

+ 12 - 13
drivers/misc/mei/bus.c

@@ -22,7 +22,6 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/mei_cl_bus.h>
 #include <linux/mei_cl_bus.h>
 
 
 #include "mei_dev.h"
 #include "mei_dev.h"
@@ -70,7 +69,7 @@ static int mei_cl_device_probe(struct device *dev)
 
 
 	dev_dbg(dev, "Device probe\n");
 	dev_dbg(dev, "Device probe\n");
 
 
-	strncpy(id.name, dev_name(dev), sizeof(id.name));
+	strlcpy(id.name, dev_name(dev), sizeof(id.name));
 
 
 	return driver->probe(device, &id);
 	return driver->probe(device, &id);
 }
 }
@@ -147,7 +146,7 @@ static struct mei_cl *mei_bus_find_mei_cl_by_uuid(struct mei_device *dev,
 	struct mei_cl *cl;
 	struct mei_cl *cl;
 
 
 	list_for_each_entry(cl, &dev->device_list, device_link) {
 	list_for_each_entry(cl, &dev->device_list, device_link) {
-		if (!uuid_le_cmp(uuid, cl->device_uuid))
+		if (!uuid_le_cmp(uuid, cl->cl_uuid))
 			return cl;
 			return cl;
 	}
 	}
 
 
@@ -172,7 +171,7 @@ struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
 	device->cl = cl;
 	device->cl = cl;
 	device->ops = ops;
 	device->ops = ops;
 
 
-	device->dev.parent = &dev->pdev->dev;
+	device->dev.parent = dev->dev;
 	device->dev.bus = &mei_cl_bus_type;
 	device->dev.bus = &mei_cl_bus_type;
 	device->dev.type = &mei_cl_device_type;
 	device->dev.type = &mei_cl_device_type;
 
 
@@ -180,7 +179,7 @@ struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
 
 
 	status = device_register(&device->dev);
 	status = device_register(&device->dev);
 	if (status) {
 	if (status) {
-		dev_err(&dev->pdev->dev, "Failed to register MEI device\n");
+		dev_err(dev->dev, "Failed to register MEI device\n");
 		kfree(device);
 		kfree(device);
 		return NULL;
 		return NULL;
 	}
 	}
@@ -229,8 +228,8 @@ static int ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
 			bool blocking)
 			bool blocking)
 {
 {
 	struct mei_device *dev;
 	struct mei_device *dev;
+	struct mei_me_client *me_cl;
 	struct mei_cl_cb *cb;
 	struct mei_cl_cb *cb;
-	int id;
 	int rets;
 	int rets;
 
 
 	if (WARN_ON(!cl || !cl->dev))
 	if (WARN_ON(!cl || !cl->dev))
@@ -242,11 +241,11 @@ static int ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
 		return -ENODEV;
 		return -ENODEV;
 
 
 	/* Check if we have an ME client device */
 	/* Check if we have an ME client device */
-	id = mei_me_cl_by_id(dev, cl->me_client_id);
-	if (id < 0)
-		return id;
+	me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
+	if (!me_cl)
+		return -ENOTTY;
 
 
-	if (length > dev->me_clients[id].props.max_msg_length)
+	if (length > me_cl->props.max_msg_length)
 		return -EFBIG;
 		return -EFBIG;
 
 
 	cb = mei_io_cb_init(cl, NULL);
 	cb = mei_io_cb_init(cl, NULL);
@@ -430,7 +429,7 @@ int mei_cl_enable_device(struct mei_cl_device *device)
 	err = mei_cl_connect(cl, NULL);
 	err = mei_cl_connect(cl, NULL);
 	if (err < 0) {
 	if (err < 0) {
 		mutex_unlock(&dev->device_lock);
 		mutex_unlock(&dev->device_lock);
-		dev_err(&dev->pdev->dev, "Could not connect to the ME client");
+		dev_err(dev->dev, "Could not connect to the ME client");
 
 
 		return err;
 		return err;
 	}
 	}
@@ -462,7 +461,7 @@ int mei_cl_disable_device(struct mei_cl_device *device)
 
 
 	if (cl->state != MEI_FILE_CONNECTED) {
 	if (cl->state != MEI_FILE_CONNECTED) {
 		mutex_unlock(&dev->device_lock);
 		mutex_unlock(&dev->device_lock);
-		dev_err(&dev->pdev->dev, "Already disconnected");
+		dev_err(dev->dev, "Already disconnected");
 
 
 		return 0;
 		return 0;
 	}
 	}
@@ -472,7 +471,7 @@ int mei_cl_disable_device(struct mei_cl_device *device)
 	err = mei_cl_disconnect(cl);
 	err = mei_cl_disconnect(cl);
 	if (err < 0) {
 	if (err < 0) {
 		mutex_unlock(&dev->device_lock);
 		mutex_unlock(&dev->device_lock);
-		dev_err(&dev->pdev->dev,
+		dev_err(dev->dev,
 			"Could not disconnect from the ME client");
 			"Could not disconnect from the ME client");
 
 
 		return err;
 		return err;

+ 141 - 96
drivers/misc/mei/client.c

@@ -14,10 +14,10 @@
  *
  *
  */
  */
 
 
-#include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 
 
 #include <linux/mei.h>
 #include <linux/mei.h>
@@ -27,47 +27,90 @@
 #include "client.h"
 #include "client.h"
 
 
 /**
 /**
- * mei_me_cl_by_uuid - locate index of me client
+ * mei_me_cl_by_uuid - locate me client by uuid
  *
  *
  * @dev: mei device
  * @dev: mei device
+ * @uuid: me client uuid
  *
  *
  * Locking: called under "dev->device_lock" lock
  * Locking: called under "dev->device_lock" lock
  *
  *
- * returns me client index or -ENOENT if not found
+ * Return: me client or NULL if not found
  */
  */
-int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *uuid)
+struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev,
+					const uuid_le *uuid)
 {
 {
-	int i;
+	struct mei_me_client *me_cl;
 
 
-	for (i = 0; i < dev->me_clients_num; ++i)
-		if (uuid_le_cmp(*uuid,
-				dev->me_clients[i].props.protocol_name) == 0)
-			return i;
+	list_for_each_entry(me_cl, &dev->me_clients, list)
+		if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0)
+			return me_cl;
 
 
-	return -ENOENT;
+	return NULL;
 }
 }
 
 
-
 /**
 /**
- * mei_me_cl_by_id return index to me_clients for client_id
+ * mei_me_cl_by_id - locate me client by client id
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  * @client_id: me client id
  * @client_id: me client id
  *
  *
  * Locking: called under "dev->device_lock" lock
  * Locking: called under "dev->device_lock" lock
  *
  *
- * returns index on success, -ENOENT on failure.
+ * Return: me client or NULL if not found
  */
  */
+struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
+{
+
+	struct mei_me_client *me_cl;
 
 
-int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
+	list_for_each_entry(me_cl, &dev->me_clients, list)
+		if (me_cl->client_id == client_id)
+			return me_cl;
+	return NULL;
+}
+
+/**
+ * mei_me_cl_by_uuid_id - locate me client by client id and uuid
+ *
+ * @dev: the device structure
+ * @uuid: me client uuid
+ * @client_id: me client id
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * Return: me client or NULL if not found
+ */
+struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
+					   const uuid_le *uuid, u8 client_id)
 {
 {
-	int i;
+	struct mei_me_client *me_cl;
 
 
-	for (i = 0; i < dev->me_clients_num; i++)
-		if (dev->me_clients[i].client_id == client_id)
-			return i;
+	list_for_each_entry(me_cl, &dev->me_clients, list)
+		if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0 &&
+		    me_cl->client_id == client_id)
+			return me_cl;
+	return NULL;
+}
 
 
-	return -ENOENT;
+/**
+ * mei_me_cl_remove - remove me client matching uuid and client_id
+ *
+ * @dev: the device structure
+ * @uuid: me client uuid
+ * @client_id: me client address
+ */
+void mei_me_cl_remove(struct mei_device *dev, const uuid_le *uuid, u8 client_id)
+{
+	struct mei_me_client *me_cl, *next;
+
+	list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) {
+		if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0 &&
+		    me_cl->client_id == client_id) {
+			list_del(&me_cl->list);
+			kfree(me_cl);
+			break;
+		}
+	}
 }
 }
 
 
 
 
@@ -77,7 +120,7 @@ int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
  * @cl1: host client 1
  * @cl1: host client 1
  * @cl2: host client 2
  * @cl2: host client 2
  *
  *
- * returns true  - if the clients has same host and me ids
+ * Return: true  - if the clients has same host and me ids
  *         false - otherwise
  *         false - otherwise
  */
  */
 static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
 static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
@@ -117,7 +160,7 @@ static void __mei_io_list_flush(struct mei_cl_cb *list,
  * @list:  An instance of our list structure
  * @list:  An instance of our list structure
  * @cl: host client
  * @cl: host client
  */
  */
-static inline void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
+void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
 {
 {
 	__mei_io_list_flush(list, cl, false);
 	__mei_io_list_flush(list, cl, false);
 }
 }
@@ -152,10 +195,10 @@ void mei_io_cb_free(struct mei_cl_cb *cb)
 /**
 /**
  * mei_io_cb_init - allocate and initialize io callback
  * mei_io_cb_init - allocate and initialize io callback
  *
  *
- * @cl - mei client
+ * @cl: mei client
  * @fp: pointer to file structure
  * @fp: pointer to file structure
  *
  *
- * returns mei_cl_cb pointer or NULL;
+ * Return: mei_cl_cb pointer or NULL;
  */
  */
 struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
 struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
 {
 {
@@ -179,7 +222,7 @@ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
  * @cb: io callback structure
  * @cb: io callback structure
  * @length: size of the buffer
  * @length: size of the buffer
  *
  *
- * returns 0 on success
+ * Return: 0 on success
  *         -EINVAL if cb is NULL
  *         -EINVAL if cb is NULL
  *         -ENOMEM if allocation failed
  *         -ENOMEM if allocation failed
  */
  */
@@ -203,7 +246,7 @@ int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
  * @cb: io callback structure
  * @cb: io callback structure
  * @length: size of the buffer
  * @length: size of the buffer
  *
  *
- * returns 0 on success
+ * Return: 0 on success
  *         -EINVAL if cb is NULL
  *         -EINVAL if cb is NULL
  *         -ENOMEM if allocation failed
  *         -ENOMEM if allocation failed
  */
  */
@@ -228,6 +271,8 @@ int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
  * mei_cl_flush_queues - flushes queue lists belonging to cl.
  * mei_cl_flush_queues - flushes queue lists belonging to cl.
  *
  *
  * @cl: host client
  * @cl: host client
+ *
+ * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.
  */
  */
 int mei_cl_flush_queues(struct mei_cl *cl)
 int mei_cl_flush_queues(struct mei_cl *cl)
 {
 {
@@ -273,7 +318,7 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
  * mei_cl_allocate - allocates cl  structure and sets it up.
  * mei_cl_allocate - allocates cl  structure and sets it up.
  *
  *
  * @dev: mei device
  * @dev: mei device
- * returns  The allocated file or NULL on failure
+ * Return:  The allocated file or NULL on failure
  */
  */
 struct mei_cl *mei_cl_allocate(struct mei_device *dev)
 struct mei_cl *mei_cl_allocate(struct mei_device *dev)
 {
 {
@@ -293,7 +338,7 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
  *
  *
  * @cl: host client
  * @cl: host client
  *
  *
- * returns cb on success, NULL on error
+ * Return: cb on success, NULL on error
  */
  */
 struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
 struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
 {
 {
@@ -311,7 +356,7 @@ struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
  * @cl - host client
  * @cl - host client
  * @id - fixed host id or -1 for generic one
  * @id - fixed host id or -1 for generic one
  *
  *
- * returns 0 on success
+ * Return: 0 on success
  *	-EINVAL on incorrect values
  *	-EINVAL on incorrect values
  *	-ENONET if client not found
  *	-ENONET if client not found
  */
  */
@@ -331,13 +376,13 @@ int mei_cl_link(struct mei_cl *cl, int id)
 					MEI_CLIENTS_MAX);
 					MEI_CLIENTS_MAX);
 
 
 	if (id >= MEI_CLIENTS_MAX) {
 	if (id >= MEI_CLIENTS_MAX) {
-		dev_err(&dev->pdev->dev, "id exceeded %d", MEI_CLIENTS_MAX);
+		dev_err(dev->dev, "id exceeded %d", MEI_CLIENTS_MAX);
 		return -EMFILE;
 		return -EMFILE;
 	}
 	}
 
 
 	open_handle_count = dev->open_handle_count + dev->iamthif_open_count;
 	open_handle_count = dev->open_handle_count + dev->iamthif_open_count;
 	if (open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
 	if (open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
-		dev_err(&dev->pdev->dev, "open_handle_count exceeded %d",
+		dev_err(dev->dev, "open_handle_count exceeded %d",
 			MEI_MAX_OPEN_HANDLE_COUNT);
 			MEI_MAX_OPEN_HANDLE_COUNT);
 		return -EMFILE;
 		return -EMFILE;
 	}
 	}
@@ -359,6 +404,8 @@ int mei_cl_link(struct mei_cl *cl, int id)
  * mei_cl_unlink - remove me_cl from the list
  * mei_cl_unlink - remove me_cl from the list
  *
  *
  * @cl: host client
  * @cl: host client
+ *
+ * Return: always 0
  */
  */
 int mei_cl_unlink(struct mei_cl *cl)
 int mei_cl_unlink(struct mei_cl *cl)
 {
 {
@@ -395,19 +442,19 @@ void mei_host_client_init(struct work_struct *work)
 {
 {
 	struct mei_device *dev = container_of(work,
 	struct mei_device *dev = container_of(work,
 					      struct mei_device, init_work);
 					      struct mei_device, init_work);
-	struct mei_client_properties *client_props;
-	int i;
+	struct mei_me_client *me_cl;
+	struct mei_client_properties *props;
 
 
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 
 
-	for (i = 0; i < dev->me_clients_num; i++) {
-		client_props = &dev->me_clients[i].props;
+	list_for_each_entry(me_cl, &dev->me_clients, list) {
+		props = &me_cl->props;
 
 
-		if (!uuid_le_cmp(client_props->protocol_name, mei_amthif_guid))
+		if (!uuid_le_cmp(props->protocol_name, mei_amthif_guid))
 			mei_amthif_host_init(dev);
 			mei_amthif_host_init(dev);
-		else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
+		else if (!uuid_le_cmp(props->protocol_name, mei_wd_guid))
 			mei_wd_host_init(dev);
 			mei_wd_host_init(dev);
-		else if (!uuid_le_cmp(client_props->protocol_name, mei_nfc_guid))
+		else if (!uuid_le_cmp(props->protocol_name, mei_nfc_guid))
 			mei_nfc_host_init(dev);
 			mei_nfc_host_init(dev);
 
 
 	}
 	}
@@ -417,27 +464,27 @@ void mei_host_client_init(struct work_struct *work)
 
 
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 
 
-	pm_runtime_mark_last_busy(&dev->pdev->dev);
-	dev_dbg(&dev->pdev->dev, "rpm: autosuspend\n");
-	pm_runtime_autosuspend(&dev->pdev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	dev_dbg(dev->dev, "rpm: autosuspend\n");
+	pm_runtime_autosuspend(dev->dev);
 }
 }
 
 
 /**
 /**
- * mei_hbuf_acquire: try to acquire host buffer
+ * mei_hbuf_acquire - try to acquire host buffer
  *
  *
  * @dev: the device structure
  * @dev: the device structure
- * returns true if host buffer was acquired
+ * Return: true if host buffer was acquired
  */
  */
 bool mei_hbuf_acquire(struct mei_device *dev)
 bool mei_hbuf_acquire(struct mei_device *dev)
 {
 {
 	if (mei_pg_state(dev) == MEI_PG_ON ||
 	if (mei_pg_state(dev) == MEI_PG_ON ||
 	    dev->pg_event == MEI_PG_EVENT_WAIT) {
 	    dev->pg_event == MEI_PG_EVENT_WAIT) {
-		dev_dbg(&dev->pdev->dev, "device is in pg\n");
+		dev_dbg(dev->dev, "device is in pg\n");
 		return false;
 		return false;
 	}
 	}
 
 
 	if (!dev->hbuf_is_ready) {
 	if (!dev->hbuf_is_ready) {
-		dev_dbg(&dev->pdev->dev, "hbuf is not ready\n");
+		dev_dbg(dev->dev, "hbuf is not ready\n");
 		return false;
 		return false;
 	}
 	}
 
 
@@ -453,7 +500,7 @@ bool mei_hbuf_acquire(struct mei_device *dev)
  *
  *
  * Locking: called under "dev->device_lock" lock
  * Locking: called under "dev->device_lock" lock
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 int mei_cl_disconnect(struct mei_cl *cl)
 int mei_cl_disconnect(struct mei_cl *cl)
 {
 {
@@ -471,9 +518,9 @@ int mei_cl_disconnect(struct mei_cl *cl)
 	if (cl->state != MEI_FILE_DISCONNECTING)
 	if (cl->state != MEI_FILE_DISCONNECTING)
 		return 0;
 		return 0;
 
 
-	rets = pm_runtime_get(&dev->pdev->dev);
+	rets = pm_runtime_get(dev->dev);
 	if (rets < 0 && rets != -EINPROGRESS) {
 	if (rets < 0 && rets != -EINPROGRESS) {
-		pm_runtime_put_noidle(&dev->pdev->dev);
+		pm_runtime_put_noidle(dev->dev);
 		cl_err(dev, cl, "rpm: get failed %d\n", rets);
 		cl_err(dev, cl, "rpm: get failed %d\n", rets);
 		return rets;
 		return rets;
 	}
 	}
@@ -484,7 +531,8 @@ int mei_cl_disconnect(struct mei_cl *cl)
 		goto free;
 		goto free;
 	}
 	}
 
 
-	cb->fop_type = MEI_FOP_CLOSE;
+	cb->fop_type = MEI_FOP_DISCONNECT;
+
 	if (mei_hbuf_acquire(dev)) {
 	if (mei_hbuf_acquire(dev)) {
 		if (mei_hbm_cl_disconnect_req(dev, cl)) {
 		if (mei_hbm_cl_disconnect_req(dev, cl)) {
 			rets = -ENODEV;
 			rets = -ENODEV;
@@ -501,7 +549,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
 	}
 	}
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 
 
-	wait_event_timeout(dev->wait_recvd_msg,
+	wait_event_timeout(cl->wait,
 			MEI_FILE_DISCONNECTED == cl->state,
 			MEI_FILE_DISCONNECTED == cl->state,
 			mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
 			mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
 
 
@@ -519,8 +567,8 @@ int mei_cl_disconnect(struct mei_cl *cl)
 	mei_io_list_flush(&dev->ctrl_wr_list, cl);
 	mei_io_list_flush(&dev->ctrl_wr_list, cl);
 free:
 free:
 	cl_dbg(dev, cl, "rpm: autosuspend\n");
 	cl_dbg(dev, cl, "rpm: autosuspend\n");
-	pm_runtime_mark_last_busy(&dev->pdev->dev);
-	pm_runtime_put_autosuspend(&dev->pdev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 
 
 	mei_io_cb_free(cb);
 	mei_io_cb_free(cb);
 	return rets;
 	return rets;
@@ -533,7 +581,7 @@ free:
  *
  *
  * @cl: private data of the file object
  * @cl: private data of the file object
  *
  *
- * returns true if other client is connected, false - otherwise.
+ * Return: true if other client is connected, false - otherwise.
  */
  */
 bool mei_cl_is_other_connecting(struct mei_cl *cl)
 bool mei_cl_is_other_connecting(struct mei_cl *cl)
 {
 {
@@ -560,10 +608,11 @@ bool mei_cl_is_other_connecting(struct mei_cl *cl)
  * mei_cl_connect - connect host client to the me one
  * mei_cl_connect - connect host client to the me one
  *
  *
  * @cl: host client
  * @cl: host client
+ * @file: pointer to file structure
  *
  *
  * Locking: called under "dev->device_lock" lock
  * Locking: called under "dev->device_lock" lock
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 int mei_cl_connect(struct mei_cl *cl, struct file *file)
 int mei_cl_connect(struct mei_cl *cl, struct file *file)
 {
 {
@@ -576,9 +625,9 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 
 
 	dev = cl->dev;
 	dev = cl->dev;
 
 
-	rets = pm_runtime_get(&dev->pdev->dev);
+	rets = pm_runtime_get(dev->dev);
 	if (rets < 0 && rets != -EINPROGRESS) {
 	if (rets < 0 && rets != -EINPROGRESS) {
-		pm_runtime_put_noidle(&dev->pdev->dev);
+		pm_runtime_put_noidle(dev->dev);
 		cl_err(dev, cl, "rpm: get failed %d\n", rets);
 		cl_err(dev, cl, "rpm: get failed %d\n", rets);
 		return rets;
 		return rets;
 	}
 	}
@@ -606,7 +655,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 	}
 	}
 
 
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
-	wait_event_timeout(dev->wait_recvd_msg,
+	wait_event_timeout(cl->wait,
 			(cl->state == MEI_FILE_CONNECTED ||
 			(cl->state == MEI_FILE_CONNECTED ||
 			 cl->state == MEI_FILE_DISCONNECTED),
 			 cl->state == MEI_FILE_DISCONNECTED),
 			mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
 			mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
@@ -626,8 +675,8 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 
 
 out:
 out:
 	cl_dbg(dev, cl, "rpm: autosuspend\n");
 	cl_dbg(dev, cl, "rpm: autosuspend\n");
-	pm_runtime_mark_last_busy(&dev->pdev->dev);
-	pm_runtime_put_autosuspend(&dev->pdev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 
 
 	mei_io_cb_free(cb);
 	mei_io_cb_free(cb);
 	return rets;
 	return rets;
@@ -638,7 +687,7 @@ out:
  *
  *
  * @cl: private data of the file object
  * @cl: private data of the file object
  *
  *
- * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
+ * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
  *	-ENOENT if mei_cl is not present
  *	-ENOENT if mei_cl is not present
  *	-EINVAL if single_recv_buf == 0
  *	-EINVAL if single_recv_buf == 0
  */
  */
@@ -646,26 +695,21 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
 {
 {
 	struct mei_device *dev;
 	struct mei_device *dev;
 	struct mei_me_client *me_cl;
 	struct mei_me_client *me_cl;
-	int id;
 
 
 	if (WARN_ON(!cl || !cl->dev))
 	if (WARN_ON(!cl || !cl->dev))
 		return -EINVAL;
 		return -EINVAL;
 
 
 	dev = cl->dev;
 	dev = cl->dev;
 
 
-	if (!dev->me_clients_num)
-		return 0;
-
 	if (cl->mei_flow_ctrl_creds > 0)
 	if (cl->mei_flow_ctrl_creds > 0)
 		return 1;
 		return 1;
 
 
-	id = mei_me_cl_by_id(dev, cl->me_client_id);
-	if (id < 0) {
+	me_cl = mei_me_cl_by_id(dev, cl->me_client_id);
+	if (!me_cl) {
 		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
 		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
-		return id;
+		return -ENOENT;
 	}
 	}
 
 
-	me_cl = &dev->me_clients[id];
 	if (me_cl->mei_flow_ctrl_creds) {
 	if (me_cl->mei_flow_ctrl_creds) {
 		if (WARN_ON(me_cl->props.single_recv_buf == 0))
 		if (WARN_ON(me_cl->props.single_recv_buf == 0))
 			return -EINVAL;
 			return -EINVAL;
@@ -679,7 +723,7 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
  *
  *
  * @cl: private data of the file object
  * @cl: private data of the file object
  *
  *
- * @returns
+ * Return:
  *	0 on success
  *	0 on success
  *	-ENOENT when me client is not found
  *	-ENOENT when me client is not found
  *	-EINVAL when ctrl credits are <= 0
  *	-EINVAL when ctrl credits are <= 0
@@ -688,21 +732,19 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
 {
 {
 	struct mei_device *dev;
 	struct mei_device *dev;
 	struct mei_me_client *me_cl;
 	struct mei_me_client *me_cl;
-	int id;
 
 
 	if (WARN_ON(!cl || !cl->dev))
 	if (WARN_ON(!cl || !cl->dev))
 		return -EINVAL;
 		return -EINVAL;
 
 
 	dev = cl->dev;
 	dev = cl->dev;
 
 
-	id = mei_me_cl_by_id(dev, cl->me_client_id);
-	if (id < 0) {
+	me_cl = mei_me_cl_by_id(dev, cl->me_client_id);
+	if (!me_cl) {
 		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
 		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
-		return id;
+		return -ENOENT;
 	}
 	}
 
 
-	me_cl = &dev->me_clients[id];
-	if (me_cl->props.single_recv_buf != 0) {
+	if (me_cl->props.single_recv_buf) {
 		if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
 		if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
 			return -EINVAL;
 			return -EINVAL;
 		me_cl->mei_flow_ctrl_creds--;
 		me_cl->mei_flow_ctrl_creds--;
@@ -718,15 +760,16 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
  * mei_cl_read_start - the start read client message function.
  * mei_cl_read_start - the start read client message function.
  *
  *
  * @cl: host client
  * @cl: host client
+ * @length: number of bytes to read
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 int mei_cl_read_start(struct mei_cl *cl, size_t length)
 int mei_cl_read_start(struct mei_cl *cl, size_t length)
 {
 {
 	struct mei_device *dev;
 	struct mei_device *dev;
 	struct mei_cl_cb *cb;
 	struct mei_cl_cb *cb;
+	struct mei_me_client *me_cl;
 	int rets;
 	int rets;
-	int i;
 
 
 	if (WARN_ON(!cl || !cl->dev))
 	if (WARN_ON(!cl || !cl->dev))
 		return -ENODEV;
 		return -ENODEV;
@@ -740,15 +783,15 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
 		cl_dbg(dev, cl, "read is pending.\n");
 		cl_dbg(dev, cl, "read is pending.\n");
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
-	i = mei_me_cl_by_id(dev, cl->me_client_id);
-	if (i < 0) {
+	me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
+	if (!me_cl) {
 		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
 		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
 		return  -ENOTTY;
 		return  -ENOTTY;
 	}
 	}
 
 
-	rets = pm_runtime_get(&dev->pdev->dev);
+	rets = pm_runtime_get(dev->dev);
 	if (rets < 0 && rets != -EINPROGRESS) {
 	if (rets < 0 && rets != -EINPROGRESS) {
-		pm_runtime_put_noidle(&dev->pdev->dev);
+		pm_runtime_put_noidle(dev->dev);
 		cl_err(dev, cl, "rpm: get failed %d\n", rets);
 		cl_err(dev, cl, "rpm: get failed %d\n", rets);
 		return rets;
 		return rets;
 	}
 	}
@@ -760,7 +803,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
 	}
 	}
 
 
 	/* always allocate at least client max message */
 	/* always allocate at least client max message */
-	length = max_t(size_t, length, dev->me_clients[i].props.max_msg_length);
+	length = max_t(size_t, length, me_cl->props.max_msg_length);
 	rets = mei_io_cb_alloc_resp_buf(cb, length);
 	rets = mei_io_cb_alloc_resp_buf(cb, length);
 	if (rets)
 	if (rets)
 		goto out;
 		goto out;
@@ -780,8 +823,8 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
 
 
 out:
 out:
 	cl_dbg(dev, cl, "rpm: autosuspend\n");
 	cl_dbg(dev, cl, "rpm: autosuspend\n");
-	pm_runtime_mark_last_busy(&dev->pdev->dev);
-	pm_runtime_put_autosuspend(&dev->pdev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 
 
 	if (rets)
 	if (rets)
 		mei_io_cb_free(cb);
 		mei_io_cb_free(cb);
@@ -797,7 +840,7 @@ out:
  * @cb: callback block.
  * @cb: callback block.
  * @cmpl_list: complete list.
  * @cmpl_list: complete list.
  *
  *
- * returns 0, OK; otherwise error.
+ * Return: 0, OK; otherwise error.
  */
  */
 int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 		     struct mei_cl_cb *cmpl_list)
 		     struct mei_cl_cb *cmpl_list)
@@ -874,12 +917,13 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 
 
 /**
 /**
  * mei_cl_write - submit a write cb to mei device
  * mei_cl_write - submit a write cb to mei device
-	assumes device_lock is locked
+ *	assumes device_lock is locked
  *
  *
  * @cl: host client
  * @cl: host client
- * @cl: write callback with filled data
+ * @cb: write callback with filled data
+ * @blocking: block until completed
  *
  *
- * returns number of bytes sent on success, <0 on failure.
+ * Return: number of bytes sent on success, <0 on failure.
  */
  */
 int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 {
 {
@@ -900,11 +944,11 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 
 
 	buf = &cb->request_buffer;
 	buf = &cb->request_buffer;
 
 
-	cl_dbg(dev, cl, "mei_cl_write %d\n", buf->size);
+	cl_dbg(dev, cl, "size=%d\n", buf->size);
 
 
-	rets = pm_runtime_get(&dev->pdev->dev);
+	rets = pm_runtime_get(dev->dev);
 	if (rets < 0 && rets != -EINPROGRESS) {
 	if (rets < 0 && rets != -EINPROGRESS) {
-		pm_runtime_put_noidle(&dev->pdev->dev);
+		pm_runtime_put_noidle(dev->dev);
 		cl_err(dev, cl, "rpm: get failed %d\n", rets);
 		cl_err(dev, cl, "rpm: get failed %d\n", rets);
 		return rets;
 		return rets;
 	}
 	}
@@ -979,8 +1023,8 @@ out:
 	rets = buf->size;
 	rets = buf->size;
 err:
 err:
 	cl_dbg(dev, cl, "rpm: autosuspend\n");
 	cl_dbg(dev, cl, "rpm: autosuspend\n");
-	pm_runtime_mark_last_busy(&dev->pdev->dev);
-	pm_runtime_put_autosuspend(&dev->pdev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 
 
 	return rets;
 	return rets;
 }
 }
@@ -1016,7 +1060,7 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
 /**
 /**
  * mei_cl_all_disconnect - disconnect forcefully all connected clients
  * mei_cl_all_disconnect - disconnect forcefully all connected clients
  *
  *
- * @dev - mei device
+ * @dev: mei device
  */
  */
 
 
 void mei_cl_all_disconnect(struct mei_device *dev)
 void mei_cl_all_disconnect(struct mei_device *dev)
@@ -1034,11 +1078,12 @@ void mei_cl_all_disconnect(struct mei_device *dev)
 /**
 /**
  * mei_cl_all_wakeup  - wake up all readers and writers they can be interrupted
  * mei_cl_all_wakeup  - wake up all readers and writers they can be interrupted
  *
  *
- * @dev  - mei device
+ * @dev: mei device
  */
  */
 void mei_cl_all_wakeup(struct mei_device *dev)
 void mei_cl_all_wakeup(struct mei_device *dev)
 {
 {
 	struct mei_cl *cl;
 	struct mei_cl *cl;
+
 	list_for_each_entry(cl, &dev->file_list, link) {
 	list_for_each_entry(cl, &dev->file_list, link) {
 		if (waitqueue_active(&cl->rx_wait)) {
 		if (waitqueue_active(&cl->rx_wait)) {
 			cl_dbg(dev, cl, "Waking up reading client!\n");
 			cl_dbg(dev, cl, "Waking up reading client!\n");
@@ -1053,8 +1098,8 @@ void mei_cl_all_wakeup(struct mei_device *dev)
 
 
 /**
 /**
  * mei_cl_all_write_clear - clear all pending writes
  * mei_cl_all_write_clear - clear all pending writes
-
- * @dev - mei device
+ *
+ * @dev: mei device
  */
  */
 void mei_cl_all_write_clear(struct mei_device *dev)
 void mei_cl_all_write_clear(struct mei_device *dev)
 {
 {

+ 13 - 4
drivers/misc/mei/client.h

@@ -24,8 +24,15 @@
 
 
 #include "mei_dev.h"
 #include "mei_dev.h"
 
 
-int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid);
-int mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
+struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev,
+					const uuid_le *cuuid);
+struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
+
+struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
+					   const uuid_le *uuid, u8 client_id);
+
+void mei_me_cl_remove(struct mei_device *dev,
+		      const uuid_le *uuid, u8 client_id);
 
 
 /*
 /*
  * MEI IO Functions
  * MEI IO Functions
@@ -45,6 +52,8 @@ static inline void mei_io_list_init(struct mei_cl_cb *list)
 {
 {
 	INIT_LIST_HEAD(&list->list);
 	INIT_LIST_HEAD(&list->list);
 }
 }
+void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl);
+
 /*
 /*
  * MEI Host Client Functions
  * MEI Host Client Functions
  */
  */
@@ -101,9 +110,9 @@ void mei_cl_all_write_clear(struct mei_device *dev);
 #define MEI_CL_PRM(cl) (cl)->host_client_id, (cl)->me_client_id
 #define MEI_CL_PRM(cl) (cl)->host_client_id, (cl)->me_client_id
 
 
 #define cl_dbg(dev, cl, format, arg...) \
 #define cl_dbg(dev, cl, format, arg...) \
-	dev_dbg(&(dev)->pdev->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
+	dev_dbg((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
 
 
 #define cl_err(dev, cl, format, arg...) \
 #define cl_err(dev, cl, format, arg...) \
-	dev_err(&(dev)->pdev->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
+	dev_err((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
 
 
 #endif /* _MEI_CLIENT_H_ */
 #endif /* _MEI_CLIENT_H_ */

+ 44 - 26
drivers/misc/mei/debugfs.c

@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/debugfs.h>
 #include <linux/debugfs.h>
-#include <linux/pci.h>
 
 
 #include <linux/mei.h>
 #include <linux/mei.h>
 
 
@@ -28,39 +27,47 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
 					size_t cnt, loff_t *ppos)
 					size_t cnt, loff_t *ppos)
 {
 {
 	struct mei_device *dev = fp->private_data;
 	struct mei_device *dev = fp->private_data;
-	struct mei_me_client *cl;
-	const size_t bufsz = 1024;
-	char *buf = kzalloc(bufsz, GFP_KERNEL);
-	int i;
+	struct mei_me_client *me_cl;
+	size_t bufsz = 1;
+	char *buf;
+	int i = 0;
 	int pos = 0;
 	int pos = 0;
 	int ret;
 	int ret;
 
 
-	if  (!buf)
-		return -ENOMEM;
-
-	pos += scnprintf(buf + pos, bufsz - pos,
-			"  |id|addr|         UUID                       |con|msg len|\n");
+#define HDR "  |id|addr|         UUID                       |con|msg len|sb|\n"
 
 
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 
 
+	list_for_each_entry(me_cl, &dev->me_clients, list)
+		bufsz++;
+
+	bufsz *= sizeof(HDR) + 1;
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		mutex_unlock(&dev->device_lock);
+		return -ENOMEM;
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, HDR);
+
 	/*  if the driver is not enabled the list won't be consistent */
 	/*  if the driver is not enabled the list won't be consistent */
 	if (dev->dev_state != MEI_DEV_ENABLED)
 	if (dev->dev_state != MEI_DEV_ENABLED)
 		goto out;
 		goto out;
 
 
-	for (i = 0; i < dev->me_clients_num; i++) {
-		cl = &dev->me_clients[i];
+	list_for_each_entry(me_cl, &dev->me_clients, list) {
 
 
 		/* skip me clients that cannot be connected */
 		/* skip me clients that cannot be connected */
-		if (cl->props.max_number_of_connections == 0)
+		if (me_cl->props.max_number_of_connections == 0)
 			continue;
 			continue;
 
 
 		pos += scnprintf(buf + pos, bufsz - pos,
 		pos += scnprintf(buf + pos, bufsz - pos,
-			"%2d|%2d|%4d|%pUl|%3d|%7d|\n",
-			i, cl->client_id,
-			cl->props.fixed_address,
-			&cl->props.protocol_name,
-			cl->props.max_number_of_connections,
-			cl->props.max_msg_length);
+			"%2d|%2d|%4d|%pUl|%3d|%7d|%2d|\n",
+			i++, me_cl->client_id,
+			me_cl->props.fixed_address,
+			&me_cl->props.protocol_name,
+			me_cl->props.max_number_of_connections,
+			me_cl->props.max_msg_length,
+			me_cl->props.single_recv_buf);
 	}
 	}
 out:
 out:
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
@@ -98,7 +105,7 @@ static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf,
 
 
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 
 
-	/*  if the driver is not enabled the list won't b consitent */
+	/*  if the driver is not enabled the list won't be consistent */
 	if (dev->dev_state != MEI_DEV_ENABLED)
 	if (dev->dev_state != MEI_DEV_ENABLED)
 		goto out;
 		goto out;
 
 
@@ -135,8 +142,13 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf,
 	if  (!buf)
 	if  (!buf)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
+	pos += scnprintf(buf + pos, bufsz - pos, "dev: %s\n",
 			mei_dev_state_str(dev->dev_state));
 			mei_dev_state_str(dev->dev_state));
+	pos += scnprintf(buf + pos, bufsz - pos, "hbm: %s\n",
+			mei_hbm_state_str(dev->hbm_state));
+	pos += scnprintf(buf + pos, bufsz - pos, "pg:  %s, %s\n",
+			mei_pg_is_enabled(dev) ? "ENABLED" : "DISABLED",
+			mei_pg_state_str(mei_pg_state(dev)));
 	ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos);
 	ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos);
 	kfree(buf);
 	kfree(buf);
 	return ret;
 	return ret;
@@ -149,7 +161,8 @@ static const struct file_operations mei_dbgfs_fops_devstate = {
 
 
 /**
 /**
  * mei_dbgfs_deregister - Remove the debugfs files and directories
  * mei_dbgfs_deregister - Remove the debugfs files and directories
- * @mei - pointer to mei device private data
+ *
+ * @dev: the mei device structure
  */
  */
 void mei_dbgfs_deregister(struct mei_device *dev)
 void mei_dbgfs_deregister(struct mei_device *dev)
 {
 {
@@ -160,12 +173,17 @@ void mei_dbgfs_deregister(struct mei_device *dev)
 }
 }
 
 
 /**
 /**
- * Add the debugfs files
+ * mei_dbgfs_register - Add the debugfs files
  *
  *
+ * @dev: the mei device structure
+ * @name: the mei device name
+ *
+ * Return: 0 on success, <0 on failure.
  */
  */
 int mei_dbgfs_register(struct mei_device *dev, const char *name)
 int mei_dbgfs_register(struct mei_device *dev, const char *name)
 {
 {
 	struct dentry *dir, *f;
 	struct dentry *dir, *f;
+
 	dir = debugfs_create_dir(name, NULL);
 	dir = debugfs_create_dir(name, NULL);
 	if (!dir)
 	if (!dir)
 		return -ENOMEM;
 		return -ENOMEM;
@@ -173,19 +191,19 @@ int mei_dbgfs_register(struct mei_device *dev, const char *name)
 	f = debugfs_create_file("meclients", S_IRUSR, dir,
 	f = debugfs_create_file("meclients", S_IRUSR, dir,
 				dev, &mei_dbgfs_fops_meclients);
 				dev, &mei_dbgfs_fops_meclients);
 	if (!f) {
 	if (!f) {
-		dev_err(&dev->pdev->dev, "meclients: registration failed\n");
+		dev_err(dev->dev, "meclients: registration failed\n");
 		goto err;
 		goto err;
 	}
 	}
 	f = debugfs_create_file("active", S_IRUSR, dir,
 	f = debugfs_create_file("active", S_IRUSR, dir,
 				dev, &mei_dbgfs_fops_active);
 				dev, &mei_dbgfs_fops_active);
 	if (!f) {
 	if (!f) {
-		dev_err(&dev->pdev->dev, "meclients: registration failed\n");
+		dev_err(dev->dev, "meclients: registration failed\n");
 		goto err;
 		goto err;
 	}
 	}
 	f = debugfs_create_file("devstate", S_IRUSR, dir,
 	f = debugfs_create_file("devstate", S_IRUSR, dir,
 				dev, &mei_dbgfs_fops_devstate);
 				dev, &mei_dbgfs_fops_devstate);
 	if (!f) {
 	if (!f) {
-		dev_err(&dev->pdev->dev, "devstate: registration failed\n");
+		dev_err(dev->dev, "devstate: registration failed\n");
 		goto err;
 		goto err;
 	}
 	}
 	dev->dbgfs_dir = dir;
 	dev->dbgfs_dir = dir;

+ 323 - 244
drivers/misc/mei/hbm.c

@@ -15,16 +15,34 @@
  */
  */
 
 
 #include <linux/export.h>
 #include <linux/export.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/wait.h>
-#include <linux/mei.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+#include <linux/mei.h>
 
 
 #include "mei_dev.h"
 #include "mei_dev.h"
 #include "hbm.h"
 #include "hbm.h"
 #include "client.h"
 #include "client.h"
 
 
+static const char *mei_hbm_status_str(enum mei_hbm_status status)
+{
+#define MEI_HBM_STATUS(status) case MEI_HBMS_##status: return #status
+	switch (status) {
+	MEI_HBM_STATUS(SUCCESS);
+	MEI_HBM_STATUS(CLIENT_NOT_FOUND);
+	MEI_HBM_STATUS(ALREADY_EXISTS);
+	MEI_HBM_STATUS(REJECTED);
+	MEI_HBM_STATUS(INVALID_PARAMETER);
+	MEI_HBM_STATUS(NOT_ALLOWED);
+	MEI_HBM_STATUS(ALREADY_STARTED);
+	MEI_HBM_STATUS(NOT_STARTED);
+	default: return "unknown";
+	}
+#undef MEI_HBM_STATUS
+};
+
 static const char *mei_cl_conn_status_str(enum mei_cl_connect_status status)
 static const char *mei_cl_conn_status_str(enum mei_cl_connect_status status)
 {
 {
 #define MEI_CL_CS(status) case MEI_CL_CONN_##status: return #status
 #define MEI_CL_CS(status) case MEI_CL_CONN_##status: return #status
@@ -39,13 +57,29 @@ static const char *mei_cl_conn_status_str(enum mei_cl_connect_status status)
 #undef MEI_CL_CCS
 #undef MEI_CL_CCS
 }
 }
 
 
+const char *mei_hbm_state_str(enum mei_hbm_state state)
+{
+#define MEI_HBM_STATE(state) case MEI_HBM_##state: return #state
+	switch (state) {
+	MEI_HBM_STATE(IDLE);
+	MEI_HBM_STATE(STARTING);
+	MEI_HBM_STATE(STARTED);
+	MEI_HBM_STATE(ENUM_CLIENTS);
+	MEI_HBM_STATE(CLIENT_PROPERTIES);
+	MEI_HBM_STATE(STOPPED);
+	default:
+		return "unknown";
+	}
+#undef MEI_HBM_STATE
+}
+
 /**
 /**
  * mei_cl_conn_status_to_errno - convert client connect response
  * mei_cl_conn_status_to_errno - convert client connect response
  * status to error code
  * status to error code
  *
  *
  * @status: client connect response status
  * @status: client connect response status
  *
  *
- * returns corresponding error code
+ * Return: corresponding error code
  */
  */
 static int mei_cl_conn_status_to_errno(enum mei_cl_connect_status status)
 static int mei_cl_conn_status_to_errno(enum mei_cl_connect_status status)
 {
 {
@@ -71,60 +105,54 @@ void mei_hbm_idle(struct mei_device *dev)
 }
 }
 
 
 /**
 /**
- * mei_hbm_reset - reset hbm counters and book keeping data structurs
+ * mei_me_cl_remove_all - remove all me clients
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  */
  */
-void mei_hbm_reset(struct mei_device *dev)
+static void mei_me_cl_remove_all(struct mei_device *dev)
 {
 {
-	dev->me_clients_num = 0;
-	dev->me_client_presentation_num = 0;
-	dev->me_client_index = 0;
-
-	kfree(dev->me_clients);
-	dev->me_clients = NULL;
+	struct mei_me_client *me_cl, *next;
 
 
-	mei_hbm_idle(dev);
+	list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) {
+			list_del(&me_cl->list);
+			kfree(me_cl);
+	}
 }
 }
 
 
 /**
 /**
- * mei_hbm_me_cl_allocate - allocates storage for me clients
+ * mei_hbm_reset - reset hbm counters and book keeping data structurs
  *
  *
  * @dev: the device structure
  * @dev: the device structure
- *
- * returns 0 on success -ENOMEM on allocation failure
  */
  */
-static int mei_hbm_me_cl_allocate(struct mei_device *dev)
+void mei_hbm_reset(struct mei_device *dev)
 {
 {
-	struct mei_me_client *clients;
-	int b;
+	dev->me_client_index = 0;
 
 
-	mei_hbm_reset(dev);
+	mei_me_cl_remove_all(dev);
 
 
-	/* count how many ME clients we have */
-	for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
-		dev->me_clients_num++;
+	mei_hbm_idle(dev);
+}
 
 
-	if (dev->me_clients_num == 0)
-		return 0;
+/**
+ * mei_hbm_hdr - construct hbm header
+ *
+ * @hdr: hbm header
+ * @length: payload length
+ */
 
 
-	dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%ld.\n",
-		dev->me_clients_num * sizeof(struct mei_me_client));
-	/* allocate storage for ME clients representation */
-	clients = kcalloc(dev->me_clients_num,
-			sizeof(struct mei_me_client), GFP_KERNEL);
-	if (!clients) {
-		dev_err(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
-		return -ENOMEM;
-	}
-	dev->me_clients = clients;
-	return 0;
+static inline void mei_hbm_hdr(struct mei_msg_hdr *hdr, size_t length)
+{
+	hdr->host_addr = 0;
+	hdr->me_addr = 0;
+	hdr->length = length;
+	hdr->msg_complete = 1;
+	hdr->reserved = 0;
 }
 }
 
 
 /**
 /**
  * mei_hbm_cl_hdr - construct client hbm header
  * mei_hbm_cl_hdr - construct client hbm header
  *
  *
- * @cl: - client
+ * @cl: client
  * @hbm_cmd: host bus message command
  * @hbm_cmd: host bus message command
  * @buf: buffer for cl header
  * @buf: buffer for cl header
  * @len: buffer length
  * @len: buffer length
@@ -142,38 +170,87 @@ void mei_hbm_cl_hdr(struct mei_cl *cl, u8 hbm_cmd, void *buf, size_t len)
 }
 }
 
 
 /**
 /**
- * mei_hbm_cl_addr_equal - tells if they have the same address
+ * mei_hbm_cl_write - write simple hbm client message
  *
  *
- * @cl: - client
- * @buf: buffer with cl header
+ * @dev: the device structure
+ * @cl: client
+ * @hbm_cmd: host bus message command
+ * @len: buffer length
  *
  *
- * returns true if addresses are the same
+ * Return: 0 on success, <0 on failure.
  */
  */
 static inline
 static inline
-bool mei_hbm_cl_addr_equal(struct mei_cl *cl, void *buf)
+int mei_hbm_cl_write(struct mei_device *dev,
+		     struct mei_cl *cl, u8 hbm_cmd, size_t len)
+{
+	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
+
+	mei_hbm_hdr(mei_hdr, len);
+	mei_hbm_cl_hdr(cl, hbm_cmd, dev->wr_msg.data, len);
+
+	return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+}
+
+/**
+ * mei_hbm_cl_addr_equal - check if the client's and
+ *	the message address match
+ *
+ * @cl: client
+ * @cmd: hbm client message
+ *
+ * Return: true if addresses are the same
+ */
+static inline
+bool mei_hbm_cl_addr_equal(struct mei_cl *cl, struct mei_hbm_cl_cmd *cmd)
 {
 {
-	struct mei_hbm_cl_cmd *cmd = buf;
 	return cl->host_client_id == cmd->host_addr &&
 	return cl->host_client_id == cmd->host_addr &&
 		cl->me_client_id == cmd->me_addr;
 		cl->me_client_id == cmd->me_addr;
 }
 }
 
 
+/**
+ * mei_hbm_cl_find_by_cmd - find recipient client
+ *
+ * @dev: the device structure
+ * @buf: a buffer with hbm cl command
+ *
+ * Return: the recipient client or NULL if not found
+ */
+static inline
+struct mei_cl *mei_hbm_cl_find_by_cmd(struct mei_device *dev, void *buf)
+{
+	struct mei_hbm_cl_cmd *cmd = (struct mei_hbm_cl_cmd *)buf;
+	struct mei_cl *cl;
+
+	list_for_each_entry(cl, &dev->file_list, link)
+		if (mei_hbm_cl_addr_equal(cl, cmd))
+			return cl;
+	return NULL;
+}
+
 
 
+/**
+ * mei_hbm_start_wait - wait for start response message.
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success and < 0 on failure
+ */
 int mei_hbm_start_wait(struct mei_device *dev)
 int mei_hbm_start_wait(struct mei_device *dev)
 {
 {
 	int ret;
 	int ret;
-	if (dev->hbm_state > MEI_HBM_START)
+
+	if (dev->hbm_state > MEI_HBM_STARTING)
 		return 0;
 		return 0;
 
 
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
-	ret = wait_event_interruptible_timeout(dev->wait_recvd_msg,
-			dev->hbm_state == MEI_HBM_IDLE ||
-			dev->hbm_state >= MEI_HBM_STARTED,
+	ret = wait_event_timeout(dev->wait_hbm_start,
+			dev->hbm_state != MEI_HBM_STARTING,
 			mei_secs_to_jiffies(MEI_HBM_TIMEOUT));
 			mei_secs_to_jiffies(MEI_HBM_TIMEOUT));
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 
 
-	if (ret <= 0 && (dev->hbm_state <= MEI_HBM_START)) {
+	if (ret == 0 && (dev->hbm_state <= MEI_HBM_STARTING)) {
 		dev->hbm_state = MEI_HBM_IDLE;
 		dev->hbm_state = MEI_HBM_IDLE;
-		dev_err(&dev->pdev->dev, "waiting for mei start failed\n");
+		dev_err(dev->dev, "waiting for mei start failed\n");
 		return -ETIME;
 		return -ETIME;
 	}
 	}
 	return 0;
 	return 0;
@@ -184,7 +261,7 @@ int mei_hbm_start_wait(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 on success and < 0 on failure
+ * Return: 0 on success and < 0 on failure
  */
  */
 int mei_hbm_start_req(struct mei_device *dev)
 int mei_hbm_start_req(struct mei_device *dev)
 {
 {
@@ -193,6 +270,8 @@ int mei_hbm_start_req(struct mei_device *dev)
 	const size_t len = sizeof(struct hbm_host_version_request);
 	const size_t len = sizeof(struct hbm_host_version_request);
 	int ret;
 	int ret;
 
 
+	mei_hbm_reset(dev);
+
 	mei_hbm_hdr(mei_hdr, len);
 	mei_hbm_hdr(mei_hdr, len);
 
 
 	/* host start message */
 	/* host start message */
@@ -205,12 +284,12 @@ int mei_hbm_start_req(struct mei_device *dev)
 	dev->hbm_state = MEI_HBM_IDLE;
 	dev->hbm_state = MEI_HBM_IDLE;
 	ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 	ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "version message write failed: ret = %d\n",
+		dev_err(dev->dev, "version message write failed: ret = %d\n",
 			ret);
 			ret);
 		return ret;
 		return ret;
 	}
 	}
 
 
-	dev->hbm_state = MEI_HBM_START;
+	dev->hbm_state = MEI_HBM_STARTING;
 	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
 	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
 	return 0;
 	return 0;
 }
 }
@@ -220,7 +299,7 @@ int mei_hbm_start_req(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 on success and < 0 on failure
+ * Return: 0 on success and < 0 on failure
  */
  */
 static int mei_hbm_enum_clients_req(struct mei_device *dev)
 static int mei_hbm_enum_clients_req(struct mei_device *dev)
 {
 {
@@ -238,7 +317,7 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev)
 
 
 	ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 	ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "enumeration request write failed: ret = %d.\n",
+		dev_err(dev->dev, "enumeration request write failed: ret = %d.\n",
 			ret);
 			ret);
 		return ret;
 		return ret;
 	}
 	}
@@ -247,12 +326,38 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev)
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * mei_hbm_me_cl_add - add new me client to the list
+ *
+ * @dev: the device structure
+ * @res: hbm property response
+ *
+ * Return: 0 on success and -ENOMEM on allocation failure
+ */
+
+static int mei_hbm_me_cl_add(struct mei_device *dev,
+			     struct hbm_props_response *res)
+{
+	struct mei_me_client *me_cl;
+
+	me_cl = kzalloc(sizeof(struct mei_me_client), GFP_KERNEL);
+	if (!me_cl)
+		return -ENOMEM;
+
+	me_cl->props = res->client_properties;
+	me_cl->client_id = res->me_addr;
+	me_cl->mei_flow_ctrl_creds = 0;
+
+	list_add(&me_cl->list, &dev->me_clients);
+	return 0;
+}
+
 /**
 /**
  * mei_hbm_prop_req - request property for a single client
  * mei_hbm_prop_req - request property for a single client
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 on success and < 0 on failure
+ * Return: 0 on success and < 0 on failure
  */
  */
 
 
 static int mei_hbm_prop_req(struct mei_device *dev)
 static int mei_hbm_prop_req(struct mei_device *dev)
@@ -262,11 +367,8 @@ static int mei_hbm_prop_req(struct mei_device *dev)
 	struct hbm_props_request *prop_req;
 	struct hbm_props_request *prop_req;
 	const size_t len = sizeof(struct hbm_props_request);
 	const size_t len = sizeof(struct hbm_props_request);
 	unsigned long next_client_index;
 	unsigned long next_client_index;
-	unsigned long client_num;
 	int ret;
 	int ret;
 
 
-	client_num = dev->me_client_presentation_num;
-
 	next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
 	next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
 					  dev->me_client_index);
 					  dev->me_client_index);
 
 
@@ -278,21 +380,17 @@ static int mei_hbm_prop_req(struct mei_device *dev)
 		return 0;
 		return 0;
 	}
 	}
 
 
-	dev->me_clients[client_num].client_id = next_client_index;
-	dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
-
 	mei_hbm_hdr(mei_hdr, len);
 	mei_hbm_hdr(mei_hdr, len);
 	prop_req = (struct hbm_props_request *)dev->wr_msg.data;
 	prop_req = (struct hbm_props_request *)dev->wr_msg.data;
 
 
 	memset(prop_req, 0, sizeof(struct hbm_props_request));
 	memset(prop_req, 0, sizeof(struct hbm_props_request));
 
 
-
 	prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
 	prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
-	prop_req->address = next_client_index;
+	prop_req->me_addr = next_client_index;
 
 
 	ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 	ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "properties request write failed: ret = %d\n",
+		dev_err(dev->dev, "properties request write failed: ret = %d\n",
 			ret);
 			ret);
 		return ret;
 		return ret;
 	}
 	}
@@ -309,7 +407,8 @@ static int mei_hbm_prop_req(struct mei_device *dev)
  * @dev: the device structure
  * @dev: the device structure
  * @pg_cmd: the pg command code
  * @pg_cmd: the pg command code
  *
  *
- * This function returns -EIO on write failure
+ * Return: -EIO on write failure
+ *         -EOPNOTSUPP if the operation is not supported by the protocol
  */
  */
 int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
 int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
 {
 {
@@ -318,6 +417,9 @@ int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
 	const size_t len = sizeof(struct hbm_power_gate);
 	const size_t len = sizeof(struct hbm_power_gate);
 	int ret;
 	int ret;
 
 
+	if (!dev->hbm_f_pg_supported)
+		return -EOPNOTSUPP;
+
 	mei_hbm_hdr(mei_hdr, len);
 	mei_hbm_hdr(mei_hdr, len);
 
 
 	req = (struct hbm_power_gate *)dev->wr_msg.data;
 	req = (struct hbm_power_gate *)dev->wr_msg.data;
@@ -326,7 +428,7 @@ int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
 
 
 	ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 	ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 	if (ret)
 	if (ret)
-		dev_err(&dev->pdev->dev, "power gate command write failed.\n");
+		dev_err(dev->dev, "power gate command write failed.\n");
 	return ret;
 	return ret;
 }
 }
 EXPORT_SYMBOL_GPL(mei_hbm_pg);
 EXPORT_SYMBOL_GPL(mei_hbm_pg);
@@ -334,10 +436,9 @@ EXPORT_SYMBOL_GPL(mei_hbm_pg);
 /**
 /**
  * mei_hbm_stop_req - send stop request message
  * mei_hbm_stop_req - send stop request message
  *
  *
- * @dev - mei device
- * @cl: client info
+ * @dev: mei device
  *
  *
- * This function returns -EIO on write failure
+ * Return: -EIO on write failure
  */
  */
 static int mei_hbm_stop_req(struct mei_device *dev)
 static int mei_hbm_stop_req(struct mei_device *dev)
 {
 {
@@ -361,19 +462,14 @@ static int mei_hbm_stop_req(struct mei_device *dev)
  * @dev: the device structure
  * @dev: the device structure
  * @cl: client info
  * @cl: client info
  *
  *
- * This function returns -EIO on write failure
+ * Return: -EIO on write failure
  */
  */
 int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
 int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
 {
 {
-	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
 	const size_t len = sizeof(struct hbm_flow_control);
 	const size_t len = sizeof(struct hbm_flow_control);
 
 
-	mei_hbm_hdr(mei_hdr, len);
-	mei_hbm_cl_hdr(cl, MEI_FLOW_CONTROL_CMD, dev->wr_msg.data, len);
-
 	cl_dbg(dev, cl, "sending flow control\n");
 	cl_dbg(dev, cl, "sending flow control\n");
-
-	return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+	return mei_hbm_cl_write(dev, cl, MEI_FLOW_CONTROL_CMD, len);
 }
 }
 
 
 /**
 /**
@@ -382,31 +478,26 @@ int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
  * @dev: the device structure
  * @dev: the device structure
  * @flow: flow control.
  * @flow: flow control.
  *
  *
- * return 0 on success, < 0 otherwise
+ * Return: 0 on success, < 0 otherwise
  */
  */
 static int mei_hbm_add_single_flow_creds(struct mei_device *dev,
 static int mei_hbm_add_single_flow_creds(struct mei_device *dev,
 				  struct hbm_flow_control *flow)
 				  struct hbm_flow_control *flow)
 {
 {
 	struct mei_me_client *me_cl;
 	struct mei_me_client *me_cl;
-	int id;
 
 
-	id = mei_me_cl_by_id(dev, flow->me_addr);
-	if (id < 0) {
-		dev_err(&dev->pdev->dev, "no such me client %d\n",
+	me_cl = mei_me_cl_by_id(dev, flow->me_addr);
+	if (!me_cl) {
+		dev_err(dev->dev, "no such me client %d\n",
 			flow->me_addr);
 			flow->me_addr);
-		return id;
+		return -ENOENT;
 	}
 	}
 
 
-	me_cl = &dev->me_clients[id];
-	if (me_cl->props.single_recv_buf) {
-		me_cl->mei_flow_ctrl_creds++;
-		dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
-		    flow->me_addr);
-		dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
-		    me_cl->mei_flow_ctrl_creds);
-	} else {
-		BUG();	/* error in flow control */
-	}
+	if (WARN_ON(me_cl->props.single_recv_buf == 0))
+		return -EINVAL;
+
+	me_cl->mei_flow_ctrl_creds++;
+	dev_dbg(dev->dev, "recv flow ctrl msg ME %d (single) creds = %d.\n",
+	    flow->me_addr, me_cl->mei_flow_ctrl_creds);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -418,7 +509,7 @@ static int mei_hbm_add_single_flow_creds(struct mei_device *dev,
  * @flow_control: flow control response bus message
  * @flow_control: flow control response bus message
  */
  */
 static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
 static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
-		struct hbm_flow_control *flow_control)
+					struct hbm_flow_control *flow_control)
 {
 {
 	struct mei_cl *cl;
 	struct mei_cl *cl;
 
 
@@ -428,16 +519,11 @@ static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
 		return;
 		return;
 	}
 	}
 
 
-	/* normal connection */
-	list_for_each_entry(cl, &dev->file_list, link) {
-		if (mei_hbm_cl_addr_equal(cl, flow_control)) {
-			cl->mei_flow_ctrl_creds++;
-			dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
-				flow_control->host_addr, flow_control->me_addr);
-			dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
-				    cl->mei_flow_ctrl_creds);
-				break;
-		}
+	cl = mei_hbm_cl_find_by_cmd(dev, flow_control);
+	if (cl) {
+		cl->mei_flow_ctrl_creds++;
+		cl_dbg(dev, cl, "flow control creds = %d.\n",
+				cl->mei_flow_ctrl_creds);
 	}
 	}
 }
 }
 
 
@@ -448,17 +534,13 @@ static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
  * @dev: the device structure
  * @dev: the device structure
  * @cl: a client to disconnect from
  * @cl: a client to disconnect from
  *
  *
- * This function returns -EIO on write failure
+ * Return: -EIO on write failure
  */
  */
 int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
 int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
 {
 {
-	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
 	const size_t len = sizeof(struct hbm_client_connect_request);
 	const size_t len = sizeof(struct hbm_client_connect_request);
 
 
-	mei_hbm_hdr(mei_hdr, len);
-	mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_REQ_CMD, dev->wr_msg.data, len);
-
-	return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_REQ_CMD, len);
 }
 }
 
 
 /**
 /**
@@ -467,53 +549,34 @@ int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
  * @dev: the device structure
  * @dev: the device structure
  * @cl: a client to disconnect from
  * @cl: a client to disconnect from
  *
  *
- * This function returns -EIO on write failure
+ * Return: -EIO on write failure
  */
  */
 int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
 int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
 {
 {
-	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
 	const size_t len = sizeof(struct hbm_client_connect_response);
 	const size_t len = sizeof(struct hbm_client_connect_response);
 
 
-	mei_hbm_hdr(mei_hdr, len);
-	mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD, dev->wr_msg.data, len);
-
-	return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_RES_CMD, len);
 }
 }
 
 
 /**
 /**
- * mei_hbm_cl_disconnect_res - disconnect response from ME
+ * mei_hbm_cl_disconnect_res - update the client state according
+ *       disconnect response
  *
  *
- * @dev: the device structure
- * @rs: disconnect response bus message
+ * @cl: mei host client
+ * @cmd: disconnect client response host bus message
  */
  */
-static void mei_hbm_cl_disconnect_res(struct mei_device *dev,
-		struct hbm_client_connect_response *rs)
+static void mei_hbm_cl_disconnect_res(struct mei_cl *cl,
+				      struct mei_hbm_cl_cmd *cmd)
 {
 {
-	struct mei_cl *cl;
-	struct mei_cl_cb *cb, *next;
+	struct hbm_client_connect_response *rs =
+		(struct hbm_client_connect_response *)cmd;
 
 
-	dev_dbg(&dev->pdev->dev, "hbm: disconnect response cl:host=%02d me=%02d status=%d\n",
+	dev_dbg(cl->dev->dev, "hbm: disconnect response cl:host=%02d me=%02d status=%d\n",
 			rs->me_addr, rs->host_addr, rs->status);
 			rs->me_addr, rs->host_addr, rs->status);
 
 
-	list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) {
-		cl = cb->cl;
-
-		/* this should not happen */
-		if (WARN_ON(!cl)) {
-			list_del(&cb->list);
-			return;
-		}
-
-		if (mei_hbm_cl_addr_equal(cl, rs)) {
-			list_del(&cb->list);
-			if (rs->status == MEI_CL_DISCONN_SUCCESS)
-				cl->state = MEI_FILE_DISCONNECTED;
-
-			cl->status = 0;
-			cl->timer_count = 0;
-			break;
-		}
-	}
+	if (rs->status == MEI_CL_DISCONN_SUCCESS)
+		cl->state = MEI_FILE_DISCONNECTED;
+	cl->status = 0;
 }
 }
 
 
 /**
 /**
@@ -522,38 +585,55 @@ static void mei_hbm_cl_disconnect_res(struct mei_device *dev,
  * @dev: the device structure
  * @dev: the device structure
  * @cl: a client to connect to
  * @cl: a client to connect to
  *
  *
- * returns -EIO on write failure
+ * Return: -EIO on write failure
  */
  */
 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
 {
 {
-	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
 	const size_t len = sizeof(struct hbm_client_connect_request);
 	const size_t len = sizeof(struct hbm_client_connect_request);
 
 
-	mei_hbm_hdr(mei_hdr, len);
-	mei_hbm_cl_hdr(cl, CLIENT_CONNECT_REQ_CMD, dev->wr_msg.data, len);
+	return mei_hbm_cl_write(dev, cl, CLIENT_CONNECT_REQ_CMD, len);
+}
 
 
-	return mei_write_message(dev, mei_hdr,  dev->wr_msg.data);
+/**
+ * mei_hbm_cl_connect_res - update the client state according
+ *        connection response
+ *
+ * @cl: mei host client
+ * @cmd: connect client response host bus message
+ */
+static void mei_hbm_cl_connect_res(struct mei_cl *cl,
+				   struct mei_hbm_cl_cmd *cmd)
+{
+	struct hbm_client_connect_response *rs =
+		(struct hbm_client_connect_response *)cmd;
+
+	dev_dbg(cl->dev->dev, "hbm: connect response cl:host=%02d me=%02d status=%s\n",
+			rs->me_addr, rs->host_addr,
+			mei_cl_conn_status_str(rs->status));
+
+	if (rs->status == MEI_CL_CONN_SUCCESS)
+		cl->state = MEI_FILE_CONNECTED;
+	else
+		cl->state = MEI_FILE_DISCONNECTED;
+	cl->status = mei_cl_conn_status_to_errno(rs->status);
 }
 }
 
 
 /**
 /**
- * mei_hbm_cl_connect_res - connect response from the ME
+ * mei_hbm_cl_res - process hbm response received on behalf
+ *         an client
  *
  *
  * @dev: the device structure
  * @dev: the device structure
- * @rs: connect response bus message
+ * @rs:  hbm client message
+ * @fop_type: file operation type
  */
  */
-static void mei_hbm_cl_connect_res(struct mei_device *dev,
-		struct hbm_client_connect_response *rs)
+static void mei_hbm_cl_res(struct mei_device *dev,
+			   struct mei_hbm_cl_cmd *rs,
+			   enum mei_cb_file_ops fop_type)
 {
 {
-
 	struct mei_cl *cl;
 	struct mei_cl *cl;
 	struct mei_cl_cb *cb, *next;
 	struct mei_cl_cb *cb, *next;
 
 
-	dev_dbg(&dev->pdev->dev, "hbm: connect response cl:host=%02d me=%02d status=%s\n",
-			rs->me_addr, rs->host_addr,
-			mei_cl_conn_status_str(rs->status));
-
 	cl = NULL;
 	cl = NULL;
-
 	list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) {
 	list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) {
 
 
 		cl = cb->cl;
 		cl = cb->cl;
@@ -563,7 +643,7 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev,
 			continue;
 			continue;
 		}
 		}
 
 
-		if (cb->fop_type !=  MEI_FOP_CONNECT)
+		if (cb->fop_type != fop_type)
 			continue;
 			continue;
 
 
 		if (mei_hbm_cl_addr_equal(cl, rs)) {
 		if (mei_hbm_cl_addr_equal(cl, rs)) {
@@ -575,12 +655,19 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev,
 	if (!cl)
 	if (!cl)
 		return;
 		return;
 
 
+	switch (fop_type) {
+	case MEI_FOP_CONNECT:
+		mei_hbm_cl_connect_res(cl, rs);
+		break;
+	case MEI_FOP_DISCONNECT:
+		mei_hbm_cl_disconnect_res(cl, rs);
+		break;
+	default:
+		return;
+	}
+
 	cl->timer_count = 0;
 	cl->timer_count = 0;
-	if (rs->status == MEI_CL_CONN_SUCCESS)
-		cl->state = MEI_FILE_CONNECTED;
-	else
-		cl->state = MEI_FILE_DISCONNECTED;
-	cl->status = mei_cl_conn_status_to_errno(rs->status);
+	wake_up(&cl->wait);
 }
 }
 
 
 
 
@@ -591,7 +678,7 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev,
  * @dev: the device structure.
  * @dev: the device structure.
  * @disconnect_req: disconnect request bus message from the me
  * @disconnect_req: disconnect request bus message from the me
  *
  *
- * returns -ENOMEM on allocation failure
+ * Return: -ENOMEM on allocation failure
  */
  */
 static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
 static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
 		struct hbm_client_connect_request *disconnect_req)
 		struct hbm_client_connect_request *disconnect_req)
@@ -599,34 +686,46 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
 	struct mei_cl *cl;
 	struct mei_cl *cl;
 	struct mei_cl_cb *cb;
 	struct mei_cl_cb *cb;
 
 
-	list_for_each_entry(cl, &dev->file_list, link) {
-		if (mei_hbm_cl_addr_equal(cl, disconnect_req)) {
-			dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
-					disconnect_req->host_addr,
-					disconnect_req->me_addr);
-			cl->state = MEI_FILE_DISCONNECTED;
-			cl->timer_count = 0;
-
-			cb = mei_io_cb_init(cl, NULL);
-			if (!cb)
-				return -ENOMEM;
-			cb->fop_type = MEI_FOP_DISCONNECT_RSP;
-			cl_dbg(dev, cl, "add disconnect response as first\n");
-			list_add(&cb->list, &dev->ctrl_wr_list.list);
+	cl = mei_hbm_cl_find_by_cmd(dev, disconnect_req);
+	if (cl) {
+		cl_dbg(dev, cl, "disconnect request received\n");
+		cl->state = MEI_FILE_DISCONNECTED;
+		cl->timer_count = 0;
 
 
-			break;
-		}
+		cb = mei_io_cb_init(cl, NULL);
+		if (!cb)
+			return -ENOMEM;
+		cb->fop_type = MEI_FOP_DISCONNECT_RSP;
+		cl_dbg(dev, cl, "add disconnect response as first\n");
+		list_add(&cb->list, &dev->ctrl_wr_list.list);
 	}
 	}
 	return 0;
 	return 0;
 }
 }
 
 
+/**
+ * mei_hbm_config_features - check what hbm features and commands
+ *        are supported by the fw
+ *
+ * @dev: the device structure
+ */
+static void mei_hbm_config_features(struct mei_device *dev)
+{
+	/* Power Gating Isolation Support */
+	dev->hbm_f_pg_supported = 0;
+	if (dev->version.major_version > HBM_MAJOR_VERSION_PGI)
+		dev->hbm_f_pg_supported = 1;
+
+	if (dev->version.major_version == HBM_MAJOR_VERSION_PGI &&
+	    dev->version.minor_version >= HBM_MINOR_VERSION_PGI)
+		dev->hbm_f_pg_supported = 1;
+}
 
 
 /**
 /**
  * mei_hbm_version_is_supported - checks whether the driver can
  * mei_hbm_version_is_supported - checks whether the driver can
  *     support the hbm version of the device
  *     support the hbm version of the device
  *
  *
  * @dev: the device structure
  * @dev: the device structure
- * returns true if driver can support hbm version of the device
+ * Return: true if driver can support hbm version of the device
  */
  */
 bool mei_hbm_version_is_supported(struct mei_device *dev)
 bool mei_hbm_version_is_supported(struct mei_device *dev)
 {
 {
@@ -640,44 +739,44 @@ bool mei_hbm_version_is_supported(struct mei_device *dev)
  * handle the read bus message cmd processing.
  * handle the read bus message cmd processing.
  *
  *
  * @dev: the device structure
  * @dev: the device structure
- * @mei_hdr: header of bus message
+ * @hdr: header of bus message
  *
  *
- * returns 0 on success and < 0 on failure
+ * Return: 0 on success and < 0 on failure
  */
  */
 int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 {
 {
 	struct mei_bus_message *mei_msg;
 	struct mei_bus_message *mei_msg;
-	struct mei_me_client *me_client;
 	struct hbm_host_version_response *version_res;
 	struct hbm_host_version_response *version_res;
-	struct hbm_client_connect_response *connect_res;
-	struct hbm_client_connect_response *disconnect_res;
-	struct hbm_client_connect_request *disconnect_req;
-	struct hbm_flow_control *flow_control;
 	struct hbm_props_response *props_res;
 	struct hbm_props_response *props_res;
 	struct hbm_host_enum_response *enum_res;
 	struct hbm_host_enum_response *enum_res;
 
 
+	struct mei_hbm_cl_cmd *cl_cmd;
+	struct hbm_client_connect_request *disconnect_req;
+	struct hbm_flow_control *flow_control;
+
 	/* read the message to our buffer */
 	/* read the message to our buffer */
 	BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf));
 	BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf));
 	mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
 	mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
 	mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
 	mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
+	cl_cmd  = (struct mei_hbm_cl_cmd *)mei_msg;
 
 
 	/* ignore spurious message and prevent reset nesting
 	/* ignore spurious message and prevent reset nesting
 	 * hbm is put to idle during system reset
 	 * hbm is put to idle during system reset
 	 */
 	 */
 	if (dev->hbm_state == MEI_HBM_IDLE) {
 	if (dev->hbm_state == MEI_HBM_IDLE) {
-		dev_dbg(&dev->pdev->dev, "hbm: state is idle ignore spurious messages\n");
+		dev_dbg(dev->dev, "hbm: state is idle ignore spurious messages\n");
 		return 0;
 		return 0;
 	}
 	}
 
 
 	switch (mei_msg->hbm_cmd) {
 	switch (mei_msg->hbm_cmd) {
 	case HOST_START_RES_CMD:
 	case HOST_START_RES_CMD:
-		dev_dbg(&dev->pdev->dev, "hbm: start: response message received.\n");
+		dev_dbg(dev->dev, "hbm: start: response message received.\n");
 
 
 		dev->init_clients_timer = 0;
 		dev->init_clients_timer = 0;
 
 
 		version_res = (struct hbm_host_version_response *)mei_msg;
 		version_res = (struct hbm_host_version_response *)mei_msg;
 
 
-		dev_dbg(&dev->pdev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n",
+		dev_dbg(dev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n",
 				HBM_MAJOR_VERSION, HBM_MINOR_VERSION,
 				HBM_MAJOR_VERSION, HBM_MINOR_VERSION,
 				version_res->me_max_version.major_version,
 				version_res->me_max_version.major_version,
 				version_res->me_max_version.minor_version);
 				version_res->me_max_version.minor_version);
@@ -693,19 +792,21 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 		}
 		}
 
 
 		if (!mei_hbm_version_is_supported(dev)) {
 		if (!mei_hbm_version_is_supported(dev)) {
-			dev_warn(&dev->pdev->dev, "hbm: start: version mismatch - stopping the driver.\n");
+			dev_warn(dev->dev, "hbm: start: version mismatch - stopping the driver.\n");
 
 
 			dev->hbm_state = MEI_HBM_STOPPED;
 			dev->hbm_state = MEI_HBM_STOPPED;
 			if (mei_hbm_stop_req(dev)) {
 			if (mei_hbm_stop_req(dev)) {
-				dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n");
+				dev_err(dev->dev, "hbm: start: failed to send stop request\n");
 				return -EIO;
 				return -EIO;
 			}
 			}
 			break;
 			break;
 		}
 		}
 
 
+		mei_hbm_config_features(dev);
+
 		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
 		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
-		    dev->hbm_state != MEI_HBM_START) {
-			dev_err(&dev->pdev->dev, "hbm: start: state mismatch, [%d, %d]\n",
+		    dev->hbm_state != MEI_HBM_STARTING) {
+			dev_err(dev->dev, "hbm: start: state mismatch, [%d, %d]\n",
 				dev->dev_state, dev->hbm_state);
 				dev->dev_state, dev->hbm_state);
 			return -EPROTO;
 			return -EPROTO;
 		}
 		}
@@ -713,45 +814,39 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 		dev->hbm_state = MEI_HBM_STARTED;
 		dev->hbm_state = MEI_HBM_STARTED;
 
 
 		if (mei_hbm_enum_clients_req(dev)) {
 		if (mei_hbm_enum_clients_req(dev)) {
-			dev_err(&dev->pdev->dev, "hbm: start: failed to send enumeration request\n");
+			dev_err(dev->dev, "hbm: start: failed to send enumeration request\n");
 			return -EIO;
 			return -EIO;
 		}
 		}
 
 
-		wake_up_interruptible(&dev->wait_recvd_msg);
+		wake_up(&dev->wait_hbm_start);
 		break;
 		break;
 
 
 	case CLIENT_CONNECT_RES_CMD:
 	case CLIENT_CONNECT_RES_CMD:
-		dev_dbg(&dev->pdev->dev, "hbm: client connect response: message received.\n");
-
-		connect_res = (struct hbm_client_connect_response *) mei_msg;
-		mei_hbm_cl_connect_res(dev, connect_res);
-		wake_up(&dev->wait_recvd_msg);
+		dev_dbg(dev->dev, "hbm: client connect response: message received.\n");
+		mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_CONNECT);
 		break;
 		break;
 
 
 	case CLIENT_DISCONNECT_RES_CMD:
 	case CLIENT_DISCONNECT_RES_CMD:
-		dev_dbg(&dev->pdev->dev, "hbm: client disconnect response: message received.\n");
-
-		disconnect_res = (struct hbm_client_connect_response *) mei_msg;
-		mei_hbm_cl_disconnect_res(dev, disconnect_res);
-		wake_up(&dev->wait_recvd_msg);
+		dev_dbg(dev->dev, "hbm: client disconnect response: message received.\n");
+		mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_DISCONNECT);
 		break;
 		break;
 
 
 	case MEI_FLOW_CONTROL_CMD:
 	case MEI_FLOW_CONTROL_CMD:
-		dev_dbg(&dev->pdev->dev, "hbm: client flow control response: message received.\n");
+		dev_dbg(dev->dev, "hbm: client flow control response: message received.\n");
 
 
 		flow_control = (struct hbm_flow_control *) mei_msg;
 		flow_control = (struct hbm_flow_control *) mei_msg;
 		mei_hbm_cl_flow_control_res(dev, flow_control);
 		mei_hbm_cl_flow_control_res(dev, flow_control);
 		break;
 		break;
 
 
 	case MEI_PG_ISOLATION_ENTRY_RES_CMD:
 	case MEI_PG_ISOLATION_ENTRY_RES_CMD:
-		dev_dbg(&dev->pdev->dev, "power gate isolation entry response received\n");
+		dev_dbg(dev->dev, "power gate isolation entry response received\n");
 		dev->pg_event = MEI_PG_EVENT_RECEIVED;
 		dev->pg_event = MEI_PG_EVENT_RECEIVED;
 		if (waitqueue_active(&dev->wait_pg))
 		if (waitqueue_active(&dev->wait_pg))
 			wake_up(&dev->wait_pg);
 			wake_up(&dev->wait_pg);
 		break;
 		break;
 
 
 	case MEI_PG_ISOLATION_EXIT_REQ_CMD:
 	case MEI_PG_ISOLATION_EXIT_REQ_CMD:
-		dev_dbg(&dev->pdev->dev, "power gate isolation exit request received\n");
+		dev_dbg(dev->dev, "power gate isolation exit request received\n");
 		dev->pg_event = MEI_PG_EVENT_RECEIVED;
 		dev->pg_event = MEI_PG_EVENT_RECEIVED;
 		if (waitqueue_active(&dev->wait_pg))
 		if (waitqueue_active(&dev->wait_pg))
 			wake_up(&dev->wait_pg);
 			wake_up(&dev->wait_pg);
@@ -761,44 +856,33 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 			* this is HW initiated exit from PG.
 			* this is HW initiated exit from PG.
 			* Start runtime pm resume sequence to exit from PG.
 			* Start runtime pm resume sequence to exit from PG.
 			*/
 			*/
-			pm_request_resume(&dev->pdev->dev);
+			pm_request_resume(dev->dev);
 		break;
 		break;
 
 
 	case HOST_CLIENT_PROPERTIES_RES_CMD:
 	case HOST_CLIENT_PROPERTIES_RES_CMD:
-		dev_dbg(&dev->pdev->dev, "hbm: properties response: message received.\n");
+		dev_dbg(dev->dev, "hbm: properties response: message received.\n");
 
 
 		dev->init_clients_timer = 0;
 		dev->init_clients_timer = 0;
 
 
-		if (dev->me_clients == NULL) {
-			dev_err(&dev->pdev->dev, "hbm: properties response: mei_clients not allocated\n");
+		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
+		    dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
+			dev_err(dev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
+				dev->dev_state, dev->hbm_state);
 			return -EPROTO;
 			return -EPROTO;
 		}
 		}
 
 
 		props_res = (struct hbm_props_response *)mei_msg;
 		props_res = (struct hbm_props_response *)mei_msg;
-		me_client = &dev->me_clients[dev->me_client_presentation_num];
 
 
 		if (props_res->status) {
 		if (props_res->status) {
-			dev_err(&dev->pdev->dev, "hbm: properties response: wrong status = %d\n",
-				props_res->status);
+			dev_err(dev->dev, "hbm: properties response: wrong status = %d %s\n",
+				props_res->status,
+				mei_hbm_status_str(props_res->status));
 			return -EPROTO;
 			return -EPROTO;
 		}
 		}
 
 
-		if (me_client->client_id != props_res->address) {
-			dev_err(&dev->pdev->dev, "hbm: properties response: address mismatch %d ?= %d\n",
-				me_client->client_id, props_res->address);
-			return -EPROTO;
-		}
+		mei_hbm_me_cl_add(dev, props_res);
 
 
-		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
-		    dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
-			dev_err(&dev->pdev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
-				dev->dev_state, dev->hbm_state);
-			return -EPROTO;
-		}
-
-		me_client->props = props_res->client_properties;
 		dev->me_client_index++;
 		dev->me_client_index++;
-		dev->me_client_presentation_num++;
 
 
 		/* request property for the next client */
 		/* request property for the next client */
 		if (mei_hbm_prop_req(dev))
 		if (mei_hbm_prop_req(dev))
@@ -807,7 +891,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 		break;
 		break;
 
 
 	case HOST_ENUM_RES_CMD:
 	case HOST_ENUM_RES_CMD:
-		dev_dbg(&dev->pdev->dev, "hbm: enumeration response: message received\n");
+		dev_dbg(dev->dev, "hbm: enumeration response: message received\n");
 
 
 		dev->init_clients_timer = 0;
 		dev->init_clients_timer = 0;
 
 
@@ -815,20 +899,15 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 		BUILD_BUG_ON(sizeof(dev->me_clients_map)
 		BUILD_BUG_ON(sizeof(dev->me_clients_map)
 				< sizeof(enum_res->valid_addresses));
 				< sizeof(enum_res->valid_addresses));
 		memcpy(dev->me_clients_map, enum_res->valid_addresses,
 		memcpy(dev->me_clients_map, enum_res->valid_addresses,
-			sizeof(enum_res->valid_addresses));
+				sizeof(enum_res->valid_addresses));
 
 
 		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
 		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
 		    dev->hbm_state != MEI_HBM_ENUM_CLIENTS) {
 		    dev->hbm_state != MEI_HBM_ENUM_CLIENTS) {
-			dev_err(&dev->pdev->dev, "hbm: enumeration response: state mismatch, [%d, %d]\n",
+			dev_err(dev->dev, "hbm: enumeration response: state mismatch, [%d, %d]\n",
 				dev->dev_state, dev->hbm_state);
 				dev->dev_state, dev->hbm_state);
 			return -EPROTO;
 			return -EPROTO;
 		}
 		}
 
 
-		if (mei_hbm_me_cl_allocate(dev)) {
-			dev_err(&dev->pdev->dev, "hbm: enumeration response: cannot allocate clients array\n");
-			return -ENOMEM;
-		}
-
 		dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
 		dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
 
 
 		/* first property request */
 		/* first property request */
@@ -838,34 +917,34 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 		break;
 		break;
 
 
 	case HOST_STOP_RES_CMD:
 	case HOST_STOP_RES_CMD:
-		dev_dbg(&dev->pdev->dev, "hbm: stop response: message received\n");
+		dev_dbg(dev->dev, "hbm: stop response: message received\n");
 
 
 		dev->init_clients_timer = 0;
 		dev->init_clients_timer = 0;
 
 
 		if (dev->hbm_state != MEI_HBM_STOPPED) {
 		if (dev->hbm_state != MEI_HBM_STOPPED) {
-			dev_err(&dev->pdev->dev, "hbm: stop response: state mismatch, [%d, %d]\n",
+			dev_err(dev->dev, "hbm: stop response: state mismatch, [%d, %d]\n",
 				dev->dev_state, dev->hbm_state);
 				dev->dev_state, dev->hbm_state);
 			return -EPROTO;
 			return -EPROTO;
 		}
 		}
 
 
 		dev->dev_state = MEI_DEV_POWER_DOWN;
 		dev->dev_state = MEI_DEV_POWER_DOWN;
-		dev_info(&dev->pdev->dev, "hbm: stop response: resetting.\n");
+		dev_info(dev->dev, "hbm: stop response: resetting.\n");
 		/* force the reset */
 		/* force the reset */
 		return -EPROTO;
 		return -EPROTO;
 		break;
 		break;
 
 
 	case CLIENT_DISCONNECT_REQ_CMD:
 	case CLIENT_DISCONNECT_REQ_CMD:
-		dev_dbg(&dev->pdev->dev, "hbm: disconnect request: message received\n");
+		dev_dbg(dev->dev, "hbm: disconnect request: message received\n");
 
 
 		disconnect_req = (struct hbm_client_connect_request *)mei_msg;
 		disconnect_req = (struct hbm_client_connect_request *)mei_msg;
 		mei_hbm_fw_disconnect_req(dev, disconnect_req);
 		mei_hbm_fw_disconnect_req(dev, disconnect_req);
 		break;
 		break;
 
 
 	case ME_STOP_REQ_CMD:
 	case ME_STOP_REQ_CMD:
-		dev_dbg(&dev->pdev->dev, "hbm: stop request: message received\n");
+		dev_dbg(dev->dev, "hbm: stop request: message received\n");
 		dev->hbm_state = MEI_HBM_STOPPED;
 		dev->hbm_state = MEI_HBM_STOPPED;
 		if (mei_hbm_stop_req(dev)) {
 		if (mei_hbm_stop_req(dev)) {
-			dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n");
+			dev_err(dev->dev, "hbm: stop request: failed to send stop request\n");
 			return -EIO;
 			return -EIO;
 		}
 		}
 		break;
 		break;

+ 6 - 11
drivers/misc/mei/hbm.h

@@ -25,29 +25,24 @@ struct mei_cl;
  * enum mei_hbm_state - host bus message protocol state
  * enum mei_hbm_state - host bus message protocol state
  *
  *
  * @MEI_HBM_IDLE : protocol not started
  * @MEI_HBM_IDLE : protocol not started
- * @MEI_HBM_START : start request message was sent
+ * @MEI_HBM_STARTING : start request message was sent
+ * @MEI_HBM_STARTED : start reply message was received
  * @MEI_HBM_ENUM_CLIENTS : enumeration request was sent
  * @MEI_HBM_ENUM_CLIENTS : enumeration request was sent
  * @MEI_HBM_CLIENT_PROPERTIES : acquiring clients properties
  * @MEI_HBM_CLIENT_PROPERTIES : acquiring clients properties
+ * @MEI_HBM_STOPPED : stopping exchange
  */
  */
 enum mei_hbm_state {
 enum mei_hbm_state {
 	MEI_HBM_IDLE = 0,
 	MEI_HBM_IDLE = 0,
-	MEI_HBM_START,
+	MEI_HBM_STARTING,
 	MEI_HBM_STARTED,
 	MEI_HBM_STARTED,
 	MEI_HBM_ENUM_CLIENTS,
 	MEI_HBM_ENUM_CLIENTS,
 	MEI_HBM_CLIENT_PROPERTIES,
 	MEI_HBM_CLIENT_PROPERTIES,
 	MEI_HBM_STOPPED,
 	MEI_HBM_STOPPED,
 };
 };
 
 
-int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr);
+const char *mei_hbm_state_str(enum mei_hbm_state state);
 
 
-static inline void mei_hbm_hdr(struct mei_msg_hdr *hdr, size_t length)
-{
-	hdr->host_addr = 0;
-	hdr->me_addr = 0;
-	hdr->length = length;
-	hdr->msg_complete = 1;
-	hdr->reserved = 0;
-}
+int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr);
 
 
 void mei_hbm_idle(struct mei_device *dev);
 void mei_hbm_idle(struct mei_device *dev);
 void mei_hbm_reset(struct mei_device *dev);
 void mei_hbm_reset(struct mei_device *dev);

+ 126 - 68
drivers/misc/mei/hw-me.c

@@ -28,10 +28,10 @@
 /**
 /**
  * mei_me_reg_read - Reads 32bit data from the mei device
  * mei_me_reg_read - Reads 32bit data from the mei device
  *
  *
- * @dev: the device structure
+ * @hw: the me hardware structure
  * @offset: offset from which to read the data
  * @offset: offset from which to read the data
  *
  *
- * returns register value (u32)
+ * Return: register value (u32)
  */
  */
 static inline u32 mei_me_reg_read(const struct mei_me_hw *hw,
 static inline u32 mei_me_reg_read(const struct mei_me_hw *hw,
 			       unsigned long offset)
 			       unsigned long offset)
@@ -43,7 +43,7 @@ static inline u32 mei_me_reg_read(const struct mei_me_hw *hw,
 /**
 /**
  * mei_me_reg_write - Writes 32bit data to the mei device
  * mei_me_reg_write - Writes 32bit data to the mei device
  *
  *
- * @dev: the device structure
+ * @hw: the me hardware structure
  * @offset: offset from which to write the data
  * @offset: offset from which to write the data
  * @value: register value to write (u32)
  * @value: register value to write (u32)
  */
  */
@@ -59,7 +59,7 @@ static inline void mei_me_reg_write(const struct mei_me_hw *hw,
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns ME_CB_RW register value (u32)
+ * Return: ME_CB_RW register value (u32)
  */
  */
 static u32 mei_me_mecbrw_read(const struct mei_device *dev)
 static u32 mei_me_mecbrw_read(const struct mei_device *dev)
 {
 {
@@ -68,9 +68,9 @@ static u32 mei_me_mecbrw_read(const struct mei_device *dev)
 /**
 /**
  * mei_me_mecsr_read - Reads 32bit data from the ME CSR
  * mei_me_mecsr_read - Reads 32bit data from the ME CSR
  *
  *
- * @dev: the device structure
+ * @hw: the me hardware structure
  *
  *
- * returns ME_CSR_HA register value (u32)
+ * Return: ME_CSR_HA register value (u32)
  */
  */
 static inline u32 mei_me_mecsr_read(const struct mei_me_hw *hw)
 static inline u32 mei_me_mecsr_read(const struct mei_me_hw *hw)
 {
 {
@@ -80,9 +80,9 @@ static inline u32 mei_me_mecsr_read(const struct mei_me_hw *hw)
 /**
 /**
  * mei_hcsr_read - Reads 32bit data from the host CSR
  * mei_hcsr_read - Reads 32bit data from the host CSR
  *
  *
- * @dev: the device structure
+ * @hw: the me hardware structure
  *
  *
- * returns H_CSR register value (u32)
+ * Return: H_CSR register value (u32)
  */
  */
 static inline u32 mei_hcsr_read(const struct mei_me_hw *hw)
 static inline u32 mei_hcsr_read(const struct mei_me_hw *hw)
 {
 {
@@ -93,7 +93,8 @@ static inline u32 mei_hcsr_read(const struct mei_me_hw *hw)
  * mei_hcsr_set - writes H_CSR register to the mei device,
  * mei_hcsr_set - writes H_CSR register to the mei device,
  * and ignores the H_IS bit for it is write-one-to-zero.
  * and ignores the H_IS bit for it is write-one-to-zero.
  *
  *
- * @dev: the device structure
+ * @hw: the me hardware structure
+ * @hcsr: new register value
  */
  */
 static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr)
 static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr)
 {
 {
@@ -101,6 +102,36 @@ static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr)
 	mei_me_reg_write(hw, H_CSR, hcsr);
 	mei_me_reg_write(hw, H_CSR, hcsr);
 }
 }
 
 
+/**
+ * mei_me_fw_status - read fw status register from pci config space
+ *
+ * @dev: mei device
+ * @fw_status: fw status register values
+ *
+ * Return: 0 on success, error otherwise
+ */
+static int mei_me_fw_status(struct mei_device *dev,
+			    struct mei_fw_status *fw_status)
+{
+	struct pci_dev *pdev = to_pci_dev(dev->dev);
+	struct mei_me_hw *hw = to_me_hw(dev);
+	const struct mei_fw_status *fw_src = &hw->cfg->fw_status;
+	int ret;
+	int i;
+
+	if (!fw_status)
+		return -EINVAL;
+
+	fw_status->count = fw_src->count;
+	for (i = 0; i < fw_src->count && i < MEI_FW_STATUS_MAX; i++) {
+		ret = pci_read_config_dword(pdev,
+			fw_src->status[i], &fw_status->status[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
 
 
 /**
 /**
  * mei_me_hw_config - configure hw dependent settings
  * mei_me_hw_config - configure hw dependent settings
@@ -121,17 +152,19 @@ static void mei_me_hw_config(struct mei_device *dev)
  * mei_me_pg_state  - translate internal pg state
  * mei_me_pg_state  - translate internal pg state
  *   to the mei power gating state
  *   to the mei power gating state
  *
  *
- * @hw -  me hardware
- * returns: MEI_PG_OFF if aliveness is on and MEI_PG_ON otherwise
+ * @dev:  mei device
+ *
+ * Return: MEI_PG_OFF if aliveness is on and MEI_PG_ON otherwise
  */
  */
 static inline enum mei_pg_state mei_me_pg_state(struct mei_device *dev)
 static inline enum mei_pg_state mei_me_pg_state(struct mei_device *dev)
 {
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	struct mei_me_hw *hw = to_me_hw(dev);
+
 	return hw->pg_state;
 	return hw->pg_state;
 }
 }
 
 
 /**
 /**
- * mei_clear_interrupts - clear and stop interrupts
+ * mei_me_intr_clear - clear and stop interrupts
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  */
  */
@@ -139,6 +172,7 @@ static void mei_me_intr_clear(struct mei_device *dev)
 {
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr = mei_hcsr_read(hw);
 	u32 hcsr = mei_hcsr_read(hw);
+
 	if ((hcsr & H_IS) == H_IS)
 	if ((hcsr & H_IS) == H_IS)
 		mei_me_reg_write(hw, H_CSR, hcsr);
 		mei_me_reg_write(hw, H_CSR, hcsr);
 }
 }
@@ -151,12 +185,13 @@ static void mei_me_intr_enable(struct mei_device *dev)
 {
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr = mei_hcsr_read(hw);
 	u32 hcsr = mei_hcsr_read(hw);
+
 	hcsr |= H_IE;
 	hcsr |= H_IE;
 	mei_hcsr_set(hw, hcsr);
 	mei_hcsr_set(hw, hcsr);
 }
 }
 
 
 /**
 /**
- * mei_disable_interrupts - disables mei device interrupts
+ * mei_me_intr_disable - disables mei device interrupts
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  */
  */
@@ -164,6 +199,7 @@ static void mei_me_intr_disable(struct mei_device *dev)
 {
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr = mei_hcsr_read(hw);
 	u32 hcsr = mei_hcsr_read(hw);
+
 	hcsr  &= ~H_IE;
 	hcsr  &= ~H_IE;
 	mei_hcsr_set(hw, hcsr);
 	mei_hcsr_set(hw, hcsr);
 }
 }
@@ -190,6 +226,8 @@ static void mei_me_hw_reset_release(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  * @intr_enable: if interrupt should be enabled after reset.
  * @intr_enable: if interrupt should be enabled after reset.
+ *
+ * Return: always 0
  */
  */
 static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 {
 {
@@ -213,10 +251,10 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 	hcsr = mei_hcsr_read(hw);
 	hcsr = mei_hcsr_read(hw);
 
 
 	if ((hcsr & H_RST) == 0)
 	if ((hcsr & H_RST) == 0)
-		dev_warn(&dev->pdev->dev, "H_RST is not set = 0x%08X", hcsr);
+		dev_warn(dev->dev, "H_RST is not set = 0x%08X", hcsr);
 
 
 	if ((hcsr & H_RDY) == H_RDY)
 	if ((hcsr & H_RDY) == H_RDY)
-		dev_warn(&dev->pdev->dev, "H_RDY is not cleared 0x%08X", hcsr);
+		dev_warn(dev->dev, "H_RDY is not cleared 0x%08X", hcsr);
 
 
 	if (intr_enable == false)
 	if (intr_enable == false)
 		mei_me_hw_reset_release(dev);
 		mei_me_hw_reset_release(dev);
@@ -227,26 +265,27 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 /**
 /**
  * mei_me_host_set_ready - enable device
  * mei_me_host_set_ready - enable device
  *
  *
- * @dev - mei device
- * returns bool
+ * @dev: mei device
  */
  */
-
 static void mei_me_host_set_ready(struct mei_device *dev)
 static void mei_me_host_set_ready(struct mei_device *dev)
 {
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	struct mei_me_hw *hw = to_me_hw(dev);
+
 	hw->host_hw_state = mei_hcsr_read(hw);
 	hw->host_hw_state = mei_hcsr_read(hw);
 	hw->host_hw_state |= H_IE | H_IG | H_RDY;
 	hw->host_hw_state |= H_IE | H_IG | H_RDY;
 	mei_hcsr_set(hw, hw->host_hw_state);
 	mei_hcsr_set(hw, hw->host_hw_state);
 }
 }
+
 /**
 /**
  * mei_me_host_is_ready - check whether the host has turned ready
  * mei_me_host_is_ready - check whether the host has turned ready
  *
  *
- * @dev - mei device
- * returns bool
+ * @dev: mei device
+ * Return: bool
  */
  */
 static bool mei_me_host_is_ready(struct mei_device *dev)
 static bool mei_me_host_is_ready(struct mei_device *dev)
 {
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	struct mei_me_hw *hw = to_me_hw(dev);
+
 	hw->host_hw_state = mei_hcsr_read(hw);
 	hw->host_hw_state = mei_hcsr_read(hw);
 	return (hw->host_hw_state & H_RDY) == H_RDY;
 	return (hw->host_hw_state & H_RDY) == H_RDY;
 }
 }
@@ -254,43 +293,53 @@ static bool mei_me_host_is_ready(struct mei_device *dev)
 /**
 /**
  * mei_me_hw_is_ready - check whether the me(hw) has turned ready
  * mei_me_hw_is_ready - check whether the me(hw) has turned ready
  *
  *
- * @dev - mei device
- * returns bool
+ * @dev: mei device
+ * Return: bool
  */
  */
 static bool mei_me_hw_is_ready(struct mei_device *dev)
 static bool mei_me_hw_is_ready(struct mei_device *dev)
 {
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	struct mei_me_hw *hw = to_me_hw(dev);
+
 	hw->me_hw_state = mei_me_mecsr_read(hw);
 	hw->me_hw_state = mei_me_mecsr_read(hw);
 	return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
 	return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
 }
 }
 
 
+/**
+ * mei_me_hw_ready_wait - wait until the me(hw) has turned ready
+ *  or timeout is reached
+ *
+ * @dev: mei device
+ * Return: 0 on success, error otherwise
+ */
 static int mei_me_hw_ready_wait(struct mei_device *dev)
 static int mei_me_hw_ready_wait(struct mei_device *dev)
 {
 {
-	int err;
-
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
-	err = wait_event_interruptible_timeout(dev->wait_hw_ready,
+	wait_event_timeout(dev->wait_hw_ready,
 			dev->recvd_hw_ready,
 			dev->recvd_hw_ready,
 			mei_secs_to_jiffies(MEI_HW_READY_TIMEOUT));
 			mei_secs_to_jiffies(MEI_HW_READY_TIMEOUT));
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
-	if (!err && !dev->recvd_hw_ready) {
-		if (!err)
-			err = -ETIME;
-		dev_err(&dev->pdev->dev,
-			"wait hw ready failed. status = %d\n", err);
-		return err;
+	if (!dev->recvd_hw_ready) {
+		dev_err(dev->dev, "wait hw ready failed\n");
+		return -ETIME;
 	}
 	}
 
 
 	dev->recvd_hw_ready = false;
 	dev->recvd_hw_ready = false;
 	return 0;
 	return 0;
 }
 }
 
 
+/**
+ * mei_me_hw_start - hw start routine
+ *
+ * @dev: mei device
+ * Return: 0 on success, error otherwise
+ */
 static int mei_me_hw_start(struct mei_device *dev)
 static int mei_me_hw_start(struct mei_device *dev)
 {
 {
 	int ret = mei_me_hw_ready_wait(dev);
 	int ret = mei_me_hw_ready_wait(dev);
+
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
-	dev_dbg(&dev->pdev->dev, "hw is ready\n");
+	dev_dbg(dev->dev, "hw is ready\n");
 
 
 	mei_me_host_set_ready(dev);
 	mei_me_host_set_ready(dev);
 	return ret;
 	return ret;
@@ -302,7 +351,7 @@ static int mei_me_hw_start(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns number of filled slots
+ * Return: number of filled slots
  */
  */
 static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
 static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
 {
 {
@@ -322,7 +371,7 @@ static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns true if empty, false - otherwise.
+ * Return: true if empty, false - otherwise.
  */
  */
 static bool mei_me_hbuf_is_empty(struct mei_device *dev)
 static bool mei_me_hbuf_is_empty(struct mei_device *dev)
 {
 {
@@ -334,7 +383,7 @@ static bool mei_me_hbuf_is_empty(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns -EOVERFLOW if overflow, otherwise empty slots count
+ * Return: -EOVERFLOW if overflow, otherwise empty slots count
  */
  */
 static int mei_me_hbuf_empty_slots(struct mei_device *dev)
 static int mei_me_hbuf_empty_slots(struct mei_device *dev)
 {
 {
@@ -350,6 +399,13 @@ static int mei_me_hbuf_empty_slots(struct mei_device *dev)
 	return empty_slots;
 	return empty_slots;
 }
 }
 
 
+/**
+ * mei_me_hbuf_max_len - returns size of hw buffer.
+ *
+ * @dev: the device structure
+ *
+ * Return: size of hw buffer in bytes
+ */
 static size_t mei_me_hbuf_max_len(const struct mei_device *dev)
 static size_t mei_me_hbuf_max_len(const struct mei_device *dev)
 {
 {
 	return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr);
 	return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr);
@@ -363,7 +419,7 @@ static size_t mei_me_hbuf_max_len(const struct mei_device *dev)
  * @header: mei HECI header of message
  * @header: mei HECI header of message
  * @buf: message payload will be written
  * @buf: message payload will be written
  *
  *
- * This function returns -EIO if write has failed
+ * Return: -EIO if write has failed
  */
  */
 static int mei_me_write_message(struct mei_device *dev,
 static int mei_me_write_message(struct mei_device *dev,
 			struct mei_msg_hdr *header,
 			struct mei_msg_hdr *header,
@@ -378,10 +434,10 @@ static int mei_me_write_message(struct mei_device *dev,
 	int i;
 	int i;
 	int empty_slots;
 	int empty_slots;
 
 
-	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
+	dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
 
 
 	empty_slots = mei_hbuf_empty_slots(dev);
 	empty_slots = mei_hbuf_empty_slots(dev);
-	dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots);
+	dev_dbg(dev->dev, "empty slots = %hu.\n", empty_slots);
 
 
 	dw_cnt = mei_data2slots(length);
 	dw_cnt = mei_data2slots(length);
 	if (empty_slots < 0 || dw_cnt > empty_slots)
 	if (empty_slots < 0 || dw_cnt > empty_slots)
@@ -395,6 +451,7 @@ static int mei_me_write_message(struct mei_device *dev,
 	rem = length & 0x3;
 	rem = length & 0x3;
 	if (rem > 0) {
 	if (rem > 0) {
 		u32 reg = 0;
 		u32 reg = 0;
+
 		memcpy(&reg, &buf[length - rem], rem);
 		memcpy(&reg, &buf[length - rem], rem);
 		mei_me_reg_write(hw, H_CB_WW, reg);
 		mei_me_reg_write(hw, H_CB_WW, reg);
 	}
 	}
@@ -412,7 +469,7 @@ static int mei_me_write_message(struct mei_device *dev,
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns -EOVERFLOW if overflow, otherwise filled slots count
+ * Return: -EOVERFLOW if overflow, otherwise filled slots count
  */
  */
 static int mei_me_count_full_read_slots(struct mei_device *dev)
 static int mei_me_count_full_read_slots(struct mei_device *dev)
 {
 {
@@ -430,7 +487,7 @@ static int mei_me_count_full_read_slots(struct mei_device *dev)
 	if (filled_slots > buffer_depth)
 	if (filled_slots > buffer_depth)
 		return -EOVERFLOW;
 		return -EOVERFLOW;
 
 
-	dev_dbg(&dev->pdev->dev, "filled_slots =%08x\n", filled_slots);
+	dev_dbg(dev->dev, "filled_slots =%08x\n", filled_slots);
 	return (int)filled_slots;
 	return (int)filled_slots;
 }
 }
 
 
@@ -440,6 +497,8 @@ static int mei_me_count_full_read_slots(struct mei_device *dev)
  * @dev: the device structure
  * @dev: the device structure
  * @buffer: message buffer will be written
  * @buffer: message buffer will be written
  * @buffer_length: message size will be read
  * @buffer_length: message size will be read
+ *
+ * Return: always 0
  */
  */
 static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
 static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
 		    unsigned long buffer_length)
 		    unsigned long buffer_length)
@@ -453,6 +512,7 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
 
 
 	if (buffer_length > 0) {
 	if (buffer_length > 0) {
 		u32 reg = mei_me_mecbrw_read(dev);
 		u32 reg = mei_me_mecbrw_read(dev);
+
 		memcpy(reg_buf, &reg, buffer_length);
 		memcpy(reg_buf, &reg, buffer_length);
 	}
 	}
 
 
@@ -462,7 +522,7 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
 }
 }
 
 
 /**
 /**
- * mei_me_pg_enter - write pg enter register to mei device.
+ * mei_me_pg_enter - write pg enter register
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  */
  */
@@ -470,12 +530,13 @@ static void mei_me_pg_enter(struct mei_device *dev)
 {
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 reg = mei_me_reg_read(hw, H_HPG_CSR);
 	u32 reg = mei_me_reg_read(hw, H_HPG_CSR);
+
 	reg |= H_HPG_CSR_PGI;
 	reg |= H_HPG_CSR_PGI;
 	mei_me_reg_write(hw, H_HPG_CSR, reg);
 	mei_me_reg_write(hw, H_HPG_CSR, reg);
 }
 }
 
 
 /**
 /**
- * mei_me_pg_enter - write pg enter register to mei device.
+ * mei_me_pg_exit - write pg exit register
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  */
  */
@@ -495,7 +556,7 @@ static void mei_me_pg_exit(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 on success an error code otherwise
+ * Return: 0 on success an error code otherwise
  */
  */
 int mei_me_pg_set_sync(struct mei_device *dev)
 int mei_me_pg_set_sync(struct mei_device *dev)
 {
 {
@@ -532,7 +593,7 @@ int mei_me_pg_set_sync(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 on success an error code otherwise
+ * Return: 0 on success an error code otherwise
  */
  */
 int mei_me_pg_unset_sync(struct mei_device *dev)
 int mei_me_pg_unset_sync(struct mei_device *dev)
 {
 {
@@ -569,7 +630,7 @@ reply:
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns: true is pg supported, false otherwise
+ * Return: true is pg supported, false otherwise
  */
  */
 static bool mei_me_pg_is_enabled(struct mei_device *dev)
 static bool mei_me_pg_is_enabled(struct mei_device *dev)
 {
 {
@@ -579,17 +640,13 @@ static bool mei_me_pg_is_enabled(struct mei_device *dev)
 	if ((reg & ME_PGIC_HRA) == 0)
 	if ((reg & ME_PGIC_HRA) == 0)
 		goto notsupported;
 		goto notsupported;
 
 
-	if (dev->version.major_version < HBM_MAJOR_VERSION_PGI)
-		goto notsupported;
-
-	if (dev->version.major_version == HBM_MAJOR_VERSION_PGI &&
-	    dev->version.minor_version < HBM_MINOR_VERSION_PGI)
+	if (!dev->hbm_f_pg_supported)
 		goto notsupported;
 		goto notsupported;
 
 
 	return true;
 	return true;
 
 
 notsupported:
 notsupported:
-	dev_dbg(&dev->pdev->dev, "pg: not supported: HGP = %d hbm version %d.%d ?= %d.%d\n",
+	dev_dbg(dev->dev, "pg: not supported: HGP = %d hbm version %d.%d ?= %d.%d\n",
 		!!(reg & ME_PGIC_HRA),
 		!!(reg & ME_PGIC_HRA),
 		dev->version.major_version,
 		dev->version.major_version,
 		dev->version.minor_version,
 		dev->version.minor_version,
@@ -605,7 +662,7 @@ notsupported:
  * @irq: The irq number
  * @irq: The irq number
  * @dev_id: pointer to the device structure
  * @dev_id: pointer to the device structure
  *
  *
- * returns irqreturn_t
+ * Return: irqreturn_t
  */
  */
 
 
 irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
 irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
@@ -630,7 +687,7 @@ irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
  * @irq: The irq number
  * @irq: The irq number
  * @dev_id: pointer to the device structure
  * @dev_id: pointer to the device structure
  *
  *
- * returns irqreturn_t
+ * Return: irqreturn_t
  *
  *
  */
  */
 irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
@@ -640,19 +697,19 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 	s32 slots;
 	s32 slots;
 	int rets = 0;
 	int rets = 0;
 
 
-	dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
+	dev_dbg(dev->dev, "function called after ISR to handle the interrupt processing.\n");
 	/* initialize our complete list */
 	/* initialize our complete list */
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 	mei_io_list_init(&complete_list);
 	mei_io_list_init(&complete_list);
 
 
 	/* Ack the interrupt here
 	/* Ack the interrupt here
 	 * In case of MSI we don't go through the quick handler */
 	 * In case of MSI we don't go through the quick handler */
-	if (pci_dev_msi_enabled(dev->pdev))
+	if (pci_dev_msi_enabled(to_pci_dev(dev->dev)))
 		mei_clear_interrupts(dev);
 		mei_clear_interrupts(dev);
 
 
 	/* check if ME wants a reset */
 	/* check if ME wants a reset */
 	if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) {
 	if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) {
-		dev_warn(&dev->pdev->dev, "FW not ready: resetting.\n");
+		dev_warn(dev->dev, "FW not ready: resetting.\n");
 		schedule_work(&dev->reset_work);
 		schedule_work(&dev->reset_work);
 		goto end;
 		goto end;
 	}
 	}
@@ -661,19 +718,19 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 	if (!mei_host_is_ready(dev)) {
 	if (!mei_host_is_ready(dev)) {
 		if (mei_hw_is_ready(dev)) {
 		if (mei_hw_is_ready(dev)) {
 			mei_me_hw_reset_release(dev);
 			mei_me_hw_reset_release(dev);
-			dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
+			dev_dbg(dev->dev, "we need to start the dev.\n");
 
 
 			dev->recvd_hw_ready = true;
 			dev->recvd_hw_ready = true;
-			wake_up_interruptible(&dev->wait_hw_ready);
+			wake_up(&dev->wait_hw_ready);
 		} else {
 		} else {
-			dev_dbg(&dev->pdev->dev, "Spurious Interrupt\n");
+			dev_dbg(dev->dev, "Spurious Interrupt\n");
 		}
 		}
 		goto end;
 		goto end;
 	}
 	}
 	/* check slots available for reading */
 	/* check slots available for reading */
 	slots = mei_count_full_read_slots(dev);
 	slots = mei_count_full_read_slots(dev);
 	while (slots > 0) {
 	while (slots > 0) {
-		dev_dbg(&dev->pdev->dev, "slots to read = %08x\n", slots);
+		dev_dbg(dev->dev, "slots to read = %08x\n", slots);
 		rets = mei_irq_read_handler(dev, &complete_list, &slots);
 		rets = mei_irq_read_handler(dev, &complete_list, &slots);
 		/* There is a race between ME write and interrupt delivery:
 		/* There is a race between ME write and interrupt delivery:
 		 * Not all data is always available immediately after the
 		 * Not all data is always available immediately after the
@@ -683,7 +740,7 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 			break;
 			break;
 
 
 		if (rets && dev->dev_state != MEI_DEV_RESETTING) {
 		if (rets && dev->dev_state != MEI_DEV_RESETTING) {
-			dev_err(&dev->pdev->dev, "mei_irq_read_handler ret = %d.\n",
+			dev_err(dev->dev, "mei_irq_read_handler ret = %d.\n",
 						rets);
 						rets);
 			schedule_work(&dev->reset_work);
 			schedule_work(&dev->reset_work);
 			goto end;
 			goto end;
@@ -705,13 +762,14 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 	mei_irq_compl_handler(dev, &complete_list);
 	mei_irq_compl_handler(dev, &complete_list);
 
 
 end:
 end:
-	dev_dbg(&dev->pdev->dev, "interrupt thread end ret = %d\n", rets);
+	dev_dbg(dev->dev, "interrupt thread end ret = %d\n", rets);
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
 static const struct mei_hw_ops mei_me_hw_ops = {
 static const struct mei_hw_ops mei_me_hw_ops = {
 
 
+	.fw_status = mei_me_fw_status,
 	.pg_state  = mei_me_pg_state,
 	.pg_state  = mei_me_pg_state,
 
 
 	.host_is_ready = mei_me_host_is_ready,
 	.host_is_ready = mei_me_host_is_ready,
@@ -741,6 +799,7 @@ static const struct mei_hw_ops mei_me_hw_ops = {
 static bool mei_me_fw_type_nm(struct pci_dev *pdev)
 static bool mei_me_fw_type_nm(struct pci_dev *pdev)
 {
 {
 	u32 reg;
 	u32 reg;
+
 	pci_read_config_dword(pdev, PCI_CFG_HFS_2, &reg);
 	pci_read_config_dword(pdev, PCI_CFG_HFS_2, &reg);
 	/* make sure that bit 9 (NM) is up and bit 10 (DM) is down */
 	/* make sure that bit 9 (NM) is up and bit 10 (DM) is down */
 	return (reg & 0x600) == 0x200;
 	return (reg & 0x600) == 0x200;
@@ -809,23 +868,22 @@ const struct mei_cfg mei_me_lpt_cfg = {
  * @pdev: The pci device structure
  * @pdev: The pci device structure
  * @cfg: per device generation config
  * @cfg: per device generation config
  *
  *
- * returns The mei_device_device pointer on success, NULL on failure.
+ * Return: The mei_device_device pointer on success, NULL on failure.
  */
  */
 struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
 struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
 				   const struct mei_cfg *cfg)
 				   const struct mei_cfg *cfg)
 {
 {
 	struct mei_device *dev;
 	struct mei_device *dev;
+	struct mei_me_hw *hw;
 
 
 	dev = kzalloc(sizeof(struct mei_device) +
 	dev = kzalloc(sizeof(struct mei_device) +
 			 sizeof(struct mei_me_hw), GFP_KERNEL);
 			 sizeof(struct mei_me_hw), GFP_KERNEL);
 	if (!dev)
 	if (!dev)
 		return NULL;
 		return NULL;
+	hw = to_me_hw(dev);
 
 
-	mei_device_init(dev, cfg);
-
-	dev->ops = &mei_me_hw_ops;
-
-	dev->pdev = pdev;
+	mei_device_init(dev, &pdev->dev, &mei_me_hw_ops);
+	hw->cfg = cfg;
 	return dev;
 	return dev;
 }
 }
 
 

+ 31 - 1
drivers/misc/mei/hw-me.h

@@ -19,14 +19,44 @@
 #ifndef _MEI_INTERFACE_H_
 #ifndef _MEI_INTERFACE_H_
 #define _MEI_INTERFACE_H_
 #define _MEI_INTERFACE_H_
 
 
-#include <linux/mei.h>
 #include <linux/irqreturn.h>
 #include <linux/irqreturn.h>
+#include <linux/pci.h>
+#include <linux/mei.h>
+
 #include "mei_dev.h"
 #include "mei_dev.h"
 #include "client.h"
 #include "client.h"
 
 
+/*
+ * mei_cfg - mei device configuration
+ *
+ * @fw_status: FW status
+ * @quirk_probe: device exclusion quirk
+ */
+struct mei_cfg {
+	const struct mei_fw_status fw_status;
+	bool (*quirk_probe)(struct pci_dev *pdev);
+};
+
+
+#define MEI_PCI_DEVICE(dev, cfg) \
+	.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
+	.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, \
+	.driver_data = (kernel_ulong_t)&(cfg)
+
+
 #define MEI_ME_RPM_TIMEOUT    500 /* ms */
 #define MEI_ME_RPM_TIMEOUT    500 /* ms */
 
 
+/**
+ * struct mei_me_hw - me hw specific data
+ *
+ * @cfg: per device generation config and ops
+ * @mem_addr:  io memory address
+ * @host_hw_state: cached host state
+ * @me_hw_state:   cached me (fw) state
+ * @pg_state:      power gating state
+ */
 struct mei_me_hw {
 struct mei_me_hw {
+	const struct mei_cfg *cfg;
 	void __iomem *mem_addr;
 	void __iomem *mem_addr;
 	/*
 	/*
 	 * hw states of host and fw(ME)
 	 * hw states of host and fw(ME)

+ 162 - 90
drivers/misc/mei/hw-txe.c

@@ -28,11 +28,12 @@
 #include "hbm.h"
 #include "hbm.h"
 
 
 /**
 /**
- * mei_txe_reg_read - Reads 32bit data from the device
+ * mei_txe_reg_read - Reads 32bit data from the txe device
  *
  *
  * @base_addr: registers base address
  * @base_addr: registers base address
  * @offset: register offset
  * @offset: register offset
  *
  *
+ * Return: register value
  */
  */
 static inline u32 mei_txe_reg_read(void __iomem *base_addr,
 static inline u32 mei_txe_reg_read(void __iomem *base_addr,
 					unsigned long offset)
 					unsigned long offset)
@@ -41,7 +42,7 @@ static inline u32 mei_txe_reg_read(void __iomem *base_addr,
 }
 }
 
 
 /**
 /**
- * mei_txe_reg_write - Writes 32bit data to the device
+ * mei_txe_reg_write - Writes 32bit data to the txe device
  *
  *
  * @base_addr: registers base address
  * @base_addr: registers base address
  * @offset: register offset
  * @offset: register offset
@@ -56,10 +57,12 @@ static inline void mei_txe_reg_write(void __iomem *base_addr,
 /**
 /**
  * mei_txe_sec_reg_read_silent - Reads 32bit data from the SeC BAR
  * mei_txe_sec_reg_read_silent - Reads 32bit data from the SeC BAR
  *
  *
- * @dev: the device structure
+ * @hw: the txe hardware structure
  * @offset: register offset
  * @offset: register offset
  *
  *
  * Doesn't check for aliveness while Reads 32bit data from the SeC BAR
  * Doesn't check for aliveness while Reads 32bit data from the SeC BAR
+ *
+ * Return: register value
  */
  */
 static inline u32 mei_txe_sec_reg_read_silent(struct mei_txe_hw *hw,
 static inline u32 mei_txe_sec_reg_read_silent(struct mei_txe_hw *hw,
 				unsigned long offset)
 				unsigned long offset)
@@ -70,10 +73,12 @@ static inline u32 mei_txe_sec_reg_read_silent(struct mei_txe_hw *hw,
 /**
 /**
  * mei_txe_sec_reg_read - Reads 32bit data from the SeC BAR
  * mei_txe_sec_reg_read - Reads 32bit data from the SeC BAR
  *
  *
- * @dev: the device structure
+ * @hw: the txe hardware structure
  * @offset: register offset
  * @offset: register offset
  *
  *
  * Reads 32bit data from the SeC BAR and shout loud if aliveness is not set
  * Reads 32bit data from the SeC BAR and shout loud if aliveness is not set
+ *
+ * Return: register value
  */
  */
 static inline u32 mei_txe_sec_reg_read(struct mei_txe_hw *hw,
 static inline u32 mei_txe_sec_reg_read(struct mei_txe_hw *hw,
 				unsigned long offset)
 				unsigned long offset)
@@ -85,7 +90,7 @@ static inline u32 mei_txe_sec_reg_read(struct mei_txe_hw *hw,
  * mei_txe_sec_reg_write_silent - Writes 32bit data to the SeC BAR
  * mei_txe_sec_reg_write_silent - Writes 32bit data to the SeC BAR
  *   doesn't check for aliveness
  *   doesn't check for aliveness
  *
  *
- * @dev: the device structure
+ * @hw: the txe hardware structure
  * @offset: register offset
  * @offset: register offset
  * @value: value to write
  * @value: value to write
  *
  *
@@ -100,7 +105,7 @@ static inline void mei_txe_sec_reg_write_silent(struct mei_txe_hw *hw,
 /**
 /**
  * mei_txe_sec_reg_write - Writes 32bit data to the SeC BAR
  * mei_txe_sec_reg_write - Writes 32bit data to the SeC BAR
  *
  *
- * @dev: the device structure
+ * @hw: the txe hardware structure
  * @offset: register offset
  * @offset: register offset
  * @value: value to write
  * @value: value to write
  *
  *
@@ -115,9 +120,10 @@ static inline void mei_txe_sec_reg_write(struct mei_txe_hw *hw,
 /**
 /**
  * mei_txe_br_reg_read - Reads 32bit data from the Bridge BAR
  * mei_txe_br_reg_read - Reads 32bit data from the Bridge BAR
  *
  *
- * @hw: the device structure
+ * @hw: the txe hardware structure
  * @offset: offset from which to read the data
  * @offset: offset from which to read the data
  *
  *
+ * Return: the byte read.
  */
  */
 static inline u32 mei_txe_br_reg_read(struct mei_txe_hw *hw,
 static inline u32 mei_txe_br_reg_read(struct mei_txe_hw *hw,
 				unsigned long offset)
 				unsigned long offset)
@@ -128,7 +134,7 @@ static inline u32 mei_txe_br_reg_read(struct mei_txe_hw *hw,
 /**
 /**
  * mei_txe_br_reg_write - Writes 32bit data to the Bridge BAR
  * mei_txe_br_reg_write - Writes 32bit data to the Bridge BAR
  *
  *
- * @hw: the device structure
+ * @hw: the txe hardware structure
  * @offset: offset from which to write the data
  * @offset: offset from which to write the data
  * @value: the byte to write
  * @value: the byte to write
  */
  */
@@ -147,7 +153,10 @@ static inline void mei_txe_br_reg_write(struct mei_txe_hw *hw,
  * Request for aliveness change and returns true if the change is
  * Request for aliveness change and returns true if the change is
  *   really needed and false if aliveness is already
  *   really needed and false if aliveness is already
  *   in the requested state
  *   in the requested state
- * Requires device lock to be held
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * Return: true if request was send
  */
  */
 static bool mei_txe_aliveness_set(struct mei_device *dev, u32 req)
 static bool mei_txe_aliveness_set(struct mei_device *dev, u32 req)
 {
 {
@@ -155,7 +164,7 @@ static bool mei_txe_aliveness_set(struct mei_device *dev, u32 req)
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	bool do_req = hw->aliveness != req;
 	bool do_req = hw->aliveness != req;
 
 
-	dev_dbg(&dev->pdev->dev, "Aliveness current=%d request=%d\n",
+	dev_dbg(dev->dev, "Aliveness current=%d request=%d\n",
 				hw->aliveness, req);
 				hw->aliveness, req);
 	if (do_req) {
 	if (do_req) {
 		dev->pg_event = MEI_PG_EVENT_WAIT;
 		dev->pg_event = MEI_PG_EVENT_WAIT;
@@ -172,26 +181,31 @@ static bool mei_txe_aliveness_set(struct mei_device *dev, u32 req)
  *
  *
  * Extract HICR_HOST_ALIVENESS_RESP_ACK bit from
  * Extract HICR_HOST_ALIVENESS_RESP_ACK bit from
  * from HICR_HOST_ALIVENESS_REQ register value
  * from HICR_HOST_ALIVENESS_REQ register value
+ *
+ * Return: SICR_HOST_ALIVENESS_REQ_REQUESTED bit value
  */
  */
 static u32 mei_txe_aliveness_req_get(struct mei_device *dev)
 static u32 mei_txe_aliveness_req_get(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	u32 reg;
 	u32 reg;
+
 	reg = mei_txe_br_reg_read(hw, SICR_HOST_ALIVENESS_REQ_REG);
 	reg = mei_txe_br_reg_read(hw, SICR_HOST_ALIVENESS_REQ_REG);
 	return reg & SICR_HOST_ALIVENESS_REQ_REQUESTED;
 	return reg & SICR_HOST_ALIVENESS_REQ_REQUESTED;
 }
 }
 
 
 /**
 /**
  * mei_txe_aliveness_get - get aliveness response register value
  * mei_txe_aliveness_get - get aliveness response register value
+ *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * Extract HICR_HOST_ALIVENESS_RESP_ACK bit
- * from HICR_HOST_ALIVENESS_RESP register value
+ * Return: HICR_HOST_ALIVENESS_RESP_ACK bit from HICR_HOST_ALIVENESS_RESP
+ *         register
  */
  */
 static u32 mei_txe_aliveness_get(struct mei_device *dev)
 static u32 mei_txe_aliveness_get(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	u32 reg;
 	u32 reg;
+
 	reg = mei_txe_br_reg_read(hw, HICR_HOST_ALIVENESS_RESP_REG);
 	reg = mei_txe_br_reg_read(hw, HICR_HOST_ALIVENESS_RESP_REG);
 	return reg & HICR_HOST_ALIVENESS_RESP_ACK;
 	return reg & HICR_HOST_ALIVENESS_RESP_ACK;
 }
 }
@@ -203,7 +217,8 @@ static u32 mei_txe_aliveness_get(struct mei_device *dev)
  * @expected: expected aliveness value
  * @expected: expected aliveness value
  *
  *
  * Polls for HICR_HOST_ALIVENESS_RESP.ALIVENESS_RESP to be set
  * Polls for HICR_HOST_ALIVENESS_RESP.ALIVENESS_RESP to be set
- * returns > 0 if the expected value was received, -ETIME otherwise
+ *
+ * Return: > 0 if the expected value was received, -ETIME otherwise
  */
  */
 static int mei_txe_aliveness_poll(struct mei_device *dev, u32 expected)
 static int mei_txe_aliveness_poll(struct mei_device *dev, u32 expected)
 {
 {
@@ -214,7 +229,7 @@ static int mei_txe_aliveness_poll(struct mei_device *dev, u32 expected)
 		hw->aliveness = mei_txe_aliveness_get(dev);
 		hw->aliveness = mei_txe_aliveness_get(dev);
 		if (hw->aliveness == expected) {
 		if (hw->aliveness == expected) {
 			dev->pg_event = MEI_PG_EVENT_IDLE;
 			dev->pg_event = MEI_PG_EVENT_IDLE;
-			dev_dbg(&dev->pdev->dev,
+			dev_dbg(dev->dev,
 				"aliveness settled after %d msecs\n", t);
 				"aliveness settled after %d msecs\n", t);
 			return t;
 			return t;
 		}
 		}
@@ -225,7 +240,7 @@ static int mei_txe_aliveness_poll(struct mei_device *dev, u32 expected)
 	} while (t < SEC_ALIVENESS_WAIT_TIMEOUT);
 	} while (t < SEC_ALIVENESS_WAIT_TIMEOUT);
 
 
 	dev->pg_event = MEI_PG_EVENT_IDLE;
 	dev->pg_event = MEI_PG_EVENT_IDLE;
-	dev_err(&dev->pdev->dev, "aliveness timed out\n");
+	dev_err(dev->dev, "aliveness timed out\n");
 	return -ETIME;
 	return -ETIME;
 }
 }
 
 
@@ -236,7 +251,8 @@ static int mei_txe_aliveness_poll(struct mei_device *dev, u32 expected)
  * @expected: expected aliveness value
  * @expected: expected aliveness value
  *
  *
  * Waits for HICR_HOST_ALIVENESS_RESP.ALIVENESS_RESP to be set
  * Waits for HICR_HOST_ALIVENESS_RESP.ALIVENESS_RESP to be set
- * returns returns 0 on success and < 0 otherwise
+ *
+ * Return: 0 on success and < 0 otherwise
  */
  */
 static int mei_txe_aliveness_wait(struct mei_device *dev, u32 expected)
 static int mei_txe_aliveness_wait(struct mei_device *dev, u32 expected)
 {
 {
@@ -259,10 +275,10 @@ static int mei_txe_aliveness_wait(struct mei_device *dev, u32 expected)
 	ret = hw->aliveness == expected ? 0 : -ETIME;
 	ret = hw->aliveness == expected ? 0 : -ETIME;
 
 
 	if (ret)
 	if (ret)
-		dev_warn(&dev->pdev->dev, "aliveness timed out = %ld aliveness = %d event = %d\n",
+		dev_warn(dev->dev, "aliveness timed out = %ld aliveness = %d event = %d\n",
 			err, hw->aliveness, dev->pg_event);
 			err, hw->aliveness, dev->pg_event);
 	else
 	else
-		dev_dbg(&dev->pdev->dev, "aliveness settled after = %d msec aliveness = %d event = %d\n",
+		dev_dbg(dev->dev, "aliveness settled after = %d msec aliveness = %d event = %d\n",
 			jiffies_to_msecs(timeout - err),
 			jiffies_to_msecs(timeout - err),
 			hw->aliveness, dev->pg_event);
 			hw->aliveness, dev->pg_event);
 
 
@@ -274,8 +290,9 @@ static int mei_txe_aliveness_wait(struct mei_device *dev, u32 expected)
  * mei_txe_aliveness_set_sync - sets an wait for aliveness to complete
  * mei_txe_aliveness_set_sync - sets an wait for aliveness to complete
  *
  *
  * @dev: the device structure
  * @dev: the device structure
+ * @req: requested aliveness value
  *
  *
- * returns returns 0 on success and < 0 otherwise
+ * Return: 0 on success and < 0 otherwise
  */
  */
 int mei_txe_aliveness_set_sync(struct mei_device *dev, u32 req)
 int mei_txe_aliveness_set_sync(struct mei_device *dev, u32 req)
 {
 {
@@ -289,7 +306,7 @@ int mei_txe_aliveness_set_sync(struct mei_device *dev, u32 req)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns: true is pg supported, false otherwise
+ * Return: true is pg supported, false otherwise
  */
  */
 static bool mei_txe_pg_is_enabled(struct mei_device *dev)
 static bool mei_txe_pg_is_enabled(struct mei_device *dev)
 {
 {
@@ -302,11 +319,12 @@ static bool mei_txe_pg_is_enabled(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns: MEI_PG_OFF if aliveness is on and MEI_PG_ON otherwise
+ * Return: MEI_PG_OFF if aliveness is on and MEI_PG_ON otherwise
  */
  */
 static inline enum mei_pg_state mei_txe_pg_state(struct mei_device *dev)
 static inline enum mei_pg_state mei_txe_pg_state(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	return hw->aliveness ? MEI_PG_OFF : MEI_PG_ON;
 	return hw->aliveness ? MEI_PG_OFF : MEI_PG_ON;
 }
 }
 
 
@@ -326,9 +344,10 @@ static void mei_txe_input_ready_interrupt_enable(struct mei_device *dev)
 }
 }
 
 
 /**
 /**
- * mei_txe_input_doorbell_set
- *   - Sets bit 0 in SEC_IPC_INPUT_DOORBELL.IPC_INPUT_DOORBELL.
- * @dev: the device structure
+ * mei_txe_input_doorbell_set - sets bit 0 in
+ *    SEC_IPC_INPUT_DOORBELL.IPC_INPUT_DOORBELL.
+ *
+ * @hw: the txe hardware structure
  */
  */
 static void mei_txe_input_doorbell_set(struct mei_txe_hw *hw)
 static void mei_txe_input_doorbell_set(struct mei_txe_hw *hw)
 {
 {
@@ -340,7 +359,7 @@ static void mei_txe_input_doorbell_set(struct mei_txe_hw *hw)
 /**
 /**
  * mei_txe_output_ready_set - Sets the SICR_SEC_IPC_OUTPUT_STATUS bit to 1
  * mei_txe_output_ready_set - Sets the SICR_SEC_IPC_OUTPUT_STATUS bit to 1
  *
  *
- * @dev: the device structure
+ * @hw: the txe hardware structure
  */
  */
 static void mei_txe_output_ready_set(struct mei_txe_hw *hw)
 static void mei_txe_output_ready_set(struct mei_txe_hw *hw)
 {
 {
@@ -353,11 +372,14 @@ static void mei_txe_output_ready_set(struct mei_txe_hw *hw)
  * mei_txe_is_input_ready - check if TXE is ready for receiving data
  * mei_txe_is_input_ready - check if TXE is ready for receiving data
  *
  *
  * @dev: the device structure
  * @dev: the device structure
+ *
+ * Return: true if INPUT STATUS READY bit is set
  */
  */
 static bool mei_txe_is_input_ready(struct mei_device *dev)
 static bool mei_txe_is_input_ready(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	u32 status;
 	u32 status;
+
 	status = mei_txe_sec_reg_read(hw, SEC_IPC_INPUT_STATUS_REG);
 	status = mei_txe_sec_reg_read(hw, SEC_IPC_INPUT_STATUS_REG);
 	return !!(SEC_IPC_INPUT_STATUS_RDY & status);
 	return !!(SEC_IPC_INPUT_STATUS_RDY & status);
 }
 }
@@ -370,6 +392,7 @@ static bool mei_txe_is_input_ready(struct mei_device *dev)
 static inline void mei_txe_intr_clear(struct mei_device *dev)
 static inline void mei_txe_intr_clear(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	mei_txe_sec_reg_write_silent(hw, SEC_IPC_HOST_INT_STATUS_REG,
 	mei_txe_sec_reg_write_silent(hw, SEC_IPC_HOST_INT_STATUS_REG,
 		SEC_IPC_HOST_INT_STATUS_PENDING);
 		SEC_IPC_HOST_INT_STATUS_PENDING);
 	mei_txe_br_reg_write(hw, HISR_REG, HISR_INT_STS_MSK);
 	mei_txe_br_reg_write(hw, HISR_REG, HISR_INT_STS_MSK);
@@ -384,6 +407,7 @@ static inline void mei_txe_intr_clear(struct mei_device *dev)
 static void mei_txe_intr_disable(struct mei_device *dev)
 static void mei_txe_intr_disable(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	mei_txe_br_reg_write(hw, HHIER_REG, 0);
 	mei_txe_br_reg_write(hw, HHIER_REG, 0);
 	mei_txe_br_reg_write(hw, HIER_REG, 0);
 	mei_txe_br_reg_write(hw, HIER_REG, 0);
 }
 }
@@ -395,6 +419,7 @@ static void mei_txe_intr_disable(struct mei_device *dev)
 static void mei_txe_intr_enable(struct mei_device *dev)
 static void mei_txe_intr_enable(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	mei_txe_br_reg_write(hw, HHIER_REG, IPC_HHIER_MSK);
 	mei_txe_br_reg_write(hw, HHIER_REG, IPC_HHIER_MSK);
 	mei_txe_br_reg_write(hw, HIER_REG, HIER_INT_EN_MSK);
 	mei_txe_br_reg_write(hw, HIER_REG, HIER_INT_EN_MSK);
 }
 }
@@ -407,6 +432,8 @@ static void mei_txe_intr_enable(struct mei_device *dev)
  *
  *
  * Checks if there are pending interrupts
  * Checks if there are pending interrupts
  * only Aliveness, Readiness, Input ready, and Output doorbell are relevant
  * only Aliveness, Readiness, Input ready, and Output doorbell are relevant
+ *
+ * Return: true if there are pending interrupts
  */
  */
 static bool mei_txe_pending_interrupts(struct mei_device *dev)
 static bool mei_txe_pending_interrupts(struct mei_device *dev)
 {
 {
@@ -418,7 +445,7 @@ static bool mei_txe_pending_interrupts(struct mei_device *dev)
 				      TXE_INTR_OUT_DB));
 				      TXE_INTR_OUT_DB));
 
 
 	if (ret) {
 	if (ret) {
-		dev_dbg(&dev->pdev->dev,
+		dev_dbg(dev->dev,
 			"Pending Interrupts InReady=%01d Readiness=%01d, Aliveness=%01d, OutDoor=%01d\n",
 			"Pending Interrupts InReady=%01d Readiness=%01d, Aliveness=%01d, OutDoor=%01d\n",
 			!!(hw->intr_cause & TXE_INTR_IN_READY),
 			!!(hw->intr_cause & TXE_INTR_IN_READY),
 			!!(hw->intr_cause & TXE_INTR_READINESS),
 			!!(hw->intr_cause & TXE_INTR_READINESS),
@@ -440,6 +467,7 @@ static void mei_txe_input_payload_write(struct mei_device *dev,
 			unsigned long idx, u32 value)
 			unsigned long idx, u32 value)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	mei_txe_sec_reg_write(hw, SEC_IPC_INPUT_PAYLOAD_REG +
 	mei_txe_sec_reg_write(hw, SEC_IPC_INPUT_PAYLOAD_REG +
 			(idx * sizeof(u32)), value);
 			(idx * sizeof(u32)), value);
 }
 }
@@ -451,12 +479,13 @@ static void mei_txe_input_payload_write(struct mei_device *dev,
  * @dev: the device structure
  * @dev: the device structure
  * @idx: index in the device buffer
  * @idx: index in the device buffer
  *
  *
- * returns register value at index
+ * Return: register value at index
  */
  */
 static u32 mei_txe_out_data_read(const struct mei_device *dev,
 static u32 mei_txe_out_data_read(const struct mei_device *dev,
 					unsigned long idx)
 					unsigned long idx)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	return mei_txe_br_reg_read(hw,
 	return mei_txe_br_reg_read(hw,
 		BRIDGE_IPC_OUTPUT_PAYLOAD_REG + (idx * sizeof(u32)));
 		BRIDGE_IPC_OUTPUT_PAYLOAD_REG + (idx * sizeof(u32)));
 }
 }
@@ -464,26 +493,28 @@ static u32 mei_txe_out_data_read(const struct mei_device *dev,
 /* Readiness */
 /* Readiness */
 
 
 /**
 /**
- * mei_txe_readiness_set_host_rdy
+ * mei_txe_readiness_set_host_rdy - set host readiness bit
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  */
  */
 static void mei_txe_readiness_set_host_rdy(struct mei_device *dev)
 static void mei_txe_readiness_set_host_rdy(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	mei_txe_br_reg_write(hw,
 	mei_txe_br_reg_write(hw,
 		SICR_HOST_IPC_READINESS_REQ_REG,
 		SICR_HOST_IPC_READINESS_REQ_REG,
 		SICR_HOST_IPC_READINESS_HOST_RDY);
 		SICR_HOST_IPC_READINESS_HOST_RDY);
 }
 }
 
 
 /**
 /**
- * mei_txe_readiness_clear
+ * mei_txe_readiness_clear - clear host readiness bit
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  */
  */
 static void mei_txe_readiness_clear(struct mei_device *dev)
 static void mei_txe_readiness_clear(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	mei_txe_br_reg_write(hw, SICR_HOST_IPC_READINESS_REQ_REG,
 	mei_txe_br_reg_write(hw, SICR_HOST_IPC_READINESS_REQ_REG,
 				SICR_HOST_IPC_READINESS_RDY_CLR);
 				SICR_HOST_IPC_READINESS_RDY_CLR);
 }
 }
@@ -492,10 +523,13 @@ static void mei_txe_readiness_clear(struct mei_device *dev)
  *	the HICR_SEC_IPC_READINESS register value
  *	the HICR_SEC_IPC_READINESS register value
  *
  *
  * @dev: the device structure
  * @dev: the device structure
+ *
+ * Return: the HICR_SEC_IPC_READINESS register value
  */
  */
 static u32 mei_txe_readiness_get(struct mei_device *dev)
 static u32 mei_txe_readiness_get(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	return mei_txe_br_reg_read(hw, HICR_SEC_IPC_READINESS_REG);
 	return mei_txe_br_reg_read(hw, HICR_SEC_IPC_READINESS_REG);
 }
 }
 
 
@@ -504,7 +538,9 @@ static u32 mei_txe_readiness_get(struct mei_device *dev)
  * mei_txe_readiness_is_sec_rdy - check readiness
  * mei_txe_readiness_is_sec_rdy - check readiness
  *  for HICR_SEC_IPC_READINESS_SEC_RDY
  *  for HICR_SEC_IPC_READINESS_SEC_RDY
  *
  *
- * @readiness - cached readiness state
+ * @readiness: cached readiness state
+ *
+ * Return: true if readiness bit is set
  */
  */
 static inline bool mei_txe_readiness_is_sec_rdy(u32 readiness)
 static inline bool mei_txe_readiness_is_sec_rdy(u32 readiness)
 {
 {
@@ -515,10 +551,13 @@ static inline bool mei_txe_readiness_is_sec_rdy(u32 readiness)
  * mei_txe_hw_is_ready - check if the hw is ready
  * mei_txe_hw_is_ready - check if the hw is ready
  *
  *
  * @dev: the device structure
  * @dev: the device structure
+ *
+ * Return: true if sec is ready
  */
  */
 static bool mei_txe_hw_is_ready(struct mei_device *dev)
 static bool mei_txe_hw_is_ready(struct mei_device *dev)
 {
 {
 	u32 readiness =  mei_txe_readiness_get(dev);
 	u32 readiness =  mei_txe_readiness_get(dev);
+
 	return mei_txe_readiness_is_sec_rdy(readiness);
 	return mei_txe_readiness_is_sec_rdy(readiness);
 }
 }
 
 
@@ -526,11 +565,14 @@ static bool mei_txe_hw_is_ready(struct mei_device *dev)
  * mei_txe_host_is_ready - check if the host is ready
  * mei_txe_host_is_ready - check if the host is ready
  *
  *
  * @dev: the device structure
  * @dev: the device structure
+ *
+ * Return: true if host is ready
  */
  */
 static inline bool mei_txe_host_is_ready(struct mei_device *dev)
 static inline bool mei_txe_host_is_ready(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	u32 reg = mei_txe_br_reg_read(hw, HICR_SEC_IPC_READINESS_REG);
 	u32 reg = mei_txe_br_reg_read(hw, HICR_SEC_IPC_READINESS_REG);
+
 	return !!(reg & HICR_SEC_IPC_READINESS_HOST_RDY);
 	return !!(reg & HICR_SEC_IPC_READINESS_HOST_RDY);
 }
 }
 
 
@@ -539,7 +581,7 @@ static inline bool mei_txe_host_is_ready(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 on success and -ETIME on timeout
+ * Return: 0 on success and -ETIME on timeout
  */
  */
 static int mei_txe_readiness_wait(struct mei_device *dev)
 static int mei_txe_readiness_wait(struct mei_device *dev)
 {
 {
@@ -551,7 +593,7 @@ static int mei_txe_readiness_wait(struct mei_device *dev)
 			msecs_to_jiffies(SEC_RESET_WAIT_TIMEOUT));
 			msecs_to_jiffies(SEC_RESET_WAIT_TIMEOUT));
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 	if (!dev->recvd_hw_ready) {
 	if (!dev->recvd_hw_ready) {
-		dev_err(&dev->pdev->dev, "wait for readiness failed\n");
+		dev_err(dev->dev, "wait for readiness failed\n");
 		return -ETIME;
 		return -ETIME;
 	}
 	}
 
 
@@ -559,6 +601,42 @@ static int mei_txe_readiness_wait(struct mei_device *dev)
 	return 0;
 	return 0;
 }
 }
 
 
+static const struct mei_fw_status mei_txe_fw_sts = {
+	.count = 2,
+	.status[0] = PCI_CFG_TXE_FW_STS0,
+	.status[1] = PCI_CFG_TXE_FW_STS1
+};
+
+/**
+ * mei_txe_fw_status - read fw status register from pci config space
+ *
+ * @dev: mei device
+ * @fw_status: fw status register values
+ *
+ * Return: 0 on success, error otherwise
+ */
+static int mei_txe_fw_status(struct mei_device *dev,
+			     struct mei_fw_status *fw_status)
+{
+	const struct mei_fw_status *fw_src = &mei_txe_fw_sts;
+	struct pci_dev *pdev = to_pci_dev(dev->dev);
+	int ret;
+	int i;
+
+	if (!fw_status)
+		return -EINVAL;
+
+	fw_status->count = fw_src->count;
+	for (i = 0; i < fw_src->count && i < MEI_FW_STATUS_MAX; i++) {
+		ret = pci_read_config_dword(pdev,
+			fw_src->status[i], &fw_status->status[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 /**
 /**
  *  mei_txe_hw_config - configure hardware at the start of the devices
  *  mei_txe_hw_config - configure hardware at the start of the devices
  *
  *
@@ -571,13 +649,14 @@ static void mei_txe_hw_config(struct mei_device *dev)
 {
 {
 
 
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	/* Doesn't change in runtime */
 	/* Doesn't change in runtime */
 	dev->hbuf_depth = PAYLOAD_SIZE / 4;
 	dev->hbuf_depth = PAYLOAD_SIZE / 4;
 
 
 	hw->aliveness = mei_txe_aliveness_get(dev);
 	hw->aliveness = mei_txe_aliveness_get(dev);
 	hw->readiness = mei_txe_readiness_get(dev);
 	hw->readiness = mei_txe_readiness_get(dev);
 
 
-	dev_dbg(&dev->pdev->dev, "aliveness_resp = 0x%08x, readiness = 0x%08x.\n",
+	dev_dbg(dev->dev, "aliveness_resp = 0x%08x, readiness = 0x%08x.\n",
 		hw->aliveness, hw->readiness);
 		hw->aliveness, hw->readiness);
 }
 }
 
 
@@ -588,7 +667,8 @@ static void mei_txe_hw_config(struct mei_device *dev)
  * @dev: the device structure
  * @dev: the device structure
  * @header: header of message
  * @header: header of message
  * @buf: message buffer will be written
  * @buf: message buffer will be written
- * returns 1 if success, 0 - otherwise.
+ *
+ * Return: 0 if success, <0 - otherwise.
  */
  */
 
 
 static int mei_txe_write(struct mei_device *dev,
 static int mei_txe_write(struct mei_device *dev,
@@ -607,7 +687,7 @@ static int mei_txe_write(struct mei_device *dev,
 
 
 	length = header->length;
 	length = header->length;
 
 
-	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
+	dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
 
 
 	dw_cnt = mei_data2slots(length);
 	dw_cnt = mei_data2slots(length);
 	if (dw_cnt > slots)
 	if (dw_cnt > slots)
@@ -621,8 +701,9 @@ static int mei_txe_write(struct mei_device *dev,
 
 
 	if (!mei_txe_is_input_ready(dev)) {
 	if (!mei_txe_is_input_ready(dev)) {
 		struct mei_fw_status fw_status;
 		struct mei_fw_status fw_status;
+
 		mei_fw_status(dev, &fw_status);
 		mei_fw_status(dev, &fw_status);
-		dev_err(&dev->pdev->dev, "Input is not ready " FW_STS_FMT "\n",
+		dev_err(dev->dev, "Input is not ready " FW_STS_FMT "\n",
 			FW_STS_PRM(fw_status));
 			FW_STS_PRM(fw_status));
 		return -EAGAIN;
 		return -EAGAIN;
 	}
 	}
@@ -635,6 +716,7 @@ static int mei_txe_write(struct mei_device *dev,
 	rem = length & 0x3;
 	rem = length & 0x3;
 	if (rem > 0) {
 	if (rem > 0) {
 		u32 reg = 0;
 		u32 reg = 0;
+
 		memcpy(&reg, &buf[length - rem], rem);
 		memcpy(&reg, &buf[length - rem], rem);
 		mei_txe_input_payload_write(dev, i + 1, reg);
 		mei_txe_input_payload_write(dev, i + 1, reg);
 	}
 	}
@@ -653,7 +735,7 @@ static int mei_txe_write(struct mei_device *dev,
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns the PAYLOAD_SIZE - 4
+ * Return: the PAYLOAD_SIZE - 4
  */
  */
 static size_t mei_txe_hbuf_max_len(const struct mei_device *dev)
 static size_t mei_txe_hbuf_max_len(const struct mei_device *dev)
 {
 {
@@ -665,11 +747,12 @@ static size_t mei_txe_hbuf_max_len(const struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns always hbuf_depth
+ * Return: always hbuf_depth
  */
  */
 static int mei_txe_hbuf_empty_slots(struct mei_device *dev)
 static int mei_txe_hbuf_empty_slots(struct mei_device *dev)
 {
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+
 	return hw->slots;
 	return hw->slots;
 }
 }
 
 
@@ -678,7 +761,7 @@ static int mei_txe_hbuf_empty_slots(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns always buffer size in dwords count
+ * Return: always buffer size in dwords count
  */
  */
 static int mei_txe_count_full_read_slots(struct mei_device *dev)
 static int mei_txe_count_full_read_slots(struct mei_device *dev)
 {
 {
@@ -691,7 +774,7 @@ static int mei_txe_count_full_read_slots(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns mei message header
+ * Return: mei message header
  */
  */
 
 
 static u32 mei_txe_read_hdr(const struct mei_device *dev)
 static u32 mei_txe_read_hdr(const struct mei_device *dev)
@@ -705,33 +788,35 @@ static u32 mei_txe_read_hdr(const struct mei_device *dev)
  * @buf: message buffer will be written
  * @buf: message buffer will be written
  * @len: message size will be read
  * @len: message size will be read
  *
  *
- * returns -EINVAL on error wrong argument and 0 on success
+ * Return: -EINVAL on error wrong argument and 0 on success
  */
  */
 static int mei_txe_read(struct mei_device *dev,
 static int mei_txe_read(struct mei_device *dev,
 		unsigned char *buf, unsigned long len)
 		unsigned char *buf, unsigned long len)
 {
 {
 
 
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	struct mei_txe_hw *hw = to_txe_hw(dev);
+	u32 *reg_buf, reg;
+	u32 rem;
 	u32 i;
 	u32 i;
-	u32 *reg_buf = (u32 *)buf;
-	u32 rem = len & 0x3;
 
 
 	if (WARN_ON(!buf || !len))
 	if (WARN_ON(!buf || !len))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	dev_dbg(&dev->pdev->dev,
-		"buffer-length = %lu buf[0]0x%08X\n",
+	reg_buf = (u32 *)buf;
+	rem = len & 0x3;
+
+	dev_dbg(dev->dev, "buffer-length = %lu buf[0]0x%08X\n",
 		len, mei_txe_out_data_read(dev, 0));
 		len, mei_txe_out_data_read(dev, 0));
 
 
 	for (i = 0; i < len / 4; i++) {
 	for (i = 0; i < len / 4; i++) {
 		/* skip header: index starts from 1 */
 		/* skip header: index starts from 1 */
-		u32 reg = mei_txe_out_data_read(dev, i + 1);
-		dev_dbg(&dev->pdev->dev, "buf[%d] = 0x%08X\n", i, reg);
+		reg = mei_txe_out_data_read(dev, i + 1);
+		dev_dbg(dev->dev, "buf[%d] = 0x%08X\n", i, reg);
 		*reg_buf++ = reg;
 		*reg_buf++ = reg;
 	}
 	}
 
 
 	if (rem) {
 	if (rem) {
-		u32 reg = mei_txe_out_data_read(dev, i + 1);
+		reg = mei_txe_out_data_read(dev, i + 1);
 		memcpy(reg_buf, &reg, rem);
 		memcpy(reg_buf, &reg, rem);
 	}
 	}
 
 
@@ -745,7 +830,7 @@ static int mei_txe_read(struct mei_device *dev,
  * @dev: the device structure
  * @dev: the device structure
  * @intr_enable: if interrupt should be enabled after reset.
  * @intr_enable: if interrupt should be enabled after reset.
  *
  *
- * returns 0 on success and < 0 in case of error
+ * Return: 0 on success and < 0 in case of error
  */
  */
 static int mei_txe_hw_reset(struct mei_device *dev, bool intr_enable)
 static int mei_txe_hw_reset(struct mei_device *dev, bool intr_enable)
 {
 {
@@ -771,8 +856,7 @@ static int mei_txe_hw_reset(struct mei_device *dev, bool intr_enable)
 	 */
 	 */
 	if (aliveness_req != hw->aliveness)
 	if (aliveness_req != hw->aliveness)
 		if (mei_txe_aliveness_poll(dev, aliveness_req) < 0) {
 		if (mei_txe_aliveness_poll(dev, aliveness_req) < 0) {
-			dev_err(&dev->pdev->dev,
-				"wait for aliveness settle failed ... bailing out\n");
+			dev_err(dev->dev, "wait for aliveness settle failed ... bailing out\n");
 			return -EIO;
 			return -EIO;
 		}
 		}
 
 
@@ -782,14 +866,13 @@ static int mei_txe_hw_reset(struct mei_device *dev, bool intr_enable)
 	if (aliveness_req) {
 	if (aliveness_req) {
 		mei_txe_aliveness_set(dev, 0);
 		mei_txe_aliveness_set(dev, 0);
 		if (mei_txe_aliveness_poll(dev, 0) < 0) {
 		if (mei_txe_aliveness_poll(dev, 0) < 0) {
-			dev_err(&dev->pdev->dev,
-				"wait for aliveness failed ... bailing out\n");
+			dev_err(dev->dev, "wait for aliveness failed ... bailing out\n");
 			return -EIO;
 			return -EIO;
 		}
 		}
 	}
 	}
 
 
 	/*
 	/*
-	 * Set rediness RDY_CLR bit
+	 * Set readiness RDY_CLR bit
 	 */
 	 */
 	mei_txe_readiness_clear(dev);
 	mei_txe_readiness_clear(dev);
 
 
@@ -801,7 +884,7 @@ static int mei_txe_hw_reset(struct mei_device *dev, bool intr_enable)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 on success and < 0 in case of error
+ * Return: 0 on success an error code otherwise
  */
  */
 static int mei_txe_hw_start(struct mei_device *dev)
 static int mei_txe_hw_start(struct mei_device *dev)
 {
 {
@@ -815,7 +898,7 @@ static int mei_txe_hw_start(struct mei_device *dev)
 
 
 	ret = mei_txe_readiness_wait(dev);
 	ret = mei_txe_readiness_wait(dev);
 	if (ret < 0) {
 	if (ret < 0) {
-		dev_err(&dev->pdev->dev, "wating for readiness failed\n");
+		dev_err(dev->dev, "waiting for readiness failed\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -831,7 +914,7 @@ static int mei_txe_hw_start(struct mei_device *dev)
 
 
 	ret = mei_txe_aliveness_set_sync(dev, 1);
 	ret = mei_txe_aliveness_set_sync(dev, 1);
 	if (ret < 0) {
 	if (ret < 0) {
-		dev_err(&dev->pdev->dev, "wait for aliveness failed ... bailing out\n");
+		dev_err(dev->dev, "wait for aliveness failed ... bailing out\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -857,6 +940,8 @@ static int mei_txe_hw_start(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  * @do_ack: acknowledge interrupts
  * @do_ack: acknowledge interrupts
+ *
+ * Return: true if found interrupts to process.
  */
  */
 static bool mei_txe_check_and_ack_intrs(struct mei_device *dev, bool do_ack)
 static bool mei_txe_check_and_ack_intrs(struct mei_device *dev, bool do_ack)
 {
 {
@@ -912,7 +997,8 @@ out:
  * @irq: The irq number
  * @irq: The irq number
  * @dev_id: pointer to the device structure
  * @dev_id: pointer to the device structure
  *
  *
- * returns irqreturn_t
+ * Return: IRQ_WAKE_THREAD if interrupt is designed for the device
+ *         IRQ_NONE otherwise
  */
  */
 irqreturn_t mei_txe_irq_quick_handler(int irq, void *dev_id)
 irqreturn_t mei_txe_irq_quick_handler(int irq, void *dev_id)
 {
 {
@@ -930,8 +1016,7 @@ irqreturn_t mei_txe_irq_quick_handler(int irq, void *dev_id)
  * @irq: The irq number
  * @irq: The irq number
  * @dev_id: pointer to the device structure
  * @dev_id: pointer to the device structure
  *
  *
- * returns irqreturn_t
- *
+ * Return: IRQ_HANDLED
  */
  */
 irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 {
 {
@@ -941,7 +1026,7 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 	s32 slots;
 	s32 slots;
 	int rets = 0;
 	int rets = 0;
 
 
-	dev_dbg(&dev->pdev->dev, "irq thread: Interrupt Registers HHISR|HISR|SEC=%02X|%04X|%02X\n",
+	dev_dbg(dev->dev, "irq thread: Interrupt Registers HHISR|HISR|SEC=%02X|%04X|%02X\n",
 		mei_txe_br_reg_read(hw, HHISR_REG),
 		mei_txe_br_reg_read(hw, HHISR_REG),
 		mei_txe_br_reg_read(hw, HISR_REG),
 		mei_txe_br_reg_read(hw, HISR_REG),
 		mei_txe_sec_reg_read_silent(hw, SEC_IPC_HOST_INT_STATUS_REG));
 		mei_txe_sec_reg_read_silent(hw, SEC_IPC_HOST_INT_STATUS_REG));
@@ -951,7 +1036,7 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 	mei_io_list_init(&complete_list);
 	mei_io_list_init(&complete_list);
 
 
-	if (pci_dev_msi_enabled(dev->pdev))
+	if (pci_dev_msi_enabled(to_pci_dev(dev->dev)))
 		mei_txe_check_and_ack_intrs(dev, true);
 		mei_txe_check_and_ack_intrs(dev, true);
 
 
 	/* show irq events */
 	/* show irq events */
@@ -965,17 +1050,17 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 	 * or TXE driver resetting the HECI interface.
 	 * or TXE driver resetting the HECI interface.
 	 */
 	 */
 	if (test_and_clear_bit(TXE_INTR_READINESS_BIT, &hw->intr_cause)) {
 	if (test_and_clear_bit(TXE_INTR_READINESS_BIT, &hw->intr_cause)) {
-		dev_dbg(&dev->pdev->dev, "Readiness Interrupt was received...\n");
+		dev_dbg(dev->dev, "Readiness Interrupt was received...\n");
 
 
 		/* Check if SeC is going through reset */
 		/* Check if SeC is going through reset */
 		if (mei_txe_readiness_is_sec_rdy(hw->readiness)) {
 		if (mei_txe_readiness_is_sec_rdy(hw->readiness)) {
-			dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
+			dev_dbg(dev->dev, "we need to start the dev.\n");
 			dev->recvd_hw_ready = true;
 			dev->recvd_hw_ready = true;
 		} else {
 		} else {
 			dev->recvd_hw_ready = false;
 			dev->recvd_hw_ready = false;
 			if (dev->dev_state != MEI_DEV_RESETTING) {
 			if (dev->dev_state != MEI_DEV_RESETTING) {
 
 
-				dev_warn(&dev->pdev->dev, "FW not ready: resetting.\n");
+				dev_warn(dev->dev, "FW not ready: resetting.\n");
 				schedule_work(&dev->reset_work);
 				schedule_work(&dev->reset_work);
 				goto end;
 				goto end;
 
 
@@ -992,7 +1077,7 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 
 
 	if (test_and_clear_bit(TXE_INTR_ALIVENESS_BIT, &hw->intr_cause)) {
 	if (test_and_clear_bit(TXE_INTR_ALIVENESS_BIT, &hw->intr_cause)) {
 		/* Clear the interrupt cause */
 		/* Clear the interrupt cause */
-		dev_dbg(&dev->pdev->dev,
+		dev_dbg(dev->dev,
 			"Aliveness Interrupt: Status: %d\n", hw->aliveness);
 			"Aliveness Interrupt: Status: %d\n", hw->aliveness);
 		dev->pg_event = MEI_PG_EVENT_RECEIVED;
 		dev->pg_event = MEI_PG_EVENT_RECEIVED;
 		if (waitqueue_active(&hw->wait_aliveness_resp))
 		if (waitqueue_active(&hw->wait_aliveness_resp))
@@ -1008,7 +1093,7 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 		/* Read from TXE */
 		/* Read from TXE */
 		rets = mei_irq_read_handler(dev, &complete_list, &slots);
 		rets = mei_irq_read_handler(dev, &complete_list, &slots);
 		if (rets && dev->dev_state != MEI_DEV_RESETTING) {
 		if (rets && dev->dev_state != MEI_DEV_RESETTING) {
-			dev_err(&dev->pdev->dev,
+			dev_err(dev->dev,
 				"mei_irq_read_handler ret = %d.\n", rets);
 				"mei_irq_read_handler ret = %d.\n", rets);
 
 
 			schedule_work(&dev->reset_work);
 			schedule_work(&dev->reset_work);
@@ -1026,7 +1111,7 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 		rets = mei_irq_write_handler(dev, &complete_list);
 		rets = mei_irq_write_handler(dev, &complete_list);
 		if (rets && rets != -EMSGSIZE)
 		if (rets && rets != -EMSGSIZE)
-			dev_err(&dev->pdev->dev, "mei_irq_write_handler ret = %d.\n",
+			dev_err(dev->dev, "mei_irq_write_handler ret = %d.\n",
 				rets);
 				rets);
 		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 	}
 	}
@@ -1034,7 +1119,7 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 	mei_irq_compl_handler(dev, &complete_list);
 	mei_irq_compl_handler(dev, &complete_list);
 
 
 end:
 end:
-	dev_dbg(&dev->pdev->dev, "interrupt thread end ret = %d\n", rets);
+	dev_dbg(dev->dev, "interrupt thread end ret = %d\n", rets);
 
 
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 
 
@@ -1046,6 +1131,7 @@ static const struct mei_hw_ops mei_txe_hw_ops = {
 
 
 	.host_is_ready = mei_txe_host_is_ready,
 	.host_is_ready = mei_txe_host_is_ready,
 
 
+	.fw_status = mei_txe_fw_status,
 	.pg_state = mei_txe_pg_state,
 	.pg_state = mei_txe_pg_state,
 
 
 	.hw_is_ready = mei_txe_hw_is_ready,
 	.hw_is_ready = mei_txe_hw_is_ready,
@@ -1072,27 +1158,14 @@ static const struct mei_hw_ops mei_txe_hw_ops = {
 
 
 };
 };
 
 
-#define MEI_CFG_TXE_FW_STS                            \
-	.fw_status.count = 2,                         \
-	.fw_status.status[0] = PCI_CFG_TXE_FW_STS0,   \
-	.fw_status.status[1] = PCI_CFG_TXE_FW_STS1
-
-const struct mei_cfg mei_txe_cfg = {
-	MEI_CFG_TXE_FW_STS,
-};
-
-
 /**
 /**
  * mei_txe_dev_init - allocates and initializes txe hardware specific structure
  * mei_txe_dev_init - allocates and initializes txe hardware specific structure
  *
  *
- * @pdev - pci device
- * @cfg - per device generation config
- *
- * returns struct mei_device * on success or NULL;
+ * @pdev: pci device
  *
  *
+ * Return: struct mei_device * on success or NULL
  */
  */
-struct mei_device *mei_txe_dev_init(struct pci_dev *pdev,
-				    const struct mei_cfg *cfg)
+struct mei_device *mei_txe_dev_init(struct pci_dev *pdev)
 {
 {
 	struct mei_device *dev;
 	struct mei_device *dev;
 	struct mei_txe_hw *hw;
 	struct mei_txe_hw *hw;
@@ -1102,15 +1175,12 @@ struct mei_device *mei_txe_dev_init(struct pci_dev *pdev,
 	if (!dev)
 	if (!dev)
 		return NULL;
 		return NULL;
 
 
-	mei_device_init(dev, cfg);
+	mei_device_init(dev, &pdev->dev, &mei_txe_hw_ops);
 
 
 	hw = to_txe_hw(dev);
 	hw = to_txe_hw(dev);
 
 
 	init_waitqueue_head(&hw->wait_aliveness_resp);
 	init_waitqueue_head(&hw->wait_aliveness_resp);
 
 
-	dev->ops = &mei_txe_hw_ops;
-
-	dev->pdev = pdev;
 	return dev;
 	return dev;
 }
 }
 
 
@@ -1120,6 +1190,8 @@ struct mei_device *mei_txe_dev_init(struct pci_dev *pdev,
  * @dev:   the device structure
  * @dev:   the device structure
  * @addr:  physical address start of the range
  * @addr:  physical address start of the range
  * @range: physical range size
  * @range: physical range size
+ *
+ * Return: 0 on success an error code otherwise
  */
  */
 int mei_txe_setup_satt2(struct mei_device *dev, phys_addr_t addr, u32 range)
 int mei_txe_setup_satt2(struct mei_device *dev, phys_addr_t addr, u32 range)
 {
 {
@@ -1151,7 +1223,7 @@ int mei_txe_setup_satt2(struct mei_device *dev, phys_addr_t addr, u32 range)
 	mei_txe_br_reg_write(hw, SATT2_SAP_SIZE_REG, range);
 	mei_txe_br_reg_write(hw, SATT2_SAP_SIZE_REG, range);
 	mei_txe_br_reg_write(hw, SATT2_BRG_BA_LSB_REG, lo32);
 	mei_txe_br_reg_write(hw, SATT2_BRG_BA_LSB_REG, lo32);
 	mei_txe_br_reg_write(hw, SATT2_CTRL_REG, ctrl);
 	mei_txe_br_reg_write(hw, SATT2_CTRL_REG, ctrl);
-	dev_dbg(&dev->pdev->dev, "SATT2: SAP_SIZE_OFFSET=0x%08X, BRG_BA_LSB_OFFSET=0x%08X, CTRL_OFFSET=0x%08X\n",
+	dev_dbg(dev->dev, "SATT2: SAP_SIZE_OFFSET=0x%08X, BRG_BA_LSB_OFFSET=0x%08X, CTRL_OFFSET=0x%08X\n",
 		range, lo32, ctrl);
 		range, lo32, ctrl);
 
 
 	return 0;
 	return 0;

+ 2 - 4
drivers/misc/mei/hw-txe.h

@@ -40,6 +40,7 @@
  * @mem_addr:            SeC and BRIDGE bars
  * @mem_addr:            SeC and BRIDGE bars
  * @aliveness:           aliveness (power gating) state of the hardware
  * @aliveness:           aliveness (power gating) state of the hardware
  * @readiness:           readiness state of the hardware
  * @readiness:           readiness state of the hardware
+ * @slots:               number of empty slots
  * @wait_aliveness_resp: aliveness wait queue
  * @wait_aliveness_resp: aliveness wait queue
  * @intr_cause:          translated interrupt cause
  * @intr_cause:          translated interrupt cause
  */
  */
@@ -61,10 +62,7 @@ static inline struct mei_device *hw_txe_to_mei(struct mei_txe_hw *hw)
 	return container_of((void *)hw, struct mei_device, hw);
 	return container_of((void *)hw, struct mei_device, hw);
 }
 }
 
 
-extern const struct mei_cfg mei_txe_cfg;
-
-struct mei_device *mei_txe_dev_init(struct pci_dev *pdev,
-	const struct mei_cfg *cfg);
+struct mei_device *mei_txe_dev_init(struct pci_dev *pdev);
 
 
 irqreturn_t mei_txe_irq_quick_handler(int irq, void *dev_id);
 irqreturn_t mei_txe_irq_quick_handler(int irq, void *dev_id);
 irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id);
 irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id);

+ 51 - 23
drivers/misc/mei/hw.h

@@ -97,23 +97,52 @@ enum mei_stop_reason_types {
 	SYSTEM_S5_ENTRY = 0x08
 	SYSTEM_S5_ENTRY = 0x08
 };
 };
 
 
+
+/**
+ * enum mei_hbm_status  - mei host bus messages return values
+ *
+ * @MEI_HBMS_SUCCESS           : status success
+ * @MEI_HBMS_CLIENT_NOT_FOUND  : client not found
+ * @MEI_HBMS_ALREADY_EXISTS    : connection already established
+ * @MEI_HBMS_REJECTED          : connection is rejected
+ * @MEI_HBMS_INVALID_PARAMETER : invalid parameter
+ * @MEI_HBMS_NOT_ALLOWED       : operation not allowed
+ * @MEI_HBMS_ALREADY_STARTED   : system is already started
+ * @MEI_HBMS_NOT_STARTED       : system not started
+ *
+ * @MEI_HBMS_MAX               : sentinel
+ */
+enum mei_hbm_status {
+	MEI_HBMS_SUCCESS           = 0,
+	MEI_HBMS_CLIENT_NOT_FOUND  = 1,
+	MEI_HBMS_ALREADY_EXISTS    = 2,
+	MEI_HBMS_REJECTED          = 3,
+	MEI_HBMS_INVALID_PARAMETER = 4,
+	MEI_HBMS_NOT_ALLOWED       = 5,
+	MEI_HBMS_ALREADY_STARTED   = 6,
+	MEI_HBMS_NOT_STARTED       = 7,
+
+	MEI_HBMS_MAX
+};
+
+
 /*
 /*
  * Client Connect Status
  * Client Connect Status
  * used by hbm_client_connect_response.status
  * used by hbm_client_connect_response.status
  */
  */
 enum mei_cl_connect_status {
 enum mei_cl_connect_status {
-	MEI_CL_CONN_SUCCESS          = 0x00,
-	MEI_CL_CONN_NOT_FOUND        = 0x01,
-	MEI_CL_CONN_ALREADY_STARTED  = 0x02,
-	MEI_CL_CONN_OUT_OF_RESOURCES = 0x03,
-	MEI_CL_CONN_MESSAGE_SMALL    = 0x04
+	MEI_CL_CONN_SUCCESS          = MEI_HBMS_SUCCESS,
+	MEI_CL_CONN_NOT_FOUND        = MEI_HBMS_CLIENT_NOT_FOUND,
+	MEI_CL_CONN_ALREADY_STARTED  = MEI_HBMS_ALREADY_EXISTS,
+	MEI_CL_CONN_OUT_OF_RESOURCES = MEI_HBMS_REJECTED,
+	MEI_CL_CONN_MESSAGE_SMALL    = MEI_HBMS_INVALID_PARAMETER,
 };
 };
 
 
 /*
 /*
  * Client Disconnect Status
  * Client Disconnect Status
  */
  */
 enum  mei_cl_disconnect_status {
 enum  mei_cl_disconnect_status {
-	MEI_CL_DISCONN_SUCCESS = 0x00
+	MEI_CL_DISCONN_SUCCESS = MEI_HBMS_SUCCESS
 };
 };
 
 
 /*
 /*
@@ -138,10 +167,10 @@ struct mei_bus_message {
  * struct hbm_cl_cmd - client specific host bus command
  * struct hbm_cl_cmd - client specific host bus command
  *	CONNECT, DISCONNECT, and FlOW CONTROL
  *	CONNECT, DISCONNECT, and FlOW CONTROL
  *
  *
- * @hbm_cmd - bus message command header
- * @me_addr - address of the client in ME
- * @host_addr - address of the client in the driver
- * @data
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @host_addr: address of the client in the driver
+ * @data: generic data
  */
  */
 struct mei_hbm_cl_cmd {
 struct mei_hbm_cl_cmd {
 	u8 hbm_cmd;
 	u8 hbm_cmd;
@@ -206,14 +235,13 @@ struct mei_client_properties {
 
 
 struct hbm_props_request {
 struct hbm_props_request {
 	u8 hbm_cmd;
 	u8 hbm_cmd;
-	u8 address;
+	u8 me_addr;
 	u8 reserved[2];
 	u8 reserved[2];
 } __packed;
 } __packed;
 
 
-
 struct hbm_props_response {
 struct hbm_props_response {
 	u8 hbm_cmd;
 	u8 hbm_cmd;
-	u8 address;
+	u8 me_addr;
 	u8 status;
 	u8 status;
 	u8 reserved[1];
 	u8 reserved[1];
 	struct mei_client_properties client_properties;
 	struct mei_client_properties client_properties;
@@ -222,8 +250,8 @@ struct hbm_props_response {
 /**
 /**
  * struct hbm_power_gate - power gate request/response
  * struct hbm_power_gate - power gate request/response
  *
  *
- * @hbm_cmd - bus message command header
- * @reserved[3]
+ * @hbm_cmd: bus message command header
+ * @reserved: reserved
  */
  */
 struct hbm_power_gate {
 struct hbm_power_gate {
 	u8 hbm_cmd;
 	u8 hbm_cmd;
@@ -233,10 +261,10 @@ struct hbm_power_gate {
 /**
 /**
  * struct hbm_client_connect_request - connect/disconnect request
  * struct hbm_client_connect_request - connect/disconnect request
  *
  *
- * @hbm_cmd - bus message command header
- * @me_addr - address of the client in ME
- * @host_addr - address of the client in the driver
- * @reserved
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @host_addr: address of the client in the driver
+ * @reserved: reserved
  */
  */
 struct hbm_client_connect_request {
 struct hbm_client_connect_request {
 	u8 hbm_cmd;
 	u8 hbm_cmd;
@@ -248,10 +276,10 @@ struct hbm_client_connect_request {
 /**
 /**
  * struct hbm_client_connect_response - connect/disconnect response
  * struct hbm_client_connect_response - connect/disconnect response
  *
  *
- * @hbm_cmd - bus message command header
- * @me_addr - address of the client in ME
- * @host_addr - address of the client in the driver
- * @status - status of the request
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @host_addr: address of the client in the driver
+ * @status: status of the request
  */
  */
 struct hbm_client_connect_response {
 struct hbm_client_connect_response {
 	u8 hbm_cmd;
 	u8 hbm_cmd;

+ 55 - 52
drivers/misc/mei/init.c

@@ -15,7 +15,6 @@
  */
  */
 
 
 #include <linux/export.h>
 #include <linux/export.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
@@ -43,13 +42,23 @@ const char *mei_dev_state_str(int state)
 #undef MEI_DEV_STATE
 #undef MEI_DEV_STATE
 }
 }
 
 
+const char *mei_pg_state_str(enum mei_pg_state state)
+{
+#define MEI_PG_STATE(state) case MEI_PG_##state: return #state
+	switch (state) {
+	MEI_PG_STATE(OFF);
+	MEI_PG_STATE(ON);
+	default:
+		return "unknown";
+	}
+#undef MEI_PG_STATE
+}
+
 
 
 /**
 /**
- * mei_cancel_work. Cancel mei background jobs
+ * mei_cancel_work - Cancel mei background jobs
  *
  *
  * @dev: the device structure
  * @dev: the device structure
- *
- * returns 0 on success or < 0 if the reset hasn't succeeded
  */
  */
 void mei_cancel_work(struct mei_device *dev)
 void mei_cancel_work(struct mei_device *dev)
 {
 {
@@ -64,6 +73,8 @@ EXPORT_SYMBOL_GPL(mei_cancel_work);
  * mei_reset - resets host and fw.
  * mei_reset - resets host and fw.
  *
  *
  * @dev: the device structure
  * @dev: the device structure
+ *
+ * Return: 0 on success or < 0 if the reset hasn't succeeded
  */
  */
 int mei_reset(struct mei_device *dev)
 int mei_reset(struct mei_device *dev)
 {
 {
@@ -76,8 +87,9 @@ int mei_reset(struct mei_device *dev)
 	    state != MEI_DEV_POWER_DOWN &&
 	    state != MEI_DEV_POWER_DOWN &&
 	    state != MEI_DEV_POWER_UP) {
 	    state != MEI_DEV_POWER_UP) {
 		struct mei_fw_status fw_status;
 		struct mei_fw_status fw_status;
+
 		mei_fw_status(dev, &fw_status);
 		mei_fw_status(dev, &fw_status);
-		dev_warn(&dev->pdev->dev,
+		dev_warn(dev->dev,
 			"unexpected reset: dev_state = %s " FW_STS_FMT "\n",
 			"unexpected reset: dev_state = %s " FW_STS_FMT "\n",
 			mei_dev_state_str(state), FW_STS_PRM(fw_status));
 			mei_dev_state_str(state), FW_STS_PRM(fw_status));
 	}
 	}
@@ -95,7 +107,7 @@ int mei_reset(struct mei_device *dev)
 
 
 	dev->reset_count++;
 	dev->reset_count++;
 	if (dev->reset_count > MEI_MAX_CONSEC_RESET) {
 	if (dev->reset_count > MEI_MAX_CONSEC_RESET) {
-		dev_err(&dev->pdev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
+		dev_err(dev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
 		dev->dev_state = MEI_DEV_DISABLED;
 		dev->dev_state = MEI_DEV_DISABLED;
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -116,7 +128,7 @@ int mei_reset(struct mei_device *dev)
 		mei_cl_all_wakeup(dev);
 		mei_cl_all_wakeup(dev);
 
 
 		/* remove entry if already in list */
 		/* remove entry if already in list */
-		dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
+		dev_dbg(dev->dev, "remove iamthif and wd from the file list.\n");
 		mei_cl_unlink(&dev->wd_cl);
 		mei_cl_unlink(&dev->wd_cl);
 		mei_cl_unlink(&dev->iamthif_cl);
 		mei_cl_unlink(&dev->iamthif_cl);
 		mei_amthif_reset_params(dev);
 		mei_amthif_reset_params(dev);
@@ -128,28 +140,28 @@ int mei_reset(struct mei_device *dev)
 	dev->wd_pending = false;
 	dev->wd_pending = false;
 
 
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "hw_reset failed ret = %d\n", ret);
+		dev_err(dev->dev, "hw_reset failed ret = %d\n", ret);
 		return ret;
 		return ret;
 	}
 	}
 
 
 	if (state == MEI_DEV_POWER_DOWN) {
 	if (state == MEI_DEV_POWER_DOWN) {
-		dev_dbg(&dev->pdev->dev, "powering down: end of reset\n");
+		dev_dbg(dev->dev, "powering down: end of reset\n");
 		dev->dev_state = MEI_DEV_DISABLED;
 		dev->dev_state = MEI_DEV_DISABLED;
 		return 0;
 		return 0;
 	}
 	}
 
 
 	ret = mei_hw_start(dev);
 	ret = mei_hw_start(dev);
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "hw_start failed ret = %d\n", ret);
+		dev_err(dev->dev, "hw_start failed ret = %d\n", ret);
 		return ret;
 		return ret;
 	}
 	}
 
 
-	dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
+	dev_dbg(dev->dev, "link is established start sending messages.\n");
 
 
 	dev->dev_state = MEI_DEV_INIT_CLIENTS;
 	dev->dev_state = MEI_DEV_INIT_CLIENTS;
 	ret = mei_hbm_start_req(dev);
 	ret = mei_hbm_start_req(dev);
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "hbm_start failed ret = %d\n", ret);
+		dev_err(dev->dev, "hbm_start failed ret = %d\n", ret);
 		dev->dev_state = MEI_DEV_RESETTING;
 		dev->dev_state = MEI_DEV_RESETTING;
 		return ret;
 		return ret;
 	}
 	}
@@ -163,11 +175,12 @@ EXPORT_SYMBOL_GPL(mei_reset);
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 int mei_start(struct mei_device *dev)
 int mei_start(struct mei_device *dev)
 {
 {
 	int ret;
 	int ret;
+
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 
 
 	/* acknowledge interrupt and stop interrupts */
 	/* acknowledge interrupt and stop interrupts */
@@ -175,7 +188,7 @@ int mei_start(struct mei_device *dev)
 
 
 	mei_hw_config(dev);
 	mei_hw_config(dev);
 
 
-	dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
+	dev_dbg(dev->dev, "reset in start the mei device.\n");
 
 
 	dev->reset_count = 0;
 	dev->reset_count = 0;
 	do {
 	do {
@@ -183,43 +196,43 @@ int mei_start(struct mei_device *dev)
 		ret = mei_reset(dev);
 		ret = mei_reset(dev);
 
 
 		if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
 		if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
-			dev_err(&dev->pdev->dev, "reset failed ret = %d", ret);
+			dev_err(dev->dev, "reset failed ret = %d", ret);
 			goto err;
 			goto err;
 		}
 		}
 	} while (ret);
 	} while (ret);
 
 
 	/* we cannot start the device w/o hbm start message completed */
 	/* we cannot start the device w/o hbm start message completed */
 	if (dev->dev_state == MEI_DEV_DISABLED) {
 	if (dev->dev_state == MEI_DEV_DISABLED) {
-		dev_err(&dev->pdev->dev, "reset failed");
+		dev_err(dev->dev, "reset failed");
 		goto err;
 		goto err;
 	}
 	}
 
 
 	if (mei_hbm_start_wait(dev)) {
 	if (mei_hbm_start_wait(dev)) {
-		dev_err(&dev->pdev->dev, "HBM haven't started");
+		dev_err(dev->dev, "HBM haven't started");
 		goto err;
 		goto err;
 	}
 	}
 
 
 	if (!mei_host_is_ready(dev)) {
 	if (!mei_host_is_ready(dev)) {
-		dev_err(&dev->pdev->dev, "host is not ready.\n");
+		dev_err(dev->dev, "host is not ready.\n");
 		goto err;
 		goto err;
 	}
 	}
 
 
 	if (!mei_hw_is_ready(dev)) {
 	if (!mei_hw_is_ready(dev)) {
-		dev_err(&dev->pdev->dev, "ME is not ready.\n");
+		dev_err(dev->dev, "ME is not ready.\n");
 		goto err;
 		goto err;
 	}
 	}
 
 
 	if (!mei_hbm_version_is_supported(dev)) {
 	if (!mei_hbm_version_is_supported(dev)) {
-		dev_dbg(&dev->pdev->dev, "MEI start failed.\n");
+		dev_dbg(dev->dev, "MEI start failed.\n");
 		goto err;
 		goto err;
 	}
 	}
 
 
-	dev_dbg(&dev->pdev->dev, "link layer has been established.\n");
+	dev_dbg(dev->dev, "link layer has been established.\n");
 
 
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 	return 0;
 	return 0;
 err:
 err:
-	dev_err(&dev->pdev->dev, "link layer initialization failed.\n");
+	dev_err(dev->dev, "link layer initialization failed.\n");
 	dev->dev_state = MEI_DEV_DISABLED;
 	dev->dev_state = MEI_DEV_DISABLED;
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 	return -ENODEV;
 	return -ENODEV;
@@ -231,7 +244,7 @@ EXPORT_SYMBOL_GPL(mei_start);
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 on success or -ENODEV if the restart hasn't succeeded
+ * Return: 0 on success or -ENODEV if the restart hasn't succeeded
  */
  */
 int mei_restart(struct mei_device *dev)
 int mei_restart(struct mei_device *dev)
 {
 {
@@ -249,7 +262,7 @@ int mei_restart(struct mei_device *dev)
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 
 
 	if (err == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
 	if (err == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
-		dev_err(&dev->pdev->dev, "device disabled = %d\n", err);
+		dev_err(dev->dev, "device disabled = %d\n", err);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -275,7 +288,7 @@ static void mei_reset_work(struct work_struct *work)
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 
 
 	if (dev->dev_state == MEI_DEV_DISABLED) {
 	if (dev->dev_state == MEI_DEV_DISABLED) {
-		dev_err(&dev->pdev->dev, "device disabled = %d\n", ret);
+		dev_err(dev->dev, "device disabled = %d\n", ret);
 		return;
 		return;
 	}
 	}
 
 
@@ -286,7 +299,7 @@ static void mei_reset_work(struct work_struct *work)
 
 
 void mei_stop(struct mei_device *dev)
 void mei_stop(struct mei_device *dev)
 {
 {
-	dev_dbg(&dev->pdev->dev, "stopping the device.\n");
+	dev_dbg(dev->dev, "stopping the device.\n");
 
 
 	mei_cancel_work(dev);
 	mei_cancel_work(dev);
 
 
@@ -312,7 +325,7 @@ EXPORT_SYMBOL_GPL(mei_stop);
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns true of there is no pending write
+ * Return: true of there is no pending write
  */
  */
 bool mei_write_is_idle(struct mei_device *dev)
 bool mei_write_is_idle(struct mei_device *dev)
 {
 {
@@ -320,7 +333,7 @@ bool mei_write_is_idle(struct mei_device *dev)
 		list_empty(&dev->ctrl_wr_list.list) &&
 		list_empty(&dev->ctrl_wr_list.list) &&
 		list_empty(&dev->write_list.list));
 		list_empty(&dev->write_list.list));
 
 
-	dev_dbg(&dev->pdev->dev, "write pg: is idle[%d] state=%s ctrl=%d write=%d\n",
+	dev_dbg(dev->dev, "write pg: is idle[%d] state=%s ctrl=%d write=%d\n",
 		idle,
 		idle,
 		mei_dev_state_str(dev->dev_state),
 		mei_dev_state_str(dev->dev_state),
 		list_empty(&dev->ctrl_wr_list.list),
 		list_empty(&dev->ctrl_wr_list.list),
@@ -330,36 +343,25 @@ bool mei_write_is_idle(struct mei_device *dev)
 }
 }
 EXPORT_SYMBOL_GPL(mei_write_is_idle);
 EXPORT_SYMBOL_GPL(mei_write_is_idle);
 
 
-int mei_fw_status(struct mei_device *dev, struct mei_fw_status *fw_status)
-{
-	int i;
-	const struct mei_fw_status *fw_src = &dev->cfg->fw_status;
-
-	if (!fw_status)
-		return -EINVAL;
-
-	fw_status->count = fw_src->count;
-	for (i = 0; i < fw_src->count && i < MEI_FW_STATUS_MAX; i++) {
-		int ret;
-		ret = pci_read_config_dword(dev->pdev,
-			fw_src->status[i], &fw_status->status[i]);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(mei_fw_status);
-
-void mei_device_init(struct mei_device *dev, const struct mei_cfg *cfg)
+/**
+ * mei_device_init  -- initialize mei_device structure
+ *
+ * @dev: the mei device
+ * @device: the device structure
+ * @hw_ops: hw operations
+ */
+void mei_device_init(struct mei_device *dev,
+		     struct device *device,
+		     const struct mei_hw_ops *hw_ops)
 {
 {
 	/* setup our list array */
 	/* setup our list array */
 	INIT_LIST_HEAD(&dev->file_list);
 	INIT_LIST_HEAD(&dev->file_list);
 	INIT_LIST_HEAD(&dev->device_list);
 	INIT_LIST_HEAD(&dev->device_list);
+	INIT_LIST_HEAD(&dev->me_clients);
 	mutex_init(&dev->device_lock);
 	mutex_init(&dev->device_lock);
 	init_waitqueue_head(&dev->wait_hw_ready);
 	init_waitqueue_head(&dev->wait_hw_ready);
 	init_waitqueue_head(&dev->wait_pg);
 	init_waitqueue_head(&dev->wait_pg);
-	init_waitqueue_head(&dev->wait_recvd_msg);
+	init_waitqueue_head(&dev->wait_hbm_start);
 	init_waitqueue_head(&dev->wait_stop_wd);
 	init_waitqueue_head(&dev->wait_stop_wd);
 	dev->dev_state = MEI_DEV_INITIALIZING;
 	dev->dev_state = MEI_DEV_INITIALIZING;
 	dev->reset_count = 0;
 	dev->reset_count = 0;
@@ -389,7 +391,8 @@ void mei_device_init(struct mei_device *dev, const struct mei_cfg *cfg)
 	bitmap_set(dev->host_clients_map, 0, 1);
 	bitmap_set(dev->host_clients_map, 0, 1);
 
 
 	dev->pg_event = MEI_PG_EVENT_IDLE;
 	dev->pg_event = MEI_PG_EVENT_IDLE;
-	dev->cfg      = cfg;
+	dev->ops      = hw_ops;
+	dev->dev      = device;
 }
 }
 EXPORT_SYMBOL_GPL(mei_device_init);
 EXPORT_SYMBOL_GPL(mei_device_init);
 
 

+ 43 - 53
drivers/misc/mei/interrupt.c

@@ -16,11 +16,11 @@
 
 
 
 
 #include <linux/export.h>
 #include <linux/export.h>
-#include <linux/pci.h>
 #include <linux/kthread.h>
 #include <linux/kthread.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/jiffies.h>
 #include <linux/jiffies.h>
+#include <linux/slab.h>
 
 
 #include <linux/mei.h>
 #include <linux/mei.h>
 
 
@@ -33,8 +33,8 @@
  * mei_irq_compl_handler - dispatch complete handlers
  * mei_irq_compl_handler - dispatch complete handlers
  *	for the completed callbacks
  *	for the completed callbacks
  *
  *
- * @dev - mei device
- * @compl_list - list of completed cbs
+ * @dev: mei device
+ * @compl_list: list of completed cbs
  */
  */
 void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
 void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
 {
 {
@@ -47,7 +47,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
 		if (!cl)
 		if (!cl)
 			continue;
 			continue;
 
 
-		dev_dbg(&dev->pdev->dev, "completing call back.\n");
+		dev_dbg(dev->dev, "completing call back.\n");
 		if (cl == &dev->iamthif_cl)
 		if (cl == &dev->iamthif_cl)
 			mei_amthif_complete(dev, cb);
 			mei_amthif_complete(dev, cb);
 		else
 		else
@@ -62,7 +62,7 @@ EXPORT_SYMBOL_GPL(mei_irq_compl_handler);
  * @cl: host client
  * @cl: host client
  * @mei_hdr: header of mei client message
  * @mei_hdr: header of mei client message
  *
  *
- * returns true if matches, false otherwise
+ * Return: true if matches, false otherwise
  */
  */
 static inline int mei_cl_hbm_equal(struct mei_cl *cl,
 static inline int mei_cl_hbm_equal(struct mei_cl *cl,
 			struct mei_msg_hdr *mei_hdr)
 			struct mei_msg_hdr *mei_hdr)
@@ -72,12 +72,12 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
 }
 }
 /**
 /**
  * mei_cl_is_reading - checks if the client
  * mei_cl_is_reading - checks if the client
-		is the one to read this message
+ *		is the one to read this message
  *
  *
  * @cl: mei client
  * @cl: mei client
  * @mei_hdr: header of mei message
  * @mei_hdr: header of mei message
  *
  *
- * returns true on match and false otherwise
+ * Return: true on match and false otherwise
  */
  */
 static bool mei_cl_is_reading(struct mei_cl *cl, struct mei_msg_hdr *mei_hdr)
 static bool mei_cl_is_reading(struct mei_cl *cl, struct mei_msg_hdr *mei_hdr)
 {
 {
@@ -87,13 +87,13 @@ static bool mei_cl_is_reading(struct mei_cl *cl, struct mei_msg_hdr *mei_hdr)
 }
 }
 
 
 /**
 /**
- * mei_irq_read_client_message - process client message
+ * mei_cl_irq_read_msg - process client message
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  * @mei_hdr: header of mei client message
  * @mei_hdr: header of mei client message
  * @complete_list: An instance of our list structure
  * @complete_list: An instance of our list structure
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 static int mei_cl_irq_read_msg(struct mei_device *dev,
 static int mei_cl_irq_read_msg(struct mei_device *dev,
 			       struct mei_msg_hdr *mei_hdr,
 			       struct mei_msg_hdr *mei_hdr,
@@ -126,7 +126,6 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
 					  GFP_KERNEL);
 					  GFP_KERNEL);
 
 
 			if (!buffer) {
 			if (!buffer) {
-				cl_err(dev, cl, "allocation failed.\n");
 				list_del(&cb->list);
 				list_del(&cb->list);
 				return -ENOMEM;
 				return -ENOMEM;
 			}
 			}
@@ -149,10 +148,10 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
 		break;
 		break;
 	}
 	}
 
 
-	dev_dbg(&dev->pdev->dev, "message read\n");
+	dev_dbg(dev->dev, "message read\n");
 	if (!buffer) {
 	if (!buffer) {
 		mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
 		mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
-		dev_dbg(&dev->pdev->dev, "discarding message " MEI_HDR_FMT "\n",
+		dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
 				MEI_HDR_PRM(mei_hdr));
 				MEI_HDR_PRM(mei_hdr));
 	}
 	}
 
 
@@ -166,7 +165,7 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
  * @cb: callback block.
  * @cb: callback block.
  * @cmpl_list: complete list.
  * @cmpl_list: complete list.
  *
  *
- * returns 0, OK; otherwise, error.
+ * Return: 0, OK; otherwise, error.
  */
  */
 static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
 static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
 				     struct mei_cl_cb *cmpl_list)
 				     struct mei_cl_cb *cmpl_list)
@@ -195,16 +194,16 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
 
 
 
 
 /**
 /**
- * mei_cl_irq_close - processes close related operation from
+ * mei_cl_irq_disconnect - processes close related operation from
  *	interrupt thread context - send disconnect request
  *	interrupt thread context - send disconnect request
  *
  *
  * @cl: client
  * @cl: client
  * @cb: callback block.
  * @cb: callback block.
  * @cmpl_list: complete list.
  * @cmpl_list: complete list.
  *
  *
- * returns 0, OK; otherwise, error.
+ * Return: 0, OK; otherwise, error.
  */
  */
-static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
+static int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
 			    struct mei_cl_cb *cmpl_list)
 			    struct mei_cl_cb *cmpl_list)
 {
 {
 	struct mei_device *dev = cl->dev;
 	struct mei_device *dev = cl->dev;
@@ -235,14 +234,14 @@ static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
 
 
 
 
 /**
 /**
- * mei_cl_irq_close - processes client read related operation from the
+ * mei_cl_irq_read - processes client read related operation from the
  *	interrupt thread context - request for flow control credits
  *	interrupt thread context - request for flow control credits
  *
  *
  * @cl: client
  * @cl: client
  * @cb: callback block.
  * @cb: callback block.
  * @cmpl_list: complete list.
  * @cmpl_list: complete list.
  *
  *
- * returns 0, OK; otherwise, error.
+ * Return: 0, OK; otherwise, error.
  */
  */
 static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
 static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
 			   struct mei_cl_cb *cmpl_list)
 			   struct mei_cl_cb *cmpl_list)
@@ -279,7 +278,7 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
  * @cb: callback block.
  * @cb: callback block.
  * @cmpl_list: complete list.
  * @cmpl_list: complete list.
  *
  *
- * returns 0, OK; otherwise, error.
+ * Return: 0, OK; otherwise, error.
  */
  */
 static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
 static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
 			      struct mei_cl_cb *cmpl_list)
 			      struct mei_cl_cb *cmpl_list)
@@ -322,7 +321,7 @@ static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
  * @cmpl_list: An instance of our list structure
  * @cmpl_list: An instance of our list structure
  * @slots: slots to read.
  * @slots: slots to read.
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 int mei_irq_read_handler(struct mei_device *dev,
 int mei_irq_read_handler(struct mei_device *dev,
 		struct mei_cl_cb *cmpl_list, s32 *slots)
 		struct mei_cl_cb *cmpl_list, s32 *slots)
@@ -334,20 +333,20 @@ int mei_irq_read_handler(struct mei_device *dev,
 	if (!dev->rd_msg_hdr) {
 	if (!dev->rd_msg_hdr) {
 		dev->rd_msg_hdr = mei_read_hdr(dev);
 		dev->rd_msg_hdr = mei_read_hdr(dev);
 		(*slots)--;
 		(*slots)--;
-		dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
+		dev_dbg(dev->dev, "slots =%08x.\n", *slots);
 	}
 	}
 	mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
 	mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
-	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
+	dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
 
 
 	if (mei_hdr->reserved || !dev->rd_msg_hdr) {
 	if (mei_hdr->reserved || !dev->rd_msg_hdr) {
-		dev_err(&dev->pdev->dev, "corrupted message header 0x%08X\n",
+		dev_err(dev->dev, "corrupted message header 0x%08X\n",
 				dev->rd_msg_hdr);
 				dev->rd_msg_hdr);
 		ret = -EBADMSG;
 		ret = -EBADMSG;
 		goto end;
 		goto end;
 	}
 	}
 
 
 	if (mei_slots2data(*slots) < mei_hdr->length) {
 	if (mei_slots2data(*slots) < mei_hdr->length) {
-		dev_err(&dev->pdev->dev, "less data available than length=%08x.\n",
+		dev_err(dev->dev, "less data available than length=%08x.\n",
 				*slots);
 				*slots);
 		/* we can't read the message */
 		/* we can't read the message */
 		ret = -ENODATA;
 		ret = -ENODATA;
@@ -358,7 +357,7 @@ int mei_irq_read_handler(struct mei_device *dev,
 	if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) {
 	if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) {
 		ret = mei_hbm_dispatch(dev, mei_hdr);
 		ret = mei_hbm_dispatch(dev, mei_hdr);
 		if (ret) {
 		if (ret) {
-			dev_dbg(&dev->pdev->dev, "mei_hbm_dispatch failed ret = %d\n",
+			dev_dbg(dev->dev, "mei_hbm_dispatch failed ret = %d\n",
 					ret);
 					ret);
 			goto end;
 			goto end;
 		}
 		}
@@ -375,7 +374,7 @@ int mei_irq_read_handler(struct mei_device *dev,
 
 
 	/* if no recipient cl was found we assume corrupted header */
 	/* if no recipient cl was found we assume corrupted header */
 	if (&cl->link == &dev->file_list) {
 	if (&cl->link == &dev->file_list) {
-		dev_err(&dev->pdev->dev, "no destination client found 0x%08X\n",
+		dev_err(dev->dev, "no destination client found 0x%08X\n",
 				dev->rd_msg_hdr);
 				dev->rd_msg_hdr);
 		ret = -EBADMSG;
 		ret = -EBADMSG;
 		goto end;
 		goto end;
@@ -387,14 +386,14 @@ int mei_irq_read_handler(struct mei_device *dev,
 
 
 		ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
 		ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
 		if (ret) {
 		if (ret) {
-			dev_err(&dev->pdev->dev, "mei_amthif_irq_read_msg failed = %d\n",
+			dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n",
 					ret);
 					ret);
 			goto end;
 			goto end;
 		}
 		}
 	} else {
 	} else {
 		ret = mei_cl_irq_read_msg(dev, mei_hdr, cmpl_list);
 		ret = mei_cl_irq_read_msg(dev, mei_hdr, cmpl_list);
 		if (ret) {
 		if (ret) {
-			dev_err(&dev->pdev->dev, "mei_cl_irq_read_msg failed = %d\n",
+			dev_err(dev->dev, "mei_cl_irq_read_msg failed = %d\n",
 					ret);
 					ret);
 			goto end;
 			goto end;
 		}
 		}
@@ -407,7 +406,7 @@ reset_slots:
 
 
 	if (*slots == -EOVERFLOW) {
 	if (*slots == -EOVERFLOW) {
 		/* overflow - reset */
 		/* overflow - reset */
-		dev_err(&dev->pdev->dev, "resetting due to slots overflow.\n");
+		dev_err(dev->dev, "resetting due to slots overflow.\n");
 		/* set the event since message has been read */
 		/* set the event since message has been read */
 		ret = -ERANGE;
 		ret = -ERANGE;
 		goto end;
 		goto end;
@@ -425,7 +424,7 @@ EXPORT_SYMBOL_GPL(mei_irq_read_handler);
  * @dev: the device structure
  * @dev: the device structure
  * @cmpl_list: An instance of our list structure
  * @cmpl_list: An instance of our list structure
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 {
 {
@@ -445,7 +444,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 		return -EMSGSIZE;
 		return -EMSGSIZE;
 
 
 	/* complete all waiting for write CB */
 	/* complete all waiting for write CB */
-	dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
+	dev_dbg(dev->dev, "complete all waiting for write cb.\n");
 
 
 	list = &dev->write_waiting_list;
 	list = &dev->write_waiting_list;
 	list_for_each_entry_safe(cb, next, &list->list, list) {
 	list_for_each_entry_safe(cb, next, &list->list, list) {
@@ -487,7 +486,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 	}
 	}
 
 
 	/* complete control write list CB */
 	/* complete control write list CB */
-	dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
+	dev_dbg(dev->dev, "complete control write list cb.\n");
 	list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
 	list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
 		cl = cb->cl;
 		cl = cb->cl;
 		if (!cl) {
 		if (!cl) {
@@ -495,9 +494,9 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}
 		switch (cb->fop_type) {
 		switch (cb->fop_type) {
-		case MEI_FOP_CLOSE:
+		case MEI_FOP_DISCONNECT:
 			/* send disconnect message */
 			/* send disconnect message */
-			ret = mei_cl_irq_close(cl, cb, cmpl_list);
+			ret = mei_cl_irq_disconnect(cl, cb, cmpl_list);
 			if (ret)
 			if (ret)
 				return ret;
 				return ret;
 
 
@@ -528,7 +527,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 
 
 	}
 	}
 	/* complete  write list CB */
 	/* complete  write list CB */
-	dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
+	dev_dbg(dev->dev, "complete write list cb.\n");
 	list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
 	list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
 		cl = cb->cl;
 		cl = cb->cl;
 		if (cl == NULL)
 		if (cl == NULL)
@@ -556,8 +555,6 @@ void mei_timer(struct work_struct *work)
 {
 {
 	unsigned long timeout;
 	unsigned long timeout;
 	struct mei_cl *cl;
 	struct mei_cl *cl;
-	struct mei_cl_cb  *cb_pos = NULL;
-	struct mei_cl_cb  *cb_next = NULL;
 
 
 	struct mei_device *dev = container_of(work,
 	struct mei_device *dev = container_of(work,
 					struct mei_device, timer_work.work);
 					struct mei_device, timer_work.work);
@@ -571,7 +568,7 @@ void mei_timer(struct work_struct *work)
 
 
 		if (dev->init_clients_timer) {
 		if (dev->init_clients_timer) {
 			if (--dev->init_clients_timer == 0) {
 			if (--dev->init_clients_timer == 0) {
-				dev_err(&dev->pdev->dev, "timer: init clients timeout hbm_state = %d.\n",
+				dev_err(dev->dev, "timer: init clients timeout hbm_state = %d.\n",
 					dev->hbm_state);
 					dev->hbm_state);
 				mei_reset(dev);
 				mei_reset(dev);
 				goto out;
 				goto out;
@@ -586,7 +583,7 @@ void mei_timer(struct work_struct *work)
 	list_for_each_entry(cl, &dev->file_list, link) {
 	list_for_each_entry(cl, &dev->file_list, link) {
 		if (cl->timer_count) {
 		if (cl->timer_count) {
 			if (--cl->timer_count == 0) {
 			if (--cl->timer_count == 0) {
-				dev_err(&dev->pdev->dev, "timer: connect/disconnect timeout.\n");
+				dev_err(dev->dev, "timer: connect/disconnect timeout.\n");
 				mei_reset(dev);
 				mei_reset(dev);
 				goto out;
 				goto out;
 			}
 			}
@@ -598,7 +595,7 @@ void mei_timer(struct work_struct *work)
 
 
 	if (dev->iamthif_stall_timer) {
 	if (dev->iamthif_stall_timer) {
 		if (--dev->iamthif_stall_timer == 0) {
 		if (--dev->iamthif_stall_timer == 0) {
-			dev_err(&dev->pdev->dev, "timer: amthif  hanged.\n");
+			dev_err(dev->dev, "timer: amthif  hanged.\n");
 			mei_reset(dev);
 			mei_reset(dev);
 			dev->iamthif_msg_buf_size = 0;
 			dev->iamthif_msg_buf_size = 0;
 			dev->iamthif_msg_buf_index = 0;
 			dev->iamthif_msg_buf_index = 0;
@@ -620,27 +617,20 @@ void mei_timer(struct work_struct *work)
 		timeout = dev->iamthif_timer +
 		timeout = dev->iamthif_timer +
 			mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
 			mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
 
 
-		dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
+		dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n",
 				dev->iamthif_timer);
 				dev->iamthif_timer);
-		dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
-		dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
+		dev_dbg(dev->dev, "timeout = %ld\n", timeout);
+		dev_dbg(dev->dev, "jiffies = %ld\n", jiffies);
 		if (time_after(jiffies, timeout)) {
 		if (time_after(jiffies, timeout)) {
 			/*
 			/*
 			 * User didn't read the AMTHI data on time (15sec)
 			 * User didn't read the AMTHI data on time (15sec)
 			 * freeing AMTHI for other requests
 			 * freeing AMTHI for other requests
 			 */
 			 */
 
 
-			dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
+			dev_dbg(dev->dev, "freeing AMTHI for other requests\n");
 
 
-			list_for_each_entry_safe(cb_pos, cb_next,
-				&dev->amthif_rd_complete_list.list, list) {
-
-				cl = cb_pos->file_object->private_data;
-
-				/* Finding the AMTHI entry. */
-				if (cl == &dev->iamthif_cl)
-					list_del(&cb_pos->list);
-			}
+			mei_io_list_flush(&dev->amthif_rd_complete_list,
+				&dev->iamthif_cl);
 			mei_io_cb_free(dev->iamthif_current_cb);
 			mei_io_cb_free(dev->iamthif_current_cb);
 			dev->iamthif_current_cb = NULL;
 			dev->iamthif_current_cb = NULL;
 
 

+ 66 - 77
drivers/misc/mei/main.c

@@ -17,12 +17,12 @@
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/fcntl.h>
 #include <linux/aio.h>
 #include <linux/aio.h>
-#include <linux/pci.h>
 #include <linux/poll.h>
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/ioctl.h>
 #include <linux/ioctl.h>
@@ -44,7 +44,7 @@
  * @inode: pointer to inode structure
  * @inode: pointer to inode structure
  * @file: pointer to file structure
  * @file: pointer to file structure
  *
  *
- * returns 0 on success, <0 on error
+ * Return: 0 on success, <0 on error
  */
  */
 static int mei_open(struct inode *inode, struct file *file)
 static int mei_open(struct inode *inode, struct file *file)
 {
 {
@@ -63,7 +63,7 @@ static int mei_open(struct inode *inode, struct file *file)
 
 
 	err = -ENODEV;
 	err = -ENODEV;
 	if (dev->dev_state != MEI_DEV_ENABLED) {
 	if (dev->dev_state != MEI_DEV_ENABLED) {
-		dev_dbg(&dev->pdev->dev, "dev_state != MEI_ENABLED  dev_state = %s\n",
+		dev_dbg(dev->dev, "dev_state != MEI_ENABLED  dev_state = %s\n",
 		    mei_dev_state_str(dev->dev_state));
 		    mei_dev_state_str(dev->dev_state));
 		goto err_unlock;
 		goto err_unlock;
 	}
 	}
@@ -96,7 +96,7 @@ err_unlock:
  * @inode: pointer to inode structure
  * @inode: pointer to inode structure
  * @file: pointer to file structure
  * @file: pointer to file structure
  *
  *
- * returns 0 on success, <0 on error
+ * Return: 0 on success, <0 on error
  */
  */
 static int mei_release(struct inode *inode, struct file *file)
 static int mei_release(struct inode *inode, struct file *file)
 {
 {
@@ -157,7 +157,7 @@ out:
  * @length: buffer length
  * @length: buffer length
  * @offset: data offset in buffer
  * @offset: data offset in buffer
  *
  *
- * returns >=0 data length on success , <0 on error
+ * Return: >=0 data length on success , <0 on error
  */
  */
 static ssize_t mei_read(struct file *file, char __user *ubuf,
 static ssize_t mei_read(struct file *file, char __user *ubuf,
 			size_t length, loff_t *offset)
 			size_t length, loff_t *offset)
@@ -211,7 +211,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 
 
 	err = mei_cl_read_start(cl, length);
 	err = mei_cl_read_start(cl, length);
 	if (err && err != -EBUSY) {
 	if (err && err != -EBUSY) {
-		dev_dbg(&dev->pdev->dev,
+		dev_dbg(dev->dev,
 			"mei start read failure with status = %d\n", err);
 			"mei start read failure with status = %d\n", err);
 		rets = err;
 		rets = err;
 		goto out;
 		goto out;
@@ -254,7 +254,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 	}
 	}
 	/* now copy the data to user space */
 	/* now copy the data to user space */
 copy_buffer:
 copy_buffer:
-	dev_dbg(&dev->pdev->dev, "buf.size = %d buf.idx= %ld\n",
+	dev_dbg(dev->dev, "buf.size = %d buf.idx= %ld\n",
 	    cb->response_buffer.size, cb->buf_idx);
 	    cb->response_buffer.size, cb->buf_idx);
 	if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
 	if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
 		rets = -EMSGSIZE;
 		rets = -EMSGSIZE;
@@ -266,7 +266,7 @@ copy_buffer:
 	length = min_t(size_t, length, cb->buf_idx - *offset);
 	length = min_t(size_t, length, cb->buf_idx - *offset);
 
 
 	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
 	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
-		dev_dbg(&dev->pdev->dev, "failed to copy data to userland\n");
+		dev_dbg(dev->dev, "failed to copy data to userland\n");
 		rets = -EFAULT;
 		rets = -EFAULT;
 		goto free;
 		goto free;
 	}
 	}
@@ -285,7 +285,7 @@ free:
 	cl->reading_state = MEI_IDLE;
 	cl->reading_state = MEI_IDLE;
 	cl->read_cb = NULL;
 	cl->read_cb = NULL;
 out:
 out:
-	dev_dbg(&dev->pdev->dev, "end mei read rets= %d\n", rets);
+	dev_dbg(dev->dev, "end mei read rets= %d\n", rets);
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 	return rets;
 	return rets;
 }
 }
@@ -297,17 +297,17 @@ out:
  * @length: buffer length
  * @length: buffer length
  * @offset: data offset in buffer
  * @offset: data offset in buffer
  *
  *
- * returns >=0 data length on success , <0 on error
+ * Return: >=0 data length on success , <0 on error
  */
  */
 static ssize_t mei_write(struct file *file, const char __user *ubuf,
 static ssize_t mei_write(struct file *file, const char __user *ubuf,
 			 size_t length, loff_t *offset)
 			 size_t length, loff_t *offset)
 {
 {
 	struct mei_cl *cl = file->private_data;
 	struct mei_cl *cl = file->private_data;
+	struct mei_me_client *me_cl;
 	struct mei_cl_cb *write_cb = NULL;
 	struct mei_cl_cb *write_cb = NULL;
 	struct mei_device *dev;
 	struct mei_device *dev;
 	unsigned long timeout = 0;
 	unsigned long timeout = 0;
 	int rets;
 	int rets;
-	int id;
 
 
 	if (WARN_ON(!cl || !cl->dev))
 	if (WARN_ON(!cl || !cl->dev))
 		return -ENODEV;
 		return -ENODEV;
@@ -321,8 +321,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		goto out;
 		goto out;
 	}
 	}
 
 
-	id = mei_me_cl_by_id(dev, cl->me_client_id);
-	if (id < 0) {
+	me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
+	if (!me_cl) {
 		rets = -ENOTTY;
 		rets = -ENOTTY;
 		goto out;
 		goto out;
 	}
 	}
@@ -332,13 +332,13 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		goto out;
 		goto out;
 	}
 	}
 
 
-	if (length > dev->me_clients[id].props.max_msg_length) {
+	if (length > me_cl->props.max_msg_length) {
 		rets = -EFBIG;
 		rets = -EFBIG;
 		goto out;
 		goto out;
 	}
 	}
 
 
 	if (cl->state != MEI_FILE_CONNECTED) {
 	if (cl->state != MEI_FILE_CONNECTED) {
-		dev_err(&dev->pdev->dev, "host client = %d,  is not connected to ME client = %d",
+		dev_err(dev->dev, "host client = %d,  is not connected to ME client = %d",
 			cl->host_client_id, cl->me_client_id);
 			cl->host_client_id, cl->me_client_id);
 		rets = -ENODEV;
 		rets = -ENODEV;
 		goto out;
 		goto out;
@@ -377,7 +377,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 
 
 	write_cb = mei_io_cb_init(cl, file);
 	write_cb = mei_io_cb_init(cl, file);
 	if (!write_cb) {
 	if (!write_cb) {
-		dev_err(&dev->pdev->dev, "write cb allocation failed\n");
 		rets = -ENOMEM;
 		rets = -ENOMEM;
 		goto out;
 		goto out;
 	}
 	}
@@ -387,7 +386,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 
 
 	rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
 	rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
 	if (rets) {
 	if (rets) {
-		dev_dbg(&dev->pdev->dev, "failed to copy data from userland\n");
+		dev_dbg(dev->dev, "failed to copy data from userland\n");
 		rets = -EFAULT;
 		rets = -EFAULT;
 		goto out;
 		goto out;
 	}
 	}
@@ -396,7 +395,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		rets = mei_amthif_write(dev, write_cb);
 		rets = mei_amthif_write(dev, write_cb);
 
 
 		if (rets) {
 		if (rets) {
-			dev_err(&dev->pdev->dev,
+			dev_err(dev->dev,
 				"amthif write failed with status = %d\n", rets);
 				"amthif write failed with status = %d\n", rets);
 			goto out;
 			goto out;
 		}
 		}
@@ -415,27 +414,23 @@ out:
 /**
 /**
  * mei_ioctl_connect_client - the connect to fw client IOCTL function
  * mei_ioctl_connect_client - the connect to fw client IOCTL function
  *
  *
- * @dev: the device structure
- * @data: IOCTL connect data, input and output parameters
  * @file: private data of the file object
  * @file: private data of the file object
+ * @data: IOCTL connect data, input and output parameters
  *
  *
  * Locking: called under "dev->device_lock" lock
  * Locking: called under "dev->device_lock" lock
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 static int mei_ioctl_connect_client(struct file *file,
 static int mei_ioctl_connect_client(struct file *file,
 			struct mei_connect_client_data *data)
 			struct mei_connect_client_data *data)
 {
 {
 	struct mei_device *dev;
 	struct mei_device *dev;
 	struct mei_client *client;
 	struct mei_client *client;
+	struct mei_me_client *me_cl;
 	struct mei_cl *cl;
 	struct mei_cl *cl;
-	int i;
 	int rets;
 	int rets;
 
 
 	cl = file->private_data;
 	cl = file->private_data;
-	if (WARN_ON(!cl || !cl->dev))
-		return -ENODEV;
-
 	dev = cl->dev;
 	dev = cl->dev;
 
 
 	if (dev->dev_state != MEI_DEV_ENABLED) {
 	if (dev->dev_state != MEI_DEV_ENABLED) {
@@ -450,28 +445,29 @@ static int mei_ioctl_connect_client(struct file *file,
 	}
 	}
 
 
 	/* find ME client we're trying to connect to */
 	/* find ME client we're trying to connect to */
-	i = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
-	if (i < 0 || dev->me_clients[i].props.fixed_address) {
-		dev_dbg(&dev->pdev->dev, "Cannot connect to FW Client UUID = %pUl\n",
+	me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
+	if (!me_cl || me_cl->props.fixed_address) {
+		dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n",
 				&data->in_client_uuid);
 				&data->in_client_uuid);
 		rets = -ENOTTY;
 		rets = -ENOTTY;
 		goto end;
 		goto end;
 	}
 	}
 
 
-	cl->me_client_id = dev->me_clients[i].client_id;
+	cl->me_client_id = me_cl->client_id;
+	cl->cl_uuid = me_cl->props.protocol_name;
 
 
-	dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
+	dev_dbg(dev->dev, "Connect to FW Client ID = %d\n",
 			cl->me_client_id);
 			cl->me_client_id);
-	dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
-			dev->me_clients[i].props.protocol_version);
-	dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
-			dev->me_clients[i].props.max_msg_length);
+	dev_dbg(dev->dev, "FW Client - Protocol Version = %d\n",
+			me_cl->props.protocol_version);
+	dev_dbg(dev->dev, "FW Client - Max Msg Len = %d\n",
+			me_cl->props.max_msg_length);
 
 
 	/* if we're connecting to amthif client then we will use the
 	/* if we're connecting to amthif client then we will use the
 	 * existing connection
 	 * existing connection
 	 */
 	 */
 	if (uuid_le_cmp(data->in_client_uuid, mei_amthif_guid) == 0) {
 	if (uuid_le_cmp(data->in_client_uuid, mei_amthif_guid) == 0) {
-		dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
+		dev_dbg(dev->dev, "FW Client is amthi\n");
 		if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
 		if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
 			rets = -ENODEV;
 			rets = -ENODEV;
 			goto end;
 			goto end;
@@ -484,10 +480,8 @@ static int mei_ioctl_connect_client(struct file *file,
 		file->private_data = &dev->iamthif_cl;
 		file->private_data = &dev->iamthif_cl;
 
 
 		client = &data->out_client_properties;
 		client = &data->out_client_properties;
-		client->max_msg_length =
-			dev->me_clients[i].props.max_msg_length;
-		client->protocol_version =
-			dev->me_clients[i].props.protocol_version;
+		client->max_msg_length = me_cl->props.max_msg_length;
+		client->protocol_version = me_cl->props.protocol_version;
 		rets = dev->iamthif_cl.status;
 		rets = dev->iamthif_cl.status;
 
 
 		goto end;
 		goto end;
@@ -496,9 +490,9 @@ static int mei_ioctl_connect_client(struct file *file,
 
 
 	/* prepare the output buffer */
 	/* prepare the output buffer */
 	client = &data->out_client_properties;
 	client = &data->out_client_properties;
-	client->max_msg_length = dev->me_clients[i].props.max_msg_length;
-	client->protocol_version = dev->me_clients[i].props.protocol_version;
-	dev_dbg(&dev->pdev->dev, "Can connect?\n");
+	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");
 
 
 
 
 	rets = mei_cl_connect(cl, file);
 	rets = mei_cl_connect(cl, file);
@@ -507,7 +501,6 @@ end:
 	return rets;
 	return rets;
 }
 }
 
 
-
 /**
 /**
  * mei_ioctl - the IOCTL function
  * mei_ioctl - the IOCTL function
  *
  *
@@ -515,24 +508,22 @@ end:
  * @cmd: ioctl command
  * @cmd: ioctl command
  * @data: pointer to mei message structure
  * @data: pointer to mei message structure
  *
  *
- * returns 0 on success , <0 on error
+ * Return: 0 on success , <0 on error
  */
  */
 static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
 static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
 {
 {
 	struct mei_device *dev;
 	struct mei_device *dev;
 	struct mei_cl *cl = file->private_data;
 	struct mei_cl *cl = file->private_data;
-	struct mei_connect_client_data *connect_data = NULL;
+	struct mei_connect_client_data connect_data;
 	int rets;
 	int rets;
 
 
-	if (cmd != IOCTL_MEI_CONNECT_CLIENT)
-		return -EINVAL;
 
 
 	if (WARN_ON(!cl || !cl->dev))
 	if (WARN_ON(!cl || !cl->dev))
 		return -ENODEV;
 		return -ENODEV;
 
 
 	dev = cl->dev;
 	dev = cl->dev;
 
 
-	dev_dbg(&dev->pdev->dev, "IOCTL cmd = 0x%x", cmd);
+	dev_dbg(dev->dev, "IOCTL cmd = 0x%x", cmd);
 
 
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 	if (dev->dev_state != MEI_DEV_ENABLED) {
 	if (dev->dev_state != MEI_DEV_ENABLED) {
@@ -540,38 +531,36 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
 		goto out;
 		goto out;
 	}
 	}
 
 
-	dev_dbg(&dev->pdev->dev, ": IOCTL_MEI_CONNECT_CLIENT.\n");
-
-	connect_data = kzalloc(sizeof(struct mei_connect_client_data),
-							GFP_KERNEL);
-	if (!connect_data) {
-		rets = -ENOMEM;
-		goto out;
-	}
-	dev_dbg(&dev->pdev->dev, "copy connect data from user\n");
-	if (copy_from_user(connect_data, (char __user *)data,
+	switch (cmd) {
+	case IOCTL_MEI_CONNECT_CLIENT:
+		dev_dbg(dev->dev, ": IOCTL_MEI_CONNECT_CLIENT.\n");
+		if (copy_from_user(&connect_data, (char __user *)data,
 				sizeof(struct mei_connect_client_data))) {
 				sizeof(struct mei_connect_client_data))) {
-		dev_dbg(&dev->pdev->dev, "failed to copy data from userland\n");
-		rets = -EFAULT;
-		goto out;
-	}
-
-	rets = mei_ioctl_connect_client(file, connect_data);
+			dev_dbg(dev->dev, "failed to copy data from userland\n");
+			rets = -EFAULT;
+			goto out;
+		}
 
 
-	/* if all is ok, copying the data back to user. */
-	if (rets)
-		goto out;
+		rets = mei_ioctl_connect_client(file, &connect_data);
+		if (rets)
+			goto out;
 
 
-	dev_dbg(&dev->pdev->dev, "copy connect data to user\n");
-	if (copy_to_user((char __user *)data, connect_data,
+		/* if all is ok, copying the data back to user. */
+		if (copy_to_user((char __user *)data, &connect_data,
 				sizeof(struct mei_connect_client_data))) {
 				sizeof(struct mei_connect_client_data))) {
-		dev_dbg(&dev->pdev->dev, "failed to copy data to userland\n");
-		rets = -EFAULT;
-		goto out;
+			dev_dbg(dev->dev, "failed to copy data to userland\n");
+			rets = -EFAULT;
+			goto out;
+		}
+
+		break;
+
+	default:
+		dev_err(dev->dev, ": unsupported ioctl %d.\n", cmd);
+		rets = -ENOIOCTLCMD;
 	}
 	}
 
 
 out:
 out:
-	kfree(connect_data);
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 	return rets;
 	return rets;
 }
 }
@@ -583,7 +572,7 @@ out:
  * @cmd: ioctl command
  * @cmd: ioctl command
  * @data: pointer to mei message structure
  * @data: pointer to mei message structure
  *
  *
- * returns 0 on success , <0 on error
+ * Return: 0 on success , <0 on error
  */
  */
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
 static long mei_compat_ioctl(struct file *file,
 static long mei_compat_ioctl(struct file *file,
@@ -600,7 +589,7 @@ static long mei_compat_ioctl(struct file *file,
  * @file: pointer to file structure
  * @file: pointer to file structure
  * @wait: pointer to poll_table structure
  * @wait: pointer to poll_table structure
  *
  *
- * returns poll mask
+ * Return: poll mask
  */
  */
 static unsigned int mei_poll(struct file *file, poll_table *wait)
 static unsigned int mei_poll(struct file *file, poll_table *wait)
 {
 {
@@ -670,7 +659,7 @@ static DEFINE_IDR(mei_idr);
  *
  *
  * @dev:  device pointer
  * @dev:  device pointer
  *
  *
- * returns allocated minor, or -ENOSPC if no free minor left
+ * Return: allocated minor, or -ENOSPC if no free minor left
  */
  */
 static int mei_minor_get(struct mei_device *dev)
 static int mei_minor_get(struct mei_device *dev)
 {
 {
@@ -681,7 +670,7 @@ static int mei_minor_get(struct mei_device *dev)
 	if (ret >= 0)
 	if (ret >= 0)
 		dev->minor = ret;
 		dev->minor = ret;
 	else if (ret == -ENOSPC)
 	else if (ret == -ENOSPC)
-		dev_err(&dev->pdev->dev, "too many mei devices\n");
+		dev_err(dev->dev, "too many mei devices\n");
 
 
 	mutex_unlock(&mei_minor_lock);
 	mutex_unlock(&mei_minor_lock);
 	return ret;
 	return ret;

+ 179 - 100
drivers/misc/mei/mei_dev.h

@@ -129,20 +129,18 @@ enum mei_wd_states {
 
 
 /**
 /**
  * enum mei_cb_file_ops  - file operation associated with the callback
  * enum mei_cb_file_ops  - file operation associated with the callback
- * @MEI_FOP_READ      - read
- * @MEI_FOP_WRITE     - write
- * @MEI_FOP_CONNECT   - connect
- * @MEI_FOP_DISCONNECT_RSP - disconnect response
- * @MEI_FOP_OPEN      - open
- * @MEI_FOP_CLOSE     - close
+ * @MEI_FOP_READ:       read
+ * @MEI_FOP_WRITE:      write
+ * @MEI_FOP_CONNECT:    connect
+ * @MEI_FOP_DISCONNECT: disconnect
+ * @MEI_FOP_DISCONNECT_RSP: disconnect response
  */
  */
 enum mei_cb_file_ops {
 enum mei_cb_file_ops {
 	MEI_FOP_READ = 0,
 	MEI_FOP_READ = 0,
 	MEI_FOP_WRITE,
 	MEI_FOP_WRITE,
 	MEI_FOP_CONNECT,
 	MEI_FOP_CONNECT,
+	MEI_FOP_DISCONNECT,
 	MEI_FOP_DISCONNECT_RSP,
 	MEI_FOP_DISCONNECT_RSP,
-	MEI_FOP_OPEN,
-	MEI_FOP_CLOSE
 };
 };
 
 
 /*
 /*
@@ -159,8 +157,8 @@ struct mei_msg_data {
 /*
 /*
  * struct mei_fw_status - storage of FW status data
  * struct mei_fw_status - storage of FW status data
  *
  *
- * @count - number of actually available elements in array
- * @status - FW status registers
+ * @count: number of actually available elements in array
+ * @status: FW status registers
  */
  */
 struct mei_fw_status {
 struct mei_fw_status {
 	int count;
 	int count;
@@ -170,11 +168,13 @@ struct mei_fw_status {
 /**
 /**
  * struct mei_me_client - representation of me (fw) client
  * struct mei_me_client - representation of me (fw) client
  *
  *
- * @props  - client properties
- * @client_id - me client id
- * @mei_flow_ctrl_creds - flow control credits
+ * @list: link in me client list
+ * @props: client properties
+ * @client_id: me client id
+ * @mei_flow_ctrl_creds: flow control credits
  */
  */
 struct mei_me_client {
 struct mei_me_client {
+	struct list_head list;
 	struct mei_client_properties props;
 	struct mei_client_properties props;
 	u8 client_id;
 	u8 client_id;
 	u8 mei_flow_ctrl_creds;
 	u8 mei_flow_ctrl_creds;
@@ -186,8 +186,15 @@ struct mei_cl;
 /**
 /**
  * struct mei_cl_cb - file operation callback structure
  * struct mei_cl_cb - file operation callback structure
  *
  *
- * @cl - file client who is running this operation
- * @fop_type - file operation type
+ * @list: link in callback queue
+ * @cl: file client who is running this operation
+ * @fop_type: file operation type
+ * @request_buffer: buffer to store request data
+ * @response_buffer: buffer to store response data
+ * @buf_idx: last read index
+ * @read_time: last read operation time stamp (iamthif)
+ * @file_object: pointer to file structure
+ * @internal: communication between driver and FW flag
  */
  */
 struct mei_cl_cb {
 struct mei_cl_cb {
 	struct list_head list;
 	struct list_head list;
@@ -201,7 +208,29 @@ struct mei_cl_cb {
 	u32 internal:1;
 	u32 internal:1;
 };
 };
 
 
-/* MEI client instance carried as file->private_data*/
+/**
+ * struct mei_cl - me client host representation
+ *    carried in file->private_data
+ *
+ * @link: link in the clients list
+ * @dev: mei parent device
+ * @state: file operation state
+ * @tx_wait: wait queue for tx completion
+ * @rx_wait: wait queue for rx completion
+ * @wait:  wait queue for management operation
+ * @status: connection status
+ * @cl_uuid: client uuid name
+ * @host_client_id: host id
+ * @me_client_id: me/fw id
+ * @mei_flow_ctrl_creds: transmit flow credentials
+ * @timer_count:  watchdog timer for operation completion
+ * @reading_state: state of the rx
+ * @writing_state: state of the tx
+ * @read_cb: current pending reading callback
+ *
+ * @device: device on the mei client bus
+ * @device_link:  link to bus clients
+ */
 struct mei_cl {
 struct mei_cl {
 	struct list_head link;
 	struct list_head link;
 	struct mei_device *dev;
 	struct mei_device *dev;
@@ -210,7 +239,7 @@ struct mei_cl {
 	wait_queue_head_t rx_wait;
 	wait_queue_head_t rx_wait;
 	wait_queue_head_t wait;
 	wait_queue_head_t wait;
 	int status;
 	int status;
-	/* ID of client connected */
+	uuid_le cl_uuid;
 	u8 host_client_id;
 	u8 host_client_id;
 	u8 me_client_id;
 	u8 me_client_id;
 	u8 mei_flow_ctrl_creds;
 	u8 mei_flow_ctrl_creds;
@@ -222,35 +251,35 @@ struct mei_cl {
 	/* MEI CL bus data */
 	/* MEI CL bus data */
 	struct mei_cl_device *device;
 	struct mei_cl_device *device;
 	struct list_head device_link;
 	struct list_head device_link;
-	uuid_le device_uuid;
 };
 };
 
 
 /** struct mei_hw_ops
 /** struct mei_hw_ops
  *
  *
- * @host_is_ready    - query for host readiness
+ * @host_is_ready    : query for host readiness
 
 
- * @hw_is_ready      - query if hw is ready
- * @hw_reset         - reset hw
- * @hw_start         - start hw after reset
- * @hw_config        - configure hw
+ * @hw_is_ready      : query if hw is ready
+ * @hw_reset         : reset hw
+ * @hw_start         : start hw after reset
+ * @hw_config        : configure hw
 
 
- * @pg_state         - power gating state of the device
- * @pg_is_enabled    - is power gating enabled
+ * @fw_status        : get fw status registers
+ * @pg_state         : power gating state of the device
+ * @pg_is_enabled    : is power gating enabled
 
 
- * @intr_clear       - clear pending interrupts
- * @intr_enable      - enable interrupts
- * @intr_disable     - disable interrupts
+ * @intr_clear       : clear pending interrupts
+ * @intr_enable      : enable interrupts
+ * @intr_disable     : disable interrupts
 
 
- * @hbuf_free_slots  - query for write buffer empty slots
- * @hbuf_is_ready    - query if write buffer is empty
- * @hbuf_max_len     - query for write buffer max len
+ * @hbuf_free_slots  : query for write buffer empty slots
+ * @hbuf_is_ready    : query if write buffer is empty
+ * @hbuf_max_len     : query for write buffer max len
 
 
- * @write            - write a message to FW
+ * @write            : write a message to FW
 
 
- * @rdbuf_full_slots - query how many slots are filled
+ * @rdbuf_full_slots : query how many slots are filled
 
 
- * @read_hdr         - get first 4 bytes (header)
- * @read             - read a buffer from the FW
+ * @read_hdr         : get first 4 bytes (header)
+ * @read             : read a buffer from the FW
  */
  */
 struct mei_hw_ops {
 struct mei_hw_ops {
 
 
@@ -261,6 +290,8 @@ struct mei_hw_ops {
 	int (*hw_start)(struct mei_device *dev);
 	int (*hw_start)(struct mei_device *dev);
 	void (*hw_config)(struct mei_device *dev);
 	void (*hw_config)(struct mei_device *dev);
 
 
+
+	int (*fw_status)(struct mei_device *dev, struct mei_fw_status *fw_sts);
 	enum mei_pg_state (*pg_state)(struct mei_device *dev);
 	enum mei_pg_state (*pg_state)(struct mei_device *dev);
 	bool (*pg_is_enabled)(struct mei_device *dev);
 	bool (*pg_is_enabled)(struct mei_device *dev);
 
 
@@ -328,11 +359,12 @@ void mei_cl_bus_exit(void);
  * when being probed and shall use it for doing ME bus I/O.
  * when being probed and shall use it for doing ME bus I/O.
  *
  *
  * @dev: linux driver model device pointer
  * @dev: linux driver model device pointer
- * @uuid: me client uuid
  * @cl: mei client
  * @cl: mei client
  * @ops: ME transport ops
  * @ops: ME transport ops
+ * @event_work: async work to execute event callback
  * @event_cb: Drivers register this callback to get asynchronous ME
  * @event_cb: Drivers register this callback to get asynchronous ME
  *	events (e.g. Rx buffer pending) notifications.
  *	events (e.g. Rx buffer pending) notifications.
+ * @event_context: event callback run context
  * @events: Events bitmask sent to the driver.
  * @events: Events bitmask sent to the driver.
  * @priv_data: client private data
  * @priv_data: client private data
  */
  */
@@ -352,7 +384,7 @@ struct mei_cl_device {
 };
 };
 
 
 
 
- /**
+/**
  * enum mei_pg_event - power gating transition events
  * enum mei_pg_event - power gating transition events
  *
  *
  * @MEI_PG_EVENT_IDLE: the driver is not in power gating transition
  * @MEI_PG_EVENT_IDLE: the driver is not in power gating transition
@@ -376,67 +408,106 @@ enum mei_pg_state {
 	MEI_PG_ON =  1,
 	MEI_PG_ON =  1,
 };
 };
 
 
-/*
- * mei_cfg
- *
- * @fw_status - FW status
- * @quirk_probe - device exclusion quirk
- */
-struct mei_cfg {
-	const struct mei_fw_status fw_status;
-	bool (*quirk_probe)(struct pci_dev *pdev);
-};
-
-
-#define MEI_PCI_DEVICE(dev, cfg) \
-	.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
-	.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, \
-	.driver_data = (kernel_ulong_t)&(cfg)
-
+const char *mei_pg_state_str(enum mei_pg_state state);
 
 
 /**
 /**
  * struct mei_device -  MEI private device struct
  * struct mei_device -  MEI private device struct
-
- * @pdev - pointer to pci device struct
- * @cdev - character device
- * @minor - minor number allocated for device
  *
  *
- * @reset_count - limits the number of consecutive resets
- * @hbm_state - state of host bus message protocol
- * @pg_event - power gating event
- * @mem_addr - mem mapped base register address
-
- * @hbuf_depth - depth of hardware host/write buffer is slots
- * @hbuf_is_ready - query if the host host/write buffer is ready
- * @wr_msg - the buffer for hbm control messages
- * @cfg - per device generation config and ops
+ * @dev         : device on a bus
+ * @cdev        : character device
+ * @minor       : minor number allocated for device
+ *
+ * @read_list   : read completion list
+ * @write_list  : write pending list
+ * @write_waiting_list : write completion list
+ * @ctrl_wr_list : pending control write list
+ * @ctrl_rd_list : pending control read list
+ *
+ * @file_list   : list of opened handles
+ * @open_handle_count: number of opened handles
+ *
+ * @device_lock : big device lock
+ * @timer_work  : MEI timer delayed work (timeouts)
+ *
+ * @recvd_hw_ready : hw ready message received flag
+ *
+ * @wait_hw_ready : wait queue for receive HW ready message form FW
+ * @wait_pg     : wait queue for receive PG message from FW
+ * @wait_hbm_start : wait queue for receive HBM start message from FW
+ * @wait_stop_wd : wait queue for receive WD stop message from FW
+ *
+ * @reset_count : number of consecutive resets
+ * @dev_state   : device state
+ * @hbm_state   : state of host bus message protocol
+ * @init_clients_timer : HBM init handshake timeout
+ *
+ * @pg_event    : power gating event
+ * @pg_domain   : runtime PM domain
+ *
+ * @rd_msg_buf  : control messages buffer
+ * @rd_msg_hdr  : read message header storage
+ *
+ * @hbuf_depth  : depth of hardware host/write buffer is slots
+ * @hbuf_is_ready : query if the host host/write buffer is ready
+ * @wr_msg      : the buffer for hbm control messages
+ *
+ * @version     : HBM protocol version in use
+ * @hbm_f_pg_supported : hbm feature pgi protocol
+ *
+ * @me_clients  : list of FW clients
+ * @me_clients_map : FW clients bit map
+ * @host_clients_map : host clients id pool
+ * @me_client_index : last FW client index in enumeration
+ *
+ * @wd_cl       : watchdog client
+ * @wd_state    : watchdog client state
+ * @wd_pending  : watchdog command is pending
+ * @wd_timeout  : watchdog expiration timeout
+ * @wd_data     : watchdog message buffer
+ *
+ * @amthif_cmd_list : amthif list for cmd waiting
+ * @amthif_rd_complete_list : amthif list for reading completed cmd data
+ * @iamthif_file_object : file for current amthif operation
+ * @iamthif_cl  : amthif host client
+ * @iamthif_current_cb : amthif current operation callback
+ * @iamthif_open_count : number of opened amthif connections
+ * @iamthif_mtu : amthif client max message length
+ * @iamthif_timer : time stamp of current amthif command completion
+ * @iamthif_stall_timer : timer to detect amthif hang
+ * @iamthif_msg_buf : amthif current message buffer
+ * @iamthif_msg_buf_size : size of current amthif message request buffer
+ * @iamthif_msg_buf_index : current index in amthif message request buffer
+ * @iamthif_state : amthif processor state
+ * @iamthif_flow_control_pending: amthif waits for flow control
+ * @iamthif_ioctl : wait for completion if amthif control message
+ * @iamthif_canceled : current amthif command is canceled
+ *
+ * @init_work   : work item for the device init
+ * @reset_work  : work item for the device reset
+ *
+ * @device_list : mei client bus list
+ *
+ * @dbgfs_dir   : debugfs mei root directory
+ *
+ * @ops:        : hw specific operations
+ * @hw          : hw specific data
  */
  */
 struct mei_device {
 struct mei_device {
-	struct pci_dev *pdev;	/* pointer to pci device struct */
+	struct device *dev;
 	struct cdev cdev;
 	struct cdev cdev;
 	int minor;
 	int minor;
 
 
-	/*
-	 * lists of queues
-	 */
-	/* array of pointers to aio lists */
-	struct mei_cl_cb read_list;		/* driver read queue */
-	struct mei_cl_cb write_list;		/* driver write queue */
-	struct mei_cl_cb write_waiting_list;	/* write waiting queue */
-	struct mei_cl_cb ctrl_wr_list;		/* managed write IOCTL list */
-	struct mei_cl_cb ctrl_rd_list;		/* managed read IOCTL list */
+	struct mei_cl_cb read_list;
+	struct mei_cl_cb write_list;
+	struct mei_cl_cb write_waiting_list;
+	struct mei_cl_cb ctrl_wr_list;
+	struct mei_cl_cb ctrl_rd_list;
 
 
-	/*
-	 * list of files
-	 */
 	struct list_head file_list;
 	struct list_head file_list;
 	long open_handle_count;
 	long open_handle_count;
 
 
-	/*
-	 * lock for the device
-	 */
-	struct mutex device_lock; /* device lock */
-	struct delayed_work timer_work;	/* MEI timer delayed work (timeouts) */
+	struct mutex device_lock;
+	struct delayed_work timer_work;
 
 
 	bool recvd_hw_ready;
 	bool recvd_hw_ready;
 	/*
 	/*
@@ -444,7 +515,7 @@ struct mei_device {
 	 */
 	 */
 	wait_queue_head_t wait_hw_ready;
 	wait_queue_head_t wait_hw_ready;
 	wait_queue_head_t wait_pg;
 	wait_queue_head_t wait_pg;
-	wait_queue_head_t wait_recvd_msg;
+	wait_queue_head_t wait_hbm_start;
 	wait_queue_head_t wait_stop_wd;
 	wait_queue_head_t wait_stop_wd;
 
 
 	/*
 	/*
@@ -463,7 +534,7 @@ struct mei_device {
 	struct dev_pm_domain pg_domain;
 	struct dev_pm_domain pg_domain;
 #endif /* CONFIG_PM_RUNTIME */
 #endif /* CONFIG_PM_RUNTIME */
 
 
-	unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE];	/* control messages */
+	unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE];
 	u32 rd_msg_hdr;
 	u32 rd_msg_hdr;
 
 
 	/* write buffer */
 	/* write buffer */
@@ -477,12 +548,11 @@ struct mei_device {
 	} wr_msg;
 	} wr_msg;
 
 
 	struct hbm_version version;
 	struct hbm_version version;
+	unsigned int hbm_f_pg_supported:1;
 
 
-	struct mei_me_client *me_clients; /* Note: memory has to be allocated */
+	struct list_head me_clients;
 	DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
 	DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
 	DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
 	DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
-	unsigned long me_clients_num;
-	unsigned long me_client_presentation_num;
 	unsigned long me_client_index;
 	unsigned long me_client_index;
 
 
 	struct mei_cl wd_cl;
 	struct mei_cl wd_cl;
@@ -523,7 +593,6 @@ struct mei_device {
 
 
 
 
 	const struct mei_hw_ops *ops;
 	const struct mei_hw_ops *ops;
-	const struct mei_cfg *cfg;
 	char hw[0] __aligned(sizeof(void *));
 	char hw[0] __aligned(sizeof(void *));
 };
 };
 
 
@@ -535,8 +604,10 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
 /**
 /**
  * mei_data2slots - get slots - number of (dwords) from a message length
  * mei_data2slots - get slots - number of (dwords) from a message length
  *	+ size of the mei header
  *	+ size of the mei header
- * @length - size of the messages in bytes
- * returns  - number of slots
+ *
+ * @length: size of the messages in bytes
+ *
+ * Return: number of slots
  */
  */
 static inline u32 mei_data2slots(size_t length)
 static inline u32 mei_data2slots(size_t length)
 {
 {
@@ -544,9 +615,11 @@ static inline u32 mei_data2slots(size_t length)
 }
 }
 
 
 /**
 /**
- * mei_slots2data- get data in slots - bytes from slots
- * @slots -  number of available slots
- * returns  - number of bytes in slots
+ * mei_slots2data - get data in slots - bytes from slots
+ *
+ * @slots: number of available slots
+ *
+ * Return: number of bytes in slots
  */
  */
 static inline u32 mei_slots2data(int slots)
 static inline u32 mei_slots2data(int slots)
 {
 {
@@ -556,7 +629,9 @@ static inline u32 mei_slots2data(int slots)
 /*
 /*
  * mei init function prototypes
  * mei init function prototypes
  */
  */
-void mei_device_init(struct mei_device *dev, const struct mei_cfg *cfg);
+void mei_device_init(struct mei_device *dev,
+		     struct device *device,
+		     const struct mei_hw_ops *hw_ops);
 int mei_reset(struct mei_device *dev);
 int mei_reset(struct mei_device *dev);
 int mei_start(struct mei_device *dev);
 int mei_start(struct mei_device *dev);
 int mei_restart(struct mei_device *dev);
 int mei_restart(struct mei_device *dev);
@@ -622,12 +697,12 @@ int mei_wd_host_init(struct mei_device *dev);
 /*
 /*
  * mei_watchdog_register  - Registering watchdog interface
  * mei_watchdog_register  - Registering watchdog interface
  *   once we got connection to the WD Client
  *   once we got connection to the WD Client
- * @dev - mei device
+ * @dev: mei device
  */
  */
 int mei_watchdog_register(struct mei_device *dev);
 int mei_watchdog_register(struct mei_device *dev);
 /*
 /*
  * mei_watchdog_unregister  - Unregistering watchdog interface
  * mei_watchdog_unregister  - Unregistering watchdog interface
- * @dev - mei device
+ * @dev: mei device
  */
  */
 void mei_watchdog_unregister(struct mei_device *dev);
 void mei_watchdog_unregister(struct mei_device *dev);
 
 
@@ -723,7 +798,11 @@ static inline int mei_count_full_read_slots(struct mei_device *dev)
 	return dev->ops->rdbuf_full_slots(dev);
 	return dev->ops->rdbuf_full_slots(dev);
 }
 }
 
 
-int mei_fw_status(struct mei_device *dev, struct mei_fw_status *fw_status);
+static inline int mei_fw_status(struct mei_device *dev,
+				struct mei_fw_status *fw_status)
+{
+	return dev->ops->fw_status(dev, fw_status);
+}
 
 
 #define FW_STS_FMT "%08X %08X"
 #define FW_STS_FMT "%08X %08X"
 #define FW_STS_PRM(fw_status) \
 #define FW_STS_PRM(fw_status) \

+ 39 - 38
drivers/misc/mei/nfc.c

@@ -19,7 +19,8 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/device.h>
-#include <linux/pci.h>
+#include <linux/slab.h>
+
 #include <linux/mei_cl_bus.h>
 #include <linux/mei_cl_bus.h>
 
 
 #include "mei_dev.h"
 #include "mei_dev.h"
@@ -87,14 +88,20 @@ struct mei_nfc_hci_hdr {
 
 
 #define MEI_NFC_HEADER_SIZE 10
 #define MEI_NFC_HEADER_SIZE 10
 
 
-/** mei_nfc_dev - NFC mei device
+/**
+ * struct mei_nfc_dev - NFC mei device
  *
  *
  * @cl: NFC host client
  * @cl: NFC host client
  * @cl_info: NFC info host client
  * @cl_info: NFC info host client
  * @init_work: perform connection to the info client
  * @init_work: perform connection to the info client
+ * @send_wq: send completion wait queue
  * @fw_ivn: NFC Interface Version Number
  * @fw_ivn: NFC Interface Version Number
  * @vendor_id: NFC manufacturer ID
  * @vendor_id: NFC manufacturer ID
  * @radio_type: NFC radio type
  * @radio_type: NFC radio type
+ * @bus_name: bus name
+ *
+ * @req_id:  message counter
+ * @recv_req_id: reception message counter
  */
  */
 struct mei_nfc_dev {
 struct mei_nfc_dev {
 	struct mei_cl *cl;
 	struct mei_cl *cl;
@@ -163,7 +170,7 @@ static int mei_nfc_build_bus_name(struct mei_nfc_dev *ndev)
 			return 0;
 			return 0;
 
 
 		default:
 		default:
-			dev_err(&dev->pdev->dev, "Unknown radio type 0x%x\n",
+			dev_err(dev->dev, "Unknown radio type 0x%x\n",
 				ndev->radio_type);
 				ndev->radio_type);
 
 
 			return -EINVAL;
 			return -EINVAL;
@@ -175,14 +182,14 @@ static int mei_nfc_build_bus_name(struct mei_nfc_dev *ndev)
 			ndev->bus_name = "pn544";
 			ndev->bus_name = "pn544";
 			return 0;
 			return 0;
 		default:
 		default:
-			dev_err(&dev->pdev->dev, "Unknown radio type 0x%x\n",
+			dev_err(dev->dev, "Unknown radio type 0x%x\n",
 				ndev->radio_type);
 				ndev->radio_type);
 
 
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 
 
 	default:
 	default:
-		dev_err(&dev->pdev->dev, "Unknown vendor ID 0x%x\n",
+		dev_err(dev->dev, "Unknown vendor ID 0x%x\n",
 			ndev->vendor_id);
 			ndev->vendor_id);
 
 
 		return -EINVAL;
 		return -EINVAL;
@@ -231,21 +238,21 @@ static int mei_nfc_connect(struct mei_nfc_dev *ndev)
 
 
 	ret = __mei_cl_send(cl, (u8 *)cmd, connect_length);
 	ret = __mei_cl_send(cl, (u8 *)cmd, connect_length);
 	if (ret < 0) {
 	if (ret < 0) {
-		dev_err(&dev->pdev->dev, "Could not send connect cmd\n");
+		dev_err(dev->dev, "Could not send connect cmd\n");
 		goto err;
 		goto err;
 	}
 	}
 
 
 	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, connect_resp_length);
 	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, connect_resp_length);
 	if (bytes_recv < 0) {
 	if (bytes_recv < 0) {
-		dev_err(&dev->pdev->dev, "Could not read connect response\n");
+		dev_err(dev->dev, "Could not read connect response\n");
 		ret = bytes_recv;
 		ret = bytes_recv;
 		goto err;
 		goto err;
 	}
 	}
 
 
-	dev_info(&dev->pdev->dev, "IVN 0x%x Vendor ID 0x%x\n",
+	dev_info(dev->dev, "IVN 0x%x Vendor ID 0x%x\n",
 		 connect_resp->fw_ivn, connect_resp->vendor_id);
 		 connect_resp->fw_ivn, connect_resp->vendor_id);
 
 
-	dev_info(&dev->pdev->dev, "ME FW %d.%d.%d.%d\n",
+	dev_info(dev->dev, "ME FW %d.%d.%d.%d\n",
 		connect_resp->me_major, connect_resp->me_minor,
 		connect_resp->me_major, connect_resp->me_minor,
 		connect_resp->me_hotfix, connect_resp->me_build);
 		connect_resp->me_hotfix, connect_resp->me_build);
 
 
@@ -279,7 +286,7 @@ static int mei_nfc_if_version(struct mei_nfc_dev *ndev)
 
 
 	ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd));
 	ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd));
 	if (ret < 0) {
 	if (ret < 0) {
-		dev_err(&dev->pdev->dev, "Could not send IF version cmd\n");
+		dev_err(dev->dev, "Could not send IF version cmd\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -293,7 +300,7 @@ static int mei_nfc_if_version(struct mei_nfc_dev *ndev)
 
 
 	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
 	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
 	if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
 	if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
-		dev_err(&dev->pdev->dev, "Could not read IF version\n");
+		dev_err(dev->dev, "Could not read IF version\n");
 		ret = -EIO;
 		ret = -EIO;
 		goto err;
 		goto err;
 	}
 	}
@@ -319,7 +326,7 @@ static int mei_nfc_enable(struct mei_cl_device *cldev)
 
 
 	ret = mei_nfc_connect(ndev);
 	ret = mei_nfc_connect(ndev);
 	if (ret < 0) {
 	if (ret < 0) {
-		dev_err(&dev->pdev->dev, "Could not connect to NFC");
+		dev_err(dev->dev, "Could not connect to NFC");
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -361,7 +368,7 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
 
 
 	if (!wait_event_interruptible_timeout(ndev->send_wq,
 	if (!wait_event_interruptible_timeout(ndev->send_wq,
 				ndev->recv_req_id == ndev->req_id, HZ)) {
 				ndev->recv_req_id == ndev->req_id, HZ)) {
-		dev_err(&dev->pdev->dev, "NFC MEI command timeout\n");
+		dev_err(dev->dev, "NFC MEI command timeout\n");
 		err = -ETIME;
 		err = -ETIME;
 	} else {
 	} else {
 		ndev->req_id++;
 		ndev->req_id++;
@@ -418,8 +425,7 @@ static void mei_nfc_init(struct work_struct *work)
 
 
 	if (mei_cl_connect(cl_info, NULL) < 0) {
 	if (mei_cl_connect(cl_info, NULL) < 0) {
 		mutex_unlock(&dev->device_lock);
 		mutex_unlock(&dev->device_lock);
-		dev_err(&dev->pdev->dev,
-			"Could not connect to the NFC INFO ME client");
+		dev_err(dev->dev, "Could not connect to the NFC INFO ME client");
 
 
 		goto err;
 		goto err;
 	}
 	}
@@ -427,21 +433,19 @@ static void mei_nfc_init(struct work_struct *work)
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 
 
 	if (mei_nfc_if_version(ndev) < 0) {
 	if (mei_nfc_if_version(ndev) < 0) {
-		dev_err(&dev->pdev->dev, "Could not get the NFC interface version");
+		dev_err(dev->dev, "Could not get the NFC interface version");
 
 
 		goto err;
 		goto err;
 	}
 	}
 
 
-	dev_info(&dev->pdev->dev,
-		"NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
+	dev_info(dev->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
 		ndev->fw_ivn, ndev->vendor_id, ndev->radio_type);
 		ndev->fw_ivn, ndev->vendor_id, ndev->radio_type);
 
 
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 
 
 	if (mei_cl_disconnect(cl_info) < 0) {
 	if (mei_cl_disconnect(cl_info) < 0) {
 		mutex_unlock(&dev->device_lock);
 		mutex_unlock(&dev->device_lock);
-		dev_err(&dev->pdev->dev,
-			"Could not disconnect the NFC INFO ME client");
+		dev_err(dev->dev, "Could not disconnect the NFC INFO ME client");
 
 
 		goto err;
 		goto err;
 	}
 	}
@@ -449,15 +453,13 @@ static void mei_nfc_init(struct work_struct *work)
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 
 
 	if (mei_nfc_build_bus_name(ndev) < 0) {
 	if (mei_nfc_build_bus_name(ndev) < 0) {
-		dev_err(&dev->pdev->dev,
-			"Could not build the bus ID name\n");
+		dev_err(dev->dev, "Could not build the bus ID name\n");
 		return;
 		return;
 	}
 	}
 
 
 	cldev = mei_cl_add_device(dev, mei_nfc_guid, ndev->bus_name, &nfc_ops);
 	cldev = mei_cl_add_device(dev, mei_nfc_guid, ndev->bus_name, &nfc_ops);
 	if (!cldev) {
 	if (!cldev) {
-		dev_err(&dev->pdev->dev,
-			"Could not add the NFC device to the MEI bus\n");
+		dev_err(dev->dev, "Could not add the NFC device to the MEI bus\n");
 
 
 		goto err;
 		goto err;
 	}
 	}
@@ -472,7 +474,6 @@ err:
 	mei_nfc_free(ndev);
 	mei_nfc_free(ndev);
 	mutex_unlock(&dev->device_lock);
 	mutex_unlock(&dev->device_lock);
 
 
-	return;
 }
 }
 
 
 
 
@@ -480,7 +481,8 @@ int mei_nfc_host_init(struct mei_device *dev)
 {
 {
 	struct mei_nfc_dev *ndev = &nfc_dev;
 	struct mei_nfc_dev *ndev = &nfc_dev;
 	struct mei_cl *cl_info, *cl = NULL;
 	struct mei_cl *cl_info, *cl = NULL;
-	int i, ret;
+	struct mei_me_client *me_cl;
+	int ret;
 
 
 	/* already initialized */
 	/* already initialized */
 	if (ndev->cl_info)
 	if (ndev->cl_info)
@@ -498,40 +500,38 @@ int mei_nfc_host_init(struct mei_device *dev)
 	}
 	}
 
 
 	/* check for valid client id */
 	/* check for valid client id */
-	i = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
-	if (i < 0) {
-		dev_info(&dev->pdev->dev, "nfc: failed to find the client\n");
+	me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
+	if (!me_cl) {
+		dev_info(dev->dev, "nfc: failed to find the client\n");
 		ret = -ENOTTY;
 		ret = -ENOTTY;
 		goto err;
 		goto err;
 	}
 	}
 
 
-	cl_info->me_client_id = dev->me_clients[i].client_id;
+	cl_info->me_client_id = me_cl->client_id;
+	cl_info->cl_uuid = me_cl->props.protocol_name;
 
 
 	ret = mei_cl_link(cl_info, MEI_HOST_CLIENT_ID_ANY);
 	ret = mei_cl_link(cl_info, MEI_HOST_CLIENT_ID_ANY);
 	if (ret)
 	if (ret)
 		goto err;
 		goto err;
 
 
-	cl_info->device_uuid = mei_nfc_info_guid;
 
 
 	list_add_tail(&cl_info->device_link, &dev->device_list);
 	list_add_tail(&cl_info->device_link, &dev->device_list);
 
 
 	/* check for valid client id */
 	/* check for valid client id */
-	i = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
-	if (i < 0) {
-		dev_info(&dev->pdev->dev, "nfc: failed to find the client\n");
+	me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
+	if (!me_cl) {
+		dev_info(dev->dev, "nfc: failed to find the client\n");
 		ret = -ENOTTY;
 		ret = -ENOTTY;
 		goto err;
 		goto err;
 	}
 	}
 
 
-	cl->me_client_id = dev->me_clients[i].client_id;
+	cl->me_client_id = me_cl->client_id;
+	cl->cl_uuid = me_cl->props.protocol_name;
 
 
 	ret = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
 	ret = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
 	if (ret)
 	if (ret)
 		goto err;
 		goto err;
 
 
-	cl->device_uuid = mei_nfc_guid;
-
-
 	list_add_tail(&cl->device_link, &dev->device_list);
 	list_add_tail(&cl->device_link, &dev->device_list);
 
 
 	ndev->req_id = 1;
 	ndev->req_id = 1;
@@ -551,6 +551,7 @@ err:
 void mei_nfc_host_exit(struct mei_device *dev)
 void mei_nfc_host_exit(struct mei_device *dev)
 {
 {
 	struct mei_nfc_dev *ndev = &nfc_dev;
 	struct mei_nfc_dev *ndev = &nfc_dev;
+
 	cancel_work_sync(&ndev->init_work);
 	cancel_work_sync(&ndev->init_work);
 }
 }
 
 

+ 7 - 7
drivers/misc/mei/pci-me.c

@@ -98,12 +98,12 @@ static inline void mei_me_unset_pm_domain(struct mei_device *dev) {}
 #endif /* CONFIG_PM_RUNTIME */
 #endif /* CONFIG_PM_RUNTIME */
 
 
 /**
 /**
- * mei_quirk_probe - probe for devices that doesn't valid ME interface
+ * mei_me_quirk_probe - probe for devices that doesn't valid ME interface
  *
  *
  * @pdev: PCI device structure
  * @pdev: PCI device structure
  * @cfg: per generation config
  * @cfg: per generation config
  *
  *
- * returns true if ME Interface is valid, false otherwise
+ * Return: true if ME Interface is valid, false otherwise
  */
  */
 static bool mei_me_quirk_probe(struct pci_dev *pdev,
 static bool mei_me_quirk_probe(struct pci_dev *pdev,
 				const struct mei_cfg *cfg)
 				const struct mei_cfg *cfg)
@@ -117,12 +117,12 @@ static bool mei_me_quirk_probe(struct pci_dev *pdev,
 }
 }
 
 
 /**
 /**
- * mei_probe - Device Initialization Routine
+ * mei_me_probe - Device Initialization Routine
  *
  *
  * @pdev: PCI device structure
  * @pdev: PCI device structure
  * @ent: entry in kcs_pci_tbl
  * @ent: entry in kcs_pci_tbl
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 {
@@ -249,7 +249,7 @@ end:
 }
 }
 
 
 /**
 /**
- * mei_remove - Device Removal Routine
+ * mei_me_remove - Device Removal Routine
  *
  *
  * @pdev: PCI device structure
  * @pdev: PCI device structure
  *
  *
@@ -430,7 +430,7 @@ static int mei_me_pm_runtime_resume(struct device *device)
  */
  */
 static inline void mei_me_set_pm_domain(struct mei_device *dev)
 static inline void mei_me_set_pm_domain(struct mei_device *dev)
 {
 {
-	struct pci_dev *pdev  = dev->pdev;
+	struct pci_dev *pdev  = to_pci_dev(dev->dev);
 
 
 	if (pdev->dev.bus && pdev->dev.bus->pm) {
 	if (pdev->dev.bus && pdev->dev.bus->pm) {
 		dev->pg_domain.ops = *pdev->dev.bus->pm;
 		dev->pg_domain.ops = *pdev->dev.bus->pm;
@@ -451,7 +451,7 @@ static inline void mei_me_set_pm_domain(struct mei_device *dev)
 static inline void mei_me_unset_pm_domain(struct mei_device *dev)
 static inline void mei_me_unset_pm_domain(struct mei_device *dev)
 {
 {
 	/* stop using pm callbacks if any */
 	/* stop using pm callbacks if any */
-	dev->pdev->dev.pm_domain = NULL;
+	dev->dev->pm_domain = NULL;
 }
 }
 #endif /* CONFIG_PM_RUNTIME */
 #endif /* CONFIG_PM_RUNTIME */
 
 

+ 7 - 6
drivers/misc/mei/pci-txe.c

@@ -36,7 +36,8 @@
 #include "hw-txe.h"
 #include "hw-txe.h"
 
 
 static const struct pci_device_id mei_txe_pci_tbl[] = {
 static const struct pci_device_id mei_txe_pci_tbl[] = {
-	{MEI_PCI_DEVICE(0x0F18, mei_txe_cfg)}, /* Baytrail */
+	{PCI_VDEVICE(INTEL, 0x0F18)}, /* Baytrail */
+
 	{0, }
 	{0, }
 };
 };
 MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl);
 MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl);
@@ -52,6 +53,7 @@ static inline void mei_txe_unset_pm_domain(struct mei_device *dev) {}
 static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw)
 static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw)
 {
 {
 	int i;
 	int i;
+
 	for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) {
 	for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) {
 		if (hw->mem_addr[i]) {
 		if (hw->mem_addr[i]) {
 			pci_iounmap(pdev, hw->mem_addr[i]);
 			pci_iounmap(pdev, hw->mem_addr[i]);
@@ -65,11 +67,10 @@ static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw)
  * @pdev: PCI device structure
  * @pdev: PCI device structure
  * @ent: entry in mei_txe_pci_tbl
  * @ent: entry in mei_txe_pci_tbl
  *
  *
- * returns 0 on success, <0 on failure.
+ * Return: 0 on success, <0 on failure.
  */
  */
 static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 {
-	const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data);
 	struct mei_device *dev;
 	struct mei_device *dev;
 	struct mei_txe_hw *hw;
 	struct mei_txe_hw *hw;
 	int err;
 	int err;
@@ -100,7 +101,7 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 	}
 
 
 	/* allocates and initializes the mei dev structure */
 	/* allocates and initializes the mei dev structure */
-	dev = mei_txe_dev_init(pdev, cfg);
+	dev = mei_txe_dev_init(pdev);
 	if (!dev) {
 	if (!dev) {
 		err = -ENOMEM;
 		err = -ENOMEM;
 		goto release_regions;
 		goto release_regions;
@@ -377,7 +378,7 @@ static int mei_txe_pm_runtime_resume(struct device *device)
  */
  */
 static inline void mei_txe_set_pm_domain(struct mei_device *dev)
 static inline void mei_txe_set_pm_domain(struct mei_device *dev)
 {
 {
-	struct pci_dev *pdev  = dev->pdev;
+	struct pci_dev *pdev  = to_pci_dev(dev->dev);
 
 
 	if (pdev->dev.bus && pdev->dev.bus->pm) {
 	if (pdev->dev.bus && pdev->dev.bus->pm) {
 		dev->pg_domain.ops = *pdev->dev.bus->pm;
 		dev->pg_domain.ops = *pdev->dev.bus->pm;
@@ -398,7 +399,7 @@ static inline void mei_txe_set_pm_domain(struct mei_device *dev)
 static inline void mei_txe_unset_pm_domain(struct mei_device *dev)
 static inline void mei_txe_unset_pm_domain(struct mei_device *dev)
 {
 {
 	/* stop using pm callbacks if any */
 	/* stop using pm callbacks if any */
-	dev->pdev->dev.pm_domain = NULL;
+	dev->dev->pm_domain = NULL;
 }
 }
 #endif /* CONFIG_PM_RUNTIME */
 #endif /* CONFIG_PM_RUNTIME */
 
 

+ 27 - 32
drivers/misc/mei/wd.c

@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/device.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <linux/watchdog.h>
 #include <linux/watchdog.h>
 
 
@@ -42,7 +41,7 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89,
 
 
 static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
 static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
 {
 {
-	dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", timeout);
+	dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout);
 	memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE);
 	memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE);
 	memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16));
 	memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16));
 }
 }
@@ -52,14 +51,14 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns -ENOTTY if wd client cannot be found
+ * Return: -ENOTTY if wd client cannot be found
  *         -EIO if write has failed
  *         -EIO if write has failed
  *         0 on success
  *         0 on success
  */
  */
 int mei_wd_host_init(struct mei_device *dev)
 int mei_wd_host_init(struct mei_device *dev)
 {
 {
 	struct mei_cl *cl = &dev->wd_cl;
 	struct mei_cl *cl = &dev->wd_cl;
-	int id;
+	struct mei_me_client *me_cl;
 	int ret;
 	int ret;
 
 
 	mei_cl_init(cl, dev);
 	mei_cl_init(cl, dev);
@@ -69,25 +68,26 @@ int mei_wd_host_init(struct mei_device *dev)
 
 
 
 
 	/* check for valid client id */
 	/* check for valid client id */
-	id = mei_me_cl_by_uuid(dev, &mei_wd_guid);
-	if (id < 0) {
-		dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
+	me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid);
+	if (!me_cl) {
+		dev_info(dev->dev, "wd: failed to find the client\n");
 		return -ENOTTY;
 		return -ENOTTY;
 	}
 	}
 
 
-	cl->me_client_id = dev->me_clients[id].client_id;
+	cl->me_client_id = me_cl->client_id;
+	cl->cl_uuid = me_cl->props.protocol_name;
 
 
 	ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID);
 	ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID);
 
 
 	if (ret < 0) {
 	if (ret < 0) {
-		dev_info(&dev->pdev->dev, "wd: failed link client\n");
+		dev_info(dev->dev, "wd: failed link client\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
 	ret = mei_cl_connect(cl, NULL);
 	ret = mei_cl_connect(cl, NULL);
 
 
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "wd: failed to connect = %d\n", ret);
+		dev_err(dev->dev, "wd: failed to connect = %d\n", ret);
 		mei_cl_unlink(cl);
 		mei_cl_unlink(cl);
 		return ret;
 		return ret;
 	}
 	}
@@ -105,7 +105,7 @@ int mei_wd_host_init(struct mei_device *dev)
  *
  *
  * @dev: the device structure
  * @dev: the device structure
  *
  *
- * returns 0 if success,
+ * Return: 0 if success,
  *	-EIO when message send fails
  *	-EIO when message send fails
  *	-EINVAL when invalid message is to be sent
  *	-EINVAL when invalid message is to be sent
  *	-ENODEV on flow control failure
  *	-ENODEV on flow control failure
@@ -127,19 +127,19 @@ int mei_wd_send(struct mei_device *dev)
 	else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE))
 	else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE))
 		hdr.length = MEI_WD_STOP_MSG_SIZE;
 		hdr.length = MEI_WD_STOP_MSG_SIZE;
 	else {
 	else {
-		dev_err(&dev->pdev->dev, "wd: invalid message is to be sent, aborting\n");
+		dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
 	ret = mei_write_message(dev, &hdr, dev->wd_data);
 	ret = mei_write_message(dev, &hdr, dev->wd_data);
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "wd: write message failed\n");
+		dev_err(dev->dev, "wd: write message failed\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
 	ret = mei_cl_flow_ctrl_reduce(cl);
 	ret = mei_cl_flow_ctrl_reduce(cl);
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "wd: flow_ctrl_reduce failed.\n");
+		dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -150,9 +150,8 @@ int mei_wd_send(struct mei_device *dev)
  * mei_wd_stop - sends watchdog stop message to fw.
  * mei_wd_stop - sends watchdog stop message to fw.
  *
  *
  * @dev: the device structure
  * @dev: the device structure
- * @preserve: indicate if to keep the timeout value
  *
  *
- * returns 0 if success
+ * Return: 0 if success
  * on error:
  * on error:
  *	-EIO    when message send fails
  *	-EIO    when message send fails
  *	-EINVAL when invalid message is to be sent
  *	-EINVAL when invalid message is to be sent
@@ -192,11 +191,10 @@ int mei_wd_stop(struct mei_device *dev)
 	if (dev->wd_state != MEI_WD_IDLE) {
 	if (dev->wd_state != MEI_WD_IDLE) {
 		/* timeout */
 		/* timeout */
 		ret = -ETIME;
 		ret = -ETIME;
-		dev_warn(&dev->pdev->dev,
-			"wd: stop failed to complete ret=%d.\n", ret);
+		dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret);
 		goto err;
 		goto err;
 	}
 	}
-	dev_dbg(&dev->pdev->dev, "wd: stop completed after %u msec\n",
+	dev_dbg(dev->dev, "wd: stop completed after %u msec\n",
 			MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret));
 			MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret));
 	return 0;
 	return 0;
 err:
 err:
@@ -208,7 +206,7 @@ err:
  *
  *
  * @wd_dev - watchdog device struct
  * @wd_dev - watchdog device struct
  *
  *
- * returns 0 if success, negative errno code for failure
+ * Return: 0 if success, negative errno code for failure
  */
  */
 static int mei_wd_ops_start(struct watchdog_device *wd_dev)
 static int mei_wd_ops_start(struct watchdog_device *wd_dev)
 {
 {
@@ -222,15 +220,13 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev)
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 
 
 	if (dev->dev_state != MEI_DEV_ENABLED) {
 	if (dev->dev_state != MEI_DEV_ENABLED) {
-		dev_dbg(&dev->pdev->dev,
-			"wd: dev_state != MEI_DEV_ENABLED  dev_state = %s\n",
+		dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED  dev_state = %s\n",
 			mei_dev_state_str(dev->dev_state));
 			mei_dev_state_str(dev->dev_state));
 		goto end_unlock;
 		goto end_unlock;
 	}
 	}
 
 
 	if (dev->wd_cl.state != MEI_FILE_CONNECTED)	{
 	if (dev->wd_cl.state != MEI_FILE_CONNECTED)	{
-		dev_dbg(&dev->pdev->dev,
-			"MEI Driver is not connected to Watchdog Client\n");
+		dev_dbg(dev->dev, "MEI Driver is not connected to Watchdog Client\n");
 		goto end_unlock;
 		goto end_unlock;
 	}
 	}
 
 
@@ -247,7 +243,7 @@ end_unlock:
  *
  *
  * @wd_dev - watchdog device struct
  * @wd_dev - watchdog device struct
  *
  *
- * returns 0 if success, negative errno code for failure
+ * Return: 0 if success, negative errno code for failure
  */
  */
 static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
 static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
 {
 {
@@ -269,7 +265,7 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
  *
  *
  * @wd_dev - watchdog device struct
  * @wd_dev - watchdog device struct
  *
  *
- * returns 0 if success, negative errno code for failure
+ * Return: 0 if success, negative errno code for failure
  */
  */
 static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 {
 {
@@ -283,7 +279,7 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 
 
 	if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
 	if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
-		dev_err(&dev->pdev->dev, "wd: not connected.\n");
+		dev_err(dev->dev, "wd: not connected.\n");
 		ret = -ENODEV;
 		ret = -ENODEV;
 		goto end;
 		goto end;
 	}
 	}
@@ -296,7 +292,7 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 	/* Check if we can send the ping to HW*/
 	/* Check if we can send the ping to HW*/
 	if (ret && mei_hbuf_acquire(dev)) {
 	if (ret && mei_hbuf_acquire(dev)) {
 
 
-		dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
+		dev_dbg(dev->dev, "wd: sending ping\n");
 
 
 		ret = mei_wd_send(dev);
 		ret = mei_wd_send(dev);
 		if (ret)
 		if (ret)
@@ -317,7 +313,7 @@ end:
  * @wd_dev - watchdog device struct
  * @wd_dev - watchdog device struct
  * @timeout - timeout value to set
  * @timeout - timeout value to set
  *
  *
- * returns 0 if success, negative errno code for failure
+ * Return: 0 if success, negative errno code for failure
  */
  */
 static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev,
 static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev,
 		unsigned int timeout)
 		unsigned int timeout)
@@ -379,13 +375,12 @@ int mei_watchdog_register(struct mei_device *dev)
 	ret = watchdog_register_device(&amt_wd_dev);
 	ret = watchdog_register_device(&amt_wd_dev);
 	mutex_lock(&dev->device_lock);
 	mutex_lock(&dev->device_lock);
 	if (ret) {
 	if (ret) {
-		dev_err(&dev->pdev->dev, "wd: unable to register watchdog device = %d.\n",
+		dev_err(dev->dev, "wd: unable to register watchdog device = %d.\n",
 			ret);
 			ret);
 		return ret;
 		return ret;
 	}
 	}
 
 
-	dev_dbg(&dev->pdev->dev,
-		"wd: successfully register watchdog interface.\n");
+	dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n");
 	watchdog_set_drvdata(&amt_wd_dev, dev);
 	watchdog_set_drvdata(&amt_wd_dev, dev);
 	return 0;
 	return 0;
 }
 }

+ 23 - 75
drivers/misc/spear13xx_pcie_gadget.c

@@ -9,6 +9,7 @@
  * warranty of any kind, whether express or implied.
  * warranty of any kind, whether express or implied.
  */
  */
 
 
+#include <linux/device.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
@@ -743,58 +744,33 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev)
 	struct config_item		*cg_item;
 	struct config_item		*cg_item;
 	struct configfs_subsystem *subsys;
 	struct configfs_subsystem *subsys;
 
 
-	/* get resource for application registers*/
-
-	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res0) {
-		dev_err(&pdev->dev, "no resource defined\n");
-		return -EBUSY;
-	}
-	if (!request_mem_region(res0->start, resource_size(res0),
-				pdev->name)) {
-		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
-		return -EBUSY;
-	}
-	/* get resource for dbi registers*/
-
-	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!res1) {
-		dev_err(&pdev->dev, "no resource defined\n");
-		goto err_rel_res0;
-	}
-	if (!request_mem_region(res1->start, resource_size(res1),
-				pdev->name)) {
-		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
-		goto err_rel_res0;
-	}
-
-	target = kzalloc(sizeof(*target), GFP_KERNEL);
+	target = devm_kzalloc(&pdev->dev, sizeof(*target), GFP_KERNEL);
 	if (!target) {
 	if (!target) {
 		dev_err(&pdev->dev, "out of memory\n");
 		dev_err(&pdev->dev, "out of memory\n");
-		status = -ENOMEM;
-		goto err_rel_res;
+		return -ENOMEM;
 	}
 	}
 
 
 	cg_item = &target->subsys.su_group.cg_item;
 	cg_item = &target->subsys.su_group.cg_item;
 	sprintf(cg_item->ci_namebuf, "pcie_gadget.%d", pdev->id);
 	sprintf(cg_item->ci_namebuf, "pcie_gadget.%d", pdev->id);
 	cg_item->ci_type	= &pcie_gadget_target_type;
 	cg_item->ci_type	= &pcie_gadget_target_type;
 	config = &target->config;
 	config = &target->config;
-	config->va_app_base = (void __iomem *)ioremap(res0->start,
-			resource_size(res0));
-	if (!config->va_app_base) {
+
+	/* get resource for application registers*/
+	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	config->va_app_base = devm_ioremap_resource(&pdev->dev, res0);
+	if (IS_ERR(config->va_app_base)) {
 		dev_err(&pdev->dev, "ioremap fail\n");
 		dev_err(&pdev->dev, "ioremap fail\n");
-		status = -ENOMEM;
-		goto err_kzalloc;
+		return PTR_ERR(config->va_app_base);
 	}
 	}
 
 
+	/* get resource for dbi registers*/
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	config->base = (void __iomem *)res1->start;
 	config->base = (void __iomem *)res1->start;
 
 
-	config->va_dbi_base = (void __iomem *)ioremap(res1->start,
-			resource_size(res1));
-	if (!config->va_dbi_base) {
+	config->va_dbi_base = devm_ioremap_resource(&pdev->dev, res1);
+	if (IS_ERR(config->va_dbi_base)) {
 		dev_err(&pdev->dev, "ioremap fail\n");
 		dev_err(&pdev->dev, "ioremap fail\n");
-		status = -ENOMEM;
-		goto err_iounmap_app;
+		return PTR_ERR(config->va_dbi_base);
 	}
 	}
 
 
 	platform_set_drvdata(pdev, target);
 	platform_set_drvdata(pdev, target);
@@ -802,15 +778,15 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev)
 	irq = platform_get_irq(pdev, 0);
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 	if (irq < 0) {
 		dev_err(&pdev->dev, "no update irq?\n");
 		dev_err(&pdev->dev, "no update irq?\n");
-		status = irq;
-		goto err_iounmap;
+		return irq;
 	}
 	}
 
 
-	status = request_irq(irq, spear_pcie_gadget_irq, 0, pdev->name, NULL);
+	status = devm_request_irq(&pdev->dev, irq, spear_pcie_gadget_irq,
+				  0, pdev->name, NULL);
 	if (status) {
 	if (status) {
 		dev_err(&pdev->dev,
 		dev_err(&pdev->dev,
 			"pcie gadget interrupt IRQ%d already claimed\n", irq);
 			"pcie gadget interrupt IRQ%d already claimed\n", irq);
-		goto err_iounmap;
+		return status;
 	}
 	}
 
 
 	/* Register configfs hooks */
 	/* Register configfs hooks */
@@ -819,7 +795,7 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev)
 	mutex_init(&subsys->su_mutex);
 	mutex_init(&subsys->su_mutex);
 	status = configfs_register_subsystem(subsys);
 	status = configfs_register_subsystem(subsys);
 	if (status)
 	if (status)
-		goto err_irq;
+		return status;
 
 
 	/*
 	/*
 	 * init basic pcie application registers
 	 * init basic pcie application registers
@@ -835,13 +811,12 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev)
 		clk = clk_get_sys("pcie1", NULL);
 		clk = clk_get_sys("pcie1", NULL);
 		if (IS_ERR(clk)) {
 		if (IS_ERR(clk)) {
 			pr_err("%s:couldn't get clk for pcie1\n", __func__);
 			pr_err("%s:couldn't get clk for pcie1\n", __func__);
-			status = PTR_ERR(clk);
-			goto err_irq;
+			return PTR_ERR(clk);
 		}
 		}
 		status = clk_enable(clk);
 		status = clk_enable(clk);
 		if (status) {
 		if (status) {
 			pr_err("%s:couldn't enable clk for pcie1\n", __func__);
 			pr_err("%s:couldn't enable clk for pcie1\n", __func__);
-			goto err_irq;
+			return status;
 		}
 		}
 	} else if (pdev->id == 2) {
 	} else if (pdev->id == 2) {
 		/*
 		/*
@@ -851,53 +826,26 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev)
 		clk = clk_get_sys("pcie2", NULL);
 		clk = clk_get_sys("pcie2", NULL);
 		if (IS_ERR(clk)) {
 		if (IS_ERR(clk)) {
 			pr_err("%s:couldn't get clk for pcie2\n", __func__);
 			pr_err("%s:couldn't get clk for pcie2\n", __func__);
-			status = PTR_ERR(clk);
-			goto err_irq;
+			return PTR_ERR(clk);
 		}
 		}
 		status = clk_enable(clk);
 		status = clk_enable(clk);
 		if (status) {
 		if (status) {
 			pr_err("%s:couldn't enable clk for pcie2\n", __func__);
 			pr_err("%s:couldn't enable clk for pcie2\n", __func__);
-			goto err_irq;
+			return status;
 		}
 		}
 	}
 	}
 	spear13xx_pcie_device_init(config);
 	spear13xx_pcie_device_init(config);
 
 
 	return 0;
 	return 0;
-err_irq:
-	free_irq(irq, NULL);
-err_iounmap:
-	iounmap(config->va_dbi_base);
-err_iounmap_app:
-	iounmap(config->va_app_base);
-err_kzalloc:
-	kfree(target);
-err_rel_res:
-	release_mem_region(res1->start, resource_size(res1));
-err_rel_res0:
-	release_mem_region(res0->start, resource_size(res0));
-	return status;
 }
 }
 
 
 static int spear_pcie_gadget_remove(struct platform_device *pdev)
 static int spear_pcie_gadget_remove(struct platform_device *pdev)
 {
 {
-	struct resource *res0, *res1;
 	static struct pcie_gadget_target *target;
 	static struct pcie_gadget_target *target;
-	struct spear_pcie_gadget_config *config;
-	int irq;
 
 
-	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	irq = platform_get_irq(pdev, 0);
 	target = platform_get_drvdata(pdev);
 	target = platform_get_drvdata(pdev);
-	config = &target->config;
 
 
-	free_irq(irq, NULL);
-	iounmap(config->va_dbi_base);
-	iounmap(config->va_app_base);
-	release_mem_region(res1->start, resource_size(res1));
-	release_mem_region(res0->start, resource_size(res0));
 	configfs_unregister_subsystem(&target->subsys);
 	configfs_unregister_subsystem(&target->subsys);
-	kfree(target);
 
 
 	return 0;
 	return 0;
 }
 }

+ 5 - 6
drivers/misc/ti-st/st_core.c

@@ -153,8 +153,9 @@ static void st_reg_complete(struct st_data_s *st_gdata, char err)
 				(st_gdata->list[i]->priv_data, err);
 				(st_gdata->list[i]->priv_data, err);
 			pr_info("protocol %d's cb sent %d\n", i, err);
 			pr_info("protocol %d's cb sent %d\n", i, err);
 			if (err) { /* cleanup registered protocol */
 			if (err) { /* cleanup registered protocol */
-				st_gdata->protos_registered--;
 				st_gdata->is_registered[i] = false;
 				st_gdata->is_registered[i] = false;
+				if (st_gdata->protos_registered)
+					st_gdata->protos_registered--;
 			}
 			}
 		}
 		}
 	}
 	}
@@ -639,14 +640,12 @@ long st_unregister(struct st_proto_s *proto)
 		return -EPROTONOSUPPORT;
 		return -EPROTONOSUPPORT;
 	}
 	}
 
 
-	st_gdata->protos_registered--;
+	if (st_gdata->protos_registered)
+		st_gdata->protos_registered--;
+
 	remove_channel_from_table(st_gdata, proto);
 	remove_channel_from_table(st_gdata, proto);
 	spin_unlock_irqrestore(&st_gdata->lock, flags);
 	spin_unlock_irqrestore(&st_gdata->lock, flags);
 
 
-	/* paranoid check */
-	if (st_gdata->protos_registered < ST_EMPTY)
-		st_gdata->protos_registered = ST_EMPTY;
-
 	if ((st_gdata->protos_registered == ST_EMPTY) &&
 	if ((st_gdata->protos_registered == ST_EMPTY) &&
 	    (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
 	    (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
 		pr_info(" all chnl_ids unregistered ");
 		pr_info(" all chnl_ids unregistered ");

+ 2 - 1
drivers/misc/vmw_vmci/vmci_datagram.c

@@ -328,7 +328,8 @@ int vmci_datagram_dispatch(u32 context_id,
 
 
 	BUILD_BUG_ON(sizeof(struct vmci_datagram) != 24);
 	BUILD_BUG_ON(sizeof(struct vmci_datagram) != 24);
 
 
-	if (VMCI_DG_SIZE(dg) > VMCI_MAX_DG_SIZE) {
+	if (dg->payload_size > VMCI_MAX_DG_SIZE ||
+	    VMCI_DG_SIZE(dg) > VMCI_MAX_DG_SIZE) {
 		pr_devel("Payload (size=%llu bytes) too big to send\n",
 		pr_devel("Payload (size=%llu bytes) too big to send\n",
 			 (unsigned long long)dg->payload_size);
 			 (unsigned long long)dg->payload_size);
 		return VMCI_ERROR_INVALID_ARGS;
 		return VMCI_ERROR_INVALID_ARGS;

+ 42 - 12
drivers/parport/parport_pc.c

@@ -1702,6 +1702,46 @@ static int parport_ECP_supported(struct parport *pb)
 }
 }
 #endif
 #endif
 
 
+#ifdef CONFIG_X86_32
+static int intel_bug_present_check_epp(struct parport *pb)
+{
+	const struct parport_pc_private *priv = pb->private_data;
+	int bug_present = 0;
+
+	if (priv->ecr) {
+		/* store value of ECR */
+		unsigned char ecr = inb(ECONTROL(pb));
+		unsigned char i;
+		for (i = 0x00; i < 0x80; i += 0x20) {
+			ECR_WRITE(pb, i);
+			if (clear_epp_timeout(pb)) {
+				/* Phony EPP in ECP. */
+				bug_present = 1;
+				break;
+			}
+		}
+		/* return ECR into the inital state */
+		ECR_WRITE(pb, ecr);
+	}
+
+	return bug_present;
+}
+static int intel_bug_present(struct parport *pb)
+{
+/* Check whether the device is legacy, not PCI or PCMCIA. Only legacy is known to be affected. */
+	if (pb->dev != NULL) {
+		return 0;
+	}
+
+	return intel_bug_present_check_epp(pb);
+}
+#else
+static int intel_bug_present(struct parport *pb)
+{
+	return 0;
+}
+#endif /* CONFIG_X86_32 */
+
 static int parport_ECPPS2_supported(struct parport *pb)
 static int parport_ECPPS2_supported(struct parport *pb)
 {
 {
 	const struct parport_pc_private *priv = pb->private_data;
 	const struct parport_pc_private *priv = pb->private_data;
@@ -1722,8 +1762,6 @@ static int parport_ECPPS2_supported(struct parport *pb)
 
 
 static int parport_EPP_supported(struct parport *pb)
 static int parport_EPP_supported(struct parport *pb)
 {
 {
-	const struct parport_pc_private *priv = pb->private_data;
-
 	/*
 	/*
 	 * Theory:
 	 * Theory:
 	 *	Bit 0 of STR is the EPP timeout bit, this bit is 0
 	 *	Bit 0 of STR is the EPP timeout bit, this bit is 0
@@ -1742,16 +1780,8 @@ static int parport_EPP_supported(struct parport *pb)
 		return 0;  /* No way to clear timeout */
 		return 0;  /* No way to clear timeout */
 
 
 	/* Check for Intel bug. */
 	/* Check for Intel bug. */
-	if (priv->ecr) {
-		unsigned char i;
-		for (i = 0x00; i < 0x80; i += 0x20) {
-			ECR_WRITE(pb, i);
-			if (clear_epp_timeout(pb)) {
-				/* Phony EPP in ECP. */
-				return 0;
-			}
-		}
-	}
+	if (intel_bug_present(pb))
+		return 0;
 
 
 	pb->modes |= PARPORT_MODE_EPP;
 	pb->modes |= PARPORT_MODE_EPP;
 
 

+ 3 - 1
include/linux/extcon/extcon-gpio.h

@@ -34,8 +34,10 @@
  * @irq_flags:		IRQ Flags (e.g., IRQF_TRIGGER_LOW).
  * @irq_flags:		IRQ Flags (e.g., IRQF_TRIGGER_LOW).
  * @state_on:		print_state is overriden with state_on if attached.
  * @state_on:		print_state is overriden with state_on if attached.
  *			If NULL, default method of extcon class is used.
  *			If NULL, default method of extcon class is used.
- * @state_off:		print_state is overriden with state_on if detached.
+ * @state_off:		print_state is overriden with state_off if detached.
  *			If NUll, default method of extcon class is used.
  *			If NUll, default method of extcon class is used.
+ * @check_on_resume:	Boolean describing whether to check the state of gpio
+ *			while resuming from sleep.
  *
  *
  * Note that in order for state_on or state_off to be valid, both state_on
  * Note that in order for state_on or state_off to be valid, both state_on
  * and state_off should be not NULL. If at least one of them is NULL,
  * and state_off should be not NULL. If at least one of them is NULL,

+ 23 - 1
include/linux/ipack.h

@@ -172,6 +172,7 @@ struct ipack_bus_ops {
  *	@ops: bus operations for the mezzanine drivers
  *	@ops: bus operations for the mezzanine drivers
  */
  */
 struct ipack_bus_device {
 struct ipack_bus_device {
+	struct module *owner;
 	struct device *parent;
 	struct device *parent;
 	int slots;
 	int slots;
 	int bus_nr;
 	int bus_nr;
@@ -189,7 +190,8 @@ struct ipack_bus_device {
  * available bus device in ipack.
  * available bus device in ipack.
  */
  */
 struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
 struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
-					    const struct ipack_bus_ops *ops);
+					    const struct ipack_bus_ops *ops,
+					    struct module *owner);
 
 
 /**
 /**
  *	ipack_bus_unregister -- unregister an ipack bus
  *	ipack_bus_unregister -- unregister an ipack bus
@@ -265,3 +267,23 @@ void ipack_put_device(struct ipack_device *dev);
 	 .format = (_format), \
 	 .format = (_format), \
 	 .vendor = (vend), \
 	 .vendor = (vend), \
 	 .device = (dev)
 	 .device = (dev)
+
+/**
+ * ipack_get_carrier - it increase the carrier ref. counter of
+ *                     the carrier module
+ * @dev: mezzanine device which wants to get the carrier
+ */
+static inline int ipack_get_carrier(struct ipack_device *dev)
+{
+	return try_module_get(dev->bus->owner);
+}
+
+/**
+ * ipack_get_carrier - it decrease the carrier ref. counter of
+ *                     the carrier module
+ * @dev: mezzanine device which wants to get the carrier
+ */
+static inline void ipack_put_carrier(struct ipack_device *dev)
+{
+	module_put(dev->bus->owner);
+}

+ 1 - 0
include/linux/mei_cl_bus.h

@@ -3,6 +3,7 @@
 
 
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/uuid.h>
 #include <linux/uuid.h>
+#include <linux/mod_devicetable.h>
 
 
 struct mei_cl_device;
 struct mei_cl_device;
 
 

+ 1 - 1
include/linux/ti_wilink_st.h

@@ -268,7 +268,7 @@ struct kim_data_s {
 	struct st_data_s *core_data;
 	struct st_data_s *core_data;
 	struct chip_version version;
 	struct chip_version version;
 	unsigned char ldisc_install;
 	unsigned char ldisc_install;
-	unsigned char dev_name[UART_DEV_NAME_LEN];
+	unsigned char dev_name[UART_DEV_NAME_LEN + 1];
 	unsigned char flow_cntrl;
 	unsigned char flow_cntrl;
 	unsigned long baud_rate;
 	unsigned long baud_rate;
 };
 };

+ 1 - 1
include/uapi/linux/genwqe/genwqe_card.h

@@ -8,7 +8,7 @@
  *
  *
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Frank Haverkamp <haver@linux.vnet.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
  * Author: Joerg-Stephan Vogt <jsvogt@de.ibm.com>
- * Author: Michael Jung <mijung@de.ibm.com>
+ * Author: Michael Jung <mijung@gmx.net>
  * Author: Michael Ruettger <michael@ibmra.de>
  * Author: Michael Ruettger <michael@ibmra.de>
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify

+ 1 - 1
include/uapi/linux/hyperv.h

@@ -137,7 +137,7 @@ struct hv_do_fcopy {
 	__u64	offset;
 	__u64	offset;
 	__u32	size;
 	__u32	size;
 	__u8	data[DATA_FRAGMENT];
 	__u8	data[DATA_FRAGMENT];
-};
+} __attribute__((packed));
 
 
 /*
 /*
  * An implementation of HyperV key value pair (KVP) functionality for Linux.
  * An implementation of HyperV key value pair (KVP) functionality for Linux.