Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.1:kernel-2.6.32
intel-iamt-heci
heci_pm_wd_fix.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
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
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor