[PATCH 00/12 v2] staging: mei: adding new watchdog core support

September 07th, 2011 - 02:10 am ET by Oren Weil | Report spam
In this patches set we are adding the new watchdog core to the mei driver.
Until now the mei driver manage by itself the Intel(R) Active Management Technology
(Intel(R) AMT) watchdog, the driver send the heartbeat by a
internal timer and the internal was defined by module parameter.

for more information about the Intel(R) AMT watchdog read
drivers/staging/mei/mei.txt

Version 2 - Removed two tab indent in patch 05

Oren Weil (12):
staging: mei: removing dependency between WD and AMTHI init function.
staging: mei: fix register access function comments
staging: mei: registering the MEI driver with the kernel watchdog
core interface
staging: mei: adding watchdog ops
staging: mei: adding watchdog ping
staging: mei: adding set_timeout watchdog function
staging: mei: renaming delayed work field and function to a
meaningful name.
staging: mei: resuming timer regardless of the watchdog timeout
value.
stagign: mei: client init code cleanup
staging: mei: removing wd module parameters
staging: mei: adding mei_wd_stop function comment
staging: mei: adding watchdog core dependency to kconfig

drivers/staging/mei/Kconfig | 2 +-
drivers/staging/mei/init.c | 9 ++-
drivers/staging/mei/interface.h | 8 +-
drivers/staging/mei/interrupt.c | 45 +++--
drivers/staging/mei/main.c | 19 ++--
drivers/staging/mei/mei_dev.h | 22 +++-
drivers/staging/mei/wd.c | 242 +++++++++++++++++++++++++++++++++
7 files changed, 261 insertions(+), 86 deletions(-)

1.7.4.1

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
email Follow the discussionReplies 12 repliesReplies Make a reply

Similar topics

Replies

#6 Oren Weil
September 07th, 2011 - 02:10 am ET | Report spam
adding start and stop function.
start - check if AMT wd client is connected, which is been connected on driver
load.
stop - send stop command to AMT wd.

Signed-off-by: Oren Weil
Acked-by: Tomas Winkler

drivers/staging/mei/main.c | 2 +-
drivers/staging/mei/mei_dev.h | 5 ++
drivers/staging/mei/wd.c | 95 ++++++++++++++++++++++++++++++++++
3 files changed, 86 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c
index 37f07da..60003cd 100644
a/drivers/staging/mei/main.c
+++ b/drivers/staging/mei/main.c
@@ -58,7 +58,7 @@ static struct cdev mei_cdev;
static int mei_major;
/* The device pointer */
/* Currently this driver works as long as there is only a single AMT device. */
-static struct pci_dev *mei_device;
+struct pci_dev *mei_device;

static struct class *mei_class;

diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h
index d434afc..43d7e1c 100644
a/drivers/staging/mei/mei_dev.h
+++ b/drivers/staging/mei/mei_dev.h
@@ -38,6 +38,11 @@
#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)

/*
+ * MEI PCI Device object
+ */
+extern struct pci_dev *mei_device;
+
+/*
* AMT Watchdog Device
*/
#define INTEL_AMT_WATCHDOG_ID "INTCAMT"
diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c
index d9e41a7..fb2bd3d 100644
a/drivers/staging/mei/wd.c
+++ b/drivers/staging/mei/wd.c
@@ -27,21 +27,6 @@
#include "mei.h"

/*
- * Watchdog Device structs
- */
-const struct watchdog_info wd_info = {
- .identity = INTEL_AMT_WATCHDOG_ID,
-};
-
-struct watchdog_device amt_wd_dev = {
- .info = &wd_info,
- .timeout = AMT_WD_DEFAULT_TIMEOUT,
- .min_timeout = AMT_WD_MIN_TIMEOUT,
- .max_timeout = AMT_WD_MAX_TIMEOUT,
-};
-
-
-/*
* MEI Watchdog Module Parameters
*/
static u16 watchdog_timeout = AMT_WD_DEFAULT_TIMEOUT;
@@ -210,3 +195,83 @@ out:
return ret;
}

+/*
+ * mei_wd_ops_start - wd start command from the watchdog core.
+ *
+ * @wd_dev - watchdog device struct
+ *
+ * returns 0 if success, negative errno code for failure
+ */
+static int mei_wd_ops_start(struct watchdog_device *wd_dev)
+{
+ int err = -ENODEV;
+ struct mei_device *dev;
+
+ dev = pci_get_drvdata(mei_device);
+ if (!dev)
+ return -ENODEV;
+
+ mutex_lock(&dev->device_lock);
+
+ if (dev->mei_state != MEI_ENABLED) {
+ dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d",
+ dev->mei_state);
+ goto end_unlock;
+ }
+
+ if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
+ dev_dbg(&dev->pdev->dev, "MEI Driver is not connected to Watchdog Client");
+ goto end_unlock;
+ }
+
+ mei_wd_start_setup(dev);
+
+ err = 0;
+end_unlock:
+ mutex_unlock(&dev->device_lock);
+ return err;
+}
+
+/*
+ * mei_wd_ops_stop - wd stop command from the watchdog core.
+ *
+ * @wd_dev - watchdog device struct
+ *
+ * returns 0 if success, negative errno code for failure
+ */
+static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
+{
+ struct mei_device *dev;
+ dev = pci_get_drvdata(mei_device);
+
+ if (!dev)
+ return -ENODEV;
+
+ mutex_lock(&dev->device_lock);
+ mei_wd_stop(dev, false);
+ mutex_unlock(&dev->device_lock);
+
+ return 0;
+}
+
+/*
+ * Watchdog Device structs
+ */
+const struct watchdog_ops wd_ops = {
+ .owner = THIS_MODULE,
+ .start = mei_wd_ops_start,
+ .stop = mei_wd_ops_stop,
+};
+const struct watchdog_info wd_info = {
+ .identity = INTEL_AMT_WATCHDOG_ID,
+};
+
+struct watchdog_device amt_wd_dev = {
+ .info = &wd_info,
+ .ops = &wd_ops,
+ .timeout = AMT_WD_DEFAULT_TIMEOUT,
+ .min_timeout = AMT_WD_MIN_TIMEOUT,
+ .max_timeout = AMT_WD_MAX_TIMEOUT,
+};
+
+
1.7.4.1

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Replies Reply to this message
#7 Oren Weil
September 07th, 2011 - 02:10 am ET | Report spam
Adding kernel watchdog interface (/dev/watchdog) to the MEI Driver to support AMT Watchdog feature.
This patch and the following one will replace MEI Driver self management of the AMT watchdog
with the standard kernel watchdog interface.

Signed-off-by: Oren Weil
Acked-by: Tomas Winkler

drivers/staging/mei/init.c | 1 +
drivers/staging/mei/interface.h | 4 +++-
drivers/staging/mei/interrupt.c | 12 ++++++++++++
drivers/staging/mei/main.c | 4 ++++
drivers/staging/mei/mei_dev.h | 9 +++++++++
drivers/staging/mei/wd.c | 20 ++++++++++++++++++--
6 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/mei/init.c b/drivers/staging/mei/init.c
index 69a57e7..cb0ebbe 100644
a/drivers/staging/mei/init.c
+++ b/drivers/staging/mei/init.c
@@ -133,6 +133,7 @@ struct mei_device *mei_device_init(struct pci_dev *pdev)
init_waitqueue_head(&dev->wait_stop_wd);
dev->mei_state = MEI_INITIALIZING;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
+ dev->wd_interface_reg = false;


mei_io_list_init(&dev->read_list);
diff --git a/drivers/staging/mei/interface.h b/drivers/staging/mei/interface.h
index 7bcf096..2b5a22c 100644
a/drivers/staging/mei/interface.h
+++ b/drivers/staging/mei/interface.h
@@ -23,7 +23,9 @@
#include "mei_dev.h"


-#define AMT_WD_VALUE 120 /* seconds */
+#define AMT_WD_DEFAULT_TIMEOUT 120 /* seconds */
+#define AMT_WD_MIN_TIMEOUT 120 /* seconds */
+#define AMT_WD_MAX_TIMEOUT 65535 /* seconds */

#define MEI_WATCHDOG_DATA_SIZE 16
#define MEI_START_WD_DATA_SIZE 20
diff --git a/drivers/staging/mei/interrupt.c b/drivers/staging/mei/interrupt.c
index ca1e0c9..958a7e2 100644
a/drivers/staging/mei/interrupt.c
+++ b/drivers/staging/mei/interrupt.c
@@ -396,6 +396,18 @@ static void mei_client_connect_response(struct mei_device *dev,
dev->wd_due_counter = (dev->wd_timeout) ? 1 : 0;

dev_dbg(&dev->pdev->dev, "successfully connected to WD client.");
+
+ /* Registering watchdog interface device once we got connection
+ to the WD Client
+ */
+ if (watchdog_register_device(&amt_wd_dev)) {
+ printk(KERN_ERR "mei: unable to register watchdog device.");
+ dev->wd_interface_reg = false;
+ } else {
+ dev_dbg(&dev->pdev->dev, "successfully register watchdog interface.");
+ dev->wd_interface_reg = true;
+ }
+
mei_host_init_iamthif(dev);
return;
}
diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c
index 8d76785..37f07da 100644
a/drivers/staging/mei/main.c
+++ b/drivers/staging/mei/main.c
@@ -241,6 +241,10 @@ static void __devexit mei_remove(struct pci_dev *pdev)
mei_disconnect_host_client(dev, &dev->wd_cl);
}

+ /* Unregistering watchdog device */
+ if (dev->wd_interface_reg)
+ watchdog_unregister_device(&amt_wd_dev);
+
/* remove entry if already in list */
dev_dbg(&pdev->dev, "list del iamthif and wd file list.");
mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h
index 2e11077..d434afc 100644
a/drivers/staging/mei/mei_dev.h
+++ b/drivers/staging/mei/mei_dev.h
@@ -18,6 +18,7 @@
#define _MEI_DEV_H_

#include <linux/types.h>
+#include <linux/watchdog.h>
#include "mei.h"
#include "hw.h"

@@ -37,6 +38,12 @@
#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)

/*
+ * AMT Watchdog Device
+ */
+#define INTEL_AMT_WATCHDOG_ID "INTCAMT"
+extern struct watchdog_device amt_wd_dev;
+
+/*
* AMTHI Client UUID
*/
extern const uuid_le mei_amthi_guid;
@@ -258,6 +265,8 @@ struct mei_device {
bool iamthif_flow_control_pending;
bool iamthif_ioctl;
bool iamthif_canceled;
+
+ bool wd_interface_reg;
};


diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c
index 721487d..d9e41a7 100644
a/drivers/staging/mei/wd.c
+++ b/drivers/staging/mei/wd.c
@@ -19,6 +19,7 @@
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/sched.h>
+#include <linux/watchdog.h>

#include "mei_dev.h"
#include "hw.h"
@@ -26,13 +27,28 @@
#include "mei.h"

/*
+ * Watchdog Device structs
+ */
+const struct watchdog_info wd_info = {
+ .identity = INTEL_AMT_WATCHDOG_ID,
+};
+
+struct watchdog_device amt_wd_dev = {
+ .info = &wd_info,
+ .timeout = AMT_WD_DEFAULT_TIMEOUT,
+ .min_timeout = AMT_WD_MIN_TIMEOUT,
+ .max_timeout = AMT_WD_MAX_TIMEOUT,
+};
+
+
+/*
* MEI Watchdog Module Parameters
*/
-static u16 watchdog_timeout = AMT_WD_VALUE;
+static u16 watchdog_timeout = AMT_WD_DEFAULT_TIMEOUT;
module_param(watchdog_timeout, ushort, 0);
MODULE_PARM_DESC(watchdog_timeout,
"Intel(R) AMT Watchdog timeout value in seconds. (default="
- __MODULE_STRING(AMT_WD_VALUE)
+ __MODULE_STRING(AMT_WD_DEFAULT_TIMEOUT)
", disable=0)");

static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
1.7.4.1

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Replies Reply to this message
#8 Oren Weil
September 07th, 2011 - 02:10 am ET | Report spam
the wd_work and mei_wd_timer() function was not just for watchdog.
mei managing the AMT watchdog going to be replace by the kernel watchdog
interface.

the mei_timer() will still manage the mei driver timeouts.

Signed-off-by: Oren Weil
Acked-by: Tomas Winkler

drivers/staging/mei/interrupt.c | 6 +++
drivers/staging/mei/main.c | 6 +++
drivers/staging/mei/mei_dev.h | 4 ++--
drivers/staging/mei/wd.c | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/mei/interrupt.c b/drivers/staging/mei/interrupt.c
index 62b8001..d1da3aa 100644
a/drivers/staging/mei/interrupt.c
+++ b/drivers/staging/mei/interrupt.c
@@ -1393,7 +1393,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
*
* NOTE: This function is called by timer interrupt work
*/
-void mei_wd_timer(struct work_struct *work)
+void mei_timer(struct work_struct *work)
{
unsigned long timeout;
struct mei_cl *cl_pos = NULL;
@@ -1403,7 +1403,7 @@ void mei_wd_timer(struct work_struct *work)
struct mei_cl_cb *cb_next = NULL;

struct mei_device *dev = container_of(work,
- struct mei_device, wd_work.work);
+ struct mei_device, timer_work.work);


mutex_lock(&dev->device_lock);
@@ -1495,7 +1495,7 @@ void mei_wd_timer(struct work_struct *work)
}
}
out:
- schedule_delayed_work(&dev->wd_work, 2 * HZ);
+ schedule_delayed_work(&dev->timer_work, 2 * HZ);
mutex_unlock(&dev->device_lock);
}

diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c
index 8d124724..7009937 100644
a/drivers/staging/mei/main.c
+++ b/drivers/staging/mei/main.c
@@ -170,7 +170,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
pdev->irq);
goto unmap_memory;
}
- INIT_DELAYED_WORK(&dev->wd_work, mei_wd_timer);
+ INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
if (mei_hw_init(dev)) {
printk(KERN_ERR "mei: Init hw failure.");
err = -ENODEV;
@@ -178,7 +178,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
}
mei_device = pdev;
pci_set_drvdata(pdev, dev);
- schedule_delayed_work(&dev->wd_work, HZ);
+ schedule_delayed_work(&dev->timer_work, HZ);

mutex_unlock(&mei_mutex);

@@ -1154,7 +1154,7 @@ static int mei_pci_resume(struct device *device)
/* Start watchdog if stopped in suspend */
if (dev->wd_timeout) {
dev->wd_due_counter = 1;
- schedule_delayed_work(&dev->wd_work, HZ);
+ schedule_delayed_work(&dev->timer_work, HZ);
}
return err;
}
diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h
index 43d7e1c..6487be1 100644
a/drivers/staging/mei/mei_dev.h
+++ b/drivers/staging/mei/mei_dev.h
@@ -209,7 +209,7 @@ struct mei_device {
* lock for the device
*/
struct mutex device_lock; /* device lock */
- struct delayed_work wd_work; /* watch dog deleye work */
+ struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */
bool recvd_msg;
/*
* hw states of host and fw(ME)
@@ -336,7 +336,7 @@ void mei_host_client_properties(struct mei_device *dev);
*/
irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id);
irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id);
-void mei_wd_timer(struct work_struct *work);
+void mei_timer(struct work_struct *work);

/*
* MEI input output function prototype
diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c
index 6643f7a..68c177b 100644
a/drivers/staging/mei/wd.c
+++ b/drivers/staging/mei/wd.c
@@ -142,7 +142,7 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
int ret;
u16 wd_timeout = dev->wd_timeout;

- cancel_delayed_work(&dev->wd_work);
+ cancel_delayed_work(&dev->timer_work);
if (dev->wd_cl.state != MEI_FILE_CONNECTED || !dev->wd_timeout)
return 0;

1.7.4.1

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Replies Reply to this message
#9 Oren Weil
September 07th, 2011 - 02:10 am ET | Report spam
Signed-off-by: Oren Weil
Acked-by: Tomas Winkler

drivers/staging/mei/wd.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c
index b56b1cc..ffca7ca 100644
a/drivers/staging/mei/wd.c
+++ b/drivers/staging/mei/wd.c
@@ -120,6 +120,16 @@ int mei_wd_send(struct mei_device *dev)
return -EIO;
}

+/**
+ * mei_wd_stop - sends watchdog stop message to fw.
+ *
+ * @dev: the device structure
+ * @preserve: indicate if to keep the timeout value
+ *
+ * returns 0 if success,
+ * -EIO when message send fails
+ * -EINVAL when invalid message is to be sent
+ */
int mei_wd_stop(struct mei_device *dev, bool preserve)
{
int ret;
1.7.4.1

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Replies Reply to this message
#10 Oren Weil
September 07th, 2011 - 02:10 am ET | Report spam
Signed-off-by: Oren Weil
Acked-by: Tomas Winkler

drivers/staging/mei/mei_dev.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h
index d7bc10c..2e11077 100644
a/drivers/staging/mei/mei_dev.h
+++ b/drivers/staging/mei/mei_dev.h
@@ -356,7 +356,7 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid);
* @dev: the device structure
* @offset: offset from which to read the data
*
- * returns the byte read.
+ * returns register value (u32)
*/
static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
{
@@ -368,7 +368,7 @@ static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
*
* @dev: the device structure
* @offset: offset from which to write the data
- * @value: the byte to write
+ * @value: register value to write (u32)
*/
static inline void mei_reg_write(struct mei_device *dev,
unsigned long offset, u32 value)
1.7.4.1

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Replies Reply to this message
Help Create a new topicNext page Previous pageReplies Make a reply
Search Make your own search