Commit 7efe5d7c authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6

parents dbe0580d f8977d0a
......@@ -286,7 +286,9 @@ X!Edrivers/pci/search.c
-->
!Edrivers/pci/msi.c
!Edrivers/pci/bus.c
!Edrivers/pci/hotplug.c
<!-- FIXME: Removed for now since no structured comments in source
X!Edrivers/pci/hotplug.c
-->
!Edrivers/pci/probe.c
!Edrivers/pci/rom.c
</sect1>
......
......@@ -2,6 +2,8 @@
* Exceptions for specific devices. Usually work-arounds for fatal design flaws.
*/
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/init.h>
#include "pci.h"
......@@ -384,3 +386,60 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
/*
* Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
*
* We pretend to bring them out of full D3 state, and restore the proper
* IRQ, PCI cache line size, and BARs, otherwise the device won't function
* properly. In some cases, the device will generate an interrupt on
* the wrong IRQ line, causing any devices sharing the the line it's
* *supposed* to use to be disabled by the kernel's IRQ debug code.
*/
static u16 toshiba_line_size;
static struct dmi_system_id __devinit toshiba_ohci1394_dmi_table[] = {
{
.ident = "Toshiba PS5 based laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"),
},
},
{
.ident = "Toshiba PSM4 based laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"),
},
},
{ }
};
static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
{
if (!dmi_check_system(toshiba_ohci1394_dmi_table))
return; /* only applies to certain Toshibas (so far) */
dev->current_state = PCI_D3cold;
pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032,
pci_pre_fixup_toshiba_ohci1394);
static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
{
if (!dmi_check_system(toshiba_ohci1394_dmi_table))
return; /* only applies to certain Toshibas (so far) */
/* Restore config space on Toshiba laptops */
mdelay(10);
pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size);
pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
pci_resource_start(dev, 0));
pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
pci_resource_start(dev, 1));
}
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
pci_post_fixup_toshiba_ohci1394);
......@@ -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);
......@@ -58,6 +58,9 @@ static LIST_HEAD(bridge_list);
static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
static void handle_hotplug_event_func (acpi_handle, u32, void *);
static void acpiphp_sanitize_bus(struct pci_bus *bus);
static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
/*
* initialization & terminatation routines
......@@ -796,8 +799,13 @@ static int enable_device(struct acpiphp_slot *slot)
}
}
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
acpiphp_sanitize_bus(bus);
pci_enable_bridges(bus);
pci_bus_add_devices(bus);
acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus);
acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev));
/* associate pci_dev to our representation */
list_for_each (l, &slot->funcs) {
......
......@@ -78,11 +78,20 @@ static void __iomem *csr_int_mask;
static int zt5550_hc_config(struct pci_dev *pdev)
{
int ret;
/* Since we know that no boards exist with two HC chips, treat it as an error */
if(hc_dev) {
err("too many host controller devices?");
return -EBUSY;
}
ret = pci_enable_device(pdev);
if(ret) {
err("cannot enable %s\n", pci_name(pdev));
return ret;
}
hc_dev = pdev;
dbg("hc_dev = %p", hc_dev);
dbg("pci resource start %lx", pci_resource_start(hc_dev, 1));
......@@ -91,7 +100,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
if(!request_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1), MY_NAME)) {
err("cannot reserve MMIO region");
return -ENOMEM;
ret = -ENOMEM;
goto exit_disable_device;
}
hc_registers =
......@@ -99,9 +109,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
if(!hc_registers) {
err("cannot remap MMIO region %lx @ %lx",
pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1));
release_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1));
return -ENODEV;
ret = -ENODEV;
goto exit_release_region;
}
csr_hc_index = hc_registers + CSR_HCINDEX;
......@@ -124,6 +133,13 @@ static int zt5550_hc_config(struct pci_dev *pdev)
writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
dbg("disabled timer0, timer1 and ENUM interrupts");
return 0;
exit_release_region:
release_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1));
exit_disable_device:
pci_disable_device(hc_dev);
return ret;
}
static int zt5550_hc_cleanup(void)
......@@ -134,6 +150,7 @@ static int zt5550_hc_cleanup(void)
iounmap(hc_registers);
release_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1));
pci_disable_device(hc_dev);
return 0;
}
......
......@@ -794,12 +794,21 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
u32 rc;
struct controller *ctrl;
struct pci_func *func;
int err;
err = pci_enable_device(pdev);
if (err) {
printk(KERN_ERR MY_NAME ": cannot enable PCI device %s (%d)\n",
pci_name(pdev), err);
return err;
}
// Need to read VID early b/c it's used to differentiate CPQ and INTC discovery
rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id);
if (rc || ((vendor_id != PCI_VENDOR_ID_COMPAQ) && (vendor_id != PCI_VENDOR_ID_INTEL))) {
err(msg_HPC_non_compaq_or_intel);
return -ENODEV;
rc = -ENODEV;
goto err_disable_device;
}
dbg("Vendor ID: %x\n", vendor_id);
......@@ -807,7 +816,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dbg("revision: %d\n", rev);
if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
err(msg_HPC_rev_error);
return -ENODEV;
rc = -ENODEV;
goto err_disable_device;
}
/* Check for the proper subsytem ID's
......@@ -820,18 +830,20 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
if (rc) {
err("%s : pci_read_config_word failed\n", __FUNCTION__);
return rc;
goto err_disable_device;
}
dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
if ((subsystem_vid != PCI_VENDOR_ID_COMPAQ) && (subsystem_vid != PCI_VENDOR_ID_INTEL)) {
err(msg_HPC_non_compaq_or_intel);
return -ENODEV;
rc = -ENODEV;
goto err_disable_device;
}
ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
if (!ctrl) {
err("%s : out of memory\n", __FUNCTION__);
return -ENOMEM;
rc = -ENOMEM;
goto err_disable_device;
}
memset(ctrl, 0, sizeof(struct controller));
......@@ -1264,6 +1276,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
kfree(ctrl->pci_bus);
err_free_ctrl:
kfree(ctrl);
err_disable_device:
pci_disable_device(pdev);
return rc;
}
......
......@@ -92,9 +92,10 @@ extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn);
extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
extern int rpaphp_enable_pci_slot(struct slot *slot);
extern int register_pci_slot(struct slot *slot);
extern int rpaphp_unconfig_pci_adapter(struct slot *slot);
extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
/* rpaphp_core.c */
extern int rpaphp_add_slot(struct device_node *dn);
......
......@@ -426,8 +426,11 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
dbg("DISABLING SLOT %s\n", slot->name);
down(&rpaphp_sem);
retval = rpaphp_unconfig_pci_adapter(slot);
retval = rpaphp_unconfig_pci_adapter(slot->bus);
up(&rpaphp_sem);
slot->state = NOT_CONFIGURED;
info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
slot->name);
exit:
dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
return retval;
......
......@@ -319,20 +319,15 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
return;
}
int rpaphp_unconfig_pci_adapter(struct slot *slot)
int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
{
struct pci_dev *dev, *tmp;
int retval = 0;
list_for_each_entry_safe(dev, tmp, slot->pci_devs, bus_list) {
list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
rpaphp_eeh_remove_bus_device(dev);
pci_remove_bus_device(dev);
}
slot->state = NOT_CONFIGURED;
info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
slot->name);
return retval;
return 0;
}
static int setup_pci_hotplug_slot_info(struct slot *slot)
......
......@@ -32,8 +32,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <asm/semaphore.h>
#include <asm/io.h>
#include "pci_hotplug.h"
#if !defined(MODULE)
......@@ -52,42 +50,18 @@ extern int shpchp_debug;
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
struct pci_func {
struct pci_func *next;
u8 bus;
u8 device;
u8 function;
u8 is_a_board;
u16 status;
u8 configured;
u8 switch_save;
u8 presence_save;
u8 pwr_save;
u32 base_length[0x06];
u8 base_type[0x06];
u16 reserved2;
u32 config_space[0x20];
struct pci_resource *mem_head;
struct pci_resource *p_mem_head;
struct pci_resource *io_head;
struct pci_resource *bus_head;
struct pci_dev* pci_dev;
};
#define SLOT_MAGIC 0x67267321
struct slot {
u32 magic;
struct slot *next;
u8 bus;
u8 device;
u16 status;
u32 number;
u8 is_a_board;
u8 configured;
u8 state;
u8 switch_save;
u8 presence_save;
u32 capabilities;
u16 reserved2;
u8 pwr_save;
struct timer_list task_event;
u8 hp_slot;
struct controller *ctrl;
......@@ -96,12 +70,6 @@ struct slot {
struct list_head slot_list;
};
struct pci_resource {
struct pci_resource * next;
u32 base;
u32 length;
};
struct event_info {
u32 event_type;
u8 hp_slot;
......@@ -110,13 +78,9 @@ struct event_info {
struct controller {
struct controller *next;
struct semaphore crit_sect; /* critical section semaphore */
void * hpc_ctlr_handle; /* HPC controller handle */
struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
int num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */
struct pci_resource *mem_head;
struct pci_resource *p_mem_head;
struct pci_resource *io_head;
struct pci_resource *bus_head;
struct pci_dev *pci_dev;
struct pci_bus *pci_bus;
struct event_info event_queue[10];
......@@ -124,33 +88,21 @@ struct controller {
struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */
u8 next_event;
u8 seg;
u8 bus;
u8 device;
u8 function;
u8 rev;
u8 slot_device_offset;
u8 add_support;
enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
u8 push_flag;
u16 ctlrcap;
u16 vendor_id;
};
struct irq_mapping {
u8 barber_pole;
u8 valid_INT;
u8 interrupt[4];
};
struct resource_lists {
struct pci_resource *mem_head;
struct pci_resource *p_mem_head;
struct pci_resource *io_head;
struct pci_resource *bus_head;
struct irq_mapping *irqs;
struct hotplug_params {
u8 cache_line_size;
u8 latency_timer;
u8 enable_serr;
u8 enable_perr;
};
/* Define AMD SHPC ID */
......@@ -194,24 +146,16 @@ struct resource_lists {
* error Messages
*/
#define msg_initialization_err "Initialization failure, error=%d\n"
#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
#define msg_HPC_non_shpc "The PCI hot plug controller is not supported by this driver.\n"
#define msg_HPC_not_supported "This system is not supported by this version of shpcphd mdoule. Upgrade to a newer version of shpchpd\n"
#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
#define msg_button_on "PCI slot #%d - powering on due to button press.\n"
#define msg_button_off "PCI slot #%d - powering off due to button press.\n"
#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n"
/* sysfs functions for the hotplug controller info */
extern void shpchp_create_ctrl_files (struct controller *ctrl);
/* controller functions */
extern int shpchprm_find_available_resources(struct controller *ctrl);
extern int shpchp_event_start_thread(void);
extern void shpchp_event_stop_thread(void);
extern struct pci_func *shpchp_slot_create(unsigned char busnumber);
extern struct pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index);
extern int shpchp_enable_slot(struct slot *slot);
extern int shpchp_disable_slot(struct slot *slot);
......@@ -220,29 +164,20 @@ extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
extern u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id);
extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id);
/* resource functions */
extern int shpchp_resource_sort_and_combine(struct pci_resource **head);
/* pci functions */
extern int shpchp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
/*extern int shpchp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
extern int shpchp_save_used_resources(struct controller *ctrl, struct pci_func * func, int flag);
extern int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot);
extern void shpchp_destroy_board_resources(struct pci_func * func);
extern int shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources);
extern void shpchp_destroy_resource_list(struct resource_lists * resources);
extern int shpchp_configure_device(struct controller* ctrl, struct pci_func* func);
extern int shpchp_unconfigure_device(struct pci_func* func);
extern int shpchp_configure_device(struct slot *p_slot);
extern int shpchp_unconfigure_device(struct slot *p_slot);
extern void get_hp_hw_control_from_firmware(struct pci_dev *dev);
extern void get_hp_params_from_firmware(struct pci_dev *dev,
struct hotplug_params *hpp);
extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
u32 *sun, u8 busnum, u8 devnum);
extern void shpchp_remove_ctrl_files(struct controller *ctrl);
/* Global variables */
extern struct controller *shpchp_ctrl_list;
extern struct pci_func *shpchp_slot_list[256];
/* These are added to support AMD shpc */
extern u8 shpchp_nic_irq;
extern u8 shpchp_disk_irq;
struct ctrl_reg {
volatile u32 base_offset;
......@@ -298,7 +233,7 @@ enum ctrl_offsets {
SLOT11 = offsetof(struct ctrl_reg, slot11),
SLOT12 = offsetof(struct ctrl_reg, slot12),
};
typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id);
struct php_ctlr_state_s {
struct php_ctlr_state_s *pnext;
struct pci_dev *pci_dev;
......@@ -359,12 +294,9 @@ static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
p_slot = ctrl->slot;
dbg("p_slot = %p\n", p_slot);
while (p_slot && (p_slot->device != device)) {
tmp_slot = p_slot;
p_slot = p_slot->next;
dbg("In while loop, p_slot = %p\n", p_slot);
}
if (p_slot == NULL) {
err("ERROR: shpchp_find_slot device=0x%x\n", device);
......@@ -379,8 +311,6 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
DECLARE_WAITQUEUE(wait, current);
int retval = 0;
dbg("%s : start\n",__FUNCTION__);
add_wait_queue(&ctrl->queue, &wait);
if (!shpchp_poll_mode) {
......@@ -394,19 +324,9 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
if (signal_pending(current))
retval = -EINTR;
dbg("%s : end\n", __FUNCTION__);
return retval;
}
/* Puts node back in the resource list pointed to by head */
static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
{
if (!node || !head)
return;
node->next = *head;
*head = node;
}
#define SLOT_NAME_SIZE 10
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
......@@ -420,11 +340,7 @@ enum php_ctlr_type {
ACPI
};
int shpc_init( struct controller *ctrl, struct pci_dev *pdev,
php_intr_callback_t attention_button_callback,
php_intr_callback_t switch_change_callback,
php_intr_callback_t presence_change_callback,
php_intr_callback_t power_fault_callback);
int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
int shpc_get_ctlr_slot_config( struct controller *ctrl,
int *num_ctlr_slots,
......@@ -437,8 +353,6 @@ struct hpc_ops {
int (*power_on_slot ) (struct slot *slot);
int (*slot_enable ) (struct slot *slot);
int (*slot_disable ) (struct slot *slot);
int (*enable_all_slots) (struct slot *slot);
int (*pwr_on_all_slots) (struct slot *slot);
int (*set_bus_speed_mode) (struct slot *slot, enum pci_bus_speed speed);
int (*get_power_status) (struct slot *slot, u8 *status);
int (*get_attention_status) (struct slot *slot, u8 *status);
......
......@@ -27,26 +27,18 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include "shpchp.h"
#include "shpchprm.h"
/* Global variables */
int shpchp_debug;
int shpchp_poll_mode;
int shpchp_poll_time;
struct controller *shpchp_ctrl_list; /* = NULL */
struct pci_func *shpchp_slot_list[256];
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
......@@ -113,8 +105,6 @@ static int init_slots(struct controller *ctrl)
u32 slot_number, sun;
int result = -ENOMEM;
dbg("%s\n",__FUNCTION__);
number_of_slots = ctrl->num_slots;
slot_device = ctrl->slot_device_offset;
slot_number = ctrl->first_slot;
......@@ -352,6 +342,17 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
return 0;
}
static int is_shpc_capable(struct pci_dev *dev)
{
if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
PCI_DEVICE_ID_AMD_GOLAM_7450))
return 1;
if (pci_find_capability(dev, PCI_CAP_ID_SHPC))
return 1;
return 0;
}
static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int rc;
......@@ -360,6 +361,9 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int first_device_num; /* first PCI device number supported by this SHPC */
int num_ctlr_slots; /* number of slots supported by this SHPC */
if (!is_shpc_capable(pdev))
return -ENODEV;
ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
if (!ctrl) {
err("%s : out of memory\n", __FUNCTION__);
......@@ -367,19 +371,12 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
memset(ctrl, 0, sizeof(struct controller));
dbg("DRV_thread pid = %d\n", current->pid);
rc = shpc_init(ctrl, pdev,
(php_intr_callback_t) shpchp_handle_attention_button,
(php_intr_callback_t) shpchp_handle_switch_change,
(php_intr_callback_t) shpchp_handle_presence_change,
(php_intr_callback_t) shpchp_handle_power_fault);
rc = shpc_init(ctrl, pdev);
if (rc) {
dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME);
goto err_out_free_ctrl;
}
dbg("%s: controller initialization success\n", __FUNCTION__);
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
pci_set_drvdata(pdev, ctrl);
......@@ -411,23 +408,8 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
first_device_num = ctrl->slot_device_offset;
num_ctlr_slots = ctrl->num_slots;
/* Store PCI Config Space for all devices on this bus */
rc = shpchp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
if (rc) {
err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
goto err_out_free_ctrl_bus;
}
/* Get IO, memory, and IRQ resources for new devices */
rc = shpchprm_find_available_resources(ctrl);
ctrl->add_support = !rc;
ctrl->add_support = 1;
if (rc) {
dbg("shpchprm_find_available_resources = %#x\n", rc);
err("unable to locate PCI configuration resources for hot plug add.\n");
goto err_out_free_ctrl_bus;
}
/* Setup the slot information structures */
rc = init_slots(ctrl);
if (rc) {
......@@ -477,7 +459,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static int shpc_start_thread(void)
{
int loop;
int retval = 0;
dbg("Initialize + Start the notification/polling mechanism \n");
......@@ -488,48 +469,21 @@ static int shpc_start_thread(void)
return retval;
}
dbg("Initialize slot lists\n");
/* One slot list for each bus in the system */
for (loop = 0; loop < 256; loop++) {
shpchp_slot_list[loop] = NULL;
}
return retval;
}
static inline void __exit
free_shpchp_res(struct pci_resource *res)
{
struct pci_resource *tres;
while (res) {
tres = res;
res = res->next;
kfree(tres);
}
}
static void __exit unload_shpchpd(void)
{
struct pci_func *next;
struct pci_func *TempSlot;
int loop;
struct controller *ctrl;
struct controller *tctrl;
ctrl = shpchp_ctrl_list;
while (ctrl) {
shpchp_remove_ctrl_files(ctrl);
cleanup_slots(ctrl);
free_shpchp_res(ctrl->io_head);
free_shpchp_res(ctrl->mem_head);
free_shpchp_res(ctrl->p_mem_head);
free_shpchp_res(ctrl->bus_head);
kfree (ctrl->pci_bus);
dbg("%s: calling release_ctlr\n", __FUNCTION__);
ctrl->hpc_ops->release_ctlr(ctrl);
tctrl = ctrl;
......@@ -538,20 +492,6 @@ static void __exit unload_shpchpd(void)
kfree(tctrl);
}
for (loop = 0; loop < 256; loop++) {
next = shpchp_slot_list[loop];
while (next != NULL) {
free_shpchp_res(next->io_head);
free_shpchp_res(next->mem_head);
free_shpchp_res(next->p_mem_head);
free_shpchp_res(next->bus_head);
TempSlot = next;
next = next->next;
kfree(TempSlot);
}
}
/* Stop the notification mechanism */
shpchp_event_stop_thread();
......@@ -596,20 +536,14 @@ static int __init shpcd_init(void)
if (retval)
goto error_hpc_init;
retval = shpchprm_init(PCI);
if (!retval) {
retval = pci_register_driver(&shpc_driver);
dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
}
retval = pci_register_driver(&shpc_driver);
dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
error_hpc_init:
if (retval) {
shpchprm_cleanup();
shpchp_event_stop_thread();
} else
shpchprm_print_pirt();
}
return retval;
}
......@@ -618,9 +552,6 @@ static void __exit shpcd_cleanup(void)
dbg("unload_shpchpd()\n");
unload_shpchpd();
shpchprm_cleanup();
dbg("pci_unregister_driver\n");
pci_unregister_driver(&shpc_driver);
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -26,12 +26,9 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
#include "shpchp.h"
......@@ -40,104 +37,60 @@
static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pci_dev;
struct controller *ctrl;
struct pci_dev *pdev;
char * out = buf;
int index;
struct pci_resource *res;
int index, busnr;
struct resource *res;
struct pci_bus *bus;
pci_dev = container_of (dev, struct pci_dev, dev);
ctrl = pci_get_drvdata(pci_dev);
pdev = container_of (dev, struct pci_dev, dev);
bus = pdev->subordinate;
out += sprintf(buf, "Free resources: memory\n");
index = 11;
res = ctrl->mem_head;
while (res && index--) {
out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
res = res->next;
for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
res = bus->resource[index];
if (res && (res->flags & IORESOURCE_MEM) &&
!(res->flags & IORESOURCE_PREFETCH)) {
out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
res->start, (res->end - res->start));
}
}
out += sprintf(out, "Free resources: prefetchable memory\n");
index = 11;
res = ctrl->p_mem_head;
while (res && index--) {
out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
res = res->next;
for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
res = bus->resource[index];
if (res && (res->flags & IORESOURCE_MEM) &&
(res->flags & IORESOURCE_PREFETCH)) {
out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
res->start, (res->end - res->start));
}
}
out += sprintf(out, "Free resources: IO\n");
index = 11;
res = ctrl->io_head;
while (res && index--) {
out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
res = res->next;
for (index = 0; index < PCI_BUS_NUM_RESOURCES; index++) {
res = bus->resource[index];
if (res && (res->flags & IORESOURCE_IO)) {
out += sprintf(out, "start = %8.8lx, length = %8.8lx\n",
res->start, (res->end - res->start));
}
}
out += sprintf(out, "Free resources: bus numbers\n");
index = 11;
res = ctrl->bus_head;
while (res && index--) {
out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
res = res->next;
for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) {
if (!pci_find_bus(pci_domain_nr(bus), busnr))
break;
}
if (busnr < bus->subordinate)
out += sprintf(out, "start = %8.8x, length = %8.8x\n",
busnr, (bus->subordinate - busnr));
return out - buf;
}
static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
void shpchp_create_ctrl_files (struct controller *ctrl)
{
struct pci_dev *pci_dev;
struct controller *ctrl;
char * out = buf;
int index;
struct pci_resource *res;
struct pci_func *new_slot;
struct slot *slot;
pci_dev = container_of (dev, struct pci_dev, dev);
ctrl = pci_get_drvdata(pci_dev);
slot=ctrl->slot;
while (slot) {
new_slot = shpchp_slot_find(slot->bus, slot->device, 0);
if (!new_slot)
break;
out += sprintf(out, "assigned resources: memory\n");
index = 11;
res = new_slot->mem_head;
while (res && index--) {
out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
res = res->next;
}
out += sprintf(out, "assigned resources: prefetchable memory\n");
index = 11;
res = new_slot->p_mem_head;
while (res && index--) {
out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
res = res->next;
}
out += sprintf(out, "assigned resources: IO\n");
index = 11;
res = new_slot->io_head;
while (res && index--) {
out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
res = res->next;
}
out += sprintf(out, "assigned resources: bus numbers\n");
index = 11;
res = new_slot->bus_head;
while (res && index--) {
out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
res = res->next;
}
slot=slot->next;
}
return out - buf;
device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
}
static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
void shpchp_create_ctrl_files (struct controller *ctrl)
void shpchp_remove_ctrl_files(struct controller *ctrl)
{
device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
device_remove_file(&ctrl->pci_dev->dev, &dev_attr_ctrl);
}
/*
* SHPCHPRM : SHPCHP Resource Manager for ACPI/non-ACPI platform
*
* Copyright (C) 1995,2001 Compaq Computer Corporation
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2001 IBM Corp.
* Copyright (C) 2003-2004 Intel Corporation
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
#ifndef _SHPCHPRM_H_
#define _SHPCHPRM_H_
#ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
#include "shpchprm_legacy.h"
#else
#include "shpchprm_nonacpi.h"
#endif
int shpchprm_init(enum php_ctlr_type ct);
void shpchprm_cleanup(void);
int shpchprm_print_pirt(void);
int shpchprm_find_available_resources(struct controller *ctrl);
int shpchprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
void shpchprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum);
#ifdef DEBUG
#define RES_CHECK(this, bits) \
{ if (((this) & (bits - 1))) \
printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
#else
#define RES_CHECK(this, bits)
#endif
#endif /* _SHPCHPRM_H_ */
This diff is collapsed.
This diff is collapsed.
/*
* SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform using HRT
*
* Copyright (C) 1995,2001 Compaq Computer Corporation
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2001 IBM Corp.
* Copyright (C) 2003-2004 Intel Corporation
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
#ifndef _SHPCHPRM_LEGACY_H_
#define _SHPCHPRM_LEGACY_H_
#define ROM_PHY_ADDR 0x0F0000
#define ROM_PHY_LEN 0x00FFFF
struct slot_rt {
u8 dev_func;
u8 primary_bus;
u8 secondary_bus;
u8 max_bus;
u16 io_base;
u16 io_length;
u16 mem_base;
u16 mem_length;
u16 pre_mem_base;
u16 pre_mem_length;
} __attribute__ ((packed));
/* offsets to the hotplug slot resource table registers based on the above structure layout */
enum slot_rt_offsets {
DEV_FUNC = offsetof(struct slot_rt, dev_func),
PRIMARY_BUS = offsetof(struct slot_rt, primary_bus),
SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus),
MAX_BUS = offsetof(struct slot_rt, max_bus),
IO_BASE = offsetof(struct slot_rt, io_base),
IO_LENGTH = offsetof(struct slot_rt, io_length),
MEM_BASE = offsetof(struct slot_rt, mem_base),
MEM_LENGTH = offsetof(struct slot_rt, mem_length),
PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base),
PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length),
};
struct hrt {
char sig0;
char sig1;
char sig2;
char sig3;
u16 unused_IRQ;
u16 PCIIRQ;
u8 number_of_entries;
u8 revision;
u16 reserved1;
u32 reserved2;
} __attribute__ ((packed));
/* offsets to the hotplug resource table registers based on the above structure layout */
enum hrt_offsets {
SIG0 = offsetof(struct hrt, sig0),
SIG1 = offsetof(struct hrt, sig1),
SIG2 = offsetof(struct hrt, sig2),
SIG3 = offsetof(struct hrt, sig3),
UNUSED_IRQ = offsetof(struct hrt, unused_IRQ),
PCIIRQ = offsetof(struct hrt, PCIIRQ),
NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries),
REVISION = offsetof(struct hrt, revision),
HRT_RESERVED1 = offsetof(struct hrt, reserved1),
HRT_RESERVED2 = offsetof(struct hrt, reserved2),
};
struct irq_info {
u8 bus, devfn; /* bus, device and function */
struct {
u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
u16 bitmap; /* Available IRQs */
} __attribute__ ((packed)) irq[4];
u8 slot; /* slot number, 0=onboard */
u8 rfu;
} __attribute__ ((packed));
struct irq_routing_table {
u32 signature; /* PIRQ_SIGNATURE should be here */
u16 version; /* PIRQ_VERSION */
u16 size; /* Table size in bytes */
u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
u32 miniport_data; /* Crap */
u8 rfu[11];
u8 checksum; /* Modulo 256 checksum must give zero */
struct irq_info slots[0];
} __attribute__ ((packed));
#endif /* _SHPCHPRM_LEGACY_H_ */
This diff is collapsed.
/*
* SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
*
* Copyright (C) 1995,2001 Compaq Computer Corporation
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2001 IBM Corp.
* Copyright (C) 2003-2004 Intel Corporation
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
*
*/
#ifndef _SHPCHPRM_NONACPI_H_
#define _SHPCHPRM_NONACPI_H_
struct irq_info {
u8 bus, devfn; /* bus, device and function */
struct {
u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
u16 bitmap; /* Available IRQs */
} __attribute__ ((packed)) irq[4];
u8 slot; /* slot number, 0=onboard */
u8 rfu;
} __attribute__ ((packed));
struct irq_routing_table {
u32 signature; /* PIRQ_SIGNATURE should be here */
u16 version; /* PIRQ_VERSION */
u16 size; /* Table size in bytes */
u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
u32 miniport_data; /* Crap */
u8 rfu[11];
u8 checksum; /* Modulo 256 checksum must give zero */
struct irq_info slots[0];
} __attribute__ ((packed));
#endif /* _SHPCHPRM_NONACPI_H_ */
......@@ -575,6 +575,8 @@ static int msi_capability_init(struct pci_dev *dev)
/**
* msix_capability_init - configure device's MSI-X capability
* @dev: pointer to the pci_dev data structure of MSI-X device function
* @entries: pointer to an array of struct msix_entry entries
* @nvec: number of @entries
*
* Setup the MSI-X capability structure of device function with a
* single MSI-X vector. A return of zero indicates the successful setup of
......
......@@ -26,7 +26,10 @@ struct pci_dynid {
#ifdef CONFIG_HOTPLUG
/**
* store_new_id
* store_new_id - add a new PCI device ID to this driver and re-probe devices
* @driver: target device driver
* @buf: buffer for scanning device ID data
* @count: input size
*
* Adds a new dynamic pci device ID to this driver,
* and causes the driver to probe for all devices again.
......@@ -194,8 +197,10 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
/**
* __pci_device_probe()
* @drv: driver to call to check if it wants the PCI device
* @pci_dev: PCI device being probed
*
* returns 0 on success, else error.
* returns 0 on success, else error.
* side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
*/
static int
......@@ -377,6 +382,10 @@ int pci_register_driver(struct pci_driver *drv)
* the pci shutdown function, this test can go away. */
if (!drv->driver.shutdown)
drv->driver.shutdown = pci_device_shutdown;
else
printk(KERN_WARNING "Warning: PCI driver %s has a struct "
"device_driver shutdown method, please update!\n",
drv->name);
drv->driver.owner = drv->owner;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
......@@ -436,11 +445,11 @@ pci_dev_driver(const struct pci_dev *dev)
/**
* pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure
* @ids: array of PCI device id structures to search in
* @dev: the PCI device structure to match against
* @drv: the device driver to search for matching PCI device id structures
*
* Used by a driver to check whether a PCI device present in the
* system is in its list of supported devices.Returns the matching
* system is in its list of supported devices. Returns the matching
* pci_device_id structure or %NULL if there is no match.
*/
static int pci_bus_match(struct device *dev, struct device_driver *drv)
......
......@@ -130,7 +130,7 @@ 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--;
......@@ -138,7 +138,7 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
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;
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -192,7 +192,7 @@ 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--;
}
......@@ -200,7 +200,7 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
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;
}
......@@ -210,7 +210,7 @@ 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;
}
......@@ -218,13 +218,13 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
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;
}
......
This diff is collapsed.
......@@ -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);
......
......@@ -669,6 +669,7 @@ static void pci_release_dev(struct device *dev)
/**
* pci_cfg_space_size - get the configuration space size of the PCI device.
* @dev: PCI device
*
* Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices
* have 4096 bytes. Even if the device is capable, that doesn't mean we can
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment