cregit-Linux how code gets into the kernel

Release 4.11 drivers/misc/mei/pci-txe.c

Directory: drivers/misc/mei
/*
 *
 * Intel Management Engine Interface (Intel MEI) Linux driver
 * Copyright (c) 2013-2014, 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.
 *
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/uuid.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>

#include <linux/mei.h>


#include "mei_dev.h"
#include "hw-txe.h"


static const struct pci_device_id mei_txe_pci_tbl[] = {
	{PCI_VDEVICE(INTEL, 0x0F18)}, /* Baytrail */
	{PCI_VDEVICE(INTEL, 0x2298)}, /* Cherrytrail */

	{0, }
};
MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl);

#ifdef CONFIG_PM
static inline void mei_txe_set_pm_domain(struct mei_device *dev);
static inline void mei_txe_unset_pm_domain(struct mei_device *dev);
#else

static inline void mei_txe_set_pm_domain(struct mei_device *dev) {}

Contributors

PersonTokensPropCommitsCommitProp
Alexander Usyskin11100.00%1100.00%
Total11100.00%1100.00%


static inline void mei_txe_unset_pm_domain(struct mei_device *dev) {}

Contributors

PersonTokensPropCommitsCommitProp
Alexander Usyskin11100.00%1100.00%
Total11100.00%1100.00%

#endif /* CONFIG_PM */ /** * mei_txe_probe - Device Initialization Routine * * @pdev: PCI device structure * @ent: entry in mei_txe_pci_tbl * * Return: 0 on success, <0 on failure. */
static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct mei_device *dev; struct mei_txe_hw *hw; const int mask = BIT(SEC_BAR) | BIT(BRIDGE_BAR); int err; /* enable pci dev */ err = pcim_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 and mapping IO device memory for mei driver */ err = pcim_iomap_regions(pdev, mask, KBUILD_MODNAME); if (err) { dev_err(&pdev->dev, "failed to get pci regions.\n"); goto end; } err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); if (err) { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { dev_err(&pdev->dev, "No suitable DMA available.\n"); goto end; } } /* allocates and initializes the mei dev structure */ dev = mei_txe_dev_init(pdev); if (!dev) { err = -ENOMEM; goto end; } hw = to_txe_hw(dev); hw->mem_addr = pcim_iomap_table(pdev); pci_enable_msi(pdev); /* clear spurious interrupts */ mei_clear_interrupts(dev); /* request and enable interrupt */ if (pci_dev_msi_enabled(pdev)) err = request_threaded_irq(pdev->irq, NULL, mei_txe_irq_thread_handler, IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, mei_txe_irq_quick_handler, mei_txe_irq_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { dev_err(&pdev->dev, "mei: request_threaded_irq failure. irq = %d\n", pdev->irq); goto end; } if (mei_start(dev)) { dev_err(&pdev->dev, "init hw failure.\n"); err = -ENODEV; goto release_irq; } pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); err = mei_register(dev, &pdev->dev); if (err) goto stop; pci_set_drvdata(pdev, dev); /* * For not wake-able HW runtime pm framework * can't be used on pci device level. * Use domain runtime pm callbacks instead. */ if (!pci_dev_run_wake(pdev)) mei_txe_set_pm_domain(dev); pm_runtime_put_noidle(&pdev->dev); return 0; stop: mei_stop(dev); release_irq: mei_cancel_work(dev); mei_disable_interrupts(dev); free_irq(pdev->irq, dev); end: dev_err(&pdev->dev, "initialization failed.\n"); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Tomas Winkler36387.26%233.33%
Alexander Usyskin5312.74%466.67%
Total416100.00%6100.00%

/** * mei_txe_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_txe_remove(struct pci_dev *pdev) { struct mei_device *dev; dev = pci_get_drvdata(pdev); if (!dev) { dev_err(&pdev->dev, "mei: dev == NULL\n"); return; } pm_runtime_get_noresume(&pdev->dev); mei_stop(dev); if (!pci_dev_run_wake(pdev)) mei_txe_unset_pm_domain(dev); mei_disable_interrupts(dev); free_irq(pdev->irq, dev); mei_deregister(dev); }

Contributors

PersonTokensPropCommitsCommitProp
Tomas Winkler6575.58%250.00%
Alexander Usyskin2124.42%250.00%
Total86100.00%4100.00%

#ifdef CONFIG_PM_SLEEP
static int mei_txe_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev = pci_get_drvdata(pdev); if (!dev) return -ENODEV; dev_dbg(&pdev->dev, "suspend\n"); mei_stop(dev); mei_disable_interrupts(dev); free_irq(pdev->irq, dev); pci_disable_msi(pdev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Tomas Winkler77100.00%1100.00%
Total77100.00%1100.00%


static int mei_txe_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); mei_clear_interrupts(dev); /* request and enable interrupt */ if (pci_dev_msi_enabled(pdev)) err = request_threaded_irq(pdev->irq, NULL, mei_txe_irq_thread_handler, IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, mei_txe_irq_quick_handler, mei_txe_irq_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", pdev->irq); return err; } err = mei_restart(dev); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Tomas Winkler135100.00%1100.00%
Total135100.00%1100.00%

#endif /* CONFIG_PM_SLEEP */ #ifdef CONFIG_PM
static int mei_txe_pm_runtime_idle(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; dev_dbg(&pdev->dev, "rpm: txe: runtime_idle\n"); dev = pci_get_drvdata(pdev); if (!dev) return -ENODEV; if (mei_write_is_idle(dev)) pm_runtime_autosuspend(device); return -EBUSY; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Usyskin6392.65%266.67%
Tomas Winkler57.35%133.33%
Total68100.00%3100.00%


static int mei_txe_pm_runtime_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; int ret; dev_dbg(&pdev->dev, "rpm: txe: runtime suspend\n"); dev = pci_get_drvdata(pdev); if (!dev) return -ENODEV; mutex_lock(&dev->device_lock); if (mei_write_is_idle(dev)) ret = mei_txe_aliveness_set_sync(dev, 0); else ret = -EAGAIN; /* * If everything is okay we're about to enter PCI low * power state (D3) therefor we need to disable the * interrupts towards host. * However if device is not wakeable we do not enter * D-low state and we need to keep the interrupt kicking */ if (!ret && pci_dev_run_wake(pdev)) mei_disable_interrupts(dev); dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); mutex_unlock(&dev->device_lock); if (ret && ret != -EAGAIN) schedule_work(&dev->reset_work); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Usyskin141100.00%2100.00%
Total141100.00%2100.00%


static int mei_txe_pm_runtime_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; int ret; dev_dbg(&pdev->dev, "rpm: txe: runtime resume\n"); dev = pci_get_drvdata(pdev); if (!dev) return -ENODEV; mutex_lock(&dev->device_lock); mei_enable_interrupts(dev); ret = mei_txe_aliveness_set_sync(dev, 1); mutex_unlock(&dev->device_lock); dev_dbg(&pdev->dev, "rpm: txe: runtime resume ret = %d\n", ret); if (ret) schedule_work(&dev->reset_work); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Usyskin112100.00%2100.00%
Total112100.00%2100.00%

/** * mei_txe_set_pm_domain - fill and set pm domain structure for device * * @dev: mei_device */
static inline void mei_txe_set_pm_domain(struct mei_device *dev) { struct pci_dev *pdev = to_pci_dev(dev->dev); if (pdev->dev.bus && pdev->dev.bus->pm) { dev->pg_domain.ops = *pdev->dev.bus->pm; dev->pg_domain.ops.runtime_suspend = mei_txe_pm_runtime_suspend; dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume; dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle; dev_pm_domain_set(&pdev->dev, &dev->pg_domain); } }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Usyskin9191.00%133.33%
Tomeu Vizoso55.00%133.33%
Tomas Winkler44.00%133.33%
Total100100.00%3100.00%

/** * mei_txe_unset_pm_domain - clean pm domain structure for device * * @dev: mei_device */
static inline void mei_txe_unset_pm_domain(struct mei_device *dev) { /* stop using pm callbacks if any */ dev_pm_domain_set(dev->dev, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
Alexander Usyskin1881.82%150.00%
Tomeu Vizoso418.18%150.00%
Total22100.00%2100.00%

static const struct dev_pm_ops mei_txe_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(mei_txe_pci_suspend, mei_txe_pci_resume) SET_RUNTIME_PM_OPS( mei_txe_pm_runtime_suspend, mei_txe_pm_runtime_resume, mei_txe_pm_runtime_idle) }; #define MEI_TXE_PM_OPS (&mei_txe_pm_ops) #else #define MEI_TXE_PM_OPS NULL #endif /* CONFIG_PM */ /* * PCI driver structure */ static struct pci_driver mei_txe_driver = { .name = KBUILD_MODNAME, .id_table = mei_txe_pci_tbl, .probe = mei_txe_probe, .remove = mei_txe_remove, .shutdown = mei_txe_remove, .driver.pm = MEI_TXE_PM_OPS, }; module_pci_driver(mei_txe_driver); MODULE_AUTHOR("Intel Corporation"); MODULE_DESCRIPTION("Intel(R) Trusted Execution Environment Interface"); MODULE_LICENSE("GPL v2");

Overall Contributors

PersonTokensPropCommitsCommitProp
Tomas Winkler81257.47%738.89%
Alexander Usyskin58441.33%844.44%
Tomeu Vizoso120.85%15.56%
Rafael J. Wysocki30.21%15.56%
Geert Uytterhoeven20.14%15.56%
Total1413100.00%18100.00%
Directory: drivers/misc/mei
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.