Commit de9b2fcc authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents fb34d203 031f30d2
...@@ -115,7 +115,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci ...@@ -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_KL133_REVISION_ID 0x81
#define VIA_8363_KM133_REVISION_ID 0x84 #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 v;
u8 revision; u8 revision;
...@@ -151,6 +151,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_ ...@@ -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_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_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_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 * 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_ ...@@ -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 * issue another HALT within 80 ns of the initial HALT, the failure condition
* is avoided. * is avoided.
*/ */
static void __init pci_fixup_nforce2(struct pci_dev *dev) static void pci_fixup_nforce2(struct pci_dev *dev)
{ {
u32 val; u32 val;
...@@ -204,6 +208,7 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev) ...@@ -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_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 */ /* Max PCI Express root ports */
#define MAX_PCIEROOT 6 #define MAX_PCIEROOT 6
...@@ -419,7 +424,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032, ...@@ -419,7 +424,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
* Prevent the BIOS trapping accesses to the Cyrix CS5530A video device * Prevent the BIOS trapping accesses to the Cyrix CS5530A video device
* configuration space. * 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; u8 r;
/* clear 'F4 Video Configuration Trap' bit */ /* clear 'F4 Video Configuration Trap' bit */
...@@ -429,3 +434,5 @@ static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev) ...@@ -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, DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
pci_early_fixup_cyrix_5530); 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, ...@@ -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); u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
if (id == PCI_CAP_ID_HT) { if (id == PCI_CAP_ID_HT) {
id = readb(devbase + pos + 3); id = readb(devbase + pos + 3);
if (id == HT_CAPTYPE_IRQ) if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_IRQ)
break; break;
} }
} }
......
...@@ -368,7 +368,6 @@ static struct pci_device_id atiixp_pci_tbl[] = { ...@@ -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_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_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_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, }, { 0, },
}; };
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl); MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
......
...@@ -1682,7 +1682,7 @@ int __init acpiphp_glue_init(void) ...@@ -1682,7 +1682,7 @@ int __init acpiphp_glue_init(void)
* *
* This function frees all data allocated in acpiphp_glue_init() * 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); 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) ...@@ -47,21 +47,11 @@ static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
return retval; 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}, .attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO},
.show = location_read_file, .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 */ /* free up the memory used by a slot */
static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
{ {
...@@ -145,7 +135,7 @@ int rpaphp_deregister_slot(struct slot *slot) ...@@ -145,7 +135,7 @@ int rpaphp_deregister_slot(struct slot *slot)
list_del(&slot->rpaphp_slot_list); list_del(&slot->rpaphp_slot_list);
/* remove "phy_location" file */ /* 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); retval = pci_hp_deregister(php_slot);
if (retval) if (retval)
...@@ -160,36 +150,45 @@ EXPORT_SYMBOL_GPL(rpaphp_deregister_slot); ...@@ -160,36 +150,45 @@ EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
int rpaphp_register_slot(struct slot *slot) int rpaphp_register_slot(struct slot *slot)
{ {
struct hotplug_slot *php_slot = slot->hotplug_slot;
int retval; int retval;
dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",
__FUNCTION__, slot->dn->full_name, slot->index, slot->name, __FUNCTION__, slot->dn->full_name, slot->index, slot->name,
slot->power_domain, slot->type); slot->power_domain, slot->type);
/* should not try to register the same slot twice */ /* 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); err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
rpaphp_release_slot(slot->hotplug_slot); retval = -EAGAIN;
return -EAGAIN; goto register_fail;
} }
retval = pci_hp_register(slot->hotplug_slot);
retval = pci_hp_register(php_slot);
if (retval) { if (retval) {
err("pci_hp_register failed with error %d\n", retval); err("pci_hp_register failed with error %d\n", retval);
rpaphp_release_slot(slot->hotplug_slot); goto register_fail;
return retval;
} }
/* create "phy_locatoin" file */
rpaphp_sysfs_add_attr_location(slot->hotplug_slot);
/* add slot to our internal list */ /* create "phy_location" file */
dbg("%s adding slot[%s] to rpaphp_slot_list\n", retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr);
__FUNCTION__, slot->name); if (retval) {
err("sysfs_create_file failed with error %d\n", retval);
goto sysfs_fail;
}
/* add slot to our internal list */
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
info("Slot [%s](PCI location=%s) registered\n", slot->name, info("Slot [%s](PCI location=%s) registered\n", slot->name,
slot->location); slot->location);
num_slots++; num_slots++;
return 0; 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) int rpaphp_get_power_status(struct slot *slot, u8 * value)
......
...@@ -47,11 +47,17 @@ extern int shpchp_poll_time; ...@@ -47,11 +47,17 @@ extern int shpchp_poll_time;
extern int shpchp_debug; extern int shpchp_debug;
extern struct workqueue_struct *shpchp_wq; 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...) \
#define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) do { \
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) if (shpchp_debug) \
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) printk("%s: " format, MY_NAME , ## arg); \
#define warn(format, arg...) printk(KERN_WARNING "%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 #define SLOT_NAME_SIZE 10
struct slot { struct slot {
...@@ -83,34 +89,27 @@ struct event_info { ...@@ -83,34 +89,27 @@ struct event_info {
struct controller { struct controller {
struct mutex crit_sect; /* critical section mutex */ struct mutex crit_sect; /* critical section mutex */
struct mutex cmd_lock; /* command lock */ 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 num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */ int slot_num_inc; /* 1 or -1 */
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
struct list_head slot_list; struct list_head slot_list;
struct hpc_ops *hpc_ops; struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */ wait_queue_head_t queue; /* sleep & wake process */
u8 bus;
u8 device;
u8 function;
u8 slot_device_offset; u8 slot_device_offset;
u8 add_support;
u32 pcix_misc2_reg; /* for amd pogo errata */ u32 pcix_misc2_reg; /* for amd pogo errata */
enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */ u32 first_slot; /* First physical slot number */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
u32 cap_offset; u32 cap_offset;
unsigned long mmio_base; unsigned long mmio_base;
unsigned long mmio_size; unsigned long mmio_size;
void __iomem *creg;
struct timer_list poll_timer;
}; };
/* Define AMD SHPC ID */ /* Define AMD SHPC ID */
#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
#define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458
/* AMD PCIX bridge registers */ /* AMD PCIX bridge registers */
#define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C #define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C
#define PCIX_MISCII_OFFSET 0x48 #define PCIX_MISCII_OFFSET 0x48
#define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80 #define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80
...@@ -145,8 +144,6 @@ struct controller { ...@@ -145,8 +144,6 @@ struct controller {
#define POWERON_STATE 3 #define POWERON_STATE 3
#define POWEROFF_STATE 4 #define POWEROFF_STATE 4
#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400
/* Error messages */ /* Error messages */
#define INTERLOCK_OPEN 0x00000002 #define INTERLOCK_OPEN 0x00000002
#define ADD_NOT_SUPPORTED 0x00000003 #define ADD_NOT_SUPPORTED 0x00000003
...@@ -158,50 +155,32 @@ struct controller { ...@@ -158,50 +155,32 @@ struct controller {
#define WRONG_BUS_FREQUENCY 0x0000000D #define WRONG_BUS_FREQUENCY 0x0000000D
#define POWER_FAILURE 0x0000000E #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 __must_check shpchp_create_ctrl_files(struct controller *ctrl);
extern void shpchp_remove_ctrl_files(struct controller *ctrl);
extern int shpchp_sysfs_enable_slot(struct slot *slot); extern int shpchp_sysfs_enable_slot(struct slot *slot);
extern int shpchp_sysfs_disable_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_attention_button(u8 hp_slot, void *inst_id); extern u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id); extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
extern u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id); extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id); extern int shpchp_configure_device(struct slot *p_slot);
extern int shpchp_unconfigure_device(struct slot *p_slot);
/* pci functions */ extern void cleanup_slots(struct controller *ctrl);
extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); extern void queue_pushbutton_work(struct work_struct *work);
extern int shpchp_configure_device(struct slot *p_slot); extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
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);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static inline int get_hp_params_from_firmware(struct pci_dev *dev, 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))) if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
return -ENODEV; return -ENODEV;
return 0; return 0;
} }
#define get_hp_hw_control_from_firmware(pdev) \ #define get_hp_hw_control_from_firmware(pdev) \
do { \ do { \
if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \
acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev))); \ acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev)));\
} while (0) } while (0)
#else #else
#define get_hp_params_from_firmware(dev, hpp) (-ENODEV) #define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
...@@ -222,108 +201,40 @@ struct ctrl_reg { ...@@ -222,108 +201,40 @@ struct ctrl_reg {
volatile u32 serr_loc; volatile u32 serr_loc;
volatile u32 serr_intr_enable; volatile u32 serr_intr_enable;
volatile u32 slot1; 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)); } __attribute__ ((packed));
/* offsets to the controller registers based on the above structure layout */ /* offsets to the controller registers based on the above structure layout */
enum ctrl_offsets { enum ctrl_offsets {
BASE_OFFSET = offsetof(struct ctrl_reg, base_offset), BASE_OFFSET = offsetof(struct ctrl_reg, base_offset),
SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1), SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1),
SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2), SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2),
SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config), SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config),
SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config), SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config),
MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl), MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl),
PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface), PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface),
CMD = offsetof(struct ctrl_reg, cmd), CMD = offsetof(struct ctrl_reg, cmd),
CMD_STATUS = offsetof(struct ctrl_reg, cmd_status), CMD_STATUS = offsetof(struct ctrl_reg, cmd_status),
INTR_LOC = offsetof(struct ctrl_reg, intr_loc), INTR_LOC = offsetof(struct ctrl_reg, intr_loc),
SERR_LOC = offsetof(struct ctrl_reg, serr_loc), SERR_LOC = offsetof(struct ctrl_reg, serr_loc),
SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable), SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable),
SLOT1 = offsetof(struct ctrl_reg, slot1), 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),
};
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 */
static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot)
/* 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)
{ {
struct slot *slot; return hotplug_slot->private;
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;
} }
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; struct slot *slot;
if (!ctrl)
return NULL;
list_for_each_entry(slot, &ctrl->slot_list, slot_list) { list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
if (slot->device == device) if (slot->device == device)
return slot; return slot;
} }
err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device); err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
return NULL; return NULL;
} }
...@@ -400,44 +311,27 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot) ...@@ -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); 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 { struct hpc_ops {
int (*power_on_slot ) (struct slot *slot); int (*power_on_slot)(struct slot *slot);
int (*slot_enable ) (struct slot *slot); int (*slot_enable)(struct slot *slot);
int (*slot_disable ) (struct slot *slot); int (*slot_disable)(struct slot *slot);
int (*set_bus_speed_mode) (struct slot *slot, enum pci_bus_speed speed); int (*set_bus_speed_mode)(struct slot *slot, enum pci_bus_speed speed);
int (*get_power_status) (struct slot *slot, u8 *status); int (*get_power_status)(struct slot *slot, u8 *status);
int (*get_attention_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 (*set_attention_status)(struct slot *slot, u8 status);
int (*get_latch_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_adapter_status)(struct slot *slot, u8 *status);
int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
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_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_adapter_speed) (struct slot *slot, enum pci_bus_speed *speed); int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode);
int (*get_mode1_ECC_cap) (struct slot *slot, u8 *mode); int (*get_prog_int)(struct slot *slot, u8 *prog_int);
int (*get_prog_int) (struct slot *slot, u8 *prog_int); int (*query_power_fault)(struct slot *slot);
void (*green_led_on)(struct slot *slot);
int (*query_power_fault) (struct slot *slot); void (*green_led_off)(struct slot *slot);
void (*green_led_on) (struct slot *slot); void (*green_led_blink)(struct slot *slot);
void (*green_led_off) (struct slot *slot); void (*release_ctlr)(struct controller *ctrl);
void (*green_led_blink) (struct slot *slot); int (*check_cmd_status)(struct controller *ctrl);
void (*release_ctlr) (struct controller *ctrl);
int (*check_cmd_status) (struct controller *ctrl);
}; };
#endif /* _SHPCHP_H */ #endif /* _SHPCHP_H */
...@@ -104,23 +104,6 @@ static void make_slot_name(struct slot *slot) ...@@ -104,23 +104,6 @@ static void make_slot_name(struct slot *slot)
slot->bus, slot->number); 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) static int init_slots(struct controller *ctrl)
{ {
struct slot *slot; struct slot *slot;
...@@ -128,7 +111,6 @@ static int init_slots(struct controller *ctrl) ...@@ -128,7 +111,6 @@ static int init_slots(struct controller *ctrl)
struct hotplug_slot_info *info; struct hotplug_slot_info *info;
int retval = -ENOMEM; int retval = -ENOMEM;
int i; int i;
u32 sun;
for (i = 0; i < ctrl->num_slots; i++) { for (i = 0; i < ctrl->num_slots; i++) {
slot = kzalloc(sizeof(*slot), GFP_KERNEL); slot = kzalloc(sizeof(*slot), GFP_KERNEL);
...@@ -149,16 +131,11 @@ static int init_slots(struct controller *ctrl) ...@@ -149,16 +131,11 @@ static int init_slots(struct controller *ctrl)
slot->hp_slot = i; slot->hp_slot = i;
slot->ctrl = ctrl; slot->ctrl = ctrl;
slot->bus = ctrl->slot_bus; slot->bus = ctrl->pci_dev->subordinate->number;
slot->device = ctrl->slot_device_offset + i; slot->device = ctrl->slot_device_offset + i;
slot->hpc_ops = ctrl->hpc_ops; slot->hpc_ops = ctrl->hpc_ops;
slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
mutex_init(&slot->lock); 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); INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work);
/* register this slot with the hotplug pci core */ /* register this slot with the hotplug pci core */
...@@ -211,42 +188,12 @@ void cleanup_slots(struct controller *ctrl) ...@@ -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 * 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) 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); 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) ...@@ -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) 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); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
...@@ -267,7 +214,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot) ...@@ -267,7 +214,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
static int disable_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); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
...@@ -276,7 +223,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot) ...@@ -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) 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; int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 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) ...@@ -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) 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; int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 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) ...@@ -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) 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; int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 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) ...@@ -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) 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; int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 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) ...@@ -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) 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; struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 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) ...@@ -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) 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; int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 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 ...@@ -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) 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; int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 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) ...@@ -385,9 +332,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
int rc; int rc;
struct controller *ctrl; 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)) if (!is_shpc_capable(pdev))
return -ENODEV; return -ENODEV;
...@@ -408,47 +352,13 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -408,47 +352,13 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, ctrl); 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 */ /* Setup the slot information structures */
rc = init_slots(ctrl); rc = init_slots(ctrl);
if (rc) { if (rc) {
err(msg_initialization_err, 6); err("%s: slot initialization failed\n", SHPC_MODULE_NAME);
goto err_out_release_ctlr; 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); rc = shpchp_create_ctrl_files(ctrl);
if (rc) if (rc)
goto err_cleanup_slots; goto err_cleanup_slots;
......
...@@ -57,9 +57,8 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) ...@@ -57,9 +57,8 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
return 0; 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; struct slot *p_slot;
u32 event_type; u32 event_type;
...@@ -81,9 +80,8 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) ...@@ -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; struct slot *p_slot;
u8 getstatus; u8 getstatus;
u32 event_type; u32 event_type;
...@@ -120,9 +118,8 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) ...@@ -120,9 +118,8 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
return 1; 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; struct slot *p_slot;
u32 event_type; u32 event_type;
...@@ -154,9 +151,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) ...@@ -154,9 +151,8 @@ u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id)
return 1; 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; struct slot *p_slot;
u32 event_type; u32 event_type;
...@@ -497,10 +493,12 @@ static void handle_button_press_event(struct slot *p_slot) ...@@ -497,10 +493,12 @@ static void handle_button_press_event(struct slot *p_slot)
p_slot->hpc_ops->get_power_status(p_slot, &getstatus); p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (getstatus) { if (getstatus) {
p_slot->state = BLINKINGOFF_STATE; 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 { } else {
p_slot->state = BLINKINGON_STATE; 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 */ /* blink green LED and turn off amber */
p_slot->hpc_ops->green_led_blink(p_slot); p_slot->hpc_ops->green_led_blink(p_slot);
...@@ -523,7 +521,8 @@ static void handle_button_press_event(struct slot *p_slot) ...@@ -523,7 +521,8 @@ static void handle_button_press_event(struct slot *p_slot)
else else
p_slot->hpc_ops->green_led_off(p_slot); p_slot->hpc_ops->green_led_off(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0); 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; p_slot->state = STATIC_STATE;
break; break;
case POWEROFF_STATE: case POWEROFF_STATE:
......
...@@ -212,44 +212,40 @@ ...@@ -212,44 +212,40 @@
#define SLOT_SERR_INT_MASK 0x3 #define SLOT_SERR_INT_MASK 0x3
DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ 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 atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
static irqreturn_t shpc_isr(int irq, void *dev_id); 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 int hpc_check_cmd_status(struct controller *ctrl);
static inline u8 shpc_readb(struct controller *ctrl, int reg) 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) 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) 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) 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) 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) 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, 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, ...@@ -268,21 +264,20 @@ static inline int shpc_indirect_read(struct controller *ctrl, int index,
/* /*
* This is the interrupt polling timeout function. * 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 controller *ctrl = (struct controller *)data;
(struct php_ctlr_state_s *)lphp_ctlr;
DBG_ENTER_ROUTINE DBG_ENTER_ROUTINE
/* Poll for interrupt events. regs == NULL => polling */ /* 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) if (!shpchp_poll_time)
shpchp_poll_time = 2; /* default polling interval is 2 sec */ 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 DBG_LEAVE_ROUTINE
} }
...@@ -290,16 +285,16 @@ static void int_poll_timeout(unsigned long lphp_ctlr) ...@@ -290,16 +285,16 @@ static void int_poll_timeout(unsigned long lphp_ctlr)
/* /*
* This function starts the interrupt polling timer. * 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 */ /* Clamp to sane value */
if ((sec <= 0) || (sec > 60)) if ((sec <= 0) || (sec > 60))
sec = 2; sec = 2;
php_ctlr->int_poll_timer.function = &int_poll_timeout; ctrl->poll_timer.function = &int_poll_timeout;
php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; ctrl->poll_timer.data = (unsigned long)ctrl;
php_ctlr->int_poll_timer.expires = jiffies + sec * HZ; ctrl->poll_timer.expires = jiffies + sec * HZ;
add_timer(&php_ctlr->int_poll_timer); add_timer(&ctrl->poll_timer);
} }
static inline int is_ctrl_busy(struct controller *ctrl) static inline int is_ctrl_busy(struct controller *ctrl)
...@@ -666,33 +661,8 @@ static void hpc_set_green_led_blink(struct slot *slot) ...@@ -666,33 +661,8 @@ static void hpc_set_green_led_blink(struct slot *slot)
shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK); 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) 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; int i;
u32 slot_reg, serr_int; u32 slot_reg, serr_int;
...@@ -722,40 +692,15 @@ static void hpc_release_ctlr(struct controller *ctrl) ...@@ -722,40 +692,15 @@ static void hpc_release_ctlr(struct controller *ctrl)
serr_int &= ~SERR_INTR_RSVDZ_MASK; serr_int &= ~SERR_INTR_RSVDZ_MASK;
shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
if (shpchp_poll_mode) { if (shpchp_poll_mode)
del_timer(&php_ctlr->int_poll_timer); del_timer(&ctrl->poll_timer);
} else { else {
if (php_ctlr->irq) { free_irq(ctrl->pci_dev->irq, ctrl);
free_irq(php_ctlr->irq, ctrl); pci_disable_msi(ctrl->pci_dev);
php_ctlr->irq = 0;
pci_disable_msi(php_ctlr->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 * If this is the last controller to be released, destroy the
...@@ -764,8 +709,7 @@ static void hpc_release_ctlr(struct controller *ctrl) ...@@ -764,8 +709,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
if (atomic_dec_and_test(&shpchp_num_controllers)) if (atomic_dec_and_test(&shpchp_num_controllers))
destroy_workqueue(shpchp_wq); destroy_workqueue(shpchp_wq);
DBG_LEAVE_ROUTINE DBG_LEAVE_ROUTINE
} }
static int hpc_power_on_slot(struct slot * slot) 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) ...@@ -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) static irqreturn_t shpc_isr(int irq, void *dev_id)
{ {
struct controller *ctrl = (struct controller *)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; u32 serr_int, slot_reg, intr_loc, intr_loc2;
int hp_slot; int hp_slot;
...@@ -942,20 +885,16 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) ...@@ -942,20 +885,16 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
__FUNCTION__, hp_slot, slot_reg); __FUNCTION__, hp_slot, slot_reg);
if (slot_reg & MRL_CHANGE_DETECTED) if (slot_reg & MRL_CHANGE_DETECTED)
php_ctlr->switch_change_callback( shpchp_handle_switch_change(hp_slot, ctrl);
hp_slot, php_ctlr->callback_instance_id);
if (slot_reg & BUTTON_PRESS_DETECTED) if (slot_reg & BUTTON_PRESS_DETECTED)
php_ctlr->attention_button_callback( shpchp_handle_attention_button(hp_slot, ctrl);
hp_slot, php_ctlr->callback_instance_id);
if (slot_reg & PRSNT_CHANGE_DETECTED) if (slot_reg & PRSNT_CHANGE_DETECTED)
php_ctlr->presence_change_callback( shpchp_handle_presence_change(hp_slot, ctrl);
hp_slot , php_ctlr->callback_instance_id);
if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED)) if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))
php_ctlr->power_fault_callback( shpchp_handle_power_fault(hp_slot, ctrl);
hp_slot, php_ctlr->callback_instance_id);
/* Clear all slot events */ /* Clear all slot events */
slot_reg &= ~SLOT_REG_RSVDZ_MASK; slot_reg &= ~SLOT_REG_RSVDZ_MASK;
...@@ -1114,10 +1053,8 @@ static struct hpc_ops shpchp_hpc_ops = { ...@@ -1114,10 +1053,8 @@ static struct hpc_ops shpchp_hpc_ops = {
.release_ctlr = hpc_release_ctlr, .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; int rc = -1, num_slots = 0;
u8 hp_slot; u8 hp_slot;
u32 shpc_base_offset; u32 shpc_base_offset;
...@@ -1128,16 +1065,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ...@@ -1128,16 +1065,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ 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 == if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
PCI_DEVICE_ID_AMD_GOLAM_7450)) { PCI_DEVICE_ID_AMD_GOLAM_7450)) {
/* amd shpc driver doesn't use Base Offset; assume 0 */ /* amd shpc driver doesn't use Base Offset; assume 0 */
...@@ -1147,20 +1074,20 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ...@@ -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); ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
if (!ctrl->cap_offset) { if (!ctrl->cap_offset) {
err("%s : cap_offset == 0\n", __FUNCTION__); err("%s : cap_offset == 0\n", __FUNCTION__);
goto abort_free_ctlr; goto abort;
} }
dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset); rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
if (rc) { if (rc) {
err("%s: cannot read base_offset\n", __FUNCTION__); err("%s: cannot read base_offset\n", __FUNCTION__);
goto abort_free_ctlr; goto abort;
} }
rc = shpc_indirect_read(ctrl, 3, &tempdword); rc = shpc_indirect_read(ctrl, 3, &tempdword);
if (rc) { if (rc) {
err("%s: cannot read slot config\n", __FUNCTION__); err("%s: cannot read slot config\n", __FUNCTION__);
goto abort_free_ctlr; goto abort;
} }
num_slots = tempdword & SLOT_NUM; num_slots = tempdword & SLOT_NUM;
dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
...@@ -1170,7 +1097,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ...@@ -1170,7 +1097,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
if (rc) { if (rc) {
err("%s: cannot read creg (index = %d)\n", err("%s: cannot read creg (index = %d)\n",
__FUNCTION__, i); __FUNCTION__, i);
goto abort_free_ctlr; goto abort;
} }
dbg("%s: offset %d: value %x\n", __FUNCTION__,i, dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
tempdword); tempdword);
...@@ -1187,24 +1114,24 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ...@@ -1187,24 +1114,24 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc) { if (rc) {
err("%s: pci_enable_device failed\n", __FUNCTION__); 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)) { if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
err("%s: cannot reserve MMIO region\n", __FUNCTION__); err("%s: cannot reserve MMIO region\n", __FUNCTION__);
rc = -1; rc = -1;
goto abort_free_ctlr; goto abort;
} }
php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
if (!php_ctlr->creg) { if (!ctrl->creg) {
err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
ctrl->mmio_size, ctrl->mmio_base); ctrl->mmio_size, ctrl->mmio_base);
release_mem_region(ctrl->mmio_base, ctrl->mmio_size); release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
rc = -1; 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->crit_sect);
mutex_init(&ctrl->cmd_lock); mutex_init(&ctrl->cmd_lock);
...@@ -1212,23 +1139,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ...@@ -1212,23 +1139,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
/* Setup wait queue */ /* Setup wait queue */
init_waitqueue_head(&ctrl->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; ctrl->hpc_ops = &shpchp_hpc_ops;
/* Return PCI Controller Info */ /* Return PCI Controller Info */
slot_config = shpc_readl(ctrl, SLOT_CONFIG); slot_config = shpc_readl(ctrl, SLOT_CONFIG);
php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; ctrl->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
php_ctlr->num_slots = slot_config & SLOT_NUM; ctrl->num_slots = slot_config & SLOT_NUM;
dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset); ctrl->first_slot = (slot_config & PSN) >> 16;
dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots); ctrl->slot_num_inc = ((slot_config & UPDOWN) >> 29) ? 1 : -1;
/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
...@@ -1243,7 +1161,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ...@@ -1243,7 +1161,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
/* Mask the MRL sensor SERR Mask of individual slot in /* Mask the MRL sensor SERR Mask of individual slot in
* Slot SERR-INT Mask & clear all the existing event if any * 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)); slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
hp_slot, slot_reg); hp_slot, slot_reg);
...@@ -1255,24 +1173,27 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ...@@ -1255,24 +1173,27 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
} }
if (shpchp_poll_mode) {/* Install interrupt polling code */ if (shpchp_poll_mode) {
/* Install and start the interrupt polling timer */ /* Install interrupt polling timer. Start with 10 sec delay */
init_timer(&php_ctlr->int_poll_timer); init_timer(&ctrl->poll_timer);
start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ start_int_poll_timer(ctrl, 10);
} else { } else {
/* Installs the interrupt handler */ /* Installs the interrupt handler */
rc = pci_enable_msi(pdev); rc = pci_enable_msi(pdev);
if (rc) { if (rc) {
info("Can't get msi for the hotplug controller\n"); info("Can't get msi for the hotplug controller\n");
info("Use INTx 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); rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); 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) { if (rc) {
err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq); err("Can't get irq %d for the hotplug controller\n",
goto abort_free_ctlr; ctrl->pci_dev->irq);
goto abort_iounmap;
} }
} }
dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__, 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) ...@@ -1280,24 +1201,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
PCI_FUNC(pdev->devfn), pdev->irq); PCI_FUNC(pdev->devfn), pdev->irq);
get_hp_hw_control_from_firmware(pdev); 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, * If this is the first controller to be initialized,
* initialize the shpchpd work queue * initialize the shpchpd work queue
...@@ -1306,14 +1209,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ...@@ -1306,14 +1209,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
shpchp_wq = create_singlethread_workqueue("shpchpd"); shpchp_wq = create_singlethread_workqueue("shpchpd");
if (!shpchp_wq) { if (!shpchp_wq) {
rc = -ENOMEM; rc = -ENOMEM;
goto abort_free_ctlr; goto abort_iounmap;
} }
} }
/* /*
* Unmask all event interrupts of all slots * 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)); slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
hp_slot, slot_reg); hp_slot, slot_reg);
...@@ -1336,10 +1239,8 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ...@@ -1336,10 +1239,8 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
return 0; return 0;
/* We end up here for the many possible ways to fail this API. */ /* We end up here for the many possible ways to fail this API. */
abort_free_ctlr: abort_iounmap:
if (php_ctlr->creg) iounmap(ctrl->creg);
iounmap(php_ctlr->creg);
kfree(php_ctlr);
abort: abort:
DBG_LEAVE_ROUTINE DBG_LEAVE_ROUTINE
return rc; return rc;
......
...@@ -99,14 +99,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) ...@@ -99,14 +99,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
int pos; int pos;
int irq; int irq;
pos = pci_find_capability(dev, PCI_CAP_ID_HT); pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);
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);
}
if (!pos) if (!pos)
return -EINVAL; return -EINVAL;
......
...@@ -162,14 +162,9 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, ...@@ -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, const struct pci_device_id *pci_match_device(struct pci_driver *drv,
struct pci_dev *dev) struct pci_dev *dev)
{ {
const struct pci_device_id *id;
struct pci_dynid *dynid; struct pci_dynid *dynid;
id = pci_match_id(drv->id_table, dev); /* Look at the dynamic ids first, before the static ones */
if (id)
return id;
/* static ids didn't match, lets look at the dynamic ones */
spin_lock(&drv->dynids.lock); spin_lock(&drv->dynids.lock);
list_for_each_entry(dynid, &drv->dynids.list, node) { list_for_each_entry(dynid, &drv->dynids.list, node) {
if (pci_match_one_device(&dynid->id, dev)) { if (pci_match_one_device(&dynid->id, dev)) {
...@@ -178,7 +173,8 @@ const struct pci_device_id *pci_match_device(struct pci_driver *drv, ...@@ -178,7 +173,8 @@ const struct pci_device_id *pci_match_device(struct pci_driver *drv,
} }
} }
spin_unlock(&drv->dynids.lock); 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, 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) ...@@ -357,6 +353,8 @@ static int pci_device_resume_early(struct device * dev)
struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver; struct pci_driver * drv = pci_dev->driver;
pci_fixup_device(pci_fixup_resume, pci_dev);
if (drv && drv->resume_early) if (drv && drv->resume_early)
error = drv->resume_early(pci_dev); error = drv->resume_early(pci_dev);
return error; return error;
......
...@@ -68,12 +68,14 @@ pci_max_busnr(void) ...@@ -68,12 +68,14 @@ pci_max_busnr(void)
#endif /* 0 */ #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; u8 id;
int ttl = 48;
while (ttl--) { while ((*ttl)--) {
pci_bus_read_config_byte(bus, devfn, pos, &pos); pci_bus_read_config_byte(bus, devfn, pos, &pos);
if (pos < 0x40) if (pos < 0x40)
break; break;
...@@ -89,6 +91,14 @@ static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, ...@@ -89,6 +91,14 @@ static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos,
return 0; 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) int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
{ {
return __pci_find_next_cap(dev->bus, dev->devfn, 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) ...@@ -96,10 +106,10 @@ int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
} }
EXPORT_SYMBOL_GPL(pci_find_next_capability); 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; u16 status;
u8 pos;
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
if (!(status & PCI_STATUS_CAP_LIST)) 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 ...@@ -108,15 +118,14 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
switch (hdr_type) { switch (hdr_type) {
case PCI_HEADER_TYPE_NORMAL: case PCI_HEADER_TYPE_NORMAL:
case PCI_HEADER_TYPE_BRIDGE: case PCI_HEADER_TYPE_BRIDGE:
pos = PCI_CAPABILITY_LIST; return PCI_CAPABILITY_LIST;
break;
case PCI_HEADER_TYPE_CARDBUS: case PCI_HEADER_TYPE_CARDBUS:
pos = PCI_CB_CAPABILITY_LIST; return PCI_CB_CAPABILITY_LIST;
break;
default: default:
return 0; 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 ...@@ -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) 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) ...@@ -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 pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
{ {
int pos;
u8 hdr_type; u8 hdr_type;
pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &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) ...@@ -214,6 +234,74 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
} }
EXPORT_SYMBOL_GPL(pci_find_ext_capability); 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 * pci_find_parent_resource - return resource region of parent bus of given region
* @dev: PCI device structure contains resources to be searched * @dev: PCI device structure contains resources to be searched
......
...@@ -90,7 +90,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, ...@@ -90,7 +90,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
return -ENODEV; return -ENODEV;
pci_set_master(dev); pci_set_master(dev);
if (!dev->irq) { if (!dev->irq && dev->pin) {
printk(KERN_WARNING printk(KERN_WARNING
"%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n", "%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n",
__FUNCTION__, dev->device, dev->vendor); __FUNCTION__, dev->device, dev->vendor);
......
...@@ -649,6 +649,9 @@ static void pci_read_irq(struct pci_dev *dev) ...@@ -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 * Returns 0 on success and -1 if unknown type of device (not normal, bridge
* or CardBus). * or CardBus).
*/ */
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
static int pci_setup_device(struct pci_dev * dev) static int pci_setup_device(struct pci_dev * dev)
{ {
u32 class; u32 class;
...@@ -692,18 +695,18 @@ static int pci_setup_device(struct pci_dev * dev) ...@@ -692,18 +695,18 @@ static int pci_setup_device(struct pci_dev * dev)
if ((progif & 1) == 0) { if ((progif & 1) == 0) {
dev->resource[0].start = 0x1F0; dev->resource[0].start = 0x1F0;
dev->resource[0].end = 0x1F7; 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].start = 0x3F6;
dev->resource[1].end = 0x3F6; dev->resource[1].end = 0x3F6;
dev->resource[1].flags = IORESOURCE_IO; dev->resource[1].flags = LEGACY_IO_RESOURCE;
} }
if ((progif & 4) == 0) { if ((progif & 4) == 0) {
dev->resource[2].start = 0x170; dev->resource[2].start = 0x170;
dev->resource[2].end = 0x177; 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].start = 0x376;
dev->resource[3].end = 0x376; dev->resource[3].end = 0x376;
dev->resource[3].flags = IORESOURCE_IO; dev->resource[3].flags = LEGACY_IO_RESOURCE;
} }
} }
break; break;
......
...@@ -36,7 +36,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRID ...@@ -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, /* Deal with broken BIOS'es that neglect to enable passive release,
which can cause problems in combination with the 82441FX/PPro MTRRs */ 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; struct pci_dev *d = NULL;
unsigned char dlc; unsigned char dlc;
...@@ -53,6 +53,7 @@ static void __devinit quirk_passive_release(struct pci_dev *dev) ...@@ -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_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 /* 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 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 ...@@ -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 * Updated based on further information from the site and also on
* information provided by VIA * 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; struct pci_dev *p;
u8 rev; u8 rev;
...@@ -185,6 +186,10 @@ static void __devinit quirk_vialatency(struct pci_dev *dev) ...@@ -185,6 +186,10 @@ static void __devinit quirk_vialatency(struct pci_dev *dev)
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_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_8371_1, quirk_vialatency );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, 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 * 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 ...@@ -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, * TODO: When we have device-specific interrupt routers,
* this code will go away from quirks. * 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; u8 tmp;
...@@ -548,6 +553,7 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev) ...@@ -548,6 +553,7 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev)
pci_write_config_byte (dev, 0x58, tmp); 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_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. * 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 ...@@ -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. * Set this bit to get rid of cycle wastage.
* Otherwise uncritical. * 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; u8 misc_control2;
#define BYPASS_APIC_DEASSERT 8 #define BYPASS_APIC_DEASSERT 8
...@@ -567,6 +573,7 @@ static void __devinit quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev) ...@@ -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_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. * 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 ); ...@@ -600,7 +607,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw );
#define AMD8131_revB0 0x11 #define AMD8131_revB0 0x11
#define AMD8131_MISC 0x40 #define AMD8131_MISC 0x40
#define AMD8131_NIOAMODE_BIT 0 #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; unsigned char revid, tmp;
...@@ -616,6 +623,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) ...@@ -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_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 */ #endif /* CONFIG_X86_IO_APIC */
...@@ -641,65 +649,84 @@ static void __devinit quirk_via_acpi(struct pci_dev *d) ...@@ -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_82C586_3, quirk_via_acpi );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, 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 * VIA bridges which have VLink
* 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.
*/ */
static const struct pci_device_id via_irq_fixup_tbl[] = {
{ static const struct pci_device_id via_vlink_fixup_tbl[] = {
.vendor = PCI_VENDOR_ID_VIA, /* Internal devices need IRQ line routing, pre VLink */
.device = PCI_ANY_ID, { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686), 0 },
.subvendor = PCI_ANY_ID, { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8231), 17 },
.subdevice = PCI_ANY_ID, /* Devices with VLink */
.class = PCI_CLASS_BRIDGE_ISA << 8, { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_0), 17},
.class_mask = 0xffff00, { 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, }, { 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; u8 irq, new_irq;
if (via_irq_fixup_needed == -1) /* Check if we have VLink and cache the result */
via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl);
if (!via_irq_fixup_needed) /* Checked already - no */
if (dev_lo == -2)
return; 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; new_irq = dev->irq;
/* Don't quirk interrupts outside the legacy IRQ range */ /* Don't quirk interrupts outside the legacy IRQ range */
if (!new_irq || new_irq > 15) if (!new_irq || new_irq > 15)
return; 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); pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
if (new_irq != 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); pci_name(dev), irq, new_irq);
udelay(15); /* unknown if delay really needed */ udelay(15); /* unknown if delay really needed */
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); 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 * 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 ...@@ -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 * do this even if the Linux CardBus driver is not loaded, because
* the Linux i82365 driver does not (and should not) handle CardBus. * 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) if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class)
return; return;
pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0); 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_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 * 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); ...@@ -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 * To be fair to AMD, it follows the spec by default, its BIOS people
* who turn it off! * 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; u32 pcic;
pci_read_config_dword(dev, 0x4C, &pcic); pci_read_config_dword(dev, 0x4C, &pcic);
...@@ -749,6 +777,7 @@ static void __devinit quirk_amd_ordering(struct pci_dev *dev) ...@@ -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_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 * DreamWorks provided workaround for Dunord I-3000 problem
...@@ -784,7 +813,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge ...@@ -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 * datasheets found at http://www.national.com/ds/GX for info on what
* these bits do. <christer@weinigel.se> * 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; u8 reg;
pci_read_config_byte(dev, 0x41, &reg); pci_read_config_byte(dev, 0x41, &reg);
...@@ -795,13 +824,14 @@ static void __init quirk_mediagx_master(struct pci_dev *dev) ...@@ -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_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 * 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 * the BIOS but in the odd case it is not the results are corruption
* hence the presence of a Linux check * 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; u16 config;
u8 rev; u8 rev;
...@@ -817,7 +847,25 @@ static void __init quirk_disable_pxb(struct pci_dev *pdev) ...@@ -817,7 +847,25 @@ 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_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 * 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 ...@@ -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 * runs everywhere at present we suppress the printk output in most
* irrelevant cases. * irrelevant cases.
*/ */
static void __init k8t_sound_hostbridge(struct pci_dev *dev) static void k8t_sound_hostbridge(struct pci_dev *dev)
{ {
unsigned char val; unsigned char val;
...@@ -893,8 +941,8 @@ static void __init k8t_sound_hostbridge(struct pci_dev *dev) ...@@ -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_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 * 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 * 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 ...@@ -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 * 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 * becomes necessary to do this tweak in two steps -- I've chosen the Host
* bridge as trigger. * 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; 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 ...@@ -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_82855GM_HB, asus_hides_smbus_hostbridge );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_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; u16 val;
...@@ -1042,8 +1086,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asu ...@@ -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_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_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_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; u32 val, rcba;
void __iomem *base; void __iomem *base;
...@@ -1059,13 +1109,12 @@ static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev) ...@@ -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"); 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 ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
#endif
/* /*
* SiS 96x south bridge: BIOS typically hides SMBus device... * 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; u8 val = 0;
printk(KERN_INFO "Enabling SiS 96x SMBus.\n"); printk(KERN_INFO "Enabling SiS 96x SMBus.\n");
...@@ -1086,7 +1135,7 @@ static int __devinitdata sis_96x_compatible = 0; ...@@ -1086,7 +1135,7 @@ static int __devinitdata sis_96x_compatible = 0;
#define SIS_DETECT_REGISTER 0x40 #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; u8 reg;
u16 devid; u16 devid;
...@@ -1122,13 +1171,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_ ...@@ -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_735, quirk_sis_96x_compatible );
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); 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 * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller
* and MC97 modem controller are disabled when a second PCI soundcard is * and MC97 modem controller are disabled when a second PCI soundcard is
* present. This patch, tweaking the VT8237 ISA bridge, enables them. * present. This patch, tweaking the VT8237 ISA bridge, enables them.
* -- bjd * -- bjd
*/ */
static void __init asus_hides_ac97_lpc(struct pci_dev *dev) static void asus_hides_ac97_lpc(struct pci_dev *dev)
{ {
u8 val; u8 val;
int asus_hides_ac97 = 0; 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_ ...@@ -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_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_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) #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_ ...@@ -1167,7 +1225,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_
* the PCI scanning. * the PCI scanning.
*/ */
static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev) static void quirk_jmicron_dualfn(struct pci_dev *pdev)
{ {
u32 conf; u32 conf;
u8 hdr; u8 hdr;
...@@ -1205,6 +1263,7 @@ static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev) ...@@ -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_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 #endif
...@@ -1532,6 +1591,8 @@ extern struct pci_fixup __start_pci_fixups_final[]; ...@@ -1532,6 +1591,8 @@ extern struct pci_fixup __start_pci_fixups_final[];
extern struct pci_fixup __end_pci_fixups_final[]; extern struct pci_fixup __end_pci_fixups_final[];
extern struct pci_fixup __start_pci_fixups_enable[]; extern struct pci_fixup __start_pci_fixups_enable[];
extern struct pci_fixup __end_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) 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) ...@@ -1559,6 +1620,11 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
end = __end_pci_fixups_enable; end = __end_pci_fixups_enable;
break; break;
case pci_fixup_resume:
start = __start_pci_fixups_resume;
end = __end_pci_fixups_resume;
break;
default: default:
/* stupid compiler warning, you would think with an enum... */ /* stupid compiler warning, you would think with an enum... */
return; return;
...@@ -1596,7 +1662,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); ...@@ -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 * Force it to be linked by setting the corresponding control bit in the
* config space. * 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; uint8_t b;
if (pci_read_config_byte(dev, 0xf41, &b) == 0) { 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) ...@@ -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, DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
quirk_nvidia_ck804_pcie_aer_ext_cap); 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 #ifdef CONFIG_PCI_MSI
/* To disable MSI globally */ /* To disable MSI globally */
...@@ -1644,19 +1712,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_ ...@@ -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 */ * return 1 if a HT MSI capability is found and enabled */
static int __devinit msi_ht_cap_enabled(struct pci_dev *dev) static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
{ {
u8 pos; int pos, ttl = 48;
int ttl;
for (pos = pci_find_capability(dev, PCI_CAP_ID_HT), ttl = 48; pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
pos && ttl; while (pos && ttl--) {
pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT), ttl--) { u8 flags;
u32 cap_hdr;
/* MSI mapping section according to Hypertransport spec */ if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
if (pci_read_config_dword(dev, pos, &cap_hdr) == 0 &flags) == 0)
&& (cap_hdr & 0xf8000000) == 0xa8000000 /* MSI mapping */) { {
printk(KERN_INFO "PCI: Found HT MSI mapping on %s with capability %s\n", printk(KERN_INFO "PCI: Found %s HT MSI Mapping on %s\n",
pci_name(dev), cap_hdr & 0x10000 ? "enabled" : "disabled"); flags & HT_MSI_FLAGS_ENABLE ?
return (cap_hdr & 0x10000) != 0; /* MSI mapping cap enabled */ "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; return 0;
} }
...@@ -1688,8 +1760,9 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) ...@@ -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. * a single one having MSI is enough to be sure that MSI are supported.
*/ */
pdev = pci_get_slot(dev->bus, 0); pdev = pci_get_slot(dev->bus, 0);
if (dev->subordinate && !msi_ht_cap_enabled(dev) if (!pdev)
&& !msi_ht_cap_enabled(pdev)) { return;
if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) {
printk(KERN_WARNING "PCI: MSI quirk detected. " printk(KERN_WARNING "PCI: MSI quirk detected. "
"MSI disabled on chipset %s.\n", "MSI disabled on chipset %s.\n",
pci_name(dev)); pci_name(dev));
......
...@@ -413,6 +413,24 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) ...@@ -413,6 +413,24 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
return dev; 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. * 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 * @ids: A pointer to a null terminated list of struct pci_device_id structures
...@@ -426,25 +444,11 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) ...@@ -426,25 +444,11 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
*/ */
int pci_dev_present(const struct pci_device_id *ids) int pci_dev_present(const struct pci_device_id *ids)
{ {
struct pci_dev *dev; return pci_find_present(ids) == NULL ? 0 : 1;
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;
} }
EXPORT_SYMBOL(pci_dev_present); EXPORT_SYMBOL(pci_dev_present);
EXPORT_SYMBOL(pci_find_present);
EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_device_reverse); EXPORT_SYMBOL(pci_find_device_reverse);
......
...@@ -33,11 +33,22 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) ...@@ -33,11 +33,22 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
u32 new, check, mask; u32 new, check, mask;
int reg; 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) if (!res->flags)
return; 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, &region, res); pcibios_resource_to_bus(dev, &region, res);
pr_debug(" got res [%llx:%llx] bus [%lx:%lx] flags %lx for " 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) ...@@ -212,6 +223,10 @@ pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
resource_size_t r_align; resource_size_t r_align;
r = &dev->resource[i]; r = &dev->resource[i];
if (r->flags & IORESOURCE_PCI_FIXED)
continue;
r_align = r->end - r->start; r_align = r->end - r->start;
if (!(r->flags) || r->parent) if (!(r->flags) || r->parent)
......
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \ VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \
*(.pci_fixup_enable) \ *(.pci_fixup_enable) \
VMLINUX_SYMBOL(__end_pci_fixups_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 */ \ /* RapidIO route ops */ \
......
...@@ -119,7 +119,6 @@ header-y += nfs4_mount.h ...@@ -119,7 +119,6 @@ header-y += nfs4_mount.h
header-y += nfs_mount.h header-y += nfs_mount.h
header-y += oom.h header-y += oom.h
header-y += param.h header-y += param.h
header-y += pci_ids.h
header-y += pci_regs.h header-y += pci_regs.h
header-y += personality.h header-y += personality.h
header-y += pfkeyv2.h header-y += pfkeyv2.h
...@@ -162,7 +161,6 @@ header-y += vt.h ...@@ -162,7 +161,6 @@ header-y += vt.h
header-y += wireless.h header-y += wireless.h
header-y += xattr.h header-y += xattr.h
header-y += x25.h header-y += x25.h
header-y += zorro_ids.h
unifdef-y += acct.h unifdef-y += acct.h
unifdef-y += adb.h unifdef-y += adb.h
......
...@@ -91,6 +91,9 @@ struct resource_list { ...@@ -91,6 +91,9 @@ struct resource_list {
#define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */ #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 */ #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 */ /* PC/ISA/whatever - the normal PC address spaces: IO and memory */
extern struct resource ioport_resource; extern struct resource ioport_resource;
extern struct resource iomem_resource; extern struct resource iomem_resource;
......
...@@ -20,9 +20,6 @@ ...@@ -20,9 +20,6 @@
/* Include the pci register defines */ /* Include the pci register defines */
#include <linux/pci_regs.h> #include <linux/pci_regs.h>
/* Include the ID list */
#include <linux/pci_ids.h>
/* /*
* The PCI interface treats multi-function devices as independent * The PCI interface treats multi-function devices as independent
* devices. The slot/function address of each device is encoded * devices. The slot/function address of each device is encoded
...@@ -54,6 +51,9 @@ ...@@ -54,6 +51,9 @@
#include <asm/atomic.h> #include <asm/atomic.h>
#include <linux/device.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 */ /* File state for mmap()s on /proc/bus/pci/X/Y */
enum pci_mmap_state { enum pci_mmap_state {
pci_mmap_io, pci_mmap_io,
...@@ -396,6 +396,21 @@ struct pci_driver { ...@@ -396,6 +396,21 @@ struct pci_driver {
*/ */
#define pci_module_init pci_register_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 */ /* these external functions are only available when PCI support is enabled */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
...@@ -454,6 +469,8 @@ struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); ...@@ -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_capability (struct pci_dev *dev, int cap);
int pci_find_next_capability (struct pci_dev *dev, u8 pos, 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_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_bus *pci_find_next_bus(const struct pci_bus *from);
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, 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); ...@@ -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_bus_and_slot (unsigned int bus, unsigned int devfn);
struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from); struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from);
int pci_dev_present(const struct pci_device_id *ids); 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_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); 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 * ...@@ -681,6 +699,7 @@ static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *
{ return NULL; } { return NULL; }
#define pci_dev_present(ids) (0) #define pci_dev_present(ids) (0)
#define pci_find_present(ids) (NULL)
#define pci_dev_put(dev) do { } while (0) #define pci_dev_put(dev) do { } while (0)
static inline void pci_set_master(struct pci_dev *dev) { } static inline void pci_set_master(struct pci_dev *dev) { }
...@@ -783,6 +802,7 @@ enum pci_fixup_pass { ...@@ -783,6 +802,7 @@ enum pci_fixup_pass {
pci_fixup_header, /* After reading configuration header */ pci_fixup_header, /* After reading configuration header */
pci_fixup_final, /* Final phase of device fixups */ pci_fixup_final, /* Final phase of device fixups */
pci_fixup_enable, /* pci_enable_device() time */ pci_fixup_enable, /* pci_enable_device() time */
pci_fixup_resume, /* pci_enable_device() time */
}; };
/* Anonymous variables would be nice... */ /* Anonymous variables would be nice... */
...@@ -801,6 +821,9 @@ enum pci_fixup_pass { ...@@ -801,6 +821,9 @@ enum pci_fixup_pass {
#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \ #define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable, \ DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable, \
vendor##device##hook, vendor, device, hook) 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); void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
......
...@@ -104,6 +104,10 @@ ...@@ -104,6 +104,10 @@
#define PCI_CLASS_SERIAL_FIBER 0x0c04 #define PCI_CLASS_SERIAL_FIBER 0x0c04
#define PCI_CLASS_SERIAL_SMBUS 0x0c05 #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_BASE_CLASS_INTELLIGENT 0x0e
#define PCI_CLASS_INTELLIGENT_I2O 0x0e00 #define PCI_CLASS_INTELLIGENT_I2O 0x0e00
......
...@@ -475,15 +475,32 @@ ...@@ -475,15 +475,32 @@
#define PCI_PWR_CAP 12 /* Capability */ #define PCI_PWR_CAP 12 /* Capability */
#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */ #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_SLAVE 0x00 /* Slave/Primary link configuration */
#define HT_CAPTYPE_HOST 0x20 /* Host/Secondary 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_IRQ 0x80 /* IRQ Configuration */
#define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */ #define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */
#define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 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_UNITID_CLUMP 0x90 /* Unit ID clumping */
#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */ #define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */
#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */ #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_DIRECT_ROUTE 0xB0 /* Direct routing configuration */
#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */ #define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */
#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */ #define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment