linux/drivers/ssb/pcihost_wrapper.c
<<
>>
Prefs
   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/pci.h>
  15#include <linux/export.h>
  16#include <linux/slab.h>
  17#include <linux/ssb/ssb.h>
  18
  19
  20#ifdef CONFIG_PM
  21static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
  22{
  23        struct ssb_bus *ssb = pci_get_drvdata(dev);
  24        int err;
  25
  26        err = ssb_bus_suspend(ssb);
  27        if (err)
  28                return err;
  29        pci_save_state(dev);
  30        pci_disable_device(dev);
  31        pci_set_power_state(dev, pci_choose_state(dev, state));
  32
  33        return 0;
  34}
  35
  36static int ssb_pcihost_resume(struct pci_dev *dev)
  37{
  38        struct ssb_bus *ssb = pci_get_drvdata(dev);
  39        int err;
  40
  41        pci_set_power_state(dev, 0);
  42        err = pci_enable_device(dev);
  43        if (err)
  44                return err;
  45        pci_restore_state(dev);
  46        err = ssb_bus_resume(ssb);
  47        if (err)
  48                return err;
  49
  50        return 0;
  51}
  52#else /* CONFIG_PM */
  53# define ssb_pcihost_suspend    NULL
  54# define ssb_pcihost_resume     NULL
  55#endif /* CONFIG_PM */
  56
  57static int ssb_pcihost_probe(struct pci_dev *dev,
  58                             const struct pci_device_id *id)
  59{
  60        struct ssb_bus *ssb;
  61        int err = -ENOMEM;
  62        const char *name;
  63        u32 val;
  64
  65        ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
  66        if (!ssb)
  67                goto out;
  68        err = pci_enable_device(dev);
  69        if (err)
  70                goto err_kfree_ssb;
  71        name = dev_name(&dev->dev);
  72        if (dev->driver && dev->driver->name)
  73                name = dev->driver->name;
  74        err = pci_request_regions(dev, name);
  75        if (err)
  76                goto err_pci_disable;
  77        pci_set_master(dev);
  78
  79        /* Disable the RETRY_TIMEOUT register (0x41) to keep
  80         * PCI Tx retries from interfering with C3 CPU state */
  81        pci_read_config_dword(dev, 0x40, &val);
  82        if ((val & 0x0000ff00) != 0)
  83                pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
  84
  85        err = ssb_bus_pcibus_register(ssb, dev);
  86        if (err)
  87                goto err_pci_release_regions;
  88
  89        pci_set_drvdata(dev, ssb);
  90
  91out:
  92        return err;
  93
  94err_pci_release_regions:
  95        pci_release_regions(dev);
  96err_pci_disable:
  97        pci_disable_device(dev);
  98err_kfree_ssb:
  99        kfree(ssb);
 100        return err;
 101}
 102
 103static void ssb_pcihost_remove(struct pci_dev *dev)
 104{
 105        struct ssb_bus *ssb = pci_get_drvdata(dev);
 106
 107        ssb_bus_unregister(ssb);
 108        pci_release_regions(dev);
 109        pci_disable_device(dev);
 110        kfree(ssb);
 111        pci_set_drvdata(dev, NULL);
 112}
 113
 114int ssb_pcihost_register(struct pci_driver *driver)
 115{
 116        driver->probe = ssb_pcihost_probe;
 117        driver->remove = ssb_pcihost_remove;
 118        driver->suspend = ssb_pcihost_suspend;
 119        driver->resume = ssb_pcihost_resume;
 120
 121        return pci_register_driver(driver);
 122}
 123EXPORT_SYMBOL(ssb_pcihost_register);
 124
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.