linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [char-misc-next 0/6] MEI and ME separation
@ 2013-02-06 12:06 Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 1/6] mei: sperate interface and pci code into two files Tomas Winkler
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Tomas Winkler @ 2013-02-06 12:06 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, alan, linux-kernel, Tomas Winkler

We are about to introduce new under laying hardware
that supports MEI interface. For that purpose we
split the driver into interface hand hardware specific layers

Tomas Winkler (6):
  mei: sperate interface and pci code into two files
  mei: initial extract of ME hw specifics from mei_device
  mei: separate compilation of the ME hardware specifics
  mei: move interrupt handlers to be me hw specific
  mei: rename to mei_host_buffer_is_empty to hbuf_is_ready
  mei: move clients cleanup code from init.c to client.c

 drivers/misc/mei/Kconfig     |   17 ++-
 drivers/misc/mei/Makefile    |    5 +-
 drivers/misc/mei/amthif.c    |   12 +-
 drivers/misc/mei/client.c    |   64 ++++++-
 drivers/misc/mei/client.h    |    5 +
 drivers/misc/mei/hw-me.c     |  376 ++++++++++++++++++++++++++++++----------
 drivers/misc/mei/hw-me.h     |   30 ++--
 drivers/misc/mei/init.c      |   58 +------
 drivers/misc/mei/interrupt.c |  130 +-------------
 drivers/misc/mei/main.c      |  363 ++------------------------------------
 drivers/misc/mei/mei_dev.h   |  168 +++++++++++++++---
 drivers/misc/mei/pci-me.c    |  396 ++++++++++++++++++++++++++++++++++++++++++
 drivers/misc/mei/wd.c        |    9 +-
 13 files changed, 960 insertions(+), 673 deletions(-)
 create mode 100644 drivers/misc/mei/pci-me.c

-- 
1.7.4.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [char-misc-next 1/6] mei: sperate interface and pci code into two files
  2013-02-06 12:06 [char-misc-next 0/6] MEI and ME separation Tomas Winkler
@ 2013-02-06 12:06 ` Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 2/6] mei: initial extract of ME hw specifics from mei_device Tomas Winkler
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Tomas Winkler @ 2013-02-06 12:06 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, alan, linux-kernel, Tomas Winkler

leave misc file operations in the main
and move PCI related code into pci-me

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/Makefile  |    1 +
 drivers/misc/mei/main.c    |  354 ++--------------------------------------
 drivers/misc/mei/mei_dev.h |    3 +
 drivers/misc/mei/pci-me.c  |  393 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 409 insertions(+), 342 deletions(-)
 create mode 100644 drivers/misc/mei/pci-me.c

diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 9f71933..068f553 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -11,3 +11,4 @@ mei-objs += main.o
 mei-objs += amthif.o
 mei-objs += wd.o
 mei-objs += client.o
+mei-objs += pci-me.o
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 123c663..018623c 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -43,54 +43,6 @@
 #include "hw-me.h"
 #include "client.h"
 
-/* AMT device is a singleton on the platform */
-static struct pci_dev *mei_pdev;
-
-/* mei_pci_tbl - PCI Device ID Table */
-static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G35)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82Q965)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G965)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GM965)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GME965)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q35)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82G33)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q33)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82X38)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_3200)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_6)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_7)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_8)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_9)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_10)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_2)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_3)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_4)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_2)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_3)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_4)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_2)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_CPT_1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PBG_1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)},
-
-	/* required last entry */
-	{0, }
-};
-
-MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
-
-static DEFINE_MUTEX(mei_mutex);
-
-
 /**
  * mei_open - the open function
  *
@@ -101,15 +53,20 @@ static DEFINE_MUTEX(mei_mutex);
  */
 static int mei_open(struct inode *inode, struct file *file)
 {
+	struct miscdevice *misc = file->private_data;
+	struct pci_dev *pdev;
 	struct mei_cl *cl;
 	struct mei_device *dev;
+
 	int err;
 
 	err = -ENODEV;
-	if (!mei_pdev)
+	if (!misc->parent)
 		goto out;
 
-	dev = pci_get_drvdata(mei_pdev);
+	pdev = container_of(misc->parent, struct pci_dev, dev);
+
+	dev = pci_get_drvdata(pdev);
 	if (!dev)
 		goto out;
 
@@ -787,7 +744,6 @@ static const struct file_operations mei_fops = {
 	.llseek = no_llseek
 };
 
-
 /*
  * Misc Device Struct
  */
@@ -797,302 +753,16 @@ static struct miscdevice  mei_misc_device = {
 		.minor = MISC_DYNAMIC_MINOR,
 };
 
-/**
- * mei_quirk_probe - probe for devices that doesn't valid ME interface
- * @pdev: PCI device structure
- * @ent: entry into pci_device_table
- *
- * returns true if ME Interface is valid, false otherwise
- */
-static bool mei_quirk_probe(struct pci_dev *pdev,
-				const struct pci_device_id *ent)
+int mei_register(struct device *dev)
 {
-	u32 reg;
-	if (ent->device == MEI_DEV_ID_PBG_1) {
-		pci_read_config_dword(pdev, 0x48, &reg);
-		/* make sure that bit 9 is up and bit 10 is down */
-		if ((reg & 0x600) == 0x200) {
-			dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n");
-			return false;
-		}
-	}
-	return true;
-}
-/**
- * mei_probe - Device Initialization Routine
- *
- * @pdev: PCI device structure
- * @ent: entry in kcs_pci_tbl
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_probe(struct pci_dev *pdev,
-				const struct pci_device_id *ent)
-{
-	struct mei_device *dev;
-	int err;
-
-	mutex_lock(&mei_mutex);
-
-	if (!mei_quirk_probe(pdev, ent)) {
-		err = -ENODEV;
-		goto end;
-	}
-
-	if (mei_pdev) {
-		err = -EEXIST;
-		goto end;
-	}
-	/* enable pci dev */
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "failed to enable pci device.\n");
-		goto end;
-	}
-	/* set PCI host mastering  */
-	pci_set_master(pdev);
-	/* pci request regions for mei driver */
-	err = pci_request_regions(pdev, KBUILD_MODNAME);
-	if (err) {
-		dev_err(&pdev->dev, "failed to get pci regions.\n");
-		goto disable_device;
-	}
-	/* allocates and initializes the mei dev structure */
-	dev = mei_device_init(pdev);
-	if (!dev) {
-		err = -ENOMEM;
-		goto release_regions;
-	}
-	/* mapping  IO device memory */
-	dev->mem_addr = pci_iomap(pdev, 0, 0);
-	if (!dev->mem_addr) {
-		dev_err(&pdev->dev, "mapping I/O device memory failure.\n");
-		err = -ENOMEM;
-		goto free_device;
-	}
-	pci_enable_msi(pdev);
-
-	 /* request and enable interrupt */
-	if (pci_dev_msi_enabled(pdev))
-		err = request_threaded_irq(pdev->irq,
-			NULL,
-			mei_interrupt_thread_handler,
-			IRQF_ONESHOT, KBUILD_MODNAME, dev);
-	else
-		err = request_threaded_irq(pdev->irq,
-			mei_interrupt_quick_handler,
-			mei_interrupt_thread_handler,
-			IRQF_SHARED, KBUILD_MODNAME, dev);
-
-	if (err) {
-		dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
-		       pdev->irq);
-		goto disable_msi;
-	}
-
-	if (mei_hw_init(dev)) {
-		dev_err(&pdev->dev, "init hw failure.\n");
-		err = -ENODEV;
-		goto release_irq;
-	}
-
-	err = misc_register(&mei_misc_device);
-	if (err)
-		goto release_irq;
-
-	mei_pdev = pdev;
-	pci_set_drvdata(pdev, dev);
-
-
-	schedule_delayed_work(&dev->timer_work, HZ);
-
-	mutex_unlock(&mei_mutex);
-
-	pr_debug("initialization successful.\n");
-
-	return 0;
-
-release_irq:
-	mei_disable_interrupts(dev);
-	flush_scheduled_work();
-	free_irq(pdev->irq, dev);
-disable_msi:
-	pci_disable_msi(pdev);
-	pci_iounmap(pdev, dev->mem_addr);
-free_device:
-	kfree(dev);
-release_regions:
-	pci_release_regions(pdev);
-disable_device:
-	pci_disable_device(pdev);
-end:
-	mutex_unlock(&mei_mutex);
-	dev_err(&pdev->dev, "initialization failed.\n");
-	return err;
+	mei_misc_device.parent = dev;
+	return misc_register(&mei_misc_device);
 }
 
-/**
- * mei_remove - Device Removal Routine
- *
- * @pdev: PCI device structure
- *
- * mei_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.
- */
-static void mei_remove(struct pci_dev *pdev)
+void mei_deregister(void)
 {
-	struct mei_device *dev;
-
-	if (mei_pdev != pdev)
-		return;
-
-	dev = pci_get_drvdata(pdev);
-	if (!dev)
-		return;
-
-	mutex_lock(&dev->device_lock);
-
-	cancel_delayed_work(&dev->timer_work);
-
-	mei_wd_stop(dev);
-
-	mei_pdev = NULL;
-
-	if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
-		dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
-		mei_cl_disconnect(&dev->iamthif_cl);
-	}
-	if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
-		dev->wd_cl.state = MEI_FILE_DISCONNECTING;
-		mei_cl_disconnect(&dev->wd_cl);
-	}
-
-	/* Unregistering watchdog device */
-	mei_watchdog_unregister(dev);
-
-	/* remove entry if already in list */
-	dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
-
-	if (dev->open_handle_count > 0)
-		dev->open_handle_count--;
-	mei_cl_unlink(&dev->wd_cl);
-
-	if (dev->open_handle_count > 0)
-		dev->open_handle_count--;
-	mei_cl_unlink(&dev->iamthif_cl);
-
-	dev->iamthif_current_cb = NULL;
-	dev->me_clients_num = 0;
-
-	mutex_unlock(&dev->device_lock);
-
-	flush_scheduled_work();
-
-	/* disable interrupts */
-	mei_disable_interrupts(dev);
-
-	free_irq(pdev->irq, dev);
-	pci_disable_msi(pdev);
-	pci_set_drvdata(pdev, NULL);
-
-	if (dev->mem_addr)
-		pci_iounmap(pdev, dev->mem_addr);
-
-	kfree(dev);
-
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-
 	misc_deregister(&mei_misc_device);
+	mei_misc_device.parent = NULL;
 }
-#ifdef CONFIG_PM
-static int mei_pci_suspend(struct device *device)
-{
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct mei_device *dev = pci_get_drvdata(pdev);
-	int err;
-
-	if (!dev)
-		return -ENODEV;
-	mutex_lock(&dev->device_lock);
-
-	cancel_delayed_work(&dev->timer_work);
-
-	/* Stop watchdog if exists */
-	err = mei_wd_stop(dev);
-	/* Set new mei state */
-	if (dev->dev_state == MEI_DEV_ENABLED ||
-	    dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
-		dev->dev_state = MEI_DEV_POWER_DOWN;
-		mei_reset(dev, 0);
-	}
-	mutex_unlock(&dev->device_lock);
-
-	free_irq(pdev->irq, dev);
-	pci_disable_msi(pdev);
-
-	return err;
-}
-
-static int mei_pci_resume(struct device *device)
-{
-	struct pci_dev *pdev = to_pci_dev(device);
-	struct mei_device *dev;
-	int err;
-
-	dev = pci_get_drvdata(pdev);
-	if (!dev)
-		return -ENODEV;
-
-	pci_enable_msi(pdev);
-
-	/* request and enable interrupt */
-	if (pci_dev_msi_enabled(pdev))
-		err = request_threaded_irq(pdev->irq,
-			NULL,
-			mei_interrupt_thread_handler,
-			IRQF_ONESHOT, KBUILD_MODNAME, dev);
-	else
-		err = request_threaded_irq(pdev->irq,
-			mei_interrupt_quick_handler,
-			mei_interrupt_thread_handler,
-			IRQF_SHARED, KBUILD_MODNAME, dev);
-
-	if (err) {
-		dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
-				pdev->irq);
-		return err;
-	}
-
-	mutex_lock(&dev->device_lock);
-	dev->dev_state = MEI_DEV_POWER_UP;
-	mei_reset(dev, 1);
-	mutex_unlock(&dev->device_lock);
-
-	/* Start timer if stopped in suspend */
-	schedule_delayed_work(&dev->timer_work, HZ);
-
-	return err;
-}
-static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume);
-#define MEI_PM_OPS	(&mei_pm_ops)
-#else
-#define MEI_PM_OPS	NULL
-#endif /* CONFIG_PM */
-/*
- *  PCI driver structure
- */
-static struct pci_driver mei_driver = {
-	.name = KBUILD_MODNAME,
-	.id_table = mei_pci_tbl,
-	.probe = mei_probe,
-	.remove = mei_remove,
-	.shutdown = mei_remove,
-	.driver.pm = MEI_PM_OPS,
-};
 
-module_pci_driver(mei_driver);
 
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index d6589d0..3b2bca3 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -401,6 +401,9 @@ bool mei_me_is_ready(struct mei_device *dev);
 
 
 
+int mei_register(struct device *dev);
+void mei_deregister(void);
+
 #define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d comp=%1d"
 #define MEI_HDR_PRM(hdr)                  \
 	(hdr)->host_addr, (hdr)->me_addr, \
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
new file mode 100644
index 0000000..eaed398
--- /dev/null
+++ b/drivers/misc/mei/pci-me.c
@@ -0,0 +1,393 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2003-2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/aio.h>
+#include <linux/pci.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <linux/uuid.h>
+#include <linux/compat.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/miscdevice.h>
+
+#include <linux/mei.h>
+
+#include "mei_dev.h"
+#include "hw-me.h"
+#include "client.h"
+
+/* AMT device is a singleton on the platform */
+static struct pci_dev *mei_pdev;
+
+/* mei_pci_tbl - PCI Device ID Table */
+static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G35)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82Q965)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G965)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GM965)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GME965)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q35)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82G33)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q33)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82X38)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_3200)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_6)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_7)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_8)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_9)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_10)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_1)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_2)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_3)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_4)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_1)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_2)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_3)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_4)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_1)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_2)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_CPT_1)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PBG_1)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)},
+
+	/* required last entry */
+	{0, }
+};
+
+MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
+
+static DEFINE_MUTEX(mei_mutex);
+
+
+/**
+ * mei_quirk_probe - probe for devices that doesn't valid ME interface
+ * @pdev: PCI device structure
+ * @ent: entry into pci_device_table
+ *
+ * returns true if ME Interface is valid, false otherwise
+ */
+static bool mei_quirk_probe(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
+{
+	u32 reg;
+	if (ent->device == MEI_DEV_ID_PBG_1) {
+		pci_read_config_dword(pdev, 0x48, &reg);
+		/* make sure that bit 9 is up and bit 10 is down */
+		if ((reg & 0x600) == 0x200) {
+			dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n");
+			return false;
+		}
+	}
+	return true;
+}
+/**
+ * mei_probe - Device Initialization Routine
+ *
+ * @pdev: PCI device structure
+ * @ent: entry in kcs_pci_tbl
+ *
+ * returns 0 on success, <0 on failure.
+ */
+static int mei_probe(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
+{
+	struct mei_device *dev;
+	int err;
+
+	mutex_lock(&mei_mutex);
+
+	if (!mei_quirk_probe(pdev, ent)) {
+		err = -ENODEV;
+		goto end;
+	}
+
+	if (mei_pdev) {
+		err = -EEXIST;
+		goto end;
+	}
+	/* enable pci dev */
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable pci device.\n");
+		goto end;
+	}
+	/* set PCI host mastering  */
+	pci_set_master(pdev);
+	/* pci request regions for mei driver */
+	err = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (err) {
+		dev_err(&pdev->dev, "failed to get pci regions.\n");
+		goto disable_device;
+	}
+	/* allocates and initializes the mei dev structure */
+	dev = mei_device_init(pdev);
+	if (!dev) {
+		err = -ENOMEM;
+		goto release_regions;
+	}
+	/* mapping  IO device memory */
+	dev->mem_addr = pci_iomap(pdev, 0, 0);
+	if (!dev->mem_addr) {
+		dev_err(&pdev->dev, "mapping I/O device memory failure.\n");
+		err = -ENOMEM;
+		goto free_device;
+	}
+	pci_enable_msi(pdev);
+
+	 /* request and enable interrupt */
+	if (pci_dev_msi_enabled(pdev))
+		err = request_threaded_irq(pdev->irq,
+			NULL,
+			mei_interrupt_thread_handler,
+			IRQF_ONESHOT, KBUILD_MODNAME, dev);
+	else
+		err = request_threaded_irq(pdev->irq,
+			mei_interrupt_quick_handler,
+			mei_interrupt_thread_handler,
+			IRQF_SHARED, KBUILD_MODNAME, dev);
+
+	if (err) {
+		dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
+		       pdev->irq);
+		goto disable_msi;
+	}
+
+	if (mei_hw_init(dev)) {
+		dev_err(&pdev->dev, "init hw failure.\n");
+		err = -ENODEV;
+		goto release_irq;
+	}
+
+	err = mei_register(&pdev->dev);
+	if (err)
+		goto release_irq;
+
+	mei_pdev = pdev;
+	pci_set_drvdata(pdev, dev);
+
+
+	schedule_delayed_work(&dev->timer_work, HZ);
+
+	mutex_unlock(&mei_mutex);
+
+	pr_debug("initialization successful.\n");
+
+	return 0;
+
+release_irq:
+	mei_disable_interrupts(dev);
+	flush_scheduled_work();
+	free_irq(pdev->irq, dev);
+disable_msi:
+	pci_disable_msi(pdev);
+	pci_iounmap(pdev, dev->mem_addr);
+free_device:
+	kfree(dev);
+release_regions:
+	pci_release_regions(pdev);
+disable_device:
+	pci_disable_device(pdev);
+end:
+	mutex_unlock(&mei_mutex);
+	dev_err(&pdev->dev, "initialization failed.\n");
+	return err;
+}
+
+/**
+ * mei_remove - Device Removal Routine
+ *
+ * @pdev: PCI device structure
+ *
+ * mei_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.
+ */
+static void mei_remove(struct pci_dev *pdev)
+{
+	struct mei_device *dev;
+
+	if (mei_pdev != pdev)
+		return;
+
+	dev = pci_get_drvdata(pdev);
+	if (!dev)
+		return;
+
+	mutex_lock(&dev->device_lock);
+
+	cancel_delayed_work(&dev->timer_work);
+
+	mei_wd_stop(dev);
+
+	mei_pdev = NULL;
+
+	if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
+		dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
+		mei_cl_disconnect(&dev->iamthif_cl);
+	}
+	if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
+		dev->wd_cl.state = MEI_FILE_DISCONNECTING;
+		mei_cl_disconnect(&dev->wd_cl);
+	}
+
+	/* Unregistering watchdog device */
+	mei_watchdog_unregister(dev);
+
+	/* remove entry if already in list */
+	dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
+
+	if (dev->open_handle_count > 0)
+		dev->open_handle_count--;
+	mei_cl_unlink(&dev->wd_cl);
+
+	if (dev->open_handle_count > 0)
+		dev->open_handle_count--;
+	mei_cl_unlink(&dev->iamthif_cl);
+
+	dev->iamthif_current_cb = NULL;
+	dev->me_clients_num = 0;
+
+	mutex_unlock(&dev->device_lock);
+
+	flush_scheduled_work();
+
+	/* disable interrupts */
+	mei_disable_interrupts(dev);
+
+	free_irq(pdev->irq, dev);
+	pci_disable_msi(pdev);
+	pci_set_drvdata(pdev, NULL);
+
+	if (dev->mem_addr)
+		pci_iounmap(pdev, dev->mem_addr);
+
+	kfree(dev);
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+
+	mei_deregister();
+
+}
+#ifdef CONFIG_PM
+static int mei_pci_suspend(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct mei_device *dev = pci_get_drvdata(pdev);
+	int err;
+
+	if (!dev)
+		return -ENODEV;
+	mutex_lock(&dev->device_lock);
+
+	cancel_delayed_work(&dev->timer_work);
+
+	/* Stop watchdog if exists */
+	err = mei_wd_stop(dev);
+	/* Set new mei state */
+	if (dev->dev_state == MEI_DEV_ENABLED ||
+	    dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
+		dev->dev_state = MEI_DEV_POWER_DOWN;
+		mei_reset(dev, 0);
+	}
+	mutex_unlock(&dev->device_lock);
+
+	free_irq(pdev->irq, dev);
+	pci_disable_msi(pdev);
+
+	return err;
+}
+
+static int mei_pci_resume(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct mei_device *dev;
+	int err;
+
+	dev = pci_get_drvdata(pdev);
+	if (!dev)
+		return -ENODEV;
+
+	pci_enable_msi(pdev);
+
+	/* request and enable interrupt */
+	if (pci_dev_msi_enabled(pdev))
+		err = request_threaded_irq(pdev->irq,
+			NULL,
+			mei_interrupt_thread_handler,
+			IRQF_ONESHOT, KBUILD_MODNAME, dev);
+	else
+		err = request_threaded_irq(pdev->irq,
+			mei_interrupt_quick_handler,
+			mei_interrupt_thread_handler,
+			IRQF_SHARED, KBUILD_MODNAME, dev);
+
+	if (err) {
+		dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
+				pdev->irq);
+		return err;
+	}
+
+	mutex_lock(&dev->device_lock);
+	dev->dev_state = MEI_DEV_POWER_UP;
+	mei_reset(dev, 1);
+	mutex_unlock(&dev->device_lock);
+
+	/* Start timer if stopped in suspend */
+	schedule_delayed_work(&dev->timer_work, HZ);
+
+	return err;
+}
+static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume);
+#define MEI_PM_OPS	(&mei_pm_ops)
+#else
+#define MEI_PM_OPS	NULL
+#endif /* CONFIG_PM */
+/*
+ *  PCI driver structure
+ */
+static struct pci_driver mei_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = mei_pci_tbl,
+	.probe = mei_probe,
+	.remove = mei_remove,
+	.shutdown = mei_remove,
+	.driver.pm = MEI_PM_OPS,
+};
+
+module_pci_driver(mei_driver);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
+MODULE_LICENSE("GPL v2");
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [char-misc-next 2/6] mei: initial extract of ME hw specifics from mei_device
  2013-02-06 12:06 [char-misc-next 0/6] MEI and ME separation Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 1/6] mei: sperate interface and pci code into two files Tomas Winkler
@ 2013-02-06 12:06 ` Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 3/6] mei: separate compilation of the ME hardware specifics Tomas Winkler
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Tomas Winkler @ 2013-02-06 12:06 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, alan, linux-kernel, Tomas Winkler

This is initial step of move the ME hw specifics
out of mei_device structure into mei_me_hw

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/hw-me.c   |  131 +++++++++++++++++++++++++++++---------------
 drivers/misc/mei/hw-me.h   |   12 ++++
 drivers/misc/mei/init.c    |   28 +---------
 drivers/misc/mei/mei_dev.h |   10 +--
 drivers/misc/mei/pci-me.c  |   21 ++++---
 5 files changed, 114 insertions(+), 88 deletions(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 94b203e..3bdf228 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -28,10 +28,10 @@
  *
  * returns register value (u32)
  */
-static inline u32 mei_reg_read(const struct mei_device *dev,
+static inline u32 mei_reg_read(const struct mei_me_hw *hw,
 			       unsigned long offset)
 {
-	return ioread32(dev->mem_addr + offset);
+	return ioread32(hw->mem_addr + offset);
 }
 
 
@@ -42,10 +42,10 @@ static inline u32 mei_reg_read(const struct mei_device *dev,
  * @offset: offset from which to write the data
  * @value: register value to write (u32)
  */
-static inline void mei_reg_write(const struct mei_device *dev,
+static inline void mei_reg_write(const struct mei_me_hw *hw,
 				 unsigned long offset, u32 value)
 {
-	iowrite32(value, dev->mem_addr + offset);
+	iowrite32(value, hw->mem_addr + offset);
 }
 
 /**
@@ -58,7 +58,7 @@ static inline void mei_reg_write(const struct mei_device *dev,
  */
 u32 mei_mecbrw_read(const struct mei_device *dev)
 {
-	return mei_reg_read(dev, ME_CB_RW);
+	return mei_reg_read(to_me_hw(dev), ME_CB_RW);
 }
 /**
  * mei_mecsr_read - Reads 32bit data from the ME CSR
@@ -67,9 +67,9 @@ u32 mei_mecbrw_read(const struct mei_device *dev)
  *
  * returns ME_CSR_HA register value (u32)
  */
-static inline u32 mei_mecsr_read(const struct mei_device *dev)
+static inline u32 mei_mecsr_read(const struct mei_me_hw *hw)
 {
-	return mei_reg_read(dev, ME_CSR_HA);
+	return mei_reg_read(hw, ME_CSR_HA);
 }
 
 /**
@@ -79,9 +79,9 @@ static inline u32 mei_mecsr_read(const struct mei_device *dev)
  *
  * returns H_CSR register value (u32)
  */
-static inline u32 mei_hcsr_read(const struct mei_device *dev)
+static inline u32 mei_hcsr_read(const struct mei_me_hw *hw)
 {
-	return mei_reg_read(dev, H_CSR);
+	return mei_reg_read(hw, H_CSR);
 }
 
 /**
@@ -90,10 +90,10 @@ static inline u32 mei_hcsr_read(const struct mei_device *dev)
  *
  * @dev: the device structure
  */
-static inline void mei_hcsr_set(struct mei_device *dev, u32 hcsr)
+static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr)
 {
 	hcsr &= ~H_IS;
-	mei_reg_write(dev, H_CSR, hcsr);
+	mei_reg_write(hw, H_CSR, hcsr);
 }
 
 
@@ -104,7 +104,7 @@ static inline void mei_hcsr_set(struct mei_device *dev, u32 hcsr)
  */
 void mei_hw_config(struct mei_device *dev)
 {
-	u32 hcsr = mei_hcsr_read(dev);
+	u32 hcsr = mei_hcsr_read(to_me_hw(dev));
 	/* Doesn't change in runtime */
 	dev->hbuf_depth = (hcsr & H_CBD) >> 24;
 }
@@ -115,9 +115,10 @@ void mei_hw_config(struct mei_device *dev)
  */
 void mei_clear_interrupts(struct mei_device *dev)
 {
-	u32 hcsr = mei_hcsr_read(dev);
+	struct mei_me_hw *hw = to_me_hw(dev);
+	u32 hcsr = mei_hcsr_read(hw);
 	if ((hcsr & H_IS) == H_IS)
-		mei_reg_write(dev, H_CSR, hcsr);
+		mei_reg_write(hw, H_CSR, hcsr);
 }
 
 /**
@@ -127,9 +128,10 @@ void mei_clear_interrupts(struct mei_device *dev)
  */
 void mei_enable_interrupts(struct mei_device *dev)
 {
-	u32 hcsr = mei_hcsr_read(dev);
+	struct mei_me_hw *hw = to_me_hw(dev);
+	u32 hcsr = mei_hcsr_read(hw);
 	hcsr |= H_IE;
-	mei_hcsr_set(dev, hcsr);
+	mei_hcsr_set(hw, hcsr);
 }
 
 /**
@@ -139,9 +141,10 @@ void mei_enable_interrupts(struct mei_device *dev)
  */
 void mei_disable_interrupts(struct mei_device *dev)
 {
-	u32 hcsr = mei_hcsr_read(dev);
+	struct mei_me_hw *hw = to_me_hw(dev);
+	u32 hcsr = mei_hcsr_read(hw);
 	hcsr  &= ~H_IE;
-	mei_hcsr_set(dev, hcsr);
+	mei_hcsr_set(hw, hcsr);
 }
 
 /**
@@ -152,7 +155,8 @@ void mei_disable_interrupts(struct mei_device *dev)
  */
 void mei_hw_reset(struct mei_device *dev, bool intr_enable)
 {
-	u32 hcsr = mei_hcsr_read(dev);
+	struct mei_me_hw *hw = to_me_hw(dev);
+	u32 hcsr = mei_hcsr_read(hw);
 
 	dev_dbg(&dev->pdev->dev, "before reset HCSR = 0x%08x.\n", hcsr);
 
@@ -163,14 +167,14 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable)
 	else
 		hcsr &= ~H_IE;
 
-	mei_hcsr_set(dev, hcsr);
+	mei_hcsr_set(hw, hcsr);
 
-	hcsr = mei_hcsr_read(dev) | H_IG;
+	hcsr = mei_hcsr_read(hw) | H_IG;
 	hcsr &= ~H_RST;
 
-	mei_hcsr_set(dev, hcsr);
+	mei_hcsr_set(hw, hcsr);
 
-	hcsr = mei_hcsr_read(dev);
+	hcsr = mei_hcsr_read(hw);
 
 	dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr);
 }
@@ -184,8 +188,9 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable)
 
 void mei_host_set_ready(struct mei_device *dev)
 {
-	dev->host_hw_state |= H_IE | H_IG | H_RDY;
-	mei_hcsr_set(dev, dev->host_hw_state);
+	struct mei_me_hw *hw = to_me_hw(dev);
+	hw->host_hw_state |= H_IE | H_IG | H_RDY;
+	mei_hcsr_set(hw, hw->host_hw_state);
 }
 /**
  * mei_host_is_ready - check whether the host has turned ready
@@ -195,8 +200,9 @@ void mei_host_set_ready(struct mei_device *dev)
  */
 bool mei_host_is_ready(struct mei_device *dev)
 {
-	dev->host_hw_state = mei_hcsr_read(dev);
-	return (dev->host_hw_state & H_RDY) == H_RDY;
+	struct mei_me_hw *hw = to_me_hw(dev);
+	hw->host_hw_state = mei_hcsr_read(hw);
+	return (hw->host_hw_state & H_RDY) == H_RDY;
 }
 
 /**
@@ -207,8 +213,9 @@ bool mei_host_is_ready(struct mei_device *dev)
  */
 bool mei_me_is_ready(struct mei_device *dev)
 {
-	dev->me_hw_state = mei_mecsr_read(dev);
-	return (dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
+	struct mei_me_hw *hw = to_me_hw(dev);
+	hw->me_hw_state = mei_mecsr_read(hw);
+	return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
 }
 
 /**
@@ -222,13 +229,14 @@ bool mei_me_is_ready(struct mei_device *dev)
 irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
 {
 	struct mei_device *dev = (struct mei_device *) dev_id;
-	u32 csr_reg = mei_hcsr_read(dev);
+	struct mei_me_hw *hw = to_me_hw(dev);
+	u32 csr_reg = mei_hcsr_read(hw);
 
 	if ((csr_reg & H_IS) != H_IS)
 		return IRQ_NONE;
 
 	/* clear H_IS bit in H_CSR */
-	mei_reg_write(dev, H_CSR, csr_reg);
+	mei_reg_write(hw, H_CSR, csr_reg);
 
 	return IRQ_WAKE_THREAD;
 }
@@ -242,12 +250,13 @@ irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
  */
 static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
 {
+	struct mei_me_hw *hw = to_me_hw(dev);
 	char read_ptr, write_ptr;
 
-	dev->host_hw_state = mei_hcsr_read(dev);
+	hw->host_hw_state = mei_hcsr_read(hw);
 
-	read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
-	write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
+	read_ptr = (char) ((hw->host_hw_state & H_CBRP) >> 8);
+	write_ptr = (char) ((hw->host_hw_state & H_CBWP) >> 16);
 
 	return (unsigned char) (write_ptr - read_ptr);
 }
@@ -297,6 +306,7 @@ int mei_hbuf_empty_slots(struct mei_device *dev)
 int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
 		      unsigned char *buf)
 {
+	struct mei_me_hw *hw = to_me_hw(dev);
 	unsigned long rem, dw_cnt;
 	unsigned long length = header->length;
 	u32 *reg_buf = (u32 *)buf;
@@ -313,20 +323,20 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
 	if (empty_slots < 0 || dw_cnt > empty_slots)
 		return -EIO;
 
-	mei_reg_write(dev, H_CB_WW, *((u32 *) header));
+	mei_reg_write(hw, H_CB_WW, *((u32 *) header));
 
 	for (i = 0; i < length / 4; i++)
-		mei_reg_write(dev, H_CB_WW, reg_buf[i]);
+		mei_reg_write(hw, H_CB_WW, reg_buf[i]);
 
 	rem = length & 0x3;
 	if (rem > 0) {
 		u32 reg = 0;
 		memcpy(&reg, &buf[length - rem], rem);
-		mei_reg_write(dev, H_CB_WW, reg);
+		mei_reg_write(hw, H_CB_WW, reg);
 	}
 
-	hcsr = mei_hcsr_read(dev) | H_IG;
-	mei_hcsr_set(dev, hcsr);
+	hcsr = mei_hcsr_read(hw) | H_IG;
+	mei_hcsr_set(hw, hcsr);
 	if (!mei_me_is_ready(dev))
 		return -EIO;
 
@@ -342,13 +352,14 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
  */
 int mei_count_full_read_slots(struct mei_device *dev)
 {
+	struct mei_me_hw *hw = to_me_hw(dev);
 	char read_ptr, write_ptr;
 	unsigned char buffer_depth, filled_slots;
 
-	dev->me_hw_state = mei_mecsr_read(dev);
-	buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24);
-	read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8);
-	write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16);
+	hw->me_hw_state = mei_mecsr_read(hw);
+	buffer_depth = (unsigned char)((hw->me_hw_state & ME_CBD_HRA) >> 24);
+	read_ptr = (char) ((hw->me_hw_state & ME_CBRP_HRA) >> 8);
+	write_ptr = (char) ((hw->me_hw_state & ME_CBWP_HRA) >> 16);
 	filled_slots = (unsigned char) (write_ptr - read_ptr);
 
 	/* check for overflow */
@@ -369,6 +380,7 @@ int mei_count_full_read_slots(struct mei_device *dev)
 void mei_read_slots(struct mei_device *dev, unsigned char *buffer,
 		    unsigned long buffer_length)
 {
+	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 *reg_buf = (u32 *)buffer;
 	u32 hcsr;
 
@@ -380,7 +392,36 @@ void mei_read_slots(struct mei_device *dev, unsigned char *buffer,
 		memcpy(reg_buf, &reg, buffer_length);
 	}
 
-	hcsr = mei_hcsr_read(dev) | H_IG;
-	mei_hcsr_set(dev, hcsr);
+	hcsr = mei_hcsr_read(hw) | H_IG;
+	mei_hcsr_set(hw, hcsr);
 }
 
+/**
+ * init_mei_device - allocates and initializes the mei device structure
+ *
+ * @pdev: The pci device structure
+ *
+ * returns The mei_device_device pointer on success, NULL on failure.
+ */
+struct mei_device *mei_me_dev_init(struct pci_dev *pdev)
+{
+	struct mei_device *dev;
+
+	dev = kzalloc(sizeof(struct mei_device) +
+			 sizeof(struct mei_me_hw), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	mei_device_init(dev);
+
+	INIT_LIST_HEAD(&dev->wd_cl.link);
+	INIT_LIST_HEAD(&dev->iamthif_cl.link);
+	mei_io_list_init(&dev->amthif_cmd_list);
+	mei_io_list_init(&dev->amthif_rd_complete_list);
+
+	INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
+	INIT_WORK(&dev->init_work, mei_host_client_init);
+
+	dev->pdev = pdev;
+	return dev;
+}
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 73bef54..53bcc00 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -21,8 +21,20 @@
 
 #include <linux/mei.h>
 #include "mei_dev.h"
+#include "client.h"
 
+struct mei_me_hw {
+	void __iomem *mem_addr;
+	/*
+	 * hw states of host and fw(ME)
+	 */
+	u32 host_hw_state;
+	u32 me_hw_state;
+};
 
+#define to_me_hw(dev) (struct mei_me_hw *)((dev)->hw)
+
+struct mei_device *mei_me_dev_init(struct pci_dev *pdev);
 
 void mei_read_slots(struct mei_device *dev,
 		     unsigned char *buffer,
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 5d08db5..1e1876f 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -42,28 +42,10 @@ const char *mei_dev_state_str(int state)
 #undef MEI_DEV_STATE
 }
 
-
-
-
-/**
- * init_mei_device - allocates and initializes the mei device structure
- *
- * @pdev: The pci device structure
- *
- * returns The mei_device_device pointer on success, NULL on failure.
- */
-struct mei_device *mei_device_init(struct pci_dev *pdev)
+void mei_device_init(struct mei_device *dev)
 {
-	struct mei_device *dev;
-
-	dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL);
-	if (!dev)
-		return NULL;
-
 	/* setup our list array */
 	INIT_LIST_HEAD(&dev->file_list);
-	INIT_LIST_HEAD(&dev->wd_cl.link);
-	INIT_LIST_HEAD(&dev->iamthif_cl.link);
 	mutex_init(&dev->device_lock);
 	init_waitqueue_head(&dev->wait_recvd_msg);
 	init_waitqueue_head(&dev->wait_stop_wd);
@@ -74,14 +56,6 @@ struct mei_device *mei_device_init(struct pci_dev *pdev)
 	mei_io_list_init(&dev->write_waiting_list);
 	mei_io_list_init(&dev->ctrl_wr_list);
 	mei_io_list_init(&dev->ctrl_rd_list);
-	mei_io_list_init(&dev->amthif_cmd_list);
-	mei_io_list_init(&dev->amthif_rd_complete_list);
-
-	INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
-	INIT_WORK(&dev->init_work, mei_host_client_init);
-
-	dev->pdev = pdev;
-	return dev;
 }
 
 /**
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 3b2bca3..bb759fd 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -235,18 +235,13 @@ struct mei_device {
 	struct list_head file_list;
 	long open_handle_count;
 
-	void __iomem *mem_addr;
 	/*
 	 * lock for the device
 	 */
 	struct mutex device_lock; /* device lock */
 	struct delayed_work timer_work;	/* MEI timer delayed work (timeouts) */
 	bool recvd_msg;
-	/*
-	 * hw states of host and fw(ME)
-	 */
-	u32 host_hw_state;
-	u32 me_hw_state;
+
 	u8  hbuf_depth;
 	/*
 	 * waiting queue for receive message from FW
@@ -311,6 +306,7 @@ struct mei_device {
 	bool iamthif_canceled;
 
 	struct work_struct init_work;
+	char hw[0] __aligned(sizeof(void *));
 };
 
 static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
@@ -322,7 +318,7 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
 /*
  * mei init function prototypes
  */
-struct mei_device *mei_device_init(struct pci_dev *pdev);
+void mei_device_init(struct mei_device *dev);
 void mei_reset(struct mei_device *dev, int interrupts);
 int mei_hw_init(struct mei_device *dev);
 
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index eaed398..27ac717 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -90,7 +90,6 @@ MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
 
 static DEFINE_MUTEX(mei_mutex);
 
-
 /**
  * mei_quirk_probe - probe for devices that doesn't valid ME interface
  * @pdev: PCI device structure
@@ -120,10 +119,10 @@ static bool mei_quirk_probe(struct pci_dev *pdev,
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_probe(struct pci_dev *pdev,
-				const struct pci_device_id *ent)
+static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct mei_device *dev;
+	struct mei_me_hw *hw;
 	int err;
 
 	mutex_lock(&mei_mutex);
@@ -152,14 +151,15 @@ static int mei_probe(struct pci_dev *pdev,
 		goto disable_device;
 	}
 	/* allocates and initializes the mei dev structure */
-	dev = mei_device_init(pdev);
+	dev = mei_me_dev_init(pdev);
 	if (!dev) {
 		err = -ENOMEM;
 		goto release_regions;
 	}
+	hw = to_me_hw(dev);
 	/* mapping  IO device memory */
-	dev->mem_addr = pci_iomap(pdev, 0, 0);
-	if (!dev->mem_addr) {
+	hw->mem_addr = pci_iomap(pdev, 0, 0);
+	if (!hw->mem_addr) {
 		dev_err(&pdev->dev, "mapping I/O device memory failure.\n");
 		err = -ENOMEM;
 		goto free_device;
@@ -212,7 +212,7 @@ release_irq:
 	free_irq(pdev->irq, dev);
 disable_msi:
 	pci_disable_msi(pdev);
-	pci_iounmap(pdev, dev->mem_addr);
+	pci_iounmap(pdev, hw->mem_addr);
 free_device:
 	kfree(dev);
 release_regions:
@@ -236,6 +236,7 @@ end:
 static void mei_remove(struct pci_dev *pdev)
 {
 	struct mei_device *dev;
+	struct mei_me_hw *hw;
 
 	if (mei_pdev != pdev)
 		return;
@@ -244,6 +245,8 @@ static void mei_remove(struct pci_dev *pdev)
 	if (!dev)
 		return;
 
+	hw = to_me_hw(dev);
+
 	mutex_lock(&dev->device_lock);
 
 	cancel_delayed_work(&dev->timer_work);
@@ -289,8 +292,8 @@ static void mei_remove(struct pci_dev *pdev)
 	pci_disable_msi(pdev);
 	pci_set_drvdata(pdev, NULL);
 
-	if (dev->mem_addr)
-		pci_iounmap(pdev, dev->mem_addr);
+	if (hw->mem_addr)
+		pci_iounmap(pdev, hw->mem_addr);
 
 	kfree(dev);
 
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [char-misc-next 3/6] mei: separate compilation of the ME hardware specifics
  2013-02-06 12:06 [char-misc-next 0/6] MEI and ME separation Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 1/6] mei: sperate interface and pci code into two files Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 2/6] mei: initial extract of ME hw specifics from mei_device Tomas Winkler
@ 2013-02-06 12:06 ` Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 4/6] mei: move interrupt handlers to be me hw specific Tomas Winkler
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Tomas Winkler @ 2013-02-06 12:06 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, alan, linux-kernel, Tomas Winkler

We add struct mei_hw_ops to virtualize access to hw specific
configurations. This allows us to separate the compilation
of the ME interface from the ME hardware specifics

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/Kconfig     |   17 ++++-
 drivers/misc/mei/Makefile    |    6 +-
 drivers/misc/mei/amthif.c    |    6 +-
 drivers/misc/mei/hw-me.c     |   87 +++++++++++++++++++---------
 drivers/misc/mei/hw-me.h     |   19 ------
 drivers/misc/mei/init.c      |    2 +-
 drivers/misc/mei/interrupt.c |   10 ++--
 drivers/misc/mei/main.c      |    5 +-
 drivers/misc/mei/mei_dev.h   |  132 ++++++++++++++++++++++++++++++++++++++---
 9 files changed, 210 insertions(+), 74 deletions(-)

diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index 5a79ccd..fa5c249 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -1,11 +1,22 @@
 config INTEL_MEI
-	tristate "Intel Management Engine Interface (Intel MEI)"
-	depends on X86 && PCI && WATCHDOG_CORE
+	tristate "Intel Management Engine Interface"
+	depends on X86 && PCI
 	help
 	  The Intel Management Engine (Intel ME) provides Manageability,
 	  Security and Media services for system containing Intel chipsets.
 	  if selected /dev/mei misc device will be created.
 
+	  For more information see
+	  <http://software.intel.com/en-us/manageability/>
+
+config INTEL_MEI_ME
+	bool "ME Enabled Intel Chipsets"
+	depends on INTEL_MEI
+	depends on X86 && PCI && WATCHDOG_CORE
+	default y
+	help
+	  MEI support for ME Enabled Intel chipsets.
+
 	  Supported Chipsets are:
 	  7 Series Chipset Family
 	  6 Series Chipset Family
@@ -24,5 +35,3 @@ config INTEL_MEI
 	  82Q33 Express
 	  82X38/X48 Express
 
-	  For more information see
-	  <http://software.intel.com/en-us/manageability/>
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 068f553..040af6c 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -6,9 +6,9 @@ obj-$(CONFIG_INTEL_MEI) += mei.o
 mei-objs := init.o
 mei-objs += hbm.o
 mei-objs += interrupt.o
-mei-objs += hw-me.o
+mei-objs += client.o
 mei-objs += main.o
 mei-objs += amthif.o
 mei-objs += wd.o
-mei-objs += client.o
-mei-objs += pci-me.o
+mei-$(CONFIG_INTEL_MEI_ME) += pci-me.o
+mei-$(CONFIG_INTEL_MEI_ME) += hw-me.o
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 263ed4c..a7c4838 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -300,8 +300,8 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 	if (ret && dev->mei_host_buffer_is_empty) {
 		ret = 0;
 		dev->mei_host_buffer_is_empty = false;
-		if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
-			mei_hdr.length = mei_hbuf_max_data(dev);
+		if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
+			mei_hdr.length = mei_hbuf_max_len(dev);
 			mei_hdr.msg_complete = 0;
 		} else {
 			mei_hdr.length = cb->request_buffer.size;
@@ -583,7 +583,7 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
 	dev->iamthif_msg_buf_index = 0;
 	dev->iamthif_msg_buf_size = 0;
 	dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
-	dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
+	dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
 	return 0;
 }
 
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 3bdf228..6300943 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -56,7 +56,7 @@ static inline void mei_reg_write(const struct mei_me_hw *hw,
  *
  * returns ME_CB_RW register value (u32)
  */
-u32 mei_mecbrw_read(const struct mei_device *dev)
+static u32 mei_me_mecbrw_read(const struct mei_device *dev)
 {
 	return mei_reg_read(to_me_hw(dev), ME_CB_RW);
 }
@@ -102,7 +102,7 @@ static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr)
  *
  * @dev: mei device
  */
-void mei_hw_config(struct mei_device *dev)
+static void mei_me_hw_config(struct mei_device *dev)
 {
 	u32 hcsr = mei_hcsr_read(to_me_hw(dev));
 	/* Doesn't change in runtime */
@@ -113,20 +113,19 @@ void mei_hw_config(struct mei_device *dev)
  *
  * @dev: the device structure
  */
-void mei_clear_interrupts(struct mei_device *dev)
+static void mei_me_intr_clear(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr = mei_hcsr_read(hw);
 	if ((hcsr & H_IS) == H_IS)
 		mei_reg_write(hw, H_CSR, hcsr);
 }
-
 /**
- * mei_enable_interrupts - enables mei device interrupts
+ * mei_me_intr_enable - enables mei device interrupts
  *
  * @dev: the device structure
  */
-void mei_enable_interrupts(struct mei_device *dev)
+static void mei_me_intr_enable(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr = mei_hcsr_read(hw);
@@ -139,7 +138,7 @@ void mei_enable_interrupts(struct mei_device *dev)
  *
  * @dev: the device structure
  */
-void mei_disable_interrupts(struct mei_device *dev)
+static void mei_me_intr_disable(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr = mei_hcsr_read(hw);
@@ -148,12 +147,12 @@ void mei_disable_interrupts(struct mei_device *dev)
 }
 
 /**
- * mei_hw_reset - resets fw via mei csr register.
+ * mei_me_hw_reset - resets fw via mei csr register.
  *
  * @dev: the device structure
  * @interrupts_enabled: if interrupt should be enabled after reset.
  */
-void mei_hw_reset(struct mei_device *dev, bool intr_enable)
+static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr = mei_hcsr_read(hw);
@@ -180,25 +179,25 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable)
 }
 
 /**
- * mei_host_set_ready - enable device
+ * mei_me_host_set_ready - enable device
  *
  * @dev - mei device
  * returns bool
  */
 
-void mei_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);
 	hw->host_hw_state |= H_IE | H_IG | H_RDY;
 	mei_hcsr_set(hw, hw->host_hw_state);
 }
 /**
- * mei_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
  */
-bool mei_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);
 	hw->host_hw_state = mei_hcsr_read(hw);
@@ -206,12 +205,12 @@ bool mei_host_is_ready(struct mei_device *dev)
 }
 
 /**
- * mei_me_is_ready - check whether the me has turned ready
+ * mei_me_hw_is_ready - check whether the me(hw) has turned ready
  *
  * @dev - mei device
  * returns bool
  */
-bool mei_me_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);
 	hw->me_hw_state = mei_mecsr_read(hw);
@@ -268,19 +267,19 @@ static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
  *
  * returns true if empty, false - otherwise.
  */
-bool mei_hbuf_is_empty(struct mei_device *dev)
+static bool mei_me_hbuf_is_empty(struct mei_device *dev)
 {
 	return mei_hbuf_filled_slots(dev) == 0;
 }
 
 /**
- * mei_hbuf_empty_slots - counts write empty slots.
+ * mei_me_hbuf_empty_slots - counts write empty slots.
  *
  * @dev: the device structure
  *
  * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
  */
-int mei_hbuf_empty_slots(struct mei_device *dev)
+static int mei_me_hbuf_empty_slots(struct mei_device *dev)
 {
 	unsigned char filled_slots, empty_slots;
 
@@ -294,6 +293,12 @@ int mei_hbuf_empty_slots(struct mei_device *dev)
 	return empty_slots;
 }
 
+static size_t mei_me_hbuf_max_len(const struct mei_device *dev)
+{
+	return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr);
+}
+
+
 /**
  * mei_write_message - writes a message to mei device.
  *
@@ -303,8 +308,9 @@ int mei_hbuf_empty_slots(struct mei_device *dev)
  *
  * This function returns -EIO if write has failed
  */
-int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
-		      unsigned char *buf)
+static int mei_me_write_message(struct mei_device *dev,
+			struct mei_msg_hdr *header,
+			unsigned char *buf)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	unsigned long rem, dw_cnt;
@@ -337,20 +343,20 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
 
 	hcsr = mei_hcsr_read(hw) | H_IG;
 	mei_hcsr_set(hw, hcsr);
-	if (!mei_me_is_ready(dev))
+	if (!mei_me_hw_is_ready(dev))
 		return -EIO;
 
 	return 0;
 }
 
 /**
- * mei_count_full_read_slots - counts read full slots.
+ * mei_me_count_full_read_slots - counts read full slots.
  *
  * @dev: the device structure
  *
  * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count
  */
-int mei_count_full_read_slots(struct mei_device *dev)
+static int mei_me_count_full_read_slots(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	char read_ptr, write_ptr;
@@ -371,13 +377,13 @@ int mei_count_full_read_slots(struct mei_device *dev)
 }
 
 /**
- * mei_read_slots - reads a message from mei device.
+ * mei_me_read_slots - reads a message from mei device.
  *
  * @dev: the device structure
  * @buffer: message buffer will be written
  * @buffer_length: message size will be read
  */
-void mei_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)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
@@ -385,17 +391,42 @@ void mei_read_slots(struct mei_device *dev, unsigned char *buffer,
 	u32 hcsr;
 
 	for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32))
-		*reg_buf++ = mei_mecbrw_read(dev);
+		*reg_buf++ = mei_me_mecbrw_read(dev);
 
 	if (buffer_length > 0) {
-		u32 reg = mei_mecbrw_read(dev);
+		u32 reg = mei_me_mecbrw_read(dev);
 		memcpy(reg_buf, &reg, buffer_length);
 	}
 
 	hcsr = mei_hcsr_read(hw) | H_IG;
 	mei_hcsr_set(hw, hcsr);
+	return 0;
 }
 
+static const struct mei_hw_ops mei_me_hw_ops = {
+
+	.host_set_ready = mei_me_host_set_ready,
+	.host_is_ready = mei_me_host_is_ready,
+
+	.hw_is_ready = mei_me_hw_is_ready,
+	.hw_reset = mei_me_hw_reset,
+	.hw_config  = mei_me_hw_config,
+
+	.intr_clear = mei_me_intr_clear,
+	.intr_enable = mei_me_intr_enable,
+	.intr_disable = mei_me_intr_disable,
+
+	.hbuf_free_slots = mei_me_hbuf_empty_slots,
+	.hbuf_is_ready = mei_me_hbuf_is_empty,
+	.hbuf_max_len = mei_me_hbuf_max_len,
+
+	.write = mei_me_write_message,
+
+	.rdbuf_full_slots = mei_me_count_full_read_slots,
+	.read_hdr = mei_me_mecbrw_read,
+	.read = mei_me_read_slots
+};
+
 /**
  * init_mei_device - allocates and initializes the mei device structure
  *
@@ -422,6 +453,8 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev)
 	INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
 	INIT_WORK(&dev->init_work, mei_host_client_init);
 
+	dev->ops = &mei_me_hw_ops;
+
 	dev->pdev = pdev;
 	return dev;
 }
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 53bcc00..9a3aaab 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -36,29 +36,10 @@ struct mei_me_hw {
 
 struct mei_device *mei_me_dev_init(struct pci_dev *pdev);
 
-void mei_read_slots(struct mei_device *dev,
-		     unsigned char *buffer,
-		     unsigned long buffer_length);
-
-int mei_write_message(struct mei_device *dev,
-			struct mei_msg_hdr *header,
-			unsigned char *buf);
-
-bool mei_hbuf_is_empty(struct mei_device *dev);
-
-int mei_hbuf_empty_slots(struct mei_device *dev);
-
-static inline size_t mei_hbuf_max_data(const struct mei_device *dev)
-{
-	return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr);
-}
-
 /* get slots (dwords) from a message length + header (bytes) */
 static inline unsigned char mei_data2slots(size_t length)
 {
 	return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
 }
 
-int mei_count_full_read_slots(struct mei_device *dev);
-
 #endif /* _MEI_INTERFACE_H_ */
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 1e1876f..51a005e 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -104,7 +104,7 @@ int mei_hw_init(struct mei_device *dev)
 		goto err;
 	}
 
-	if (!mei_me_is_ready(dev)) {
+	if (!mei_hw_is_ready(dev)) {
 		dev_err(&dev->pdev->dev, "ME is not ready.\n");
 		goto err;
 	}
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index b04ed9b..431aa91 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -329,7 +329,7 @@ static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
 	int ret = 0;
 
 	if (!dev->rd_msg_hdr) {
-		dev->rd_msg_hdr = mei_mecbrw_read(dev);
+		dev->rd_msg_hdr = mei_read_hdr(dev);
 		dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
 		(*slots)--;
 		dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
@@ -430,7 +430,7 @@ static int mei_irq_thread_write_handler(struct mei_device *dev,
 	s32 slots;
 	int ret;
 
-	if (!mei_hbuf_is_empty(dev)) {
+	if (!mei_hbuf_is_ready(dev)) {
 		dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
 		return 0;
 	}
@@ -698,7 +698,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
 		mei_clear_interrupts(dev);
 
 	/* check if ME wants a reset */
-	if (!mei_me_is_ready(dev) &&
+	if (!mei_hw_is_ready(dev) &&
 	    dev->dev_state != MEI_DEV_RESETING &&
 	    dev->dev_state != MEI_DEV_INITIALIZING) {
 		dev_dbg(&dev->pdev->dev, "FW not ready.\n");
@@ -709,7 +709,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
 
 	/*  check if we need to start the dev */
 	if (!mei_host_is_ready(dev)) {
-		if (mei_me_is_ready(dev)) {
+		if (mei_hw_is_ready(dev)) {
 			dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
 
 			mei_host_set_ready(dev);
@@ -743,7 +743,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
 	rets = mei_irq_thread_write_handler(dev, &complete_list);
 end:
 	dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
-	dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
+	dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
 
 	bus_message_received = false;
 	if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 018623c..843ae2f 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -462,8 +462,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 	}
 
 	dev->mei_host_buffer_is_empty = false;
-	if (length >  mei_hbuf_max_data(dev)) {
-		mei_hdr.length = mei_hbuf_max_data(dev);
+	if (length >  mei_hbuf_max_len(dev)) {
+		mei_hdr.length = mei_hbuf_max_len(dev);
 		mei_hdr.msg_complete = 0;
 	} else {
 		mei_hdr.length = length;
@@ -765,4 +765,5 @@ void mei_deregister(void)
 	mei_misc_device.parent = NULL;
 }
 
+MODULE_LICENSE("GPL v2");
 
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index bb759fd..c974292 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -211,6 +211,58 @@ struct mei_cl {
 	struct mei_cl_cb *read_cb;
 };
 
+/** struct mei_hw_ops
+ *
+ * @host_set_ready   - notify FW that host side is ready
+ * @host_is_ready    - query for host readiness
+
+ * @hw_is_ready      - query if hw is ready
+ * @hw_reset         - reset hw
+ * @hw_config        - configure hw
+
+ * @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
+
+ * @write            - write a message to FW
+
+ * @rdbuf_full_slots - query how many slots are filled
+
+ * @read_hdr         - get first 4 bytes (header)
+ * @read             - read a buffer from the FW
+ */
+struct mei_hw_ops {
+
+	void (*host_set_ready) (struct mei_device *dev);
+	bool (*host_is_ready) (struct mei_device *dev);
+
+	bool (*hw_is_ready) (struct mei_device *dev);
+	void (*hw_reset) (struct mei_device *dev, bool enable);
+	void (*hw_config) (struct mei_device *dev);
+
+	void (*intr_clear) (struct mei_device *dev);
+	void (*intr_enable) (struct mei_device *dev);
+	void (*intr_disable) (struct mei_device *dev);
+
+	int (*hbuf_free_slots) (struct mei_device *dev);
+	bool (*hbuf_is_ready) (struct mei_device *dev);
+	size_t (*hbuf_max_len) (const struct mei_device *dev);
+
+	int (*write)(struct mei_device *dev,
+		     struct mei_msg_hdr *hdr,
+		     unsigned char *buf);
+
+	int (*rdbuf_full_slots)(struct mei_device *dev);
+
+	u32 (*read_hdr)(const struct mei_device *dev);
+	int (*read) (struct mei_device *dev,
+		     unsigned char *buf, unsigned long len);
+};
+
 /**
  * struct mei_device -  MEI private device struct
  * @mem_addr - mem mapped base register address
@@ -306,6 +358,8 @@ struct mei_device {
 	bool iamthif_canceled;
 
 	struct work_struct init_work;
+
+	const struct mei_hw_ops *ops;
 	char hw[0] __aligned(sizeof(void *));
 };
 
@@ -376,26 +430,84 @@ void mei_watchdog_register(struct mei_device *dev);
  */
 void mei_watchdog_unregister(struct mei_device *dev);
 
-
 /*
  * Register Access Function
  */
 
-void mei_hw_config(struct mei_device *dev);
-void mei_hw_reset(struct mei_device *dev, bool intr_enable);
-u32 mei_mecbrw_read(const struct mei_device *dev);
+static inline void mei_hw_config(struct mei_device *dev)
+{
+	dev->ops->hw_config(dev);
+}
+static inline void mei_hw_reset(struct mei_device *dev, bool enable)
+{
+	dev->ops->hw_reset(dev, enable);
+}
+
+static inline void mei_clear_interrupts(struct mei_device *dev)
+{
+	dev->ops->intr_clear(dev);
+}
+
+static inline void mei_enable_interrupts(struct mei_device *dev)
+{
+	dev->ops->intr_enable(dev);
+}
 
+static inline void mei_disable_interrupts(struct mei_device *dev)
+{
+	dev->ops->intr_disable(dev);
+}
 
+static inline void mei_host_set_ready(struct mei_device *dev)
+{
+	dev->ops->host_set_ready(dev);
+}
+static inline bool mei_host_is_ready(struct mei_device *dev)
+{
+	return dev->ops->host_is_ready(dev);
+}
+static inline bool mei_hw_is_ready(struct mei_device *dev)
+{
+	return dev->ops->hw_is_ready(dev);
+}
 
-void mei_clear_interrupts(struct mei_device *dev);
-void mei_enable_interrupts(struct mei_device *dev);
-void mei_disable_interrupts(struct mei_device *dev);
+static inline bool mei_hbuf_is_ready(struct mei_device *dev)
+{
+	return dev->ops->hbuf_is_ready(dev);
+}
 
-void mei_host_set_ready(struct mei_device *dev);
-bool mei_host_is_ready(struct mei_device *dev);
-bool mei_me_is_ready(struct mei_device *dev);
+static inline int mei_hbuf_empty_slots(struct mei_device *dev)
+{
+	return dev->ops->hbuf_free_slots(dev);
+}
 
+static inline size_t mei_hbuf_max_len(const struct mei_device *dev)
+{
+	return dev->ops->hbuf_max_len(dev);
+}
 
+static inline int mei_write_message(struct mei_device *dev,
+			struct mei_msg_hdr *hdr,
+			unsigned char *buf)
+{
+	return dev->ops->write(dev, hdr, buf);
+}
+
+static inline u32 mei_read_hdr(const struct mei_device *dev)
+{
+	return dev->ops->read_hdr(dev);
+}
+
+static inline void mei_read_slots(struct mei_device *dev,
+		     unsigned char *buf, unsigned long len)
+{
+	dev->ops->read(dev, buf, len);
+}
+
+static inline int mei_count_full_read_slots(struct mei_device *dev)
+{
+	return dev->ops->rdbuf_full_slots(dev);
+}
 
 int mei_register(struct device *dev);
 void mei_deregister(void);
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [char-misc-next 4/6] mei: move interrupt handlers to be me hw specific
  2013-02-06 12:06 [char-misc-next 0/6] MEI and ME separation Tomas Winkler
                   ` (2 preceding siblings ...)
  2013-02-06 12:06 ` [char-misc-next 3/6] mei: separate compilation of the ME hardware specifics Tomas Winkler
@ 2013-02-06 12:06 ` Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 5/6] mei: rename to mei_host_buffer_is_empty to hbuf_is_ready Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 6/6] mei: move clients cleanup code from init.c to client.c Tomas Winkler
  5 siblings, 0 replies; 7+ messages in thread
From: Tomas Winkler @ 2013-02-06 12:06 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, alan, linux-kernel, Tomas Winkler

interrupt handler are  platform specifics so we move
them to hw-mei.c. For sake of that we need to export
write, read, and complete handlers from the interrupt.c

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/hw-me.c     |  164 +++++++++++++++++++++++++++++++++++------
 drivers/misc/mei/hw-me.h     |    3 +
 drivers/misc/mei/interrupt.c |  126 ++------------------------------
 drivers/misc/mei/mei_dev.h   |    9 ++-
 drivers/misc/mei/pci-me.c    |   12 ++--
 5 files changed, 164 insertions(+), 150 deletions(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 6300943..3bebf8d 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -15,11 +15,16 @@
  */
 
 #include <linux/pci.h>
-#include <linux/mei.h>
+
+#include <linux/kthread.h>
+#include <linux/interrupt.h>
 
 #include "mei_dev.h"
 #include "hw-me.h"
 
+#include "hbm.h"
+
+
 /**
  * mei_reg_read - Reads 32bit data from the mei device
  *
@@ -218,29 +223,6 @@ static bool mei_me_hw_is_ready(struct mei_device *dev)
 }
 
 /**
- * mei_interrupt_quick_handler - The ISR of the MEI device
- *
- * @irq: The irq number
- * @dev_id: pointer to the device structure
- *
- * returns irqreturn_t
- */
-irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
-{
-	struct mei_device *dev = (struct mei_device *) dev_id;
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 csr_reg = mei_hcsr_read(hw);
-
-	if ((csr_reg & H_IS) != H_IS)
-		return IRQ_NONE;
-
-	/* clear H_IS bit in H_CSR */
-	mei_reg_write(hw, H_CSR, csr_reg);
-
-	return IRQ_WAKE_THREAD;
-}
-
-/**
  * mei_hbuf_filled_slots - gets number of device filled buffer slots
  *
  * @dev: the device structure
@@ -403,6 +385,139 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
 	return 0;
 }
 
+/**
+ * mei_me_irq_quick_handler - The ISR of the MEI device
+ *
+ * @irq: The irq number
+ * @dev_id: pointer to the device structure
+ *
+ * returns irqreturn_t
+ */
+
+irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
+{
+	struct mei_device *dev = (struct mei_device *) dev_id;
+	struct mei_me_hw *hw = to_me_hw(dev);
+	u32 csr_reg = mei_hcsr_read(hw);
+
+	if ((csr_reg & H_IS) != H_IS)
+		return IRQ_NONE;
+
+	/* clear H_IS bit in H_CSR */
+	mei_reg_write(hw, H_CSR, csr_reg);
+
+	return IRQ_WAKE_THREAD;
+}
+
+/**
+ * mei_me_irq_thread_handler - function called after ISR to handle the interrupt
+ * processing.
+ *
+ * @irq: The irq number
+ * @dev_id: pointer to the device structure
+ *
+ * returns irqreturn_t
+ *
+ */
+irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
+{
+	struct mei_device *dev = (struct mei_device *) dev_id;
+	struct mei_cl_cb complete_list;
+	struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
+	struct mei_cl *cl;
+	s32 slots;
+	int rets;
+	bool  bus_message_received;
+
+
+	dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
+	/* initialize our complete list */
+	mutex_lock(&dev->device_lock);
+	mei_io_list_init(&complete_list);
+
+	/* Ack the interrupt here
+	 * In case of MSI we don't go through the quick handler */
+	if (pci_dev_msi_enabled(dev->pdev))
+		mei_clear_interrupts(dev);
+
+	/* check if ME wants a reset */
+	if (!mei_hw_is_ready(dev) &&
+	    dev->dev_state != MEI_DEV_RESETING &&
+	    dev->dev_state != MEI_DEV_INITIALIZING) {
+		dev_dbg(&dev->pdev->dev, "FW not ready.\n");
+		mei_reset(dev, 1);
+		mutex_unlock(&dev->device_lock);
+		return IRQ_HANDLED;
+	}
+
+	/*  check if we need to start the dev */
+	if (!mei_host_is_ready(dev)) {
+		if (mei_hw_is_ready(dev)) {
+			dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
+
+			mei_host_set_ready(dev);
+
+			dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
+			/* link is established * start sending messages.  */
+
+			dev->dev_state = MEI_DEV_INIT_CLIENTS;
+
+			mei_hbm_start_req(dev);
+			mutex_unlock(&dev->device_lock);
+			return IRQ_HANDLED;
+		} else {
+			dev_dbg(&dev->pdev->dev, "FW not ready.\n");
+			mutex_unlock(&dev->device_lock);
+			return IRQ_HANDLED;
+		}
+	}
+	/* check slots available for reading */
+	slots = mei_count_full_read_slots(dev);
+	while (slots > 0) {
+		/* we have urgent data to send so break the read */
+		if (dev->wr_ext_msg.hdr.length)
+			break;
+		dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
+		dev_dbg(&dev->pdev->dev, "call mei_irq_read_handler.\n");
+		rets = mei_irq_read_handler(dev, &complete_list, &slots);
+		if (rets)
+			goto end;
+	}
+	rets = mei_irq_write_handler(dev, &complete_list);
+end:
+	dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
+	dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
+
+	bus_message_received = false;
+	if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
+		dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
+		bus_message_received = true;
+	}
+	mutex_unlock(&dev->device_lock);
+	if (bus_message_received) {
+		dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
+		wake_up_interruptible(&dev->wait_recvd_msg);
+		bus_message_received = false;
+	}
+	if (list_empty(&complete_list.list))
+		return IRQ_HANDLED;
+
+
+	list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
+		cl = cb_pos->cl;
+		list_del(&cb_pos->list);
+		if (cl) {
+			if (cl != &dev->iamthif_cl) {
+				dev_dbg(&dev->pdev->dev, "completing call back.\n");
+				mei_irq_complete_handler(cl, cb_pos);
+				cb_pos = NULL;
+			} else if (cl == &dev->iamthif_cl) {
+				mei_amthif_complete(dev, cb_pos);
+			}
+		}
+	}
+	return IRQ_HANDLED;
+}
 static const struct mei_hw_ops mei_me_hw_ops = {
 
 	.host_set_ready = mei_me_host_set_ready,
@@ -458,3 +573,4 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev)
 	dev->pdev = pdev;
 	return dev;
 }
+
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 9a3aaab..8518d3e 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -42,4 +42,7 @@ static inline unsigned char mei_data2slots(size_t length)
 	return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
 }
 
+irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id);
+irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id);
+
 #endif /* _MEI_INTERFACE_H_ */
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 431aa91..3535b26 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -30,12 +30,12 @@
 
 
 /**
- * _mei_cmpl - processes completed operation.
+ * mei_complete_handler - processes completed operation.
  *
  * @cl: private data of the file object.
  * @cb_pos: callback block.
  */
-static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
+void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
 {
 	if (cb_pos->fop_type == MEI_FOP_WRITE) {
 		mei_io_cb_free(cb_pos);
@@ -313,15 +313,14 @@ static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
  * mei_irq_thread_read_handler - bottom half read routine after ISR to
  * handle the read processing.
  *
- * @cmpl_list: An instance of our list structure
  * @dev: the device structure
+ * @cmpl_list: An instance of our list structure
  * @slots: slots to read.
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
-		struct mei_device *dev,
-		s32 *slots)
+int mei_irq_read_handler(struct mei_device *dev,
+		struct mei_cl_cb *cmpl_list, s32 *slots)
 {
 	struct mei_msg_hdr *mei_hdr;
 	struct mei_cl *cl_pos = NULL;
@@ -412,15 +411,15 @@ end:
 
 
 /**
- * mei_irq_thread_write_handler - bottom half write routine after
- * ISR to handle the write processing.
+ * mei_irq_write_handler -  dispatch write requests
+ *  after irq received
  *
  * @dev: the device structure
  * @cmpl_list: An instance of our list structure
  *
  * returns 0 on success, <0 on failure.
  */
-static int mei_irq_thread_write_handler(struct mei_device *dev,
+int mei_irq_write_handler(struct mei_device *dev,
 				struct mei_cl_cb *cmpl_list)
 {
 
@@ -666,112 +665,3 @@ out:
 	mutex_unlock(&dev->device_lock);
 }
 
-/**
- *  mei_interrupt_thread_handler - function called after ISR to handle the interrupt
- * processing.
- *
- * @irq: The irq number
- * @dev_id: pointer to the device structure
- *
- * returns irqreturn_t
- *
- */
-irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
-{
-	struct mei_device *dev = (struct mei_device *) dev_id;
-	struct mei_cl_cb complete_list;
-	struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
-	struct mei_cl *cl;
-	s32 slots;
-	int rets;
-	bool  bus_message_received;
-
-
-	dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
-	/* initialize our complete list */
-	mutex_lock(&dev->device_lock);
-	mei_io_list_init(&complete_list);
-
-	/* Ack the interrupt here
-	 * In case of MSI we don't go through the quick handler */
-	if (pci_dev_msi_enabled(dev->pdev))
-		mei_clear_interrupts(dev);
-
-	/* check if ME wants a reset */
-	if (!mei_hw_is_ready(dev) &&
-	    dev->dev_state != MEI_DEV_RESETING &&
-	    dev->dev_state != MEI_DEV_INITIALIZING) {
-		dev_dbg(&dev->pdev->dev, "FW not ready.\n");
-		mei_reset(dev, 1);
-		mutex_unlock(&dev->device_lock);
-		return IRQ_HANDLED;
-	}
-
-	/*  check if we need to start the dev */
-	if (!mei_host_is_ready(dev)) {
-		if (mei_hw_is_ready(dev)) {
-			dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
-
-			mei_host_set_ready(dev);
-
-			dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
-			/* link is established * start sending messages.  */
-
-			dev->dev_state = MEI_DEV_INIT_CLIENTS;
-
-			mei_hbm_start_req(dev);
-			mutex_unlock(&dev->device_lock);
-			return IRQ_HANDLED;
-		} else {
-			dev_dbg(&dev->pdev->dev, "FW not ready.\n");
-			mutex_unlock(&dev->device_lock);
-			return IRQ_HANDLED;
-		}
-	}
-	/* check slots available for reading */
-	slots = mei_count_full_read_slots(dev);
-	while (slots > 0) {
-		/* we have urgent data to send so break the read */
-		if (dev->wr_ext_msg.hdr.length)
-			break;
-		dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
-		dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
-		rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
-		if (rets)
-			goto end;
-	}
-	rets = mei_irq_thread_write_handler(dev, &complete_list);
-end:
-	dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
-	dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
-
-	bus_message_received = false;
-	if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
-		dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
-		bus_message_received = true;
-	}
-	mutex_unlock(&dev->device_lock);
-	if (bus_message_received) {
-		dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
-		wake_up_interruptible(&dev->wait_recvd_msg);
-		bus_message_received = false;
-	}
-	if (list_empty(&complete_list.list))
-		return IRQ_HANDLED;
-
-
-	list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
-		cl = cb_pos->cl;
-		list_del(&cb_pos->list);
-		if (cl) {
-			if (cl != &dev->iamthif_cl) {
-				dev_dbg(&dev->pdev->dev, "completing call back.\n");
-				_mei_cmpl(cl, cb_pos);
-				cb_pos = NULL;
-			} else if (cl == &dev->iamthif_cl) {
-				mei_amthif_complete(dev, cb_pos);
-			}
-		}
-	}
-	return IRQ_HANDLED;
-}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index c974292..7d07cef 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -379,9 +379,14 @@ int mei_hw_init(struct mei_device *dev);
 /*
  *  MEI interrupt functions prototype
  */
-irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id);
-irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id);
+
 void mei_timer(struct work_struct *work);
+int mei_irq_read_handler(struct mei_device *dev,
+		struct mei_cl_cb *cmpl_list, s32 *slots);
+
+int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list);
+
+void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos);
 
 /*
  * AMTHIF - AMT Host Interface Functions
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 27ac717..b40ec06 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -170,12 +170,12 @@ static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (pci_dev_msi_enabled(pdev))
 		err = request_threaded_irq(pdev->irq,
 			NULL,
-			mei_interrupt_thread_handler,
+			mei_me_irq_thread_handler,
 			IRQF_ONESHOT, KBUILD_MODNAME, dev);
 	else
 		err = request_threaded_irq(pdev->irq,
-			mei_interrupt_quick_handler,
-			mei_interrupt_thread_handler,
+			mei_me_irq_quick_handler,
+			mei_me_irq_thread_handler,
 			IRQF_SHARED, KBUILD_MODNAME, dev);
 
 	if (err) {
@@ -348,12 +348,12 @@ static int mei_pci_resume(struct device *device)
 	if (pci_dev_msi_enabled(pdev))
 		err = request_threaded_irq(pdev->irq,
 			NULL,
-			mei_interrupt_thread_handler,
+			mei_me_irq_thread_handler,
 			IRQF_ONESHOT, KBUILD_MODNAME, dev);
 	else
 		err = request_threaded_irq(pdev->irq,
-			mei_interrupt_quick_handler,
-			mei_interrupt_thread_handler,
+			mei_me_irq_quick_handler,
+			mei_me_irq_thread_handler,
 			IRQF_SHARED, KBUILD_MODNAME, dev);
 
 	if (err) {
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [char-misc-next 5/6] mei: rename to mei_host_buffer_is_empty to hbuf_is_ready
  2013-02-06 12:06 [char-misc-next 0/6] MEI and ME separation Tomas Winkler
                   ` (3 preceding siblings ...)
  2013-02-06 12:06 ` [char-misc-next 4/6] mei: move interrupt handlers to be me hw specific Tomas Winkler
@ 2013-02-06 12:06 ` Tomas Winkler
  2013-02-06 12:06 ` [char-misc-next 6/6] mei: move clients cleanup code from init.c to client.c Tomas Winkler
  5 siblings, 0 replies; 7+ messages in thread
From: Tomas Winkler @ 2013-02-06 12:06 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, alan, linux-kernel, Tomas Winkler

we rename the mei_host_buffer_is_empty to keep naming
convention of hbuf and also make the query more generic
to be correct also for other under laying hardware

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c  |    8 ++++----
 drivers/misc/mei/client.c  |   13 ++++++-------
 drivers/misc/mei/hw-me.c   |    2 +-
 drivers/misc/mei/main.c    |    4 ++--
 drivers/misc/mei/mei_dev.h |   14 ++++++++++----
 drivers/misc/mei/wd.c      |    9 ++++-----
 6 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index a7c4838..c86d7e3 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -297,9 +297,9 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 	if (ret < 0)
 		return ret;
 
-	if (ret && dev->mei_host_buffer_is_empty) {
+	if (ret && dev->hbuf_is_ready) {
 		ret = 0;
-		dev->mei_host_buffer_is_empty = false;
+		dev->hbuf_is_ready = false;
 		if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
 			mei_hdr.length = mei_hbuf_max_len(dev);
 			mei_hdr.msg_complete = 0;
@@ -330,7 +330,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 			list_add_tail(&cb->list, &dev->write_list.list);
 		}
 	} else {
-		if (!(dev->mei_host_buffer_is_empty))
+		if (!dev->hbuf_is_ready)
 			dev_dbg(&dev->pdev->dev, "host buffer is not empty");
 
 		dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n");
@@ -583,7 +583,7 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
 	dev->iamthif_msg_buf_index = 0;
 	dev->iamthif_msg_buf_size = 0;
 	dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
-	dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
+	dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 	return 0;
 }
 
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index a921001..e46663e 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -393,8 +393,8 @@ int mei_cl_disconnect(struct mei_cl *cl)
 		return -ENOMEM;
 
 	cb->fop_type = MEI_FOP_CLOSE;
-	if (dev->mei_host_buffer_is_empty) {
-		dev->mei_host_buffer_is_empty = false;
+	if (dev->hbuf_is_ready) {
+		dev->hbuf_is_ready = false;
 		if (mei_hbm_cl_disconnect_req(dev, cl)) {
 			rets = -ENODEV;
 			dev_err(&dev->pdev->dev, "failed to disconnect.\n");
@@ -496,9 +496,8 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 
 	cb->fop_type = MEI_FOP_IOCTL;
 
-	if (dev->mei_host_buffer_is_empty &&
-	    !mei_cl_is_other_connecting(cl)) {
-		dev->mei_host_buffer_is_empty = false;
+	if (dev->hbuf_is_ready && !mei_cl_is_other_connecting(cl)) {
+		dev->hbuf_is_ready = false;
 
 		if (mei_hbm_cl_connect_req(dev, cl)) {
 			rets = -ENODEV;
@@ -661,8 +660,8 @@ int mei_cl_read_start(struct mei_cl *cl)
 
 	cb->fop_type = MEI_FOP_READ;
 	cl->read_cb = cb;
-	if (dev->mei_host_buffer_is_empty) {
-		dev->mei_host_buffer_is_empty = false;
+	if (dev->hbuf_is_ready) {
+		dev->hbuf_is_ready = false;
 		if (mei_hbm_cl_flow_control_req(dev, cl)) {
 			rets = -ENODEV;
 			goto err;
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 3bebf8d..45ea718 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -486,7 +486,7 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 	rets = mei_irq_write_handler(dev, &complete_list);
 end:
 	dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
-	dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
+	dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 
 	bus_message_received = false;
 	if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 843ae2f..903f809 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -454,14 +454,14 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 	if (rets < 0)
 		goto err;
 
-	if (rets == 0 || dev->mei_host_buffer_is_empty == false) {
+	if (rets == 0 || !dev->hbuf_is_ready) {
 		write_cb->buf_idx = 0;
 		mei_hdr.msg_complete = 0;
 		cl->writing_state = MEI_WRITING;
 		goto out;
 	}
 
-	dev->mei_host_buffer_is_empty = false;
+	dev->hbuf_is_ready = false;
 	if (length >  mei_hbuf_max_len(dev)) {
 		mei_hdr.length = mei_hbuf_max_len(dev);
 		mei_hdr.msg_complete = 0;
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 7d07cef..cb80166 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -265,9 +265,13 @@ struct mei_hw_ops {
 
 /**
  * struct mei_device -  MEI private device struct
+
  * @mem_addr - mem mapped base register address
- * @hbuf_depth - depth of host(write) buffer
- * @wr_ext_msg - buffer for hbm control responses (set in read cycle)
+
+ * @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
+ * @wr_ext_msg - the buffer for hbm control responses (set in read cycle)
  */
 struct mei_device {
 	struct pci_dev *pdev;	/* pointer to pci device struct */
@@ -294,7 +298,6 @@ struct mei_device {
 	struct delayed_work timer_work;	/* MEI timer delayed work (timeouts) */
 	bool recvd_msg;
 
-	u8  hbuf_depth;
 	/*
 	 * waiting queue for receive message from FW
 	 */
@@ -311,6 +314,10 @@ struct mei_device {
 	unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE];	/* control messages */
 	u32 rd_msg_hdr;
 
+	/* write buffer */
+	u8 hbuf_depth;
+	bool hbuf_is_ready;
+
 	/* used for control messages */
 	struct {
 		struct mei_msg_hdr hdr;
@@ -330,7 +337,6 @@ struct mei_device {
 	u8 me_clients_num;
 	u8 me_client_presentation_num;
 	u8 me_client_index;
-	bool mei_host_buffer_is_empty;
 
 	struct mei_cl wd_cl;
 	enum mei_wd_states wd_state;
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index 77b3820..2413247 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -157,9 +157,9 @@ int mei_wd_stop(struct mei_device *dev)
 	if (ret < 0)
 		goto out;
 
-	if (ret && dev->mei_host_buffer_is_empty) {
+	if (ret && dev->hbuf_is_ready) {
 		ret = 0;
-		dev->mei_host_buffer_is_empty = false;
+		dev->hbuf_is_ready = false;
 
 		if (!mei_wd_send(dev)) {
 			ret = mei_cl_flow_ctrl_reduce(&dev->wd_cl);
@@ -282,10 +282,9 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 	dev->wd_state = MEI_WD_RUNNING;
 
 	/* Check if we can send the ping to HW*/
-	if (dev->mei_host_buffer_is_empty &&
-	    mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
+	if (dev->hbuf_is_ready && mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
 
-		dev->mei_host_buffer_is_empty = false;
+		dev->hbuf_is_ready = false;
 		dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
 
 		if (mei_wd_send(dev)) {
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [char-misc-next 6/6] mei: move clients cleanup code from init.c to client.c
  2013-02-06 12:06 [char-misc-next 0/6] MEI and ME separation Tomas Winkler
                   ` (4 preceding siblings ...)
  2013-02-06 12:06 ` [char-misc-next 5/6] mei: rename to mei_host_buffer_is_empty to hbuf_is_ready Tomas Winkler
@ 2013-02-06 12:06 ` Tomas Winkler
  5 siblings, 0 replies; 7+ messages in thread
From: Tomas Winkler @ 2013-02-06 12:06 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, alan, linux-kernel, Tomas Winkler

during reset we clean up client data structures
we move that code into wrappers in client
and call the wrappers

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/client.c |   51 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/misc/mei/client.h |    5 ++++
 drivers/misc/mei/init.c   |   28 +++++-------------------
 3 files changed, 62 insertions(+), 22 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index e46663e..1569afe 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -676,3 +676,54 @@ err:
 	return rets;
 }
 
+/**
+ * mei_cl_all_disconnect - disconnect forcefully all connected clients
+ *
+ * @dev - mei device
+ */
+
+void mei_cl_all_disconnect(struct mei_device *dev)
+{
+	struct mei_cl *cl, *next;
+
+	list_for_each_entry_safe(cl, next, &dev->file_list, link) {
+		cl->state = MEI_FILE_DISCONNECTED;
+		cl->mei_flow_ctrl_creds = 0;
+		cl->read_cb = NULL;
+		cl->timer_count = 0;
+	}
+}
+
+
+/**
+ * mei_cl_all_read_wakeup  - wake up all readings so they can be interrupted
+ *
+ * @dev  - mei device
+ */
+void mei_cl_all_read_wakeup(struct mei_device *dev)
+{
+	struct mei_cl *cl, *next;
+	list_for_each_entry_safe(cl, next, &dev->file_list, link) {
+		if (waitqueue_active(&cl->rx_wait)) {
+			dev_dbg(&dev->pdev->dev, "Waking up client!\n");
+			wake_up_interruptible(&cl->rx_wait);
+		}
+	}
+}
+
+/**
+ * mei_cl_all_write_clear - clear all pending writes
+
+ * @dev - mei device
+ */
+void mei_cl_all_write_clear(struct mei_device *dev)
+{
+	struct mei_cl_cb *cb, *next;
+
+	list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
+		list_del(&cb->list);
+		mei_io_cb_free(cb);
+	}
+}
+
+
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 240a1f3..214b239 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -94,4 +94,9 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file);
 void mei_host_client_init(struct work_struct *work);
 
 
+void mei_cl_all_disconnect(struct mei_device *dev);
+void mei_cl_all_read_wakeup(struct mei_device *dev);
+void mei_cl_all_write_clear(struct mei_device *dev);
+
+
 #endif /* _MEI_CLIENT_H_ */
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 51a005e..6ec5301 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -135,10 +135,6 @@ err:
  */
 void mei_reset(struct mei_device *dev, int interrupts_enabled)
 {
-	struct mei_cl *cl_pos = NULL;
-	struct mei_cl *cl_next = NULL;
-	struct mei_cl_cb *cb_pos = NULL;
-	struct mei_cl_cb *cb_next = NULL;
 	bool unexpected;
 
 	if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET)
@@ -157,13 +153,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 		    dev->dev_state != MEI_DEV_POWER_DOWN)
 			dev->dev_state = MEI_DEV_RESETING;
 
-		list_for_each_entry_safe(cl_pos,
-				cl_next, &dev->file_list, link) {
-			cl_pos->state = MEI_FILE_DISCONNECTED;
-			cl_pos->mei_flow_ctrl_creds = 0;
-			cl_pos->read_cb = NULL;
-			cl_pos->timer_count = 0;
-		}
+		mei_cl_all_disconnect(dev);
+
 		/* remove entry if already in list */
 		dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
 		mei_cl_unlink(&dev->wd_cl);
@@ -185,18 +176,11 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 		dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n",
 			 mei_dev_state_str(dev->dev_state));
 
-	/* Wake up all readings so they can be interrupted */
-	list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
-		if (waitqueue_active(&cl_pos->rx_wait)) {
-			dev_dbg(&dev->pdev->dev, "Waking up client!\n");
-			wake_up_interruptible(&cl_pos->rx_wait);
-		}
-	}
+	/* wake up all readings so they can be interrupted */
+	mei_cl_all_read_wakeup(dev);
+
 	/* remove all waiting requests */
-	list_for_each_entry_safe(cb_pos, cb_next, &dev->write_list.list, list) {
-		list_del(&cb_pos->list);
-		mei_io_cb_free(cb_pos);
-	}
+	mei_cl_all_write_clear(dev);
 }
 
 
-- 
1.7.4.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-02-06 12:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-06 12:06 [char-misc-next 0/6] MEI and ME separation Tomas Winkler
2013-02-06 12:06 ` [char-misc-next 1/6] mei: sperate interface and pci code into two files Tomas Winkler
2013-02-06 12:06 ` [char-misc-next 2/6] mei: initial extract of ME hw specifics from mei_device Tomas Winkler
2013-02-06 12:06 ` [char-misc-next 3/6] mei: separate compilation of the ME hardware specifics Tomas Winkler
2013-02-06 12:06 ` [char-misc-next 4/6] mei: move interrupt handlers to be me hw specific Tomas Winkler
2013-02-06 12:06 ` [char-misc-next 5/6] mei: rename to mei_host_buffer_is_empty to hbuf_is_ready Tomas Winkler
2013-02-06 12:06 ` [char-misc-next 6/6] mei: move clients cleanup code from init.c to client.c Tomas Winkler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).