File heci_pm_wd_fix.diff of Package intel-iamt-heci
diff -Nur HECI-3.1.0.31/src/heci_data_structures.h HECI-3.2.0.24/src/heci_data_structures.h
--- HECI-3.1.0.31/src/heci_data_structures.h 2007-08-20 10:07:43.000000000 -0400
+++ HECI-3.2.0.24/src/heci_data_structures.h 2008-01-24 07:04:22.000000000 -0500
@@ -153,6 +153,9 @@
#define HECI_START_WD_DATA_SIZE 20
#define HECI_WD_PARAMS_SIZE 4
+#define HECI_NO_MSG_SENT 0
+#define HECI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
+
#define HECI_WD_HOST_CLIENT_ID 1
#define HECI_LEGACY_HOST_CLIENT_ID 2
@@ -260,6 +263,7 @@
__u8 timer_count;
enum heci_file_transaction_states reading_state;
enum heci_file_transaction_states writing_state;
+ int sm_state;
struct heci_cb_private *read_cb;
};
diff -Nur HECI-3.1.0.31/src/heci.h HECI-3.2.0.24/src/heci.h
--- HECI-3.1.0.31/src/heci.h 2007-08-20 10:07:43.000000000 -0400
+++ HECI-3.2.0.24/src/heci.h 2008-01-24 07:04:21.000000000 -0500
@@ -58,6 +58,7 @@
extern const struct guid heci_wd_guid;
extern const __u8 start_wd_params[];
extern const __u8 stop_wd_params[];
+extern const __u8 heci_wd_state_independence_msg[2][4];
/**
* memory IO BAR definition
diff -Nur HECI-3.1.0.31/src/heci_init.c HECI-3.2.0.24/src/heci_init.c
--- HECI-3.1.0.31/src/heci_init.c 2007-08-20 10:07:43.000000000 -0400
+++ HECI-3.2.0.24/src/heci_init.c 2008-01-24 07:04:22.000000000 -0500
@@ -59,6 +59,9 @@
{ 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
const __u8 start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
const __u8 stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
+const __u8 heci_wd_state_independence_msg[2][4] = {
+ {0x05, 0x02, 0x51, 0x10},
+ {0x05, 0x02, 0x52, 0x10} };
const struct guid heci_asf_guid =
{ 0x75B30CD6, 0xA29E, 0x4AF7, {0xA7, 0x12, 0xE6, 0x17, 0x43, 0x93,
0xC8, 0xA6} };
@@ -308,11 +311,19 @@
struct heci_file_private *file_extension_pos = NULL;
struct heci_file_private *file_extension_next = NULL;
struct heci_cb_private *kernel_priv_cb_pos = NULL, *kernel_priv_cb_next = NULL;
+ int unexpected = 0;
if (device_object->heci_state == HECI_RECOVERING_FROM_RESET) {
device_object->need_reset = TRUE;
return;
}
+
+ if (device_object->heci_state != HECI_INITIALIZING &&
+ device_object->heci_state != HECI_DISABLED &&
+ device_object->heci_state != HECI_POWER_DOWN &&
+ device_object->heci_state != HECI_POWER_UP)
+ unexpected = 1;
+
device_object->host_hw_state =
read_heci_register(device_object, H_CSR);
@@ -346,7 +357,8 @@
device_object->need_reset = FALSE;
if (device_object->heci_state != HECI_INITIALIZING) {
- if (device_object->heci_state != HECI_DISABLED) {
+ if (device_object->heci_state != HECI_DISABLED &&
+ device_object->heci_state != HECI_POWER_DOWN) {
device_object->heci_state = HECI_RESETING;
}
list_for_each_entry_safe(file_extension_pos, file_extension_next, &device_object->file_list, link) {
@@ -394,8 +406,7 @@
DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
device_object->host_hw_state, device_object->me_hw_state);
- if (device_object->heci_state != HECI_INITIALIZING &&
- device_object->heci_state != HECI_DISABLED)
+ if (unexpected)
ERR("unexpected heci reset.\n");
//Wake up all readings so they can be interrupted
list_for_each_entry_safe(file_extension_pos,file_extension_next, &device_object->file_list,link) {
diff -Nur HECI-3.1.0.31/src/heci_main.c HECI-3.2.0.24/src/heci_main.c
--- HECI-3.1.0.31/src/heci_main.c 2007-08-20 10:07:43.000000000 -0400
+++ HECI-3.2.0.24/src/heci_main.c 2008-01-24 07:04:22.000000000 -0500
@@ -99,7 +99,6 @@
/* The device pointer */
static struct pci_dev *heci_device;
-
/* heci_pci_tbl - PCI Device ID Table */
static struct pci_device_id heci_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_HECI_DEVICE_ID1)},
@@ -134,6 +133,11 @@
static ssize_t heci_write(struct file *file, const char __user * ubuf,
size_t length, loff_t * offset);
static unsigned int heci_poll(struct file *file, poll_table * wait);
+#ifdef CONFIG_PM
+static int heci_suspend(struct pci_dev* pdev, pm_message_t state);
+static int heci_resume(struct pci_dev* pdev);
+static __u16 g_sus_wd_timeout;
+#endif
/**
* PCI driver structure
*/
@@ -143,6 +147,10 @@
.probe = heci_probe,
.remove = heci_remove,
SHUTDOWN_METHOD(heci_remove)
+#ifdef CONFIG_PM
+ .suspend = heci_suspend,
+ .resume = heci_resume
+#endif
};
/**
@@ -370,6 +378,9 @@
if (device->wd_timeout) {
mod_timer(&device->wd_timer, jiffies);
}
+#ifdef CONFIG_PM
+ g_sus_wd_timeout = 0;
+#endif
INFO("heci driver initialization successful.\n");
return ESUCCESS;
@@ -618,6 +629,7 @@
spin_unlock_bh(&device->device_lock);
spin_lock(&file_extension->file_lock);
file_extension->state = HECI_FILE_INITIALIZING;
+ file_extension->sm_state = 0;
file->private_data = file_extension;
spin_unlock(&file_extension->file_lock);
@@ -761,19 +773,26 @@
if (!file_extension)
return -ENODEV;
- /* Do not allow to read watchdog client */
- for (i = 0; i < device->num_heci_me_clients; i++) {
- if (0 == memcmp(&heci_wd_guid, &device->me_clients[i].properteis.protocol_name, sizeof(struct guid))) {
- if (file_extension->me_client_id == device->me_clients[i].client_id)
- return -EBADF;
- }
+ spin_lock(&file_extension->file_lock);
+ if((file_extension->sm_state & HECI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
+ spin_unlock(&file_extension->file_lock);
+ /* Do not allow to read watchdog client */
+ for (i = 0; i < device->num_heci_me_clients; i++) {
+ if (0 == memcmp(&heci_wd_guid, &device->me_clients[i].properteis.protocol_name, sizeof(struct guid))) {
+ if (file_extension->me_client_id == device->me_clients[i].client_id)
+ return -EBADF;
+ }
+ }
+ } else {
+ file_extension->sm_state &= ~HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
+ spin_unlock(&file_extension->file_lock);
}
if (file_extension == &device->legacy_file_extension) {
return_status = pthi_read(device, if_num, file, ubuf, length, offset);
goto out;
}
- if (file_extension->read_cb && file_extension->read_cb->information < *offset) {
+ if (file_extension->read_cb && file_extension->read_cb->information > *offset) {
kernel_priv_cb = file_extension->read_cb;
goto copy_buffer;
}
@@ -967,6 +986,16 @@
return_status = -EFAULT;
goto fail;
}
+
+ spin_lock(&file_extension->file_lock);
+ file_extension->sm_state = 0;
+ if (length == 4 &&
+ ((memcmp(heci_wd_state_independence_msg[0], ubuf, 4) == 0) ||
+ (memcmp(heci_wd_state_independence_msg[1], ubuf, 4) == 0))) {
+ file_extension->sm_state |= HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
+ }
+ spin_unlock(&file_extension->file_lock);
+
INIT_LIST_HEAD(&priv_write_cb->cb_list);
if (file_extension == &device->legacy_file_extension) {
priv_write_cb->response_buffer.data =
@@ -1305,6 +1334,110 @@
return mask;
}
+#ifdef CONFIG_PM
+static int heci_suspend(struct pci_dev* pdev, pm_message_t state)
+{
+ struct iamt_heci_device *device = pci_get_drvdata(pdev);
+ int err = 0;
+
+ //Stop watchdog if exists
+ del_timer_sync(&device->wd_timer);
+ if (device->wd_file_extension.state == HECI_FILE_CONNECTED
+ && device->wd_timeout) {
+ spin_lock_bh(&device->device_lock);
+ g_sus_wd_timeout = device->wd_timeout;
+ device->wd_timeout = 0;
+ device->wd_due_counter = 0;
+ memcpy(device->wd_data, stop_wd_params, HECI_WD_PARAMS_SIZE);
+ device->stop = TRUE;
+ if (device->host_buffer_is_empty &&
+ flow_control_credentials(device, &device->wd_file_extension)) {
+ device->host_buffer_is_empty = FALSE;
+
+ if (!heci_send_wd(device))
+ DBG("Send stop WD failed\n");
+ else
+ flow_control_reduce(device, &device->wd_file_extension);
+ device->wd_pending = FALSE;
+ } else {
+ device->wd_pending = TRUE;
+ }
+ spin_unlock_bh(&device->device_lock);
+ device->wd_stoped = FALSE;
+
+ err =
+ wait_event_interruptible_timeout(device->wait_stop_wd,
+ (TRUE == device->wd_stoped), 10 * HZ);
+ if (!device->wd_stoped)
+ DBG("stop wd failed to complete.\n");
+ else {
+ DBG("stop wd complete %d.\n", err);
+ err = 0;
+ }
+ }
+ //Set new heci state
+ spin_lock_bh(&device->device_lock);
+ if (device->heci_state == HECI_ENABLED ||
+ device->heci_state == HECI_RECOVERING_FROM_RESET) {
+ device->heci_state = HECI_POWER_DOWN;
+ heci_reset(device, FALSE);
+ }
+ spin_unlock_bh(&device->device_lock);
+
+ pci_save_state(pdev);
+
+
+ pci_disable_device(pdev);
+ free_irq(pdev->irq, device);
+
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return err;
+}
+
+static int heci_resume(struct pci_dev* pdev)
+{
+ struct iamt_heci_device *device = NULL;
+ int err = 0;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ device = pci_get_drvdata(pdev);
+ if (!device) {
+ return -ENODEV;
+ }
+
+ /* request and enable interrupt */
+ device->irq = pdev->irq;
+ err = request_irq(device->irq, heci_isr_interrupt, IRQF_SHARED,
+ heci_driver_name, device);
+ if (err) {
+ ERR("Request_irq failure. irq = %d \n", device->irq);
+ return err;
+ }
+
+ spin_lock_bh(&device->device_lock);
+ device->heci_state = HECI_POWER_UP;
+ heci_reset(device, TRUE);
+ spin_unlock_bh(&device->device_lock);
+
+ //Start watchdog if stopped in suspend
+ if (g_sus_wd_timeout != 0) {
+ device->wd_timeout = g_sus_wd_timeout;
+
+ memcpy(device->wd_data, start_wd_params, HECI_WD_PARAMS_SIZE);
+ memcpy(device->wd_data + HECI_WD_PARAMS_SIZE, &device->wd_timeout,
+ sizeof(__u16));
+ device->wd_due_counter = 1;
+
+ if (device->wd_timeout)
+ mod_timer(&device->wd_timer, jiffies);
+ g_sus_wd_timeout = 0;
+ }
+ return err;
+}
+#endif
MODULE_AUTHOR("Intel Corporation"); /* FIXME: Add email address here */
MODULE_DESCRIPTION("Intel(R) AMT Management Interface");
MODULE_LICENSE("Dual BSD/GPL");
diff -Nur HECI-3.1.0.31/src/version.h HECI-3.2.0.24/src/version.h
--- HECI-3.1.0.31/src/version.h 2007-08-20 10:07:53.000000000 -0400
+++ HECI-3.2.0.24/src/version.h 2008-01-24 07:04:42.000000000 -0500
@@ -42,9 +42,9 @@
#define HECI_VERSION_H
#define MAJOR_VERSION 3
-#define MINOR_VERSION 1
+#define MINOR_VERSION 2
#define QUICK_FIX_NUMBER 0
-#define VER_BUILD 31
+#define VER_BUILD 24
#define str(s) name(s)
#define name(s) #s