cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pcihost_wrapper.c (2876B)


      1/*
      2 * Sonics Silicon Backplane
      3 * PCI Hostdevice wrapper
      4 *
      5 * Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
      6 * Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
      7 * Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
      8 * Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
      9 * Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
     10 *
     11 * Licensed under the GNU/GPL. See COPYING for details.
     12 */
     13
     14#include <linux/pm.h>
     15#include <linux/pci.h>
     16#include <linux/export.h>
     17#include <linux/slab.h>
     18#include <linux/ssb/ssb.h>
     19
     20
     21#ifdef CONFIG_PM_SLEEP
     22static int ssb_pcihost_suspend(struct device *d)
     23{
     24	struct pci_dev *dev = to_pci_dev(d);
     25	struct ssb_bus *ssb = pci_get_drvdata(dev);
     26	int err;
     27
     28	err = ssb_bus_suspend(ssb);
     29	if (err)
     30		return err;
     31	pci_save_state(dev);
     32	pci_disable_device(dev);
     33
     34	/* if there is a wakeup enabled child device on ssb bus,
     35	   enable pci wakeup posibility. */
     36	device_set_wakeup_enable(d, d->power.wakeup_path);
     37
     38	pci_prepare_to_sleep(dev);
     39
     40	return 0;
     41}
     42
     43static int ssb_pcihost_resume(struct device *d)
     44{
     45	struct pci_dev *dev = to_pci_dev(d);
     46	struct ssb_bus *ssb = pci_get_drvdata(dev);
     47	int err;
     48
     49	pci_back_from_sleep(dev);
     50	err = pci_enable_device(dev);
     51	if (err)
     52		return err;
     53	pci_restore_state(dev);
     54	err = ssb_bus_resume(ssb);
     55	if (err)
     56		return err;
     57
     58	return 0;
     59}
     60
     61static const struct dev_pm_ops ssb_pcihost_pm_ops = {
     62	SET_SYSTEM_SLEEP_PM_OPS(ssb_pcihost_suspend, ssb_pcihost_resume)
     63};
     64
     65#endif /* CONFIG_PM_SLEEP */
     66
     67static int ssb_pcihost_probe(struct pci_dev *dev,
     68			     const struct pci_device_id *id)
     69{
     70	struct ssb_bus *ssb;
     71	int err = -ENOMEM;
     72	u32 val;
     73
     74	ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
     75	if (!ssb)
     76		goto out;
     77	err = pci_enable_device(dev);
     78	if (err)
     79		goto err_kfree_ssb;
     80	err = pci_request_regions(dev, dev_driver_string(&dev->dev));
     81	if (err)
     82		goto err_pci_disable;
     83	pci_set_master(dev);
     84
     85	/* Disable the RETRY_TIMEOUT register (0x41) to keep
     86	 * PCI Tx retries from interfering with C3 CPU state */
     87	pci_read_config_dword(dev, 0x40, &val);
     88	if ((val & 0x0000ff00) != 0)
     89		pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
     90
     91	err = ssb_bus_pcibus_register(ssb, dev);
     92	if (err)
     93		goto err_pci_release_regions;
     94
     95	pci_set_drvdata(dev, ssb);
     96
     97out:
     98	return err;
     99
    100err_pci_release_regions:
    101	pci_release_regions(dev);
    102err_pci_disable:
    103	pci_disable_device(dev);
    104err_kfree_ssb:
    105	kfree(ssb);
    106	return err;
    107}
    108
    109static void ssb_pcihost_remove(struct pci_dev *dev)
    110{
    111	struct ssb_bus *ssb = pci_get_drvdata(dev);
    112
    113	ssb_bus_unregister(ssb);
    114	pci_release_regions(dev);
    115	pci_disable_device(dev);
    116	kfree(ssb);
    117	pci_set_drvdata(dev, NULL);
    118}
    119
    120int ssb_pcihost_register(struct pci_driver *driver)
    121{
    122	driver->probe = ssb_pcihost_probe;
    123	driver->remove = ssb_pcihost_remove;
    124#ifdef CONFIG_PM_SLEEP
    125	driver->driver.pm = &ssb_pcihost_pm_ops;
    126#endif
    127
    128	return pci_register_driver(driver);
    129}
    130EXPORT_SYMBOL(ssb_pcihost_register);