Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 10665
b: refs/heads/master
c: e04b0ea
h: refs/heads/master
i:
  10663: a7a5a97
v: v3
  • Loading branch information
Brian King authored and Greg Kroah-Hartman committed Oct 28, 2005
1 parent 0a99e7e commit 859f8f6
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 32 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: 2cea752f683af1be58ee8f25717c0a8118e0ac5b
refs/heads/master: e04b0ea2e0f9c1bb0d874db4493fc7f7a623116b
89 changes: 89 additions & 0 deletions trunk/drivers/pci/access.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,92 @@ EXPORT_SYMBOL(pci_bus_read_config_dword);
EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);

static u32 pci_user_cached_config(struct pci_dev *dev, int pos)
{
u32 data;

data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])];
data >>= (pos % sizeof(dev->saved_config_space[0])) * 8;
return data;
}

#define PCI_USER_READ_CONFIG(size,type) \
int pci_user_read_config_##size \
(struct pci_dev *dev, int pos, type *val) \
{ \
unsigned long flags; \
int ret = 0; \
u32 data = -1; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
spin_lock_irqsave(&pci_lock, flags); \
if (likely(!dev->block_ucfg_access)) \
ret = dev->bus->ops->read(dev->bus, dev->devfn, \
pos, sizeof(type), &data); \
else if (pos < sizeof(dev->saved_config_space)) \
data = pci_user_cached_config(dev, pos); \
spin_unlock_irqrestore(&pci_lock, flags); \
*val = (type)data; \
return ret; \
}

#define PCI_USER_WRITE_CONFIG(size,type) \
int pci_user_write_config_##size \
(struct pci_dev *dev, int pos, type val) \
{ \
unsigned long flags; \
int ret = -EIO; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
spin_lock_irqsave(&pci_lock, flags); \
if (likely(!dev->block_ucfg_access)) \
ret = dev->bus->ops->write(dev->bus, dev->devfn, \
pos, sizeof(type), val); \
spin_unlock_irqrestore(&pci_lock, flags); \
return ret; \
}

PCI_USER_READ_CONFIG(byte, u8)
PCI_USER_READ_CONFIG(word, u16)
PCI_USER_READ_CONFIG(dword, u32)
PCI_USER_WRITE_CONFIG(byte, u8)
PCI_USER_WRITE_CONFIG(word, u16)
PCI_USER_WRITE_CONFIG(dword, u32)

/**
* pci_block_user_cfg_access - Block userspace PCI config reads/writes
* @dev: pci device struct
*
* This function blocks any userspace PCI config accesses from occurring.
* When blocked, any writes will be bit bucketed and reads will return the
* data saved using pci_save_state for the first 64 bytes of config
* space and return 0xff for all other config reads.
**/
void pci_block_user_cfg_access(struct pci_dev *dev)
{
unsigned long flags;

pci_save_state(dev);

/* spinlock to synchronize with anyone reading config space now */
spin_lock_irqsave(&pci_lock, flags);
dev->block_ucfg_access = 1;
spin_unlock_irqrestore(&pci_lock, flags);
}
EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);

/**
* pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
* @dev: pci device struct
*
* This function allows userspace PCI config accesses to resume.
**/
void pci_unblock_user_cfg_access(struct pci_dev *dev)
{
unsigned long flags;

/* spinlock to synchronize with anyone reading saved config space */
spin_lock_irqsave(&pci_lock, flags);
dev->block_ucfg_access = 0;
spin_unlock_irqrestore(&pci_lock, flags);
}
EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
20 changes: 10 additions & 10 deletions trunk/drivers/pci/pci-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,15 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)

if ((off & 1) && size) {
u8 val;
pci_read_config_byte(dev, off, &val);
pci_user_read_config_byte(dev, off, &val);
data[off - init_off] = val;
off++;
size--;
}

if ((off & 3) && size > 2) {
u16 val;
pci_read_config_word(dev, off, &val);
pci_user_read_config_word(dev, off, &val);
data[off - init_off] = val & 0xff;
data[off - init_off + 1] = (val >> 8) & 0xff;
off += 2;
Expand All @@ -147,7 +147,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)

while (size > 3) {
u32 val;
pci_read_config_dword(dev, off, &val);
pci_user_read_config_dword(dev, off, &val);
data[off - init_off] = val & 0xff;
data[off - init_off + 1] = (val >> 8) & 0xff;
data[off - init_off + 2] = (val >> 16) & 0xff;
Expand All @@ -158,7 +158,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)

if (size >= 2) {
u16 val;
pci_read_config_word(dev, off, &val);
pci_user_read_config_word(dev, off, &val);
data[off - init_off] = val & 0xff;
data[off - init_off + 1] = (val >> 8) & 0xff;
off += 2;
Expand All @@ -167,7 +167,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)

if (size > 0) {
u8 val;
pci_read_config_byte(dev, off, &val);
pci_user_read_config_byte(dev, off, &val);
data[off - init_off] = val;
off++;
--size;
Expand All @@ -192,15 +192,15 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
}

if ((off & 1) && size) {
pci_write_config_byte(dev, off, data[off - init_off]);
pci_user_write_config_byte(dev, off, data[off - init_off]);
off++;
size--;
}

if ((off & 3) && size > 2) {
u16 val = data[off - init_off];
val |= (u16) data[off - init_off + 1] << 8;
pci_write_config_word(dev, off, val);
pci_user_write_config_word(dev, off, val);
off += 2;
size -= 2;
}
Expand All @@ -210,21 +210,21 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
val |= (u32) data[off - init_off + 1] << 8;
val |= (u32) data[off - init_off + 2] << 16;
val |= (u32) data[off - init_off + 3] << 24;
pci_write_config_dword(dev, off, val);
pci_user_write_config_dword(dev, off, val);
off += 4;
size -= 4;
}

if (size >= 2) {
u16 val = data[off - init_off];
val |= (u16) data[off - init_off + 1] << 8;
pci_write_config_word(dev, off, val);
pci_user_write_config_word(dev, off, val);
off += 2;
size -= 2;
}

if (size) {
pci_write_config_byte(dev, off, data[off - init_off]);
pci_user_write_config_byte(dev, off, data[off - init_off]);
off++;
--size;
}
Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);

extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val);
extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);

/* PCI /proc functions */
#ifdef CONFIG_PROC_FS
extern int pci_proc_attach_device(struct pci_dev *dev);
Expand Down
28 changes: 14 additions & 14 deletions trunk/drivers/pci/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp

if ((pos & 1) && cnt) {
unsigned char val;
pci_read_config_byte(dev, pos, &val);
pci_user_read_config_byte(dev, pos, &val);
__put_user(val, buf);
buf++;
pos++;
Expand All @@ -89,7 +89,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp

if ((pos & 3) && cnt > 2) {
unsigned short val;
pci_read_config_word(dev, pos, &val);
pci_user_read_config_word(dev, pos, &val);
__put_user(cpu_to_le16(val), (unsigned short __user *) buf);
buf += 2;
pos += 2;
Expand All @@ -98,7 +98,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp

while (cnt >= 4) {
unsigned int val;
pci_read_config_dword(dev, pos, &val);
pci_user_read_config_dword(dev, pos, &val);
__put_user(cpu_to_le32(val), (unsigned int __user *) buf);
buf += 4;
pos += 4;
Expand All @@ -107,7 +107,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp

if (cnt >= 2) {
unsigned short val;
pci_read_config_word(dev, pos, &val);
pci_user_read_config_word(dev, pos, &val);
__put_user(cpu_to_le16(val), (unsigned short __user *) buf);
buf += 2;
pos += 2;
Expand All @@ -116,7 +116,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp

if (cnt) {
unsigned char val;
pci_read_config_byte(dev, pos, &val);
pci_user_read_config_byte(dev, pos, &val);
__put_user(val, buf);
buf++;
pos++;
Expand Down Expand Up @@ -151,7 +151,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if ((pos & 1) && cnt) {
unsigned char val;
__get_user(val, buf);
pci_write_config_byte(dev, pos, val);
pci_user_write_config_byte(dev, pos, val);
buf++;
pos++;
cnt--;
Expand All @@ -160,7 +160,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if ((pos & 3) && cnt > 2) {
unsigned short val;
__get_user(val, (unsigned short __user *) buf);
pci_write_config_word(dev, pos, le16_to_cpu(val));
pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
cnt -= 2;
Expand All @@ -169,7 +169,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
while (cnt >= 4) {
unsigned int val;
__get_user(val, (unsigned int __user *) buf);
pci_write_config_dword(dev, pos, le32_to_cpu(val));
pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
buf += 4;
pos += 4;
cnt -= 4;
Expand All @@ -178,7 +178,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if (cnt >= 2) {
unsigned short val;
__get_user(val, (unsigned short __user *) buf);
pci_write_config_word(dev, pos, le16_to_cpu(val));
pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
cnt -= 2;
Expand All @@ -187,7 +187,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if (cnt) {
unsigned char val;
__get_user(val, buf);
pci_write_config_byte(dev, pos, val);
pci_user_write_config_byte(dev, pos, val);
buf++;
pos++;
cnt--;
Expand Down Expand Up @@ -484,10 +484,10 @@ static int show_dev_config(struct seq_file *m, void *v)

drv = pci_dev_driver(dev);

pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
pci_user_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
pci_user_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
pci_user_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
pci_user_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
seq_printf(m, " Bus %2d, device %3d, function %2d:\n",
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
seq_printf(m, " Class %04x", class_rev >> 16);
Expand Down
14 changes: 7 additions & 7 deletions trunk/drivers/pci/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>

#include "pci.h"

asmlinkage long
sys_pciconfig_read(unsigned long bus, unsigned long dfn,
Expand All @@ -38,13 +38,13 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
lock_kernel();
switch (len) {
case 1:
cfg_ret = pci_read_config_byte(dev, off, &byte);
cfg_ret = pci_user_read_config_byte(dev, off, &byte);
break;
case 2:
cfg_ret = pci_read_config_word(dev, off, &word);
cfg_ret = pci_user_read_config_word(dev, off, &word);
break;
case 4:
cfg_ret = pci_read_config_dword(dev, off, &dword);
cfg_ret = pci_user_read_config_dword(dev, off, &dword);
break;
default:
err = -EINVAL;
Expand Down Expand Up @@ -112,7 +112,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = get_user(byte, (u8 __user *)buf);
if (err)
break;
err = pci_write_config_byte(dev, off, byte);
err = pci_user_write_config_byte(dev, off, byte);
if (err != PCIBIOS_SUCCESSFUL)
err = -EIO;
break;
Expand All @@ -121,7 +121,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = get_user(word, (u16 __user *)buf);
if (err)
break;
err = pci_write_config_word(dev, off, word);
err = pci_user_write_config_word(dev, off, word);
if (err != PCIBIOS_SUCCESSFUL)
err = -EIO;
break;
Expand All @@ -130,7 +130,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = get_user(dword, (u32 __user *)buf);
if (err)
break;
err = pci_write_config_dword(dev, off, dword);
err = pci_user_write_config_dword(dev, off, dword);
if (err != PCIBIOS_SUCCESSFUL)
err = -EIO;
break;
Expand Down
7 changes: 7 additions & 0 deletions trunk/include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ struct pci_dev {
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 block_ucfg_access:1; /* userspace config space access is blocked */

u32 saved_config_space[16]; /* config space saved at suspend time */
struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
Expand Down Expand Up @@ -490,6 +491,9 @@ extern void pci_disable_msix(struct pci_dev *dev);
extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
#endif

extern void pci_block_user_cfg_access(struct pci_dev *dev);
extern void pci_unblock_user_cfg_access(struct pci_dev *dev);

/*
* PCI domain support. Sometimes called PCI segment (eg by ACPI),
* a PCI domain is defined to be a set of PCI busses which share
Expand Down Expand Up @@ -560,6 +564,9 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int en

#define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)

static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
static inline void pci_unblock_user_cfg_access(struct pci_dev *dev) { }

#endif /* CONFIG_PCI */

/* Include architecture-dependent settings and functions */
Expand Down

0 comments on commit 859f8f6

Please sign in to comment.