root/drivers/misc/mei/pci-txe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mei_txe_set_pm_domain
  2. mei_txe_unset_pm_domain
  3. mei_txe_probe
  4. mei_txe_shutdown
  5. mei_txe_remove
  6. mei_txe_pci_suspend
  7. mei_txe_pci_resume
  8. mei_txe_pm_runtime_idle
  9. mei_txe_pm_runtime_suspend
  10. mei_txe_pm_runtime_resume
  11. mei_txe_set_pm_domain
  12. mei_txe_unset_pm_domain

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2013-2017, Intel Corporation. All rights reserved.
   4  * Intel Management Engine Interface (Intel MEI) Linux driver
   5  */
   6 
   7 #include <linux/module.h>
   8 #include <linux/kernel.h>
   9 #include <linux/device.h>
  10 #include <linux/fs.h>
  11 #include <linux/errno.h>
  12 #include <linux/types.h>
  13 #include <linux/pci.h>
  14 #include <linux/init.h>
  15 #include <linux/sched.h>
  16 #include <linux/uuid.h>
  17 #include <linux/jiffies.h>
  18 #include <linux/interrupt.h>
  19 #include <linux/workqueue.h>
  20 #include <linux/pm_domain.h>
  21 #include <linux/pm_runtime.h>
  22 
  23 #include <linux/mei.h>
  24 
  25 
  26 #include "mei_dev.h"
  27 #include "hw-txe.h"
  28 
  29 static const struct pci_device_id mei_txe_pci_tbl[] = {
  30         {PCI_VDEVICE(INTEL, 0x0F18)}, /* Baytrail */
  31         {PCI_VDEVICE(INTEL, 0x2298)}, /* Cherrytrail */
  32 
  33         {0, }
  34 };
  35 MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl);
  36 
  37 #ifdef CONFIG_PM
  38 static inline void mei_txe_set_pm_domain(struct mei_device *dev);
  39 static inline void mei_txe_unset_pm_domain(struct mei_device *dev);
  40 #else
  41 static inline void mei_txe_set_pm_domain(struct mei_device *dev) {}
  42 static inline void mei_txe_unset_pm_domain(struct mei_device *dev) {}
  43 #endif /* CONFIG_PM */
  44 
  45 /**
  46  * mei_txe_probe - Device Initialization Routine
  47  *
  48  * @pdev: PCI device structure
  49  * @ent: entry in mei_txe_pci_tbl
  50  *
  51  * Return: 0 on success, <0 on failure.
  52  */
  53 static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  54 {
  55         struct mei_device *dev;
  56         struct mei_txe_hw *hw;
  57         const int mask = BIT(SEC_BAR) | BIT(BRIDGE_BAR);
  58         int err;
  59 
  60         /* enable pci dev */
  61         err = pcim_enable_device(pdev);
  62         if (err) {
  63                 dev_err(&pdev->dev, "failed to enable pci device.\n");
  64                 goto end;
  65         }
  66         /* set PCI host mastering  */
  67         pci_set_master(pdev);
  68         /* pci request regions and mapping IO device memory for mei driver */
  69         err = pcim_iomap_regions(pdev, mask, KBUILD_MODNAME);
  70         if (err) {
  71                 dev_err(&pdev->dev, "failed to get pci regions.\n");
  72                 goto end;
  73         }
  74 
  75         err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
  76         if (err) {
  77                 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
  78                 if (err) {
  79                         dev_err(&pdev->dev, "No suitable DMA available.\n");
  80                         goto end;
  81                 }
  82         }
  83 
  84         /* allocates and initializes the mei dev structure */
  85         dev = mei_txe_dev_init(pdev);
  86         if (!dev) {
  87                 err = -ENOMEM;
  88                 goto end;
  89         }
  90         hw = to_txe_hw(dev);
  91         hw->mem_addr = pcim_iomap_table(pdev);
  92 
  93         pci_enable_msi(pdev);
  94 
  95         /* clear spurious interrupts */
  96         mei_clear_interrupts(dev);
  97 
  98         /* request and enable interrupt  */
  99         if (pci_dev_msi_enabled(pdev))
 100                 err = request_threaded_irq(pdev->irq,
 101                         NULL,
 102                         mei_txe_irq_thread_handler,
 103                         IRQF_ONESHOT, KBUILD_MODNAME, dev);
 104         else
 105                 err = request_threaded_irq(pdev->irq,
 106                         mei_txe_irq_quick_handler,
 107                         mei_txe_irq_thread_handler,
 108                         IRQF_SHARED, KBUILD_MODNAME, dev);
 109         if (err) {
 110                 dev_err(&pdev->dev, "mei: request_threaded_irq failure. irq = %d\n",
 111                         pdev->irq);
 112                 goto end;
 113         }
 114 
 115         if (mei_start(dev)) {
 116                 dev_err(&pdev->dev, "init hw failure.\n");
 117                 err = -ENODEV;
 118                 goto release_irq;
 119         }
 120 
 121         pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT);
 122         pm_runtime_use_autosuspend(&pdev->dev);
 123 
 124         err = mei_register(dev, &pdev->dev);
 125         if (err)
 126                 goto stop;
 127 
 128         pci_set_drvdata(pdev, dev);
 129 
 130         /*
 131          * MEI requires to resume from runtime suspend mode
 132          * in order to perform link reset flow upon system suspend.
 133          */
 134         dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NEVER_SKIP);
 135 
 136         /*
 137          * TXE maps runtime suspend/resume to own power gating states,
 138          * hence we need to go around native PCI runtime service which
 139          * eventually brings the device into D3cold/hot state.
 140          * But the TXE device cannot wake up from D3 unlike from own
 141          * power gating. To get around PCI device native runtime pm,
 142          * TXE uses runtime pm domain handlers which take precedence.
 143          */
 144         mei_txe_set_pm_domain(dev);
 145 
 146         pm_runtime_put_noidle(&pdev->dev);
 147 
 148         return 0;
 149 
 150 stop:
 151         mei_stop(dev);
 152 release_irq:
 153         mei_cancel_work(dev);
 154         mei_disable_interrupts(dev);
 155         free_irq(pdev->irq, dev);
 156 end:
 157         dev_err(&pdev->dev, "initialization failed.\n");
 158         return err;
 159 }
 160 
 161 /**
 162  * mei_txe_remove - Device Shutdown Routine
 163  *
 164  * @pdev: PCI device structure
 165  *
 166  *  mei_txe_shutdown is called from the reboot notifier
 167  *  it's a simplified version of remove so we go down
 168  *  faster.
 169  */
 170 static void mei_txe_shutdown(struct pci_dev *pdev)
 171 {
 172         struct mei_device *dev;
 173 
 174         dev = pci_get_drvdata(pdev);
 175         if (!dev)
 176                 return;
 177 
 178         dev_dbg(&pdev->dev, "shutdown\n");
 179         mei_stop(dev);
 180 
 181         mei_txe_unset_pm_domain(dev);
 182 
 183         mei_disable_interrupts(dev);
 184         free_irq(pdev->irq, dev);
 185 }
 186 
 187 /**
 188  * mei_txe_remove - Device Removal Routine
 189  *
 190  * @pdev: PCI device structure
 191  *
 192  * mei_remove is called by the PCI subsystem to alert the driver
 193  * that it should release a PCI device.
 194  */
 195 static void mei_txe_remove(struct pci_dev *pdev)
 196 {
 197         struct mei_device *dev;
 198 
 199         dev = pci_get_drvdata(pdev);
 200         if (!dev) {
 201                 dev_err(&pdev->dev, "mei: dev == NULL\n");
 202                 return;
 203         }
 204 
 205         pm_runtime_get_noresume(&pdev->dev);
 206 
 207         mei_stop(dev);
 208 
 209         mei_txe_unset_pm_domain(dev);
 210 
 211         mei_disable_interrupts(dev);
 212         free_irq(pdev->irq, dev);
 213 
 214         mei_deregister(dev);
 215 }
 216 
 217 
 218 #ifdef CONFIG_PM_SLEEP
 219 static int mei_txe_pci_suspend(struct device *device)
 220 {
 221         struct pci_dev *pdev = to_pci_dev(device);
 222         struct mei_device *dev = pci_get_drvdata(pdev);
 223 
 224         if (!dev)
 225                 return -ENODEV;
 226 
 227         dev_dbg(&pdev->dev, "suspend\n");
 228 
 229         mei_stop(dev);
 230 
 231         mei_disable_interrupts(dev);
 232 
 233         free_irq(pdev->irq, dev);
 234         pci_disable_msi(pdev);
 235 
 236         return 0;
 237 }
 238 
 239 static int mei_txe_pci_resume(struct device *device)
 240 {
 241         struct pci_dev *pdev = to_pci_dev(device);
 242         struct mei_device *dev;
 243         int err;
 244 
 245         dev = pci_get_drvdata(pdev);
 246         if (!dev)
 247                 return -ENODEV;
 248 
 249         pci_enable_msi(pdev);
 250 
 251         mei_clear_interrupts(dev);
 252 
 253         /* request and enable interrupt */
 254         if (pci_dev_msi_enabled(pdev))
 255                 err = request_threaded_irq(pdev->irq,
 256                         NULL,
 257                         mei_txe_irq_thread_handler,
 258                         IRQF_ONESHOT, KBUILD_MODNAME, dev);
 259         else
 260                 err = request_threaded_irq(pdev->irq,
 261                         mei_txe_irq_quick_handler,
 262                         mei_txe_irq_thread_handler,
 263                         IRQF_SHARED, KBUILD_MODNAME, dev);
 264         if (err) {
 265                 dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
 266                                 pdev->irq);
 267                 return err;
 268         }
 269 
 270         err = mei_restart(dev);
 271 
 272         return err;
 273 }
 274 #endif /* CONFIG_PM_SLEEP */
 275 
 276 #ifdef CONFIG_PM
 277 static int mei_txe_pm_runtime_idle(struct device *device)
 278 {
 279         struct mei_device *dev;
 280 
 281         dev_dbg(device, "rpm: txe: runtime_idle\n");
 282 
 283         dev = dev_get_drvdata(device);
 284         if (!dev)
 285                 return -ENODEV;
 286         if (mei_write_is_idle(dev))
 287                 pm_runtime_autosuspend(device);
 288 
 289         return -EBUSY;
 290 }
 291 static int mei_txe_pm_runtime_suspend(struct device *device)
 292 {
 293         struct mei_device *dev;
 294         int ret;
 295 
 296         dev_dbg(device, "rpm: txe: runtime suspend\n");
 297 
 298         dev = dev_get_drvdata(device);
 299         if (!dev)
 300                 return -ENODEV;
 301 
 302         mutex_lock(&dev->device_lock);
 303 
 304         if (mei_write_is_idle(dev))
 305                 ret = mei_txe_aliveness_set_sync(dev, 0);
 306         else
 307                 ret = -EAGAIN;
 308 
 309         /* keep irq on we are staying in D0 */
 310 
 311         dev_dbg(device, "rpm: txe: runtime suspend ret=%d\n", ret);
 312 
 313         mutex_unlock(&dev->device_lock);
 314 
 315         if (ret && ret != -EAGAIN)
 316                 schedule_work(&dev->reset_work);
 317 
 318         return ret;
 319 }
 320 
 321 static int mei_txe_pm_runtime_resume(struct device *device)
 322 {
 323         struct mei_device *dev;
 324         int ret;
 325 
 326         dev_dbg(device, "rpm: txe: runtime resume\n");
 327 
 328         dev = dev_get_drvdata(device);
 329         if (!dev)
 330                 return -ENODEV;
 331 
 332         mutex_lock(&dev->device_lock);
 333 
 334         mei_enable_interrupts(dev);
 335 
 336         ret = mei_txe_aliveness_set_sync(dev, 1);
 337 
 338         mutex_unlock(&dev->device_lock);
 339 
 340         dev_dbg(device, "rpm: txe: runtime resume ret = %d\n", ret);
 341 
 342         if (ret)
 343                 schedule_work(&dev->reset_work);
 344 
 345         return ret;
 346 }
 347 
 348 /**
 349  * mei_txe_set_pm_domain - fill and set pm domain structure for device
 350  *
 351  * @dev: mei_device
 352  */
 353 static inline void mei_txe_set_pm_domain(struct mei_device *dev)
 354 {
 355         struct pci_dev *pdev  = to_pci_dev(dev->dev);
 356 
 357         if (pdev->dev.bus && pdev->dev.bus->pm) {
 358                 dev->pg_domain.ops = *pdev->dev.bus->pm;
 359 
 360                 dev->pg_domain.ops.runtime_suspend = mei_txe_pm_runtime_suspend;
 361                 dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume;
 362                 dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle;
 363 
 364                 dev_pm_domain_set(&pdev->dev, &dev->pg_domain);
 365         }
 366 }
 367 
 368 /**
 369  * mei_txe_unset_pm_domain - clean pm domain structure for device
 370  *
 371  * @dev: mei_device
 372  */
 373 static inline void mei_txe_unset_pm_domain(struct mei_device *dev)
 374 {
 375         /* stop using pm callbacks if any */
 376         dev_pm_domain_set(dev->dev, NULL);
 377 }
 378 
 379 static const struct dev_pm_ops mei_txe_pm_ops = {
 380         SET_SYSTEM_SLEEP_PM_OPS(mei_txe_pci_suspend,
 381                                 mei_txe_pci_resume)
 382         SET_RUNTIME_PM_OPS(
 383                 mei_txe_pm_runtime_suspend,
 384                 mei_txe_pm_runtime_resume,
 385                 mei_txe_pm_runtime_idle)
 386 };
 387 
 388 #define MEI_TXE_PM_OPS  (&mei_txe_pm_ops)
 389 #else
 390 #define MEI_TXE_PM_OPS  NULL
 391 #endif /* CONFIG_PM */
 392 
 393 /*
 394  *  PCI driver structure
 395  */
 396 static struct pci_driver mei_txe_driver = {
 397         .name = KBUILD_MODNAME,
 398         .id_table = mei_txe_pci_tbl,
 399         .probe = mei_txe_probe,
 400         .remove = mei_txe_remove,
 401         .shutdown = mei_txe_shutdown,
 402         .driver.pm = MEI_TXE_PM_OPS,
 403 };
 404 
 405 module_pci_driver(mei_txe_driver);
 406 
 407 MODULE_AUTHOR("Intel Corporation");
 408 MODULE_DESCRIPTION("Intel(R) Trusted Execution Environment Interface");
 409 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */