Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 41224
b: refs/heads/master
c: bae94d0
h: refs/heads/master
v: v3
  • Loading branch information
Inaky Perez-Gonzalez authored and Greg Kroah-Hartman committed Dec 1, 2006
1 parent 996203d commit 174eff1
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 23 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 039d09a845209122c5193e650ab2d8b3c849ca7c
refs/heads/master: bae94d02371c402408a4edfb95e71e88dbd3e973
4 changes: 2 additions & 2 deletions trunk/drivers/pci/pci-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ static int pci_default_resume(struct pci_dev *pci_dev)
/* restore the PCI config space */
pci_restore_state(pci_dev);
/* if the device was enabled before suspend, reenable */
if (pci_dev->is_enabled)
retval = pci_enable_device(pci_dev);
if (atomic_read(&pci_dev->enable_cnt))
retval = __pci_enable_device(pci_dev);
/* if the device was busmaster before the suspend, make it busmaster again */
if (pci_dev->is_busmaster)
pci_set_master(pci_dev);
Expand Down
33 changes: 21 additions & 12 deletions trunk/drivers/pci/pci-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ pci_config_attr(subsystem_vendor, "0x%04x\n");
pci_config_attr(subsystem_device, "0x%04x\n");
pci_config_attr(class, "0x%06x\n");
pci_config_attr(irq, "%u\n");
pci_config_attr(is_enabled, "%u\n");

static ssize_t broken_parity_status_show(struct device *dev,
struct device_attribute *attr,
Expand Down Expand Up @@ -112,26 +111,36 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
(u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
(u8)(pci_dev->class));
}
static ssize_t
is_enabled_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)

static ssize_t is_enabled_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
ssize_t result = -EINVAL;
struct pci_dev *pdev = to_pci_dev(dev);
int retval = 0;

/* this can crash the machine when done on the "wrong" device */
if (!capable(CAP_SYS_ADMIN))
return count;

if (*buf == '0')
pci_disable_device(pdev);
if (*buf == '0') {
if (atomic_read(&pdev->enable_cnt) != 0)
pci_disable_device(pdev);
else
result = -EIO;
} else if (*buf == '1')
result = pci_enable_device(pdev);

return result < 0 ? result : count;
}

if (*buf == '1')
retval = pci_enable_device(pdev);
static ssize_t is_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;

if (retval)
return retval;
return count;
pdev = to_pci_dev (dev);
return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt));
}

static ssize_t
Expand Down
40 changes: 33 additions & 7 deletions trunk/drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,29 +612,50 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
}

/**
* pci_enable_device - Initialize device before it's used by a driver.
* __pci_enable_device - Initialize device before it's used by a driver.
* @dev: PCI device to be initialized
*
* Initialize device before it's used by a driver. Ask low-level code
* to enable I/O and memory. Wake up the device if it was suspended.
* Beware, this function can fail.
*
* Note this function is a backend and is not supposed to be called by
* normal code, use pci_enable_device() instead.
*/
int
pci_enable_device(struct pci_dev *dev)
__pci_enable_device(struct pci_dev *dev)
{
int err;

if (dev->is_enabled)
return 0;

err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
if (err)
return err;
pci_fixup_device(pci_fixup_enable, dev);
dev->is_enabled = 1;
return 0;
}

/**
* pci_enable_device - Initialize device before it's used by a driver.
* @dev: PCI device to be initialized
*
* Initialize device before it's used by a driver. Ask low-level code
* to enable I/O and memory. Wake up the device if it was suspended.
* Beware, this function can fail.
*
* Note we don't actually enable the device many times if we call
* this function repeatedly (we just increment the count).
*/
int pci_enable_device(struct pci_dev *dev)
{
int result;
if (atomic_add_return(1, &dev->enable_cnt) > 1)
return 0; /* already enabled */
result = __pci_enable_device(dev);
if (result < 0)
atomic_dec(&dev->enable_cnt);
return result;
}

/**
* pcibios_disable_device - disable arch specific PCI resources for device dev
* @dev: the PCI device to disable
Expand All @@ -651,12 +672,18 @@ void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {}
*
* Signal to the system that the PCI device is not in use by the system
* anymore. This only involves disabling PCI bus-mastering, if active.
*
* Note we don't actually disable the device until all callers of
* pci_device_enable() have called pci_device_disable().
*/
void
pci_disable_device(struct pci_dev *dev)
{
u16 pci_command;

if (atomic_sub_return(1, &dev->enable_cnt) != 0)
return;

if (dev->msi_enabled)
disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
PCI_CAP_ID_MSI);
Expand All @@ -672,7 +699,6 @@ pci_disable_device(struct pci_dev *dev)
dev->is_busmaster = 0;

pcibios_disable_device(dev);
dev->is_enabled = 0;
}

/**
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/pci/pci.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* Functions internal to the PCI core code */

extern int __must_check __pci_enable_device(struct pci_dev *);
extern int pci_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size);
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
Expand Down
3 changes: 2 additions & 1 deletion trunk/include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include <linux/list.h>
#include <linux/compiler.h>
#include <linux/errno.h>
#include <asm/atomic.h>
#include <linux/device.h>

/* File state for mmap()s on /proc/bus/pci/X/Y */
Expand Down Expand Up @@ -159,14 +160,14 @@ struct pci_dev {
unsigned int transparent:1; /* Transparent PCI bridge */
unsigned int multifunction:1;/* Part of multi-function device */
/* keep track of device state */
unsigned int is_enabled:1; /* pci_enable_device has been called */
unsigned int is_busmaster:1; /* device is busmaster */
unsigned int no_msi:1; /* device may not use msi */
unsigned int no_d1d2:1; /* only allow d0 or d3 */
unsigned int block_ucfg_access:1; /* userspace config space access is blocked */
unsigned int broken_parity_status:1; /* Device generates false positive parity */
unsigned int msi_enabled:1;
unsigned int msix_enabled:1;
atomic_t enable_cnt; /* pci_enable_device has been called */

u32 saved_config_space[16]; /* config space saved at suspend time */
struct hlist_head saved_cap_space;
Expand Down

0 comments on commit 174eff1

Please sign in to comment.