mei: add mei_stop function to stop mei device

mei_stop calls mei_reset with disabling the interrupts.
It will have the same effect as the open code it replaces in the mei_remove.

The reset sequence on remove is required for the Lynx Point LP devices
to clean the reset state.

mei_stop is called from mei_pci_suspend and mei_remove functions

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Tomas Winkler 2013-03-10 13:56:08 +02:00 committed by Greg Kroah-Hartman
parent 3d374d09f1
commit 7cb035d9e6
3 changed files with 26 additions and 45 deletions

View file

@ -183,6 +183,24 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
mei_cl_all_write_clear(dev);
}
void mei_stop(struct mei_device *dev)
{
dev_dbg(&dev->pdev->dev, "stopping the device.\n");
mutex_lock(&dev->device_lock);
cancel_delayed_work(&dev->timer_work);
mei_wd_stop(dev);
dev->dev_state = MEI_DEV_POWER_DOWN;
mei_reset(dev, 0);
mutex_unlock(&dev->device_lock);
flush_scheduled_work();
}

View file

@ -381,6 +381,7 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
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);
void mei_stop(struct mei_device *dev);
/*
* MEI interrupt functions prototype

View file

@ -247,44 +247,14 @@ static void mei_remove(struct pci_dev *pdev)
hw = to_me_hw(dev);
mutex_lock(&dev->device_lock);
cancel_delayed_work(&dev->timer_work);
mei_wd_stop(dev);
dev_err(&pdev->dev, "stop\n");
mei_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);
@ -308,28 +278,20 @@ 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);
dev_err(&pdev->dev, "suspend\n");
/* 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);
mei_stop(dev);
mei_disable_interrupts(dev);
free_irq(pdev->irq, dev);
pci_disable_msi(pdev);
return err;
return 0;
}
static int mei_pci_resume(struct device *device)