Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6: (22 commits) acpiphp: Link-time error for PCI Hotplug shpchp: cleanup shpchp.h shpchp: remove shpchprm_get_physical_slot_number shpchp: cleanup struct controller shpchp: remove unnecessary struct php_ctlr PCI: ATI sb600 sata quirk PCI legacy resource fix PCI: don't export device IDs to userspace PCI: Be a bit defensive in quirk_nvidia_ck804() so we don't risk dereferencing a NULL pdev. PCI: Fix multiple problems with VIA hardware PCI: Only check the HT capability bits in mpic.c PCI: Use pci_find_ht_capability() in drivers/pci/quirks.c PCI: Add #defines for Hypertransport MSI fields PCI: Use pci_find_ht_capability() in drivers/pci/htirq.c PCI: Add pci_find_ht_capability() for finding Hypertransport capabilities PCI: Create __pci_bus_find_cap_start() from __pci_bus_find_cap() pci: Introduce pci_find_present PCI: pcieport-driver: remove invalid warning message rpaphp: compiler warning cleanup PCI quirks: remove redundant check ...
This commit is contained in:
commit
de9b2fccb6
|
@ -115,7 +115,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci
|
|||
#define VIA_8363_KL133_REVISION_ID 0x81
|
||||
#define VIA_8363_KM133_REVISION_ID 0x84
|
||||
|
||||
static void __devinit pci_fixup_via_northbridge_bug(struct pci_dev *d)
|
||||
static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
|
||||
{
|
||||
u8 v;
|
||||
u8 revision;
|
||||
|
@ -151,6 +151,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_
|
|||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
|
||||
|
||||
/*
|
||||
* For some reasons Intel decided that certain parts of their
|
||||
|
@ -181,7 +185,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_
|
|||
* issue another HALT within 80 ns of the initial HALT, the failure condition
|
||||
* is avoided.
|
||||
*/
|
||||
static void __init pci_fixup_nforce2(struct pci_dev *dev)
|
||||
static void pci_fixup_nforce2(struct pci_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
|
@ -204,6 +208,7 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
|
||||
|
||||
/* Max PCI Express root ports */
|
||||
#define MAX_PCIEROOT 6
|
||||
|
@ -419,7 +424,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
|
|||
* Prevent the BIOS trapping accesses to the Cyrix CS5530A video device
|
||||
* configuration space.
|
||||
*/
|
||||
static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev)
|
||||
static void pci_early_fixup_cyrix_5530(struct pci_dev *dev)
|
||||
{
|
||||
u8 r;
|
||||
/* clear 'F4 Video Configuration Trap' bit */
|
||||
|
@ -429,3 +434,5 @@ static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev)
|
|||
}
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
|
||||
pci_early_fixup_cyrix_5530);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
|
||||
pci_early_fixup_cyrix_5530);
|
||||
|
|
|
@ -390,7 +390,7 @@ static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
|
|||
u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
|
||||
if (id == PCI_CAP_ID_HT) {
|
||||
id = readb(devbase + pos + 3);
|
||||
if (id == HT_CAPTYPE_IRQ)
|
||||
if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_IRQ)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -368,7 +368,6 @@ static struct pci_device_id atiixp_pci_tbl[] = {
|
|||
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
|
||||
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, PCI_ANY_ID, PCI_ANY_ID, (PCI_CLASS_STORAGE_IDE<<8)|0x8a, 0xffff05, 1},
|
||||
{ 0, },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
|
||||
|
|
|
@ -1682,7 +1682,7 @@ int __init acpiphp_glue_init(void)
|
|||
*
|
||||
* This function frees all data allocated in acpiphp_glue_init()
|
||||
*/
|
||||
void __exit acpiphp_glue_exit(void)
|
||||
void acpiphp_glue_exit(void)
|
||||
{
|
||||
acpi_pci_unregister_driver(&acpi_pci_hp_driver);
|
||||
}
|
||||
|
|
|
@ -47,21 +47,11 @@ static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static struct hotplug_slot_attribute hotplug_slot_attr_location = {
|
||||
static struct hotplug_slot_attribute php_attr_location = {
|
||||
.attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO},
|
||||
.show = location_read_file,
|
||||
};
|
||||
|
||||
static void rpaphp_sysfs_add_attr_location (struct hotplug_slot *slot)
|
||||
{
|
||||
sysfs_create_file(&slot->kobj, &hotplug_slot_attr_location.attr);
|
||||
}
|
||||
|
||||
static void rpaphp_sysfs_remove_attr_location (struct hotplug_slot *slot)
|
||||
{
|
||||
sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_location.attr);
|
||||
}
|
||||
|
||||
/* free up the memory used by a slot */
|
||||
static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
|
@ -145,7 +135,7 @@ int rpaphp_deregister_slot(struct slot *slot)
|
|||
list_del(&slot->rpaphp_slot_list);
|
||||
|
||||
/* remove "phy_location" file */
|
||||
rpaphp_sysfs_remove_attr_location(php_slot);
|
||||
sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr);
|
||||
|
||||
retval = pci_hp_deregister(php_slot);
|
||||
if (retval)
|
||||
|
@ -160,36 +150,45 @@ EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
|
|||
|
||||
int rpaphp_register_slot(struct slot *slot)
|
||||
{
|
||||
struct hotplug_slot *php_slot = slot->hotplug_slot;
|
||||
int retval;
|
||||
|
||||
dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",
|
||||
__FUNCTION__, slot->dn->full_name, slot->index, slot->name,
|
||||
slot->power_domain, slot->type);
|
||||
|
||||
/* should not try to register the same slot twice */
|
||||
if (is_registered(slot)) { /* should't be here */
|
||||
if (is_registered(slot)) {
|
||||
err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
|
||||
rpaphp_release_slot(slot->hotplug_slot);
|
||||
return -EAGAIN;
|
||||
retval = -EAGAIN;
|
||||
goto register_fail;
|
||||
}
|
||||
retval = pci_hp_register(slot->hotplug_slot);
|
||||
|
||||
retval = pci_hp_register(php_slot);
|
||||
if (retval) {
|
||||
err("pci_hp_register failed with error %d\n", retval);
|
||||
rpaphp_release_slot(slot->hotplug_slot);
|
||||
return retval;
|
||||
goto register_fail;
|
||||
}
|
||||
|
||||
/* create "phy_location" file */
|
||||
retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr);
|
||||
if (retval) {
|
||||
err("sysfs_create_file failed with error %d\n", retval);
|
||||
goto sysfs_fail;
|
||||
}
|
||||
|
||||
/* create "phy_locatoin" file */
|
||||
rpaphp_sysfs_add_attr_location(slot->hotplug_slot);
|
||||
|
||||
/* add slot to our internal list */
|
||||
dbg("%s adding slot[%s] to rpaphp_slot_list\n",
|
||||
__FUNCTION__, slot->name);
|
||||
|
||||
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
|
||||
info("Slot [%s](PCI location=%s) registered\n", slot->name,
|
||||
slot->location);
|
||||
num_slots++;
|
||||
return 0;
|
||||
|
||||
sysfs_fail:
|
||||
pci_hp_deregister(php_slot);
|
||||
register_fail:
|
||||
rpaphp_release_slot(php_slot);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int rpaphp_get_power_status(struct slot *slot, u8 * value)
|
||||
|
|
|
@ -47,11 +47,17 @@ extern int shpchp_poll_time;
|
|||
extern int shpchp_debug;
|
||||
extern struct workqueue_struct *shpchp_wq;
|
||||
|
||||
/*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
|
||||
#define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (shpchp_debug) \
|
||||
printk("%s: " format, MY_NAME , ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) \
|
||||
printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
|
||||
#define info(format, arg...) \
|
||||
printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
#define warn(format, arg...) \
|
||||
printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
|
||||
#define SLOT_NAME_SIZE 10
|
||||
struct slot {
|
||||
|
@ -83,34 +89,27 @@ struct event_info {
|
|||
struct controller {
|
||||
struct mutex crit_sect; /* critical section mutex */
|
||||
struct mutex cmd_lock; /* command lock */
|
||||
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_dev *pci_dev;
|
||||
struct list_head slot_list;
|
||||
struct hpc_ops *hpc_ops;
|
||||
wait_queue_head_t queue; /* sleep & wake process */
|
||||
u8 bus;
|
||||
u8 device;
|
||||
u8 function;
|
||||
u8 slot_device_offset;
|
||||
u8 add_support;
|
||||
u32 pcix_misc2_reg; /* for amd pogo errata */
|
||||
enum pci_bus_speed speed;
|
||||
u32 first_slot; /* First physical slot number */
|
||||
u8 slot_bus; /* Bus where the slots handled by this controller sit */
|
||||
u32 cap_offset;
|
||||
unsigned long mmio_base;
|
||||
unsigned long mmio_size;
|
||||
void __iomem *creg;
|
||||
struct timer_list poll_timer;
|
||||
};
|
||||
|
||||
|
||||
/* Define AMD SHPC ID */
|
||||
#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
|
||||
#define PCI_DEVICE_ID_AMD_POGO_7458 0x7458
|
||||
|
||||
/* AMD PCIX bridge registers */
|
||||
|
||||
#define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C
|
||||
#define PCIX_MISCII_OFFSET 0x48
|
||||
#define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80
|
||||
|
@ -145,8 +144,6 @@ struct controller {
|
|||
#define POWERON_STATE 3
|
||||
#define POWEROFF_STATE 4
|
||||
|
||||
#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400
|
||||
|
||||
/* Error messages */
|
||||
#define INTERLOCK_OPEN 0x00000002
|
||||
#define ADD_NOT_SUPPORTED 0x00000003
|
||||
|
@ -158,50 +155,32 @@ struct controller {
|
|||
#define WRONG_BUS_FREQUENCY 0x0000000D
|
||||
#define POWER_FAILURE 0x0000000E
|
||||
|
||||
#define REMOVE_NOT_SUPPORTED 0x00000003
|
||||
|
||||
#define DISABLE_CARD 1
|
||||
|
||||
/*
|
||||
* error Messages
|
||||
*/
|
||||
#define msg_initialization_err "Initialization failure, error=%d\n"
|
||||
#define msg_button_on "PCI slot #%s - powering on due to button press.\n"
|
||||
#define msg_button_off "PCI slot #%s - powering off due to button press.\n"
|
||||
#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n"
|
||||
|
||||
/* sysfs functions for the hotplug controller info */
|
||||
extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
|
||||
|
||||
extern int shpchp_sysfs_enable_slot(struct slot *slot);
|
||||
extern int shpchp_sysfs_disable_slot(struct slot *slot);
|
||||
|
||||
extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id);
|
||||
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);
|
||||
|
||||
/* pci functions */
|
||||
extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
|
||||
extern int shpchp_configure_device(struct slot *p_slot);
|
||||
extern int shpchp_unconfigure_device(struct slot *p_slot);
|
||||
extern void shpchp_remove_ctrl_files(struct controller *ctrl);
|
||||
extern void cleanup_slots(struct controller *ctrl);
|
||||
extern void queue_pushbutton_work(struct work_struct *work);
|
||||
|
||||
extern void shpchp_remove_ctrl_files(struct controller *ctrl);
|
||||
extern int shpchp_sysfs_enable_slot(struct slot *slot);
|
||||
extern int shpchp_sysfs_disable_slot(struct slot *slot);
|
||||
extern u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
|
||||
extern u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
|
||||
extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
|
||||
extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
|
||||
extern int shpchp_configure_device(struct slot *p_slot);
|
||||
extern int shpchp_unconfigure_device(struct slot *p_slot);
|
||||
extern void cleanup_slots(struct controller *ctrl);
|
||||
extern void queue_pushbutton_work(struct work_struct *work);
|
||||
extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static inline int get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
#define get_hp_hw_control_from_firmware(pdev) \
|
||||
do { \
|
||||
if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
|
||||
acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \
|
||||
#define get_hp_hw_control_from_firmware(pdev) \
|
||||
do { \
|
||||
if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
|
||||
acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev)));\
|
||||
} while (0)
|
||||
#else
|
||||
#define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
|
||||
|
@ -222,108 +201,40 @@ struct ctrl_reg {
|
|||
volatile u32 serr_loc;
|
||||
volatile u32 serr_intr_enable;
|
||||
volatile u32 slot1;
|
||||
volatile u32 slot2;
|
||||
volatile u32 slot3;
|
||||
volatile u32 slot4;
|
||||
volatile u32 slot5;
|
||||
volatile u32 slot6;
|
||||
volatile u32 slot7;
|
||||
volatile u32 slot8;
|
||||
volatile u32 slot9;
|
||||
volatile u32 slot10;
|
||||
volatile u32 slot11;
|
||||
volatile u32 slot12;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* offsets to the controller registers based on the above structure layout */
|
||||
enum ctrl_offsets {
|
||||
BASE_OFFSET = offsetof(struct ctrl_reg, base_offset),
|
||||
SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1),
|
||||
SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2),
|
||||
SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config),
|
||||
SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config),
|
||||
MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl),
|
||||
PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface),
|
||||
CMD = offsetof(struct ctrl_reg, cmd),
|
||||
CMD_STATUS = offsetof(struct ctrl_reg, cmd_status),
|
||||
INTR_LOC = offsetof(struct ctrl_reg, intr_loc),
|
||||
SERR_LOC = offsetof(struct ctrl_reg, serr_loc),
|
||||
SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable),
|
||||
SLOT1 = offsetof(struct ctrl_reg, slot1),
|
||||
SLOT2 = offsetof(struct ctrl_reg, slot2),
|
||||
SLOT3 = offsetof(struct ctrl_reg, slot3),
|
||||
SLOT4 = offsetof(struct ctrl_reg, slot4),
|
||||
SLOT5 = offsetof(struct ctrl_reg, slot5),
|
||||
SLOT6 = offsetof(struct ctrl_reg, slot6),
|
||||
SLOT7 = offsetof(struct ctrl_reg, slot7),
|
||||
SLOT8 = offsetof(struct ctrl_reg, slot8),
|
||||
SLOT9 = offsetof(struct ctrl_reg, slot9),
|
||||
SLOT10 = offsetof(struct ctrl_reg, slot10),
|
||||
SLOT11 = offsetof(struct ctrl_reg, slot11),
|
||||
SLOT12 = offsetof(struct ctrl_reg, slot12),
|
||||
BASE_OFFSET = offsetof(struct ctrl_reg, base_offset),
|
||||
SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1),
|
||||
SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2),
|
||||
SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config),
|
||||
SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config),
|
||||
MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl),
|
||||
PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface),
|
||||
CMD = offsetof(struct ctrl_reg, cmd),
|
||||
CMD_STATUS = offsetof(struct ctrl_reg, cmd_status),
|
||||
INTR_LOC = offsetof(struct ctrl_reg, intr_loc),
|
||||
SERR_LOC = offsetof(struct ctrl_reg, serr_loc),
|
||||
SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable),
|
||||
SLOT1 = offsetof(struct ctrl_reg, slot1),
|
||||
};
|
||||
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;
|
||||
unsigned int irq;
|
||||
unsigned long flags; /* spinlock's */
|
||||
u32 slot_device_offset;
|
||||
u32 num_slots;
|
||||
struct timer_list int_poll_timer; /* Added for poll event */
|
||||
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;
|
||||
void *callback_instance_id;
|
||||
void __iomem *creg; /* Ptr to controller register space */
|
||||
};
|
||||
/* Inline functions */
|
||||
|
||||
|
||||
/* Inline functions to check the sanity of a pointer that is passed to us */
|
||||
static inline int slot_paranoia_check (struct slot *slot, const char *function)
|
||||
{
|
||||
if (!slot) {
|
||||
dbg("%s - slot == NULL", function);
|
||||
return -1;
|
||||
}
|
||||
if (!slot->hotplug_slot) {
|
||||
dbg("%s - slot->hotplug_slot == NULL!", function);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function)
|
||||
static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
struct slot *slot;
|
||||
|
||||
if (!hotplug_slot) {
|
||||
dbg("%s - hotplug_slot == NULL\n", function);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slot = (struct slot *)hotplug_slot->private;
|
||||
if (slot_paranoia_check (slot, function))
|
||||
return NULL;
|
||||
return slot;
|
||||
return hotplug_slot->private;
|
||||
}
|
||||
|
||||
static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device)
|
||||
static inline struct slot *shpchp_find_slot(struct controller *ctrl, u8 device)
|
||||
{
|
||||
struct slot *slot;
|
||||
|
||||
if (!ctrl)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
|
||||
if (slot->device == device)
|
||||
return slot;
|
||||
}
|
||||
|
||||
err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -400,44 +311,27 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
|
|||
pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
|
||||
}
|
||||
|
||||
enum php_ctlr_type {
|
||||
PCI,
|
||||
ISA,
|
||||
ACPI
|
||||
};
|
||||
|
||||
int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
|
||||
|
||||
int shpc_get_ctlr_slot_config( struct controller *ctrl,
|
||||
int *num_ctlr_slots,
|
||||
int *first_device_num,
|
||||
int *physical_slot_num,
|
||||
int *updown,
|
||||
int *flags);
|
||||
|
||||
struct hpc_ops {
|
||||
int (*power_on_slot ) (struct slot *slot);
|
||||
int (*slot_enable ) (struct slot *slot);
|
||||
int (*slot_disable ) (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);
|
||||
int (*set_attention_status) (struct slot *slot, u8 status);
|
||||
int (*get_latch_status) (struct slot *slot, u8 *status);
|
||||
int (*get_adapter_status) (struct slot *slot, u8 *status);
|
||||
|
||||
int (*get_max_bus_speed) (struct slot *slot, enum pci_bus_speed *speed);
|
||||
int (*get_cur_bus_speed) (struct slot *slot, enum pci_bus_speed *speed);
|
||||
int (*get_adapter_speed) (struct slot *slot, enum pci_bus_speed *speed);
|
||||
int (*get_mode1_ECC_cap) (struct slot *slot, u8 *mode);
|
||||
int (*get_prog_int) (struct slot *slot, u8 *prog_int);
|
||||
|
||||
int (*query_power_fault) (struct slot *slot);
|
||||
void (*green_led_on) (struct slot *slot);
|
||||
void (*green_led_off) (struct slot *slot);
|
||||
void (*green_led_blink) (struct slot *slot);
|
||||
void (*release_ctlr) (struct controller *ctrl);
|
||||
int (*check_cmd_status) (struct controller *ctrl);
|
||||
int (*power_on_slot)(struct slot *slot);
|
||||
int (*slot_enable)(struct slot *slot);
|
||||
int (*slot_disable)(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);
|
||||
int (*set_attention_status)(struct slot *slot, u8 status);
|
||||
int (*get_latch_status)(struct slot *slot, u8 *status);
|
||||
int (*get_adapter_status)(struct slot *slot, u8 *status);
|
||||
int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
|
||||
int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
|
||||
int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed);
|
||||
int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode);
|
||||
int (*get_prog_int)(struct slot *slot, u8 *prog_int);
|
||||
int (*query_power_fault)(struct slot *slot);
|
||||
void (*green_led_on)(struct slot *slot);
|
||||
void (*green_led_off)(struct slot *slot);
|
||||
void (*green_led_blink)(struct slot *slot);
|
||||
void (*release_ctlr)(struct controller *ctrl);
|
||||
int (*check_cmd_status)(struct controller *ctrl);
|
||||
};
|
||||
|
||||
#endif /* _SHPCHP_H */
|
||||
|
|
|
@ -104,23 +104,6 @@ static void make_slot_name(struct slot *slot)
|
|||
slot->bus, slot->number);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun,
|
||||
u8 busnum, u8 devnum)
|
||||
{
|
||||
int offset = devnum - ctrl->slot_device_offset;
|
||||
|
||||
dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__,
|
||||
ctrl->slot_num_inc, offset);
|
||||
*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int init_slots(struct controller *ctrl)
|
||||
{
|
||||
struct slot *slot;
|
||||
|
@ -128,7 +111,6 @@ static int init_slots(struct controller *ctrl)
|
|||
struct hotplug_slot_info *info;
|
||||
int retval = -ENOMEM;
|
||||
int i;
|
||||
u32 sun;
|
||||
|
||||
for (i = 0; i < ctrl->num_slots; i++) {
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
|
@ -149,16 +131,11 @@ static int init_slots(struct controller *ctrl)
|
|||
|
||||
slot->hp_slot = i;
|
||||
slot->ctrl = ctrl;
|
||||
slot->bus = ctrl->slot_bus;
|
||||
slot->bus = ctrl->pci_dev->subordinate->number;
|
||||
slot->device = ctrl->slot_device_offset + i;
|
||||
slot->hpc_ops = ctrl->hpc_ops;
|
||||
slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
|
||||
mutex_init(&slot->lock);
|
||||
|
||||
if (shpchprm_get_physical_slot_number(ctrl, &sun,
|
||||
slot->bus, slot->device))
|
||||
goto error_info;
|
||||
|
||||
slot->number = sun;
|
||||
INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work);
|
||||
|
||||
/* register this slot with the hotplug pci core */
|
||||
|
@ -211,42 +188,12 @@ void cleanup_slots(struct controller *ctrl)
|
|||
}
|
||||
}
|
||||
|
||||
static int get_ctlr_slot_config(struct controller *ctrl)
|
||||
{
|
||||
int num_ctlr_slots;
|
||||
int first_device_num;
|
||||
int physical_slot_num;
|
||||
int updown;
|
||||
int rc;
|
||||
int flags;
|
||||
|
||||
rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots,
|
||||
&first_device_num, &physical_slot_num,
|
||||
&updown, &flags);
|
||||
if (rc) {
|
||||
err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n",
|
||||
__FUNCTION__, ctrl->bus, ctrl->device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctrl->num_slots = num_ctlr_slots;
|
||||
ctrl->slot_device_offset = first_device_num;
|
||||
ctrl->first_slot = physical_slot_num;
|
||||
ctrl->slot_num_inc = updown; /* either -1 or 1 */
|
||||
|
||||
dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d "
|
||||
"(%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num,
|
||||
physical_slot_num, updown, ctrl->bus, ctrl->device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_attention_status - Turns the Amber LED for a slot on, off or blink
|
||||
*/
|
||||
static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
|
@ -258,7 +205,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
|
|||
|
||||
static int enable_slot (struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
|
@ -267,7 +214,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
|
|||
|
||||
static int disable_slot (struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
|
@ -276,7 +223,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
|
|||
|
||||
static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
@ -290,7 +237,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
|||
|
||||
static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
@ -304,7 +251,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
|||
|
||||
static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
@ -318,7 +265,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
|||
|
||||
static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
@ -332,7 +279,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
|||
|
||||
static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
@ -344,7 +291,7 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
|
|||
|
||||
static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
@ -358,7 +305,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
|
|||
|
||||
static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
|
||||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
@ -385,9 +332,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
{
|
||||
int rc;
|
||||
struct controller *ctrl;
|
||||
struct slot *t_slot;
|
||||
int first_device_num; /* first PCI device number */
|
||||
int num_ctlr_slots; /* number of slots implemented */
|
||||
|
||||
if (!is_shpc_capable(pdev))
|
||||
return -ENODEV;
|
||||
|
@ -408,47 +352,13 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
pci_set_drvdata(pdev, ctrl);
|
||||
|
||||
ctrl->bus = pdev->bus->number;
|
||||
ctrl->slot_bus = pdev->subordinate->number;
|
||||
ctrl->device = PCI_SLOT(pdev->devfn);
|
||||
ctrl->function = PCI_FUNC(pdev->devfn);
|
||||
|
||||
dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
|
||||
ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
|
||||
|
||||
/*
|
||||
* Save configuration headers for this and subordinate PCI buses
|
||||
*/
|
||||
rc = get_ctlr_slot_config(ctrl);
|
||||
if (rc) {
|
||||
err(msg_initialization_err, rc);
|
||||
goto err_out_release_ctlr;
|
||||
}
|
||||
first_device_num = ctrl->slot_device_offset;
|
||||
num_ctlr_slots = ctrl->num_slots;
|
||||
|
||||
ctrl->add_support = 1;
|
||||
|
||||
/* Setup the slot information structures */
|
||||
rc = init_slots(ctrl);
|
||||
if (rc) {
|
||||
err(msg_initialization_err, 6);
|
||||
err("%s: slot initialization failed\n", SHPC_MODULE_NAME);
|
||||
goto err_out_release_ctlr;
|
||||
}
|
||||
|
||||
/* Now hpc_functions (slot->hpc_ops->functions) are ready */
|
||||
t_slot = shpchp_find_slot(ctrl, first_device_num);
|
||||
|
||||
/* Check for operation bus speed */
|
||||
rc = t_slot->hpc_ops->get_cur_bus_speed(t_slot, &ctrl->speed);
|
||||
dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot);
|
||||
|
||||
if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) {
|
||||
err(SHPC_MODULE_NAME ": Can't get current bus speed. "
|
||||
"Set to 33MHz PCI.\n");
|
||||
ctrl->speed = PCI_SPEED_33MHz;
|
||||
}
|
||||
|
||||
rc = shpchp_create_ctrl_files(ctrl);
|
||||
if (rc)
|
||||
goto err_cleanup_slots;
|
||||
|
|
|
@ -57,9 +57,8 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
|
||||
u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *) inst_id;
|
||||
struct slot *p_slot;
|
||||
u32 event_type;
|
||||
|
||||
|
@ -81,9 +80,8 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
|
|||
|
||||
}
|
||||
|
||||
u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
|
||||
u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *) inst_id;
|
||||
struct slot *p_slot;
|
||||
u8 getstatus;
|
||||
u32 event_type;
|
||||
|
@ -120,9 +118,8 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
|
|||
return 1;
|
||||
}
|
||||
|
||||
u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
|
||||
u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *) inst_id;
|
||||
struct slot *p_slot;
|
||||
u32 event_type;
|
||||
|
||||
|
@ -154,9 +151,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
|
|||
return 1;
|
||||
}
|
||||
|
||||
u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id)
|
||||
u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *) inst_id;
|
||||
struct slot *p_slot;
|
||||
u32 event_type;
|
||||
|
||||
|
@ -497,10 +493,12 @@ static void handle_button_press_event(struct slot *p_slot)
|
|||
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||
if (getstatus) {
|
||||
p_slot->state = BLINKINGOFF_STATE;
|
||||
info(msg_button_off, p_slot->name);
|
||||
info("PCI slot #%s - powering off due to button "
|
||||
"press.\n", p_slot->name);
|
||||
} else {
|
||||
p_slot->state = BLINKINGON_STATE;
|
||||
info(msg_button_on, p_slot->name);
|
||||
info("PCI slot #%s - powering on due to button "
|
||||
"press.\n", p_slot->name);
|
||||
}
|
||||
/* blink green LED and turn off amber */
|
||||
p_slot->hpc_ops->green_led_blink(p_slot);
|
||||
|
@ -523,7 +521,8 @@ static void handle_button_press_event(struct slot *p_slot)
|
|||
else
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||
info(msg_button_cancel, p_slot->name);
|
||||
info("PCI slot #%s - action canceled due to button press\n",
|
||||
p_slot->name);
|
||||
p_slot->state = STATIC_STATE;
|
||||
break;
|
||||
case POWEROFF_STATE:
|
||||
|
|
|
@ -212,44 +212,40 @@
|
|||
#define SLOT_SERR_INT_MASK 0x3
|
||||
|
||||
DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
|
||||
static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */
|
||||
static int ctlr_seq_num = 0; /* Controller sequenc # */
|
||||
static spinlock_t list_lock;
|
||||
|
||||
static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
|
||||
|
||||
static irqreturn_t shpc_isr(int irq, void *dev_id);
|
||||
static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec);
|
||||
static void start_int_poll_timer(struct controller *ctrl, int sec);
|
||||
static int hpc_check_cmd_status(struct controller *ctrl);
|
||||
|
||||
static inline u8 shpc_readb(struct controller *ctrl, int reg)
|
||||
{
|
||||
return readb(ctrl->hpc_ctlr_handle->creg + reg);
|
||||
return readb(ctrl->creg + reg);
|
||||
}
|
||||
|
||||
static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val)
|
||||
{
|
||||
writeb(val, ctrl->hpc_ctlr_handle->creg + reg);
|
||||
writeb(val, ctrl->creg + reg);
|
||||
}
|
||||
|
||||
static inline u16 shpc_readw(struct controller *ctrl, int reg)
|
||||
{
|
||||
return readw(ctrl->hpc_ctlr_handle->creg + reg);
|
||||
return readw(ctrl->creg + reg);
|
||||
}
|
||||
|
||||
static inline void shpc_writew(struct controller *ctrl, int reg, u16 val)
|
||||
{
|
||||
writew(val, ctrl->hpc_ctlr_handle->creg + reg);
|
||||
writew(val, ctrl->creg + reg);
|
||||
}
|
||||
|
||||
static inline u32 shpc_readl(struct controller *ctrl, int reg)
|
||||
{
|
||||
return readl(ctrl->hpc_ctlr_handle->creg + reg);
|
||||
return readl(ctrl->creg + reg);
|
||||
}
|
||||
|
||||
static inline void shpc_writel(struct controller *ctrl, int reg, u32 val)
|
||||
{
|
||||
writel(val, ctrl->hpc_ctlr_handle->creg + reg);
|
||||
writel(val, ctrl->creg + reg);
|
||||
}
|
||||
|
||||
static inline int shpc_indirect_read(struct controller *ctrl, int index,
|
||||
|
@ -268,21 +264,20 @@ static inline int shpc_indirect_read(struct controller *ctrl, int index,
|
|||
/*
|
||||
* This is the interrupt polling timeout function.
|
||||
*/
|
||||
static void int_poll_timeout(unsigned long lphp_ctlr)
|
||||
static void int_poll_timeout(unsigned long data)
|
||||
{
|
||||
struct php_ctlr_state_s *php_ctlr =
|
||||
(struct php_ctlr_state_s *)lphp_ctlr;
|
||||
struct controller *ctrl = (struct controller *)data;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
/* Poll for interrupt events. regs == NULL => polling */
|
||||
shpc_isr(0, php_ctlr->callback_instance_id);
|
||||
shpc_isr(0, ctrl);
|
||||
|
||||
init_timer(&php_ctlr->int_poll_timer);
|
||||
init_timer(&ctrl->poll_timer);
|
||||
if (!shpchp_poll_time)
|
||||
shpchp_poll_time = 2; /* default polling interval is 2 sec */
|
||||
|
||||
start_int_poll_timer(php_ctlr, shpchp_poll_time);
|
||||
start_int_poll_timer(ctrl, shpchp_poll_time);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
}
|
||||
|
@ -290,16 +285,16 @@ static void int_poll_timeout(unsigned long lphp_ctlr)
|
|||
/*
|
||||
* This function starts the interrupt polling timer.
|
||||
*/
|
||||
static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec)
|
||||
static void start_int_poll_timer(struct controller *ctrl, int sec)
|
||||
{
|
||||
/* Clamp to sane value */
|
||||
if ((sec <= 0) || (sec > 60))
|
||||
sec = 2;
|
||||
|
||||
php_ctlr->int_poll_timer.function = &int_poll_timeout;
|
||||
php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;
|
||||
php_ctlr->int_poll_timer.expires = jiffies + sec * HZ;
|
||||
add_timer(&php_ctlr->int_poll_timer);
|
||||
ctrl->poll_timer.function = &int_poll_timeout;
|
||||
ctrl->poll_timer.data = (unsigned long)ctrl;
|
||||
ctrl->poll_timer.expires = jiffies + sec * HZ;
|
||||
add_timer(&ctrl->poll_timer);
|
||||
}
|
||||
|
||||
static inline int is_ctrl_busy(struct controller *ctrl)
|
||||
|
@ -666,33 +661,8 @@ static void hpc_set_green_led_blink(struct slot *slot)
|
|||
shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK);
|
||||
}
|
||||
|
||||
int shpc_get_ctlr_slot_config(struct controller *ctrl,
|
||||
int *num_ctlr_slots, /* number of slots in this HPC */
|
||||
int *first_device_num, /* PCI dev num of the first slot in this SHPC */
|
||||
int *physical_slot_num, /* phy slot num of the first slot in this SHPC */
|
||||
int *updown, /* physical_slot_num increament: 1 or -1 */
|
||||
int *flags)
|
||||
{
|
||||
u32 slot_config;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_config = shpc_readl(ctrl, SLOT_CONFIG);
|
||||
*first_device_num = (slot_config & FIRST_DEV_NUM) >> 8;
|
||||
*num_ctlr_slots = slot_config & SLOT_NUM;
|
||||
*physical_slot_num = (slot_config & PSN) >> 16;
|
||||
*updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1;
|
||||
|
||||
dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hpc_release_ctlr(struct controller *ctrl)
|
||||
{
|
||||
struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
|
||||
struct php_ctlr_state_s *p, *p_prev;
|
||||
int i;
|
||||
u32 slot_reg, serr_int;
|
||||
|
||||
|
@ -722,40 +692,15 @@ static void hpc_release_ctlr(struct controller *ctrl)
|
|||
serr_int &= ~SERR_INTR_RSVDZ_MASK;
|
||||
shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
|
||||
|
||||
if (shpchp_poll_mode) {
|
||||
del_timer(&php_ctlr->int_poll_timer);
|
||||
} else {
|
||||
if (php_ctlr->irq) {
|
||||
free_irq(php_ctlr->irq, ctrl);
|
||||
php_ctlr->irq = 0;
|
||||
pci_disable_msi(php_ctlr->pci_dev);
|
||||
}
|
||||
if (shpchp_poll_mode)
|
||||
del_timer(&ctrl->poll_timer);
|
||||
else {
|
||||
free_irq(ctrl->pci_dev->irq, ctrl);
|
||||
pci_disable_msi(ctrl->pci_dev);
|
||||
}
|
||||
|
||||
if (php_ctlr->pci_dev) {
|
||||
iounmap(php_ctlr->creg);
|
||||
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
|
||||
php_ctlr->pci_dev = NULL;
|
||||
}
|
||||
|
||||
spin_lock(&list_lock);
|
||||
p = php_ctlr_list_head;
|
||||
p_prev = NULL;
|
||||
while (p) {
|
||||
if (p == php_ctlr) {
|
||||
if (p_prev)
|
||||
p_prev->pnext = p->pnext;
|
||||
else
|
||||
php_ctlr_list_head = p->pnext;
|
||||
break;
|
||||
} else {
|
||||
p_prev = p;
|
||||
p = p->pnext;
|
||||
}
|
||||
}
|
||||
spin_unlock(&list_lock);
|
||||
|
||||
kfree(php_ctlr);
|
||||
iounmap(ctrl->creg);
|
||||
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
|
||||
|
||||
/*
|
||||
* If this is the last controller to be released, destroy the
|
||||
|
@ -764,8 +709,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
|
|||
if (atomic_dec_and_test(&shpchp_num_controllers))
|
||||
destroy_workqueue(shpchp_wq);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
}
|
||||
|
||||
static int hpc_power_on_slot(struct slot * slot)
|
||||
|
@ -891,7 +835,6 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
|
|||
static irqreturn_t shpc_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *)dev_id;
|
||||
struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
|
||||
u32 serr_int, slot_reg, intr_loc, intr_loc2;
|
||||
int hp_slot;
|
||||
|
||||
|
@ -942,20 +885,16 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
|
|||
__FUNCTION__, hp_slot, slot_reg);
|
||||
|
||||
if (slot_reg & MRL_CHANGE_DETECTED)
|
||||
php_ctlr->switch_change_callback(
|
||||
hp_slot, php_ctlr->callback_instance_id);
|
||||
shpchp_handle_switch_change(hp_slot, ctrl);
|
||||
|
||||
if (slot_reg & BUTTON_PRESS_DETECTED)
|
||||
php_ctlr->attention_button_callback(
|
||||
hp_slot, php_ctlr->callback_instance_id);
|
||||
shpchp_handle_attention_button(hp_slot, ctrl);
|
||||
|
||||
if (slot_reg & PRSNT_CHANGE_DETECTED)
|
||||
php_ctlr->presence_change_callback(
|
||||
hp_slot , php_ctlr->callback_instance_id);
|
||||
shpchp_handle_presence_change(hp_slot, ctrl);
|
||||
|
||||
if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))
|
||||
php_ctlr->power_fault_callback(
|
||||
hp_slot, php_ctlr->callback_instance_id);
|
||||
shpchp_handle_power_fault(hp_slot, ctrl);
|
||||
|
||||
/* Clear all slot events */
|
||||
slot_reg &= ~SLOT_REG_RSVDZ_MASK;
|
||||
|
@ -1114,10 +1053,8 @@ static struct hpc_ops shpchp_hpc_ops = {
|
|||
.release_ctlr = hpc_release_ctlr,
|
||||
};
|
||||
|
||||
int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
||||
int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
|
||||
{
|
||||
struct php_ctlr_state_s *php_ctlr, *p;
|
||||
void *instance_id = ctrl;
|
||||
int rc = -1, num_slots = 0;
|
||||
u8 hp_slot;
|
||||
u32 shpc_base_offset;
|
||||
|
@ -1128,16 +1065,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
|
||||
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
|
||||
|
||||
spin_lock_init(&list_lock);
|
||||
php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL);
|
||||
|
||||
if (!php_ctlr) { /* allocate controller state data */
|
||||
err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
php_ctlr->pci_dev = pdev; /* save pci_dev in context */
|
||||
|
||||
if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
|
||||
PCI_DEVICE_ID_AMD_GOLAM_7450)) {
|
||||
/* amd shpc driver doesn't use Base Offset; assume 0 */
|
||||
|
@ -1147,20 +1074,20 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
|
||||
if (!ctrl->cap_offset) {
|
||||
err("%s : cap_offset == 0\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
goto abort;
|
||||
}
|
||||
dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
|
||||
|
||||
rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
|
||||
if (rc) {
|
||||
err("%s: cannot read base_offset\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
rc = shpc_indirect_read(ctrl, 3, &tempdword);
|
||||
if (rc) {
|
||||
err("%s: cannot read slot config\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
goto abort;
|
||||
}
|
||||
num_slots = tempdword & SLOT_NUM;
|
||||
dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
|
||||
|
@ -1170,7 +1097,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
if (rc) {
|
||||
err("%s: cannot read creg (index = %d)\n",
|
||||
__FUNCTION__, i);
|
||||
goto abort_free_ctlr;
|
||||
goto abort;
|
||||
}
|
||||
dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
|
||||
tempdword);
|
||||
|
@ -1187,24 +1114,24 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
rc = pci_enable_device(pdev);
|
||||
if (rc) {
|
||||
err("%s: pci_enable_device failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
|
||||
err("%s: cannot reserve MMIO region\n", __FUNCTION__);
|
||||
rc = -1;
|
||||
goto abort_free_ctlr;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
|
||||
if (!php_ctlr->creg) {
|
||||
ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
|
||||
if (!ctrl->creg) {
|
||||
err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
|
||||
ctrl->mmio_size, ctrl->mmio_base);
|
||||
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
|
||||
rc = -1;
|
||||
goto abort_free_ctlr;
|
||||
goto abort;
|
||||
}
|
||||
dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
|
||||
dbg("%s: ctrl->creg %p\n", __FUNCTION__, ctrl->creg);
|
||||
|
||||
mutex_init(&ctrl->crit_sect);
|
||||
mutex_init(&ctrl->cmd_lock);
|
||||
|
@ -1212,23 +1139,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
/* Setup wait queue */
|
||||
init_waitqueue_head(&ctrl->queue);
|
||||
|
||||
/* Find the IRQ */
|
||||
php_ctlr->irq = pdev->irq;
|
||||
php_ctlr->attention_button_callback = shpchp_handle_attention_button,
|
||||
php_ctlr->switch_change_callback = shpchp_handle_switch_change;
|
||||
php_ctlr->presence_change_callback = shpchp_handle_presence_change;
|
||||
php_ctlr->power_fault_callback = shpchp_handle_power_fault;
|
||||
php_ctlr->callback_instance_id = instance_id;
|
||||
|
||||
ctrl->hpc_ctlr_handle = php_ctlr;
|
||||
ctrl->hpc_ops = &shpchp_hpc_ops;
|
||||
|
||||
/* Return PCI Controller Info */
|
||||
slot_config = shpc_readl(ctrl, SLOT_CONFIG);
|
||||
php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
|
||||
php_ctlr->num_slots = slot_config & SLOT_NUM;
|
||||
dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset);
|
||||
dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots);
|
||||
ctrl->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
|
||||
ctrl->num_slots = slot_config & SLOT_NUM;
|
||||
ctrl->first_slot = (slot_config & PSN) >> 16;
|
||||
ctrl->slot_num_inc = ((slot_config & UPDOWN) >> 29) ? 1 : -1;
|
||||
|
||||
/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
|
||||
tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
|
||||
|
@ -1243,7 +1161,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
/* Mask the MRL sensor SERR Mask of individual slot in
|
||||
* Slot SERR-INT Mask & clear all the existing event if any
|
||||
*/
|
||||
for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
|
||||
for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
|
||||
slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
|
||||
dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
|
||||
hp_slot, slot_reg);
|
||||
|
@ -1255,24 +1173,27 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
|
||||
}
|
||||
|
||||
if (shpchp_poll_mode) {/* Install interrupt polling code */
|
||||
/* Install and start the interrupt polling timer */
|
||||
init_timer(&php_ctlr->int_poll_timer);
|
||||
start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */
|
||||
if (shpchp_poll_mode) {
|
||||
/* Install interrupt polling timer. Start with 10 sec delay */
|
||||
init_timer(&ctrl->poll_timer);
|
||||
start_int_poll_timer(ctrl, 10);
|
||||
} else {
|
||||
/* Installs the interrupt handler */
|
||||
rc = pci_enable_msi(pdev);
|
||||
if (rc) {
|
||||
info("Can't get msi for the hotplug controller\n");
|
||||
info("Use INTx for the hotplug controller\n");
|
||||
} else
|
||||
php_ctlr->irq = pdev->irq;
|
||||
}
|
||||
|
||||
rc = request_irq(php_ctlr->irq, shpc_isr, IRQF_SHARED, MY_NAME, (void *) ctrl);
|
||||
dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
|
||||
rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
|
||||
MY_NAME, (void *)ctrl);
|
||||
dbg("%s: request_irq %d for hpc%d (returns %d)\n",
|
||||
__FUNCTION__, ctrl->pci_dev->irq,
|
||||
atomic_read(&shpchp_num_controllers), rc);
|
||||
if (rc) {
|
||||
err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
|
||||
goto abort_free_ctlr;
|
||||
err("Can't get irq %d for the hotplug controller\n",
|
||||
ctrl->pci_dev->irq);
|
||||
goto abort_iounmap;
|
||||
}
|
||||
}
|
||||
dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__,
|
||||
|
@ -1280,24 +1201,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
PCI_FUNC(pdev->devfn), pdev->irq);
|
||||
get_hp_hw_control_from_firmware(pdev);
|
||||
|
||||
/* Add this HPC instance into the HPC list */
|
||||
spin_lock(&list_lock);
|
||||
if (php_ctlr_list_head == 0) {
|
||||
php_ctlr_list_head = php_ctlr;
|
||||
p = php_ctlr_list_head;
|
||||
p->pnext = NULL;
|
||||
} else {
|
||||
p = php_ctlr_list_head;
|
||||
|
||||
while (p->pnext)
|
||||
p = p->pnext;
|
||||
|
||||
p->pnext = php_ctlr;
|
||||
}
|
||||
spin_unlock(&list_lock);
|
||||
|
||||
ctlr_seq_num++;
|
||||
|
||||
/*
|
||||
* If this is the first controller to be initialized,
|
||||
* initialize the shpchpd work queue
|
||||
|
@ -1306,14 +1209,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
shpchp_wq = create_singlethread_workqueue("shpchpd");
|
||||
if (!shpchp_wq) {
|
||||
rc = -ENOMEM;
|
||||
goto abort_free_ctlr;
|
||||
goto abort_iounmap;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmask all event interrupts of all slots
|
||||
*/
|
||||
for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
|
||||
for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
|
||||
slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
|
||||
dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
|
||||
hp_slot, slot_reg);
|
||||
|
@ -1336,10 +1239,8 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
|
|||
return 0;
|
||||
|
||||
/* We end up here for the many possible ways to fail this API. */
|
||||
abort_free_ctlr:
|
||||
if (php_ctlr->creg)
|
||||
iounmap(php_ctlr->creg);
|
||||
kfree(php_ctlr);
|
||||
abort_iounmap:
|
||||
iounmap(ctrl->creg);
|
||||
abort:
|
||||
DBG_LEAVE_ROUTINE
|
||||
return rc;
|
||||
|
|
|
@ -99,14 +99,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
|
|||
int pos;
|
||||
int irq;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_HT);
|
||||
while (pos) {
|
||||
u8 subtype;
|
||||
pci_read_config_byte(dev, pos + 3, &subtype);
|
||||
if (subtype == HT_CAPTYPE_IRQ)
|
||||
break;
|
||||
pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT);
|
||||
}
|
||||
pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);
|
||||
if (!pos)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -162,14 +162,9 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
|
|||
const struct pci_device_id *pci_match_device(struct pci_driver *drv,
|
||||
struct pci_dev *dev)
|
||||
{
|
||||
const struct pci_device_id *id;
|
||||
struct pci_dynid *dynid;
|
||||
|
||||
id = pci_match_id(drv->id_table, dev);
|
||||
if (id)
|
||||
return id;
|
||||
|
||||
/* static ids didn't match, lets look at the dynamic ones */
|
||||
/* Look at the dynamic ids first, before the static ones */
|
||||
spin_lock(&drv->dynids.lock);
|
||||
list_for_each_entry(dynid, &drv->dynids.list, node) {
|
||||
if (pci_match_one_device(&dynid->id, dev)) {
|
||||
|
@ -178,7 +173,8 @@ const struct pci_device_id *pci_match_device(struct pci_driver *drv,
|
|||
}
|
||||
}
|
||||
spin_unlock(&drv->dynids.lock);
|
||||
return NULL;
|
||||
|
||||
return pci_match_id(drv->id_table, dev);
|
||||
}
|
||||
|
||||
static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
|
||||
|
@ -357,6 +353,8 @@ static int pci_device_resume_early(struct device * dev)
|
|||
struct pci_dev * pci_dev = to_pci_dev(dev);
|
||||
struct pci_driver * drv = pci_dev->driver;
|
||||
|
||||
pci_fixup_device(pci_fixup_resume, pci_dev);
|
||||
|
||||
if (drv && drv->resume_early)
|
||||
error = drv->resume_early(pci_dev);
|
||||
return error;
|
||||
|
|
|
@ -68,12 +68,14 @@ pci_max_busnr(void)
|
|||
|
||||
#endif /* 0 */
|
||||
|
||||
static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap)
|
||||
#define PCI_FIND_CAP_TTL 48
|
||||
|
||||
static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
|
||||
u8 pos, int cap, int *ttl)
|
||||
{
|
||||
u8 id;
|
||||
int ttl = 48;
|
||||
|
||||
while (ttl--) {
|
||||
while ((*ttl)--) {
|
||||
pci_bus_read_config_byte(bus, devfn, pos, &pos);
|
||||
if (pos < 0x40)
|
||||
break;
|
||||
|
@ -89,6 +91,14 @@ static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
|
||||
u8 pos, int cap)
|
||||
{
|
||||
int ttl = PCI_FIND_CAP_TTL;
|
||||
|
||||
return __pci_find_next_cap_ttl(bus, devfn, pos, cap, &ttl);
|
||||
}
|
||||
|
||||
int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
|
||||
{
|
||||
return __pci_find_next_cap(dev->bus, dev->devfn,
|
||||
|
@ -96,10 +106,10 @@ int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pci_find_next_capability);
|
||||
|
||||
static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap)
|
||||
static int __pci_bus_find_cap_start(struct pci_bus *bus,
|
||||
unsigned int devfn, u8 hdr_type)
|
||||
{
|
||||
u16 status;
|
||||
u8 pos;
|
||||
|
||||
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
|
||||
if (!(status & PCI_STATUS_CAP_LIST))
|
||||
|
@ -108,15 +118,14 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
|
|||
switch (hdr_type) {
|
||||
case PCI_HEADER_TYPE_NORMAL:
|
||||
case PCI_HEADER_TYPE_BRIDGE:
|
||||
pos = PCI_CAPABILITY_LIST;
|
||||
break;
|
||||
return PCI_CAPABILITY_LIST;
|
||||
case PCI_HEADER_TYPE_CARDBUS:
|
||||
pos = PCI_CB_CAPABILITY_LIST;
|
||||
break;
|
||||
return PCI_CB_CAPABILITY_LIST;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return __pci_find_next_cap(bus, devfn, pos, cap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -140,7 +149,13 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
|
|||
*/
|
||||
int pci_find_capability(struct pci_dev *dev, int cap)
|
||||
{
|
||||
return __pci_bus_find_cap(dev->bus, dev->devfn, dev->hdr_type, cap);
|
||||
int pos;
|
||||
|
||||
pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
|
||||
if (pos)
|
||||
pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,11 +173,16 @@ int pci_find_capability(struct pci_dev *dev, int cap)
|
|||
*/
|
||||
int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
|
||||
{
|
||||
int pos;
|
||||
u8 hdr_type;
|
||||
|
||||
pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
|
||||
|
||||
return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap);
|
||||
pos = __pci_bus_find_cap_start(bus, devfn, hdr_type & 0x7f);
|
||||
if (pos)
|
||||
pos = __pci_find_next_cap(bus, devfn, pos, cap);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -214,6 +234,74 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pci_find_ext_capability);
|
||||
|
||||
static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
|
||||
{
|
||||
int rc, ttl = PCI_FIND_CAP_TTL;
|
||||
u8 cap, mask;
|
||||
|
||||
if (ht_cap == HT_CAPTYPE_SLAVE || ht_cap == HT_CAPTYPE_HOST)
|
||||
mask = HT_3BIT_CAP_MASK;
|
||||
else
|
||||
mask = HT_5BIT_CAP_MASK;
|
||||
|
||||
pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, pos,
|
||||
PCI_CAP_ID_HT, &ttl);
|
||||
while (pos) {
|
||||
rc = pci_read_config_byte(dev, pos + 3, &cap);
|
||||
if (rc != PCIBIOS_SUCCESSFUL)
|
||||
return 0;
|
||||
|
||||
if ((cap & mask) == ht_cap)
|
||||
return pos;
|
||||
|
||||
pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, pos,
|
||||
PCI_CAP_ID_HT, &ttl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* pci_find_next_ht_capability - query a device's Hypertransport capabilities
|
||||
* @dev: PCI device to query
|
||||
* @pos: Position from which to continue searching
|
||||
* @ht_cap: Hypertransport capability code
|
||||
*
|
||||
* To be used in conjunction with pci_find_ht_capability() to search for
|
||||
* all capabilities matching @ht_cap. @pos should always be a value returned
|
||||
* from pci_find_ht_capability().
|
||||
*
|
||||
* NB. To be 100% safe against broken PCI devices, the caller should take
|
||||
* steps to avoid an infinite loop.
|
||||
*/
|
||||
int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap)
|
||||
{
|
||||
return __pci_find_next_ht_cap(dev, pos + PCI_CAP_LIST_NEXT, ht_cap);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_find_next_ht_capability);
|
||||
|
||||
/**
|
||||
* pci_find_ht_capability - query a device's Hypertransport capabilities
|
||||
* @dev: PCI device to query
|
||||
* @ht_cap: Hypertransport capability code
|
||||
*
|
||||
* Tell if a device supports a given Hypertransport capability.
|
||||
* Returns an address within the device's PCI configuration space
|
||||
* or 0 in case the device does not support the request capability.
|
||||
* The address points to the PCI capability, of type PCI_CAP_ID_HT,
|
||||
* which has a Hypertransport capability matching @ht_cap.
|
||||
*/
|
||||
int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
|
||||
{
|
||||
int pos;
|
||||
|
||||
pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
|
||||
if (pos)
|
||||
pos = __pci_find_next_ht_cap(dev, pos, ht_cap);
|
||||
|
||||
return pos;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_find_ht_capability);
|
||||
|
||||
/**
|
||||
* pci_find_parent_resource - return resource region of parent bus of given region
|
||||
* @dev: PCI device structure contains resources to be searched
|
||||
|
|
|
@ -90,7 +90,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
|
|||
return -ENODEV;
|
||||
|
||||
pci_set_master(dev);
|
||||
if (!dev->irq) {
|
||||
if (!dev->irq && dev->pin) {
|
||||
printk(KERN_WARNING
|
||||
"%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n",
|
||||
__FUNCTION__, dev->device, dev->vendor);
|
||||
|
|
|
@ -649,6 +649,9 @@ static void pci_read_irq(struct pci_dev *dev)
|
|||
* Returns 0 on success and -1 if unknown type of device (not normal, bridge
|
||||
* or CardBus).
|
||||
*/
|
||||
|
||||
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
|
||||
|
||||
static int pci_setup_device(struct pci_dev * dev)
|
||||
{
|
||||
u32 class;
|
||||
|
@ -692,18 +695,18 @@ static int pci_setup_device(struct pci_dev * dev)
|
|||
if ((progif & 1) == 0) {
|
||||
dev->resource[0].start = 0x1F0;
|
||||
dev->resource[0].end = 0x1F7;
|
||||
dev->resource[0].flags = IORESOURCE_IO;
|
||||
dev->resource[0].flags = LEGACY_IO_RESOURCE;
|
||||
dev->resource[1].start = 0x3F6;
|
||||
dev->resource[1].end = 0x3F6;
|
||||
dev->resource[1].flags = IORESOURCE_IO;
|
||||
dev->resource[1].flags = LEGACY_IO_RESOURCE;
|
||||
}
|
||||
if ((progif & 4) == 0) {
|
||||
dev->resource[2].start = 0x170;
|
||||
dev->resource[2].end = 0x177;
|
||||
dev->resource[2].flags = IORESOURCE_IO;
|
||||
dev->resource[2].flags = LEGACY_IO_RESOURCE;
|
||||
dev->resource[3].start = 0x376;
|
||||
dev->resource[3].end = 0x376;
|
||||
dev->resource[3].flags = IORESOURCE_IO;
|
||||
dev->resource[3].flags = LEGACY_IO_RESOURCE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -36,7 +36,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRID
|
|||
|
||||
/* Deal with broken BIOS'es that neglect to enable passive release,
|
||||
which can cause problems in combination with the 82441FX/PPro MTRRs */
|
||||
static void __devinit quirk_passive_release(struct pci_dev *dev)
|
||||
static void quirk_passive_release(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *d = NULL;
|
||||
unsigned char dlc;
|
||||
|
@ -53,6 +53,7 @@ static void __devinit quirk_passive_release(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release );
|
||||
|
||||
/* The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
|
||||
but VIA don't answer queries. If you happen to have good contacts at VIA
|
||||
|
@ -134,7 +135,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quir
|
|||
* Updated based on further information from the site and also on
|
||||
* information provided by VIA
|
||||
*/
|
||||
static void __devinit quirk_vialatency(struct pci_dev *dev)
|
||||
static void quirk_vialatency(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *p;
|
||||
u8 rev;
|
||||
|
@ -185,6 +186,10 @@ exit:
|
|||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency );
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency );
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency );
|
||||
/* Must restore this on a resume from RAM */
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency );
|
||||
|
||||
/*
|
||||
* VIA Apollo VP3 needs ETBF on BT848/878
|
||||
|
@ -532,7 +537,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235
|
|||
* TODO: When we have device-specific interrupt routers,
|
||||
* this code will go away from quirks.
|
||||
*/
|
||||
static void __devinit quirk_via_ioapic(struct pci_dev *dev)
|
||||
static void quirk_via_ioapic(struct pci_dev *dev)
|
||||
{
|
||||
u8 tmp;
|
||||
|
||||
|
@ -548,6 +553,7 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev)
|
|||
pci_write_config_byte (dev, 0x58, tmp);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
|
||||
|
||||
/*
|
||||
* VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit.
|
||||
|
@ -555,7 +561,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_i
|
|||
* Set this bit to get rid of cycle wastage.
|
||||
* Otherwise uncritical.
|
||||
*/
|
||||
static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
|
||||
static void quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
|
||||
{
|
||||
u8 misc_control2;
|
||||
#define BYPASS_APIC_DEASSERT 8
|
||||
|
@ -567,6 +573,7 @@ static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_vt8237_bypass_apic_deassert);
|
||||
|
||||
/*
|
||||
* The AMD io apic can hang the box when an apic irq is masked.
|
||||
|
@ -600,7 +607,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw );
|
|||
#define AMD8131_revB0 0x11
|
||||
#define AMD8131_MISC 0x40
|
||||
#define AMD8131_NIOAMODE_BIT 0
|
||||
static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
|
||||
static void quirk_amd_8131_ioapic(struct pci_dev *dev)
|
||||
{
|
||||
unsigned char revid, tmp;
|
||||
|
||||
|
@ -616,6 +623,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
|
||||
#endif /* CONFIG_X86_IO_APIC */
|
||||
|
||||
|
||||
|
@ -641,65 +649,84 @@ static void __devinit quirk_via_acpi(struct pci_dev *d)
|
|||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi );
|
||||
|
||||
/*
|
||||
* Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip
|
||||
* devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
|
||||
* when written, it makes an internal connection to the PIC.
|
||||
* For these devices, this register is defined to be 4 bits wide.
|
||||
* Normally this is fine. However for IO-APIC motherboards, or
|
||||
* non-x86 architectures (yes Via exists on PPC among other places),
|
||||
* we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
|
||||
* interrupts delivered properly.
|
||||
*
|
||||
* Some of the on-chip devices are actually '586 devices' so they are
|
||||
* listed here.
|
||||
*/
|
||||
|
||||
static int via_irq_fixup_needed = -1;
|
||||
|
||||
/*
|
||||
* As some VIA hardware is available in PCI-card form, we need to restrict
|
||||
* this quirk to VIA PCI hardware built onto VIA-based motherboards only.
|
||||
* We try to locate a VIA southbridge before deciding whether the quirk
|
||||
* should be applied.
|
||||
* VIA bridges which have VLink
|
||||
*/
|
||||
static const struct pci_device_id via_irq_fixup_tbl[] = {
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.class = PCI_CLASS_BRIDGE_ISA << 8,
|
||||
.class_mask = 0xffff00,
|
||||
},
|
||||
|
||||
static const struct pci_device_id via_vlink_fixup_tbl[] = {
|
||||
/* Internal devices need IRQ line routing, pre VLink */
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686), 0 },
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8231), 17 },
|
||||
/* Devices with VLink */
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_0), 17},
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233A), 17 },
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233C_0), 17 },
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8235), 16 },
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237), 15 },
|
||||
{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237A), 15 },
|
||||
{ 0, },
|
||||
};
|
||||
|
||||
static void quirk_via_irq(struct pci_dev *dev)
|
||||
/**
|
||||
* quirk_via_vlink - VIA VLink IRQ number update
|
||||
* @dev: PCI device
|
||||
*
|
||||
* If the device we are dealing with is on a PIC IRQ we need to
|
||||
* ensure that the IRQ line register which usually is not relevant
|
||||
* for PCI cards, is actually written so that interrupts get sent
|
||||
* to the right place
|
||||
*/
|
||||
|
||||
static void quirk_via_vlink(struct pci_dev *dev)
|
||||
{
|
||||
const struct pci_device_id *via_vlink_fixup;
|
||||
static int dev_lo = -1, dev_hi = 18;
|
||||
u8 irq, new_irq;
|
||||
|
||||
if (via_irq_fixup_needed == -1)
|
||||
via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl);
|
||||
/* Check if we have VLink and cache the result */
|
||||
|
||||
if (!via_irq_fixup_needed)
|
||||
/* Checked already - no */
|
||||
if (dev_lo == -2)
|
||||
return;
|
||||
|
||||
/* Not checked - see what bridge we have and find the device
|
||||
ranges */
|
||||
|
||||
if (dev_lo == -1) {
|
||||
via_vlink_fixup = pci_find_present(via_vlink_fixup_tbl);
|
||||
if (via_vlink_fixup == NULL) {
|
||||
dev_lo = -2;
|
||||
return;
|
||||
}
|
||||
dev_lo = via_vlink_fixup->driver_data;
|
||||
/* 82C686 is special - 0/0 */
|
||||
if (dev_lo == 0)
|
||||
dev_hi = 0;
|
||||
}
|
||||
new_irq = dev->irq;
|
||||
|
||||
/* Don't quirk interrupts outside the legacy IRQ range */
|
||||
if (!new_irq || new_irq > 15)
|
||||
return;
|
||||
|
||||
/* Internal device ? */
|
||||
if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) > dev_hi ||
|
||||
PCI_SLOT(dev->devfn) < dev_lo)
|
||||
return;
|
||||
|
||||
/* This is an internal VLink device on a PIC interrupt. The BIOS
|
||||
ought to have set this but may not have, so we redo it */
|
||||
|
||||
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
|
||||
if (new_irq != irq) {
|
||||
printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n",
|
||||
printk(KERN_INFO "PCI: VIA VLink IRQ fixup for %s, from %d to %d\n",
|
||||
pci_name(dev), irq, new_irq);
|
||||
udelay(15); /* unknown if delay really needed */
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_vlink);
|
||||
|
||||
/*
|
||||
* VIA VT82C598 has its device ID settable and many BIOSes
|
||||
|
@ -720,13 +747,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt
|
|||
* do this even if the Linux CardBus driver is not loaded, because
|
||||
* the Linux i82365 driver does not (and should not) handle CardBus.
|
||||
*/
|
||||
static void __devinit quirk_cardbus_legacy(struct pci_dev *dev)
|
||||
static void quirk_cardbus_legacy(struct pci_dev *dev)
|
||||
{
|
||||
if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class)
|
||||
return;
|
||||
pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy);
|
||||
|
||||
/*
|
||||
* Following the PCI ordering rules is optional on the AMD762. I'm not
|
||||
|
@ -735,7 +763,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy);
|
|||
* To be fair to AMD, it follows the spec by default, its BIOS people
|
||||
* who turn it off!
|
||||
*/
|
||||
static void __devinit quirk_amd_ordering(struct pci_dev *dev)
|
||||
static void quirk_amd_ordering(struct pci_dev *dev)
|
||||
{
|
||||
u32 pcic;
|
||||
pci_read_config_dword(dev, 0x4C, &pcic);
|
||||
|
@ -749,6 +777,7 @@ static void __devinit quirk_amd_ordering(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
|
||||
|
||||
/*
|
||||
* DreamWorks provided workaround for Dunord I-3000 problem
|
||||
|
@ -784,7 +813,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge
|
|||
* datasheets found at http://www.national.com/ds/GX for info on what
|
||||
* these bits do. <christer@weinigel.se>
|
||||
*/
|
||||
static void __init quirk_mediagx_master(struct pci_dev *dev)
|
||||
static void quirk_mediagx_master(struct pci_dev *dev)
|
||||
{
|
||||
u8 reg;
|
||||
pci_read_config_byte(dev, 0x41, ®);
|
||||
|
@ -795,13 +824,14 @@ static void __init quirk_mediagx_master(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
|
||||
|
||||
/*
|
||||
* Ensure C0 rev restreaming is off. This is normally done by
|
||||
* the BIOS but in the odd case it is not the results are corruption
|
||||
* hence the presence of a Linux check
|
||||
*/
|
||||
static void __init quirk_disable_pxb(struct pci_dev *pdev)
|
||||
static void quirk_disable_pxb(struct pci_dev *pdev)
|
||||
{
|
||||
u16 config;
|
||||
u8 rev;
|
||||
|
@ -817,8 +847,26 @@ static void __init quirk_disable_pxb(struct pci_dev *pdev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
|
||||
|
||||
|
||||
static void __devinit quirk_sb600_sata(struct pci_dev *pdev)
|
||||
{
|
||||
/* set sb600 sata to ahci mode */
|
||||
if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
|
||||
u8 tmp;
|
||||
|
||||
pci_read_config_byte(pdev, 0x40, &tmp);
|
||||
pci_write_config_byte(pdev, 0x40, tmp|1);
|
||||
pci_write_config_byte(pdev, 0x9, 1);
|
||||
pci_write_config_byte(pdev, 0xa, 6);
|
||||
pci_write_config_byte(pdev, 0x40, tmp);
|
||||
|
||||
pdev->class = 0x010601;
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_sb600_sata);
|
||||
|
||||
/*
|
||||
* Serverworks CSB5 IDE does not fully support native mode
|
||||
*/
|
||||
|
@ -874,7 +922,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e
|
|||
* runs everywhere at present we suppress the printk output in most
|
||||
* irrelevant cases.
|
||||
*/
|
||||
static void __init k8t_sound_hostbridge(struct pci_dev *dev)
|
||||
static void k8t_sound_hostbridge(struct pci_dev *dev)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
|
@ -893,8 +941,8 @@ static void __init k8t_sound_hostbridge(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
|
||||
|
||||
#ifndef CONFIG_ACPI_SLEEP
|
||||
/*
|
||||
* On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
|
||||
* is not activated. The myth is that Asus said that they do not want the
|
||||
|
@ -906,10 +954,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_ho
|
|||
* bridge. Unfortunately, this device has no subvendor/subdevice ID. So it
|
||||
* becomes necessary to do this tweak in two steps -- I've chosen the Host
|
||||
* bridge as trigger.
|
||||
*
|
||||
* Actually, leaving it unhidden and not redoing the quirk over suspend2ram
|
||||
* will cause thermal management to break down, and causing machine to
|
||||
* overheat.
|
||||
*/
|
||||
static int __initdata asus_hides_smbus;
|
||||
|
||||
|
@ -1019,7 +1063,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, as
|
|||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
|
||||
|
||||
static void __init asus_hides_smbus_lpc(struct pci_dev *dev)
|
||||
static void asus_hides_smbus_lpc(struct pci_dev *dev)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
|
@ -1042,8 +1086,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asu
|
|||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
|
||||
|
||||
static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
|
||||
static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
|
||||
{
|
||||
u32 val, rcba;
|
||||
void __iomem *base;
|
||||
|
@ -1059,13 +1109,12 @@ static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
|
|||
printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
|
||||
|
||||
#endif
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
|
||||
|
||||
/*
|
||||
* SiS 96x south bridge: BIOS typically hides SMBus device...
|
||||
*/
|
||||
static void __init quirk_sis_96x_smbus(struct pci_dev *dev)
|
||||
static void quirk_sis_96x_smbus(struct pci_dev *dev)
|
||||
{
|
||||
u8 val = 0;
|
||||
printk(KERN_INFO "Enabling SiS 96x SMBus.\n");
|
||||
|
@ -1086,7 +1135,7 @@ static int __devinitdata sis_96x_compatible = 0;
|
|||
|
||||
#define SIS_DETECT_REGISTER 0x40
|
||||
|
||||
static void __init quirk_sis_503(struct pci_dev *dev)
|
||||
static void quirk_sis_503(struct pci_dev *dev)
|
||||
{
|
||||
u8 reg;
|
||||
u16 devid;
|
||||
|
@ -1122,13 +1171,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_
|
|||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible );
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
|
||||
/*
|
||||
* On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller
|
||||
* and MC97 modem controller are disabled when a second PCI soundcard is
|
||||
* present. This patch, tweaking the VT8237 ISA bridge, enables them.
|
||||
* -- bjd
|
||||
*/
|
||||
static void __init asus_hides_ac97_lpc(struct pci_dev *dev)
|
||||
static void asus_hides_ac97_lpc(struct pci_dev *dev)
|
||||
{
|
||||
u8 val;
|
||||
int asus_hides_ac97 = 0;
|
||||
|
@ -1159,6 +1209,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_
|
|||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
|
||||
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
|
||||
|
||||
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
|
||||
|
||||
#if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE)
|
||||
|
||||
/*
|
||||
|
@ -1167,7 +1225,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_
|
|||
* the PCI scanning.
|
||||
*/
|
||||
|
||||
static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev)
|
||||
static void quirk_jmicron_dualfn(struct pci_dev *pdev)
|
||||
{
|
||||
u32 conf;
|
||||
u8 hdr;
|
||||
|
@ -1205,6 +1263,7 @@ static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1532,6 +1591,8 @@ extern struct pci_fixup __start_pci_fixups_final[];
|
|||
extern struct pci_fixup __end_pci_fixups_final[];
|
||||
extern struct pci_fixup __start_pci_fixups_enable[];
|
||||
extern struct pci_fixup __end_pci_fixups_enable[];
|
||||
extern struct pci_fixup __start_pci_fixups_resume[];
|
||||
extern struct pci_fixup __end_pci_fixups_resume[];
|
||||
|
||||
|
||||
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
|
||||
|
@ -1559,6 +1620,11 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
|
|||
end = __end_pci_fixups_enable;
|
||||
break;
|
||||
|
||||
case pci_fixup_resume:
|
||||
start = __start_pci_fixups_resume;
|
||||
end = __end_pci_fixups_resume;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* stupid compiler warning, you would think with an enum... */
|
||||
return;
|
||||
|
@ -1596,7 +1662,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io);
|
|||
* Force it to be linked by setting the corresponding control bit in the
|
||||
* config space.
|
||||
*/
|
||||
static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
|
||||
static void quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
|
||||
{
|
||||
uint8_t b;
|
||||
if (pci_read_config_byte(dev, 0xf41, &b) == 0) {
|
||||
|
@ -1610,6 +1676,8 @@ static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
|
|||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
|
||||
quirk_nvidia_ck804_pcie_aer_ext_cap);
|
||||
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
|
||||
quirk_nvidia_ck804_pcie_aer_ext_cap);
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
/* To disable MSI globally */
|
||||
|
@ -1644,19 +1712,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_
|
|||
* return 1 if a HT MSI capability is found and enabled */
|
||||
static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
|
||||
{
|
||||
u8 pos;
|
||||
int ttl;
|
||||
for (pos = pci_find_capability(dev, PCI_CAP_ID_HT), ttl = 48;
|
||||
pos && ttl;
|
||||
pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT), ttl--) {
|
||||
u32 cap_hdr;
|
||||
/* MSI mapping section according to Hypertransport spec */
|
||||
if (pci_read_config_dword(dev, pos, &cap_hdr) == 0
|
||||
&& (cap_hdr & 0xf8000000) == 0xa8000000 /* MSI mapping */) {
|
||||
printk(KERN_INFO "PCI: Found HT MSI mapping on %s with capability %s\n",
|
||||
pci_name(dev), cap_hdr & 0x10000 ? "enabled" : "disabled");
|
||||
return (cap_hdr & 0x10000) != 0; /* MSI mapping cap enabled */
|
||||
int pos, ttl = 48;
|
||||
|
||||
pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
|
||||
while (pos && ttl--) {
|
||||
u8 flags;
|
||||
|
||||
if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
|
||||
&flags) == 0)
|
||||
{
|
||||
printk(KERN_INFO "PCI: Found %s HT MSI Mapping on %s\n",
|
||||
flags & HT_MSI_FLAGS_ENABLE ?
|
||||
"enabled" : "disabled", pci_name(dev));
|
||||
return (flags & HT_MSI_FLAGS_ENABLE) != 0;
|
||||
}
|
||||
|
||||
pos = pci_find_next_ht_capability(dev, pos,
|
||||
HT_CAPTYPE_MSI_MAPPING);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1688,8 +1760,9 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
|
|||
* a single one having MSI is enough to be sure that MSI are supported.
|
||||
*/
|
||||
pdev = pci_get_slot(dev->bus, 0);
|
||||
if (dev->subordinate && !msi_ht_cap_enabled(dev)
|
||||
&& !msi_ht_cap_enabled(pdev)) {
|
||||
if (!pdev)
|
||||
return;
|
||||
if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) {
|
||||
printk(KERN_WARNING "PCI: MSI quirk detected. "
|
||||
"MSI disabled on chipset %s.\n",
|
||||
pci_name(dev));
|
||||
|
|
|
@ -413,6 +413,24 @@ exit:
|
|||
return dev;
|
||||
}
|
||||
|
||||
const struct pci_device_id *pci_find_present(const struct pci_device_id *ids)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
const struct pci_device_id *found = NULL;
|
||||
|
||||
WARN_ON(in_interrupt());
|
||||
down_read(&pci_bus_sem);
|
||||
while (ids->vendor || ids->subvendor || ids->class_mask) {
|
||||
list_for_each_entry(dev, &pci_devices, global_list) {
|
||||
if ((found = pci_match_one_device(ids, dev)) != NULL)
|
||||
break;
|
||||
}
|
||||
ids++;
|
||||
}
|
||||
up_read(&pci_bus_sem);
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
|
||||
* @ids: A pointer to a null terminated list of struct pci_device_id structures
|
||||
|
@ -426,25 +444,11 @@ exit:
|
|||
*/
|
||||
int pci_dev_present(const struct pci_device_id *ids)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
int found = 0;
|
||||
|
||||
WARN_ON(in_interrupt());
|
||||
down_read(&pci_bus_sem);
|
||||
while (ids->vendor || ids->subvendor || ids->class_mask) {
|
||||
list_for_each_entry(dev, &pci_devices, global_list) {
|
||||
if (pci_match_one_device(ids, dev)) {
|
||||
found = 1;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
ids++;
|
||||
}
|
||||
exit:
|
||||
up_read(&pci_bus_sem);
|
||||
return found;
|
||||
return pci_find_present(ids) == NULL ? 0 : 1;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pci_dev_present);
|
||||
EXPORT_SYMBOL(pci_find_present);
|
||||
|
||||
EXPORT_SYMBOL(pci_find_device);
|
||||
EXPORT_SYMBOL(pci_find_device_reverse);
|
||||
|
|
|
@ -33,11 +33,22 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
|
|||
u32 new, check, mask;
|
||||
int reg;
|
||||
|
||||
/* Ignore resources for unimplemented BARs and unused resource slots
|
||||
for 64 bit BARs. */
|
||||
/*
|
||||
* Ignore resources for unimplemented BARs and unused resource slots
|
||||
* for 64 bit BARs.
|
||||
*/
|
||||
if (!res->flags)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ignore non-moveable resources. This might be legacy resources for
|
||||
* which no functional BAR register exists or another important
|
||||
* system resource we should better not move around in system address
|
||||
* space.
|
||||
*/
|
||||
if (res->flags & IORESOURCE_PCI_FIXED)
|
||||
return;
|
||||
|
||||
pcibios_resource_to_bus(dev, ®ion, res);
|
||||
|
||||
pr_debug(" got res [%llx:%llx] bus [%lx:%lx] flags %lx for "
|
||||
|
@ -212,6 +223,10 @@ pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
|
|||
resource_size_t r_align;
|
||||
|
||||
r = &dev->resource[i];
|
||||
|
||||
if (r->flags & IORESOURCE_PCI_FIXED)
|
||||
continue;
|
||||
|
||||
r_align = r->end - r->start;
|
||||
|
||||
if (!(r->flags) || r->parent)
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \
|
||||
*(.pci_fixup_enable) \
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \
|
||||
VMLINUX_SYMBOL(__start_pci_fixups_resume) = .; \
|
||||
*(.pci_fixup_resume) \
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \
|
||||
} \
|
||||
\
|
||||
/* RapidIO route ops */ \
|
||||
|
|
|
@ -119,7 +119,6 @@ header-y += nfs4_mount.h
|
|||
header-y += nfs_mount.h
|
||||
header-y += oom.h
|
||||
header-y += param.h
|
||||
header-y += pci_ids.h
|
||||
header-y += pci_regs.h
|
||||
header-y += personality.h
|
||||
header-y += pfkeyv2.h
|
||||
|
@ -162,7 +161,6 @@ header-y += vt.h
|
|||
header-y += wireless.h
|
||||
header-y += xattr.h
|
||||
header-y += x25.h
|
||||
header-y += zorro_ids.h
|
||||
|
||||
unifdef-y += acct.h
|
||||
unifdef-y += adb.h
|
||||
|
|
|
@ -91,6 +91,9 @@ struct resource_list {
|
|||
#define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */
|
||||
#define IORESOURCE_ROM_BIOS_COPY (1<<3) /* ROM is BIOS copy, resource field overlaid */
|
||||
|
||||
/* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */
|
||||
#define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */
|
||||
|
||||
/* PC/ISA/whatever - the normal PC address spaces: IO and memory */
|
||||
extern struct resource ioport_resource;
|
||||
extern struct resource iomem_resource;
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
/* Include the pci register defines */
|
||||
#include <linux/pci_regs.h>
|
||||
|
||||
/* Include the ID list */
|
||||
#include <linux/pci_ids.h>
|
||||
|
||||
/*
|
||||
* The PCI interface treats multi-function devices as independent
|
||||
* devices. The slot/function address of each device is encoded
|
||||
|
@ -54,6 +51,9 @@
|
|||
#include <asm/atomic.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
/* Include the ID list */
|
||||
#include <linux/pci_ids.h>
|
||||
|
||||
/* File state for mmap()s on /proc/bus/pci/X/Y */
|
||||
enum pci_mmap_state {
|
||||
pci_mmap_io,
|
||||
|
@ -396,6 +396,21 @@ struct pci_driver {
|
|||
*/
|
||||
#define pci_module_init pci_register_driver
|
||||
|
||||
/**
|
||||
* PCI_VDEVICE - macro used to describe a specific pci device in short form
|
||||
* @vend: the vendor name
|
||||
* @dev: the 16 bit PCI Device ID
|
||||
*
|
||||
* This macro is used to create a struct pci_device_id that matches a
|
||||
* specific PCI device. The subvendor, and subdevice fields will be set
|
||||
* to PCI_ANY_ID. The macro allows the next field to follow as the device
|
||||
* private data.
|
||||
*/
|
||||
|
||||
#define PCI_VDEVICE(vendor, device) \
|
||||
PCI_VENDOR_ID_##vendor, (device), \
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0
|
||||
|
||||
/* these external functions are only available when PCI support is enabled */
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
|
@ -454,6 +469,8 @@ struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
|
|||
int pci_find_capability (struct pci_dev *dev, int cap);
|
||||
int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
|
||||
int pci_find_ext_capability (struct pci_dev *dev, int cap);
|
||||
int pci_find_ht_capability (struct pci_dev *dev, int ht_cap);
|
||||
int pci_find_next_ht_capability (struct pci_dev *dev, int pos, int ht_cap);
|
||||
struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
|
||||
|
||||
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
|
||||
|
@ -468,6 +485,7 @@ struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn);
|
|||
struct pci_dev *pci_get_bus_and_slot (unsigned int bus, unsigned int devfn);
|
||||
struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from);
|
||||
int pci_dev_present(const struct pci_device_id *ids);
|
||||
const struct pci_device_id *pci_find_present(const struct pci_device_id *ids);
|
||||
|
||||
int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
|
||||
int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
|
||||
|
@ -681,6 +699,7 @@ static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *
|
|||
{ return NULL; }
|
||||
|
||||
#define pci_dev_present(ids) (0)
|
||||
#define pci_find_present(ids) (NULL)
|
||||
#define pci_dev_put(dev) do { } while (0)
|
||||
|
||||
static inline void pci_set_master(struct pci_dev *dev) { }
|
||||
|
@ -783,6 +802,7 @@ enum pci_fixup_pass {
|
|||
pci_fixup_header, /* After reading configuration header */
|
||||
pci_fixup_final, /* Final phase of device fixups */
|
||||
pci_fixup_enable, /* pci_enable_device() time */
|
||||
pci_fixup_resume, /* pci_enable_device() time */
|
||||
};
|
||||
|
||||
/* Anonymous variables would be nice... */
|
||||
|
@ -801,6 +821,9 @@ enum pci_fixup_pass {
|
|||
#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \
|
||||
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable, \
|
||||
vendor##device##hook, vendor, device, hook)
|
||||
#define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook) \
|
||||
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume, \
|
||||
resume##vendor##device##hook, vendor, device, hook)
|
||||
|
||||
|
||||
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
|
||||
|
|
|
@ -104,6 +104,10 @@
|
|||
#define PCI_CLASS_SERIAL_FIBER 0x0c04
|
||||
#define PCI_CLASS_SERIAL_SMBUS 0x0c05
|
||||
|
||||
#define PCI_BASE_CLASS_WIRELESS 0x0d
|
||||
#define PCI_CLASS_WIRELESS_RF_CONTROLLER 0x0d10
|
||||
#define PCI_CLASS_WIRELESS_WHCI 0x0d1010
|
||||
|
||||
#define PCI_BASE_CLASS_INTELLIGENT 0x0e
|
||||
#define PCI_CLASS_INTELLIGENT_I2O 0x0e00
|
||||
|
||||
|
|
|
@ -475,15 +475,32 @@
|
|||
#define PCI_PWR_CAP 12 /* Capability */
|
||||
#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */
|
||||
|
||||
/* Hypertransport sub capability types */
|
||||
/*
|
||||
* Hypertransport sub capability types
|
||||
*
|
||||
* Unfortunately there are both 3 bit and 5 bit capability types defined
|
||||
* in the HT spec, catering for that is a little messy. You probably don't
|
||||
* want to use these directly, just use pci_find_ht_capability() and it
|
||||
* will do the right thing for you.
|
||||
*/
|
||||
#define HT_3BIT_CAP_MASK 0xE0
|
||||
#define HT_CAPTYPE_SLAVE 0x00 /* Slave/Primary link configuration */
|
||||
#define HT_CAPTYPE_HOST 0x20 /* Host/Secondary link configuration */
|
||||
|
||||
#define HT_5BIT_CAP_MASK 0xF8
|
||||
#define HT_CAPTYPE_IRQ 0x80 /* IRQ Configuration */
|
||||
#define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */
|
||||
#define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 bit address remapping */
|
||||
#define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */
|
||||
#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */
|
||||
#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */
|
||||
#define HT_MSI_FLAGS 0x02 /* Offset to flags */
|
||||
#define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */
|
||||
#define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */
|
||||
#define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL /* Fixed addr */
|
||||
#define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */
|
||||
#define HT_MSI_ADDR_LO_MASK 0xFFF00000 /* Low address bit mask */
|
||||
#define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */
|
||||
#define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */
|
||||
#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */
|
||||
#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */
|
||||
|
|
Loading…
Reference in New Issue