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: (41 commits) Revert "PCI: remove duplicate device id from ata_piix" msi: Make MSI useable more architectures msi: Kill the msi_desc array. msi: Remove attach_msi_entry. msi: Fix msi_remove_pci_irq_vectors. msi: Remove msi_lock. msi: Kill msi_lookup_irq MSI: Combine pci_(save|restore)_msi/msix_state MSI: Remove pci_scan_msi_device() MSI: Replace pci_msi_quirk with calls to pci_no_msi() PCI: remove duplicate device id from ipr PCI: remove duplicate device id from ata_piix PCI: power management: remove noise on non-manageable hw PCI: cleanup MSI code PCI: make isa_bridge Alpha-only PCI: remove quirk_sis_96x_compatible() PCI: Speed up the Intel SMBus unhiding quirk PCI Quirk: 1k I/O space IOBL_ADR fix on P64H2 shpchp: delete trailing whitespace shpchp: remove DBG_XXX_ROUTINE ...
This commit is contained in:
commit
78149df6d5
|
@ -575,3 +575,7 @@ void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
|
|||
|
||||
EXPORT_SYMBOL(pci_iomap);
|
||||
EXPORT_SYMBOL(pci_iounmap);
|
||||
|
||||
/* FIXME: Some boxes have multiple ISA bridges! */
|
||||
struct pci_dev *isa_bridge;
|
||||
EXPORT_SYMBOL(isa_bridge);
|
||||
|
|
|
@ -2606,25 +2606,32 @@ static struct irq_chip msi_chip = {
|
|||
.retrigger = ioapic_retrigger_irq,
|
||||
};
|
||||
|
||||
int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
|
||||
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
|
||||
{
|
||||
struct msi_msg msg;
|
||||
int ret;
|
||||
int irq, ret;
|
||||
irq = create_irq();
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
set_irq_msi(irq, desc);
|
||||
ret = msi_compose_msg(dev, irq, &msg);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
destroy_irq(irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
write_msi_msg(irq, &msg);
|
||||
|
||||
set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
|
||||
"edge");
|
||||
|
||||
return 0;
|
||||
return irq;
|
||||
}
|
||||
|
||||
void arch_teardown_msi_irq(unsigned int irq)
|
||||
{
|
||||
return;
|
||||
destroy_irq(irq);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI_MSI */
|
||||
|
|
|
@ -64,12 +64,17 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
|
|||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
||||
int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
|
||||
{
|
||||
struct msi_msg msg;
|
||||
unsigned long dest_phys_id;
|
||||
unsigned int vector;
|
||||
unsigned int irq, vector;
|
||||
|
||||
irq = create_irq();
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
set_irq_msi(irq, desc);
|
||||
dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
|
||||
vector = irq;
|
||||
|
||||
|
@ -89,12 +94,12 @@ int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
|||
write_msi_msg(irq, &msg);
|
||||
set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
return irq;
|
||||
}
|
||||
|
||||
void ia64_teardown_msi_irq(unsigned int irq)
|
||||
{
|
||||
return; /* no-op */
|
||||
destroy_irq(irq);
|
||||
}
|
||||
|
||||
static void ia64_ack_msi_irq(unsigned int irq)
|
||||
|
@ -126,12 +131,12 @@ static struct irq_chip ia64_msi_chip = {
|
|||
};
|
||||
|
||||
|
||||
int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
||||
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
|
||||
{
|
||||
if (platform_setup_msi_irq)
|
||||
return platform_setup_msi_irq(irq, pdev);
|
||||
return platform_setup_msi_irq(pdev, desc);
|
||||
|
||||
return ia64_setup_msi_irq(irq, pdev);
|
||||
return ia64_setup_msi_irq(pdev, desc);
|
||||
}
|
||||
|
||||
void arch_teardown_msi_irq(unsigned int irq)
|
||||
|
|
|
@ -59,13 +59,12 @@ void sn_teardown_msi_irq(unsigned int irq)
|
|||
sn_intr_free(nasid, widget, sn_irq_info);
|
||||
sn_msi_info[irq].sn_irq_info = NULL;
|
||||
|
||||
return;
|
||||
destroy_irq(irq);
|
||||
}
|
||||
|
||||
int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
||||
int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
|
||||
{
|
||||
struct msi_msg msg;
|
||||
struct msi_desc *entry;
|
||||
int widget;
|
||||
int status;
|
||||
nasid_t nasid;
|
||||
|
@ -73,8 +72,8 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
|||
struct sn_irq_info *sn_irq_info;
|
||||
struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
|
||||
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
|
||||
int irq;
|
||||
|
||||
entry = get_irq_data(irq);
|
||||
if (!entry->msi_attrib.is_64)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -84,6 +83,11 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
|||
if (provider == NULL || provider->dma_map_consistent == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
irq = create_irq();
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
set_irq_msi(irq, entry);
|
||||
/*
|
||||
* Set up the vector plumbing. Let the prom (via sn_intr_alloc)
|
||||
* decide which cpu to direct this msi at by default.
|
||||
|
@ -95,12 +99,15 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
|||
SWIN_WIDGETNUM(bussoft->bs_base);
|
||||
|
||||
sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
|
||||
if (! sn_irq_info)
|
||||
if (! sn_irq_info) {
|
||||
destroy_irq(irq);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
|
||||
if (status) {
|
||||
kfree(sn_irq_info);
|
||||
destroy_irq(irq);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -121,6 +128,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
|||
if (! bus_addr) {
|
||||
sn_intr_free(nasid, widget, sn_irq_info);
|
||||
kfree(sn_irq_info);
|
||||
destroy_irq(irq);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -139,7 +147,7 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
|
|||
write_msi_msg(irq, &msg);
|
||||
set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
return irq;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
|
|
@ -381,8 +381,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
|
|||
|
||||
pci_device_add(dev, bus);
|
||||
|
||||
/* XXX pci_scan_msi_device(dev); */
|
||||
|
||||
return dev;
|
||||
}
|
||||
EXPORT_SYMBOL(of_create_pci_dev);
|
||||
|
|
|
@ -1956,24 +1956,31 @@ static struct irq_chip msi_chip = {
|
|||
.retrigger = ioapic_retrigger_irq,
|
||||
};
|
||||
|
||||
int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
|
||||
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
|
||||
{
|
||||
struct msi_msg msg;
|
||||
int ret;
|
||||
int irq, ret;
|
||||
irq = create_irq();
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
set_irq_msi(irq, desc);
|
||||
ret = msi_compose_msg(dev, irq, &msg);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
destroy_irq(irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
write_msi_msg(irq, &msg);
|
||||
|
||||
set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
|
||||
|
||||
return 0;
|
||||
return irq;
|
||||
}
|
||||
|
||||
void arch_teardown_msi_irq(unsigned int irq)
|
||||
{
|
||||
return;
|
||||
destroy_irq(irq);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI_MSI */
|
||||
|
|
|
@ -5947,8 +5947,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
|
|||
* responding after a while.
|
||||
*
|
||||
* AMD believes this incompatibility is unique to the 5706, and
|
||||
* prefers to locally disable MSI rather than globally disabling it
|
||||
* using pci_msi_quirk.
|
||||
* prefers to locally disable MSI rather than globally disabling it.
|
||||
*/
|
||||
if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) {
|
||||
struct pci_dev *amd_8132 = NULL;
|
||||
|
|
|
@ -3584,7 +3584,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
|
|||
*/
|
||||
if (adapter->link_speed == 0)
|
||||
return;
|
||||
if (pdev->error_state && pdev->error_state != pci_channel_io_normal)
|
||||
if (pci_channel_offline(pdev))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&adapter->stats_lock, flags);
|
||||
|
|
|
@ -1605,7 +1605,7 @@ ixgb_update_stats(struct ixgb_adapter *adapter)
|
|||
struct pci_dev *pdev = adapter->pdev;
|
||||
|
||||
/* Prevent stats update while adapter is being reset */
|
||||
if (pdev->error_state && pdev->error_state != pci_channel_io_normal)
|
||||
if (pci_channel_offline(pdev))
|
||||
return;
|
||||
|
||||
if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) ||
|
||||
|
|
|
@ -145,15 +145,6 @@ config HOTPLUG_PCI_SHPC
|
|||
|
||||
When in doubt, say N.
|
||||
|
||||
config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE
|
||||
bool "Use polling mechanism for hot-plug events (for testing purpose)"
|
||||
depends on HOTPLUG_PCI_SHPC
|
||||
help
|
||||
Say Y here if you want to use the polling mechanism for hot-plug
|
||||
events for early platform testing.
|
||||
|
||||
When in doubt, say N.
|
||||
|
||||
config HOTPLUG_PCI_RPA
|
||||
tristate "RPA PCI Hotplug driver"
|
||||
depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
|
||||
|
|
|
@ -44,15 +44,20 @@ extern int pciehp_poll_time;
|
|||
extern int pciehp_debug;
|
||||
extern int pciehp_force;
|
||||
|
||||
/*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
|
||||
#define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (pciehp_debug) \
|
||||
printk("%s: " format, MY_NAME , ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) \
|
||||
printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
|
||||
#define info(format, arg...) \
|
||||
printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
#define warn(format, arg...) \
|
||||
printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
|
||||
#define SLOT_NAME_SIZE 10
|
||||
struct slot {
|
||||
struct slot *next;
|
||||
u8 bus;
|
||||
u8 device;
|
||||
u32 number;
|
||||
|
@ -63,6 +68,8 @@ struct slot {
|
|||
struct hpc_ops *hpc_ops;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct list_head slot_list;
|
||||
char name[SLOT_NAME_SIZE];
|
||||
unsigned long last_emi_toggle;
|
||||
};
|
||||
|
||||
struct event_info {
|
||||
|
@ -70,34 +77,15 @@ struct event_info {
|
|||
u8 hp_slot;
|
||||
};
|
||||
|
||||
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;
|
||||
struct ctrl_reg *creg; /* Ptr to controller register space */
|
||||
};
|
||||
|
||||
#define MAX_EVENTS 10
|
||||
struct controller {
|
||||
struct controller *next;
|
||||
struct mutex crit_sect; /* critical section mutex */
|
||||
struct mutex ctrl_lock; /* controller lock */
|
||||
struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
|
||||
int num_slots; /* Number of slots on ctlr */
|
||||
int slot_num_inc; /* 1 or -1 */
|
||||
struct pci_dev *pci_dev;
|
||||
struct pci_bus *pci_bus;
|
||||
struct list_head slot_list;
|
||||
struct event_info event_queue[MAX_EVENTS];
|
||||
struct slot *slot;
|
||||
struct hpc_ops *hpc_ops;
|
||||
|
@ -112,6 +100,8 @@ struct controller {
|
|||
u8 ctrlcap;
|
||||
u16 vendor_id;
|
||||
u8 cap_base;
|
||||
struct timer_list poll_timer;
|
||||
volatile int cmd_busy;
|
||||
};
|
||||
|
||||
#define INT_BUTTON_IGNORE 0
|
||||
|
@ -131,8 +121,6 @@ struct controller {
|
|||
#define POWERON_STATE 3
|
||||
#define POWEROFF_STATE 4
|
||||
|
||||
#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400
|
||||
|
||||
/* Error messages */
|
||||
#define INTERLOCK_OPEN 0x00000002
|
||||
#define ADD_NOT_SUPPORTED 0x00000003
|
||||
|
@ -144,10 +132,6 @@ struct controller {
|
|||
#define WRONG_BUS_FREQUENCY 0x0000000D
|
||||
#define POWER_FAILURE 0x0000000E
|
||||
|
||||
#define REMOVE_NOT_SUPPORTED 0x00000003
|
||||
|
||||
#define DISABLE_CARD 1
|
||||
|
||||
/* Field definitions in Slot Capabilities Register */
|
||||
#define ATTN_BUTTN_PRSN 0x00000001
|
||||
#define PWR_CTRL_PRSN 0x00000002
|
||||
|
@ -155,6 +139,7 @@ struct controller {
|
|||
#define ATTN_LED_PRSN 0x00000008
|
||||
#define PWR_LED_PRSN 0x00000010
|
||||
#define HP_SUPR_RM_SUP 0x00000020
|
||||
#define EMI_PRSN 0x00020000
|
||||
|
||||
#define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN)
|
||||
#define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN)
|
||||
|
@ -162,130 +147,65 @@ struct controller {
|
|||
#define ATTN_LED(cap) (cap & ATTN_LED_PRSN)
|
||||
#define PWR_LED(cap) (cap & PWR_LED_PRSN)
|
||||
#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP)
|
||||
#define EMI(cap) (cap & EMI_PRSN)
|
||||
|
||||
/*
|
||||
* 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"
|
||||
#define msg_button_ignore "PCI slot #%s - button press ignored. (action in progress...)\n"
|
||||
|
||||
/* controller functions */
|
||||
extern int pciehp_event_start_thread (void);
|
||||
extern void pciehp_event_stop_thread (void);
|
||||
extern int pciehp_enable_slot (struct slot *slot);
|
||||
extern int pciehp_disable_slot (struct slot *slot);
|
||||
|
||||
extern u8 pciehp_handle_attention_button (u8 hp_slot, void *inst_id);
|
||||
extern u8 pciehp_handle_switch_change (u8 hp_slot, void *inst_id);
|
||||
extern u8 pciehp_handle_presence_change (u8 hp_slot, void *inst_id);
|
||||
extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id);
|
||||
/* extern void long_delay (int delay); */
|
||||
|
||||
/* pci functions */
|
||||
extern int pciehp_configure_device (struct slot *p_slot);
|
||||
extern int pciehp_unconfigure_device (struct slot *p_slot);
|
||||
|
||||
|
||||
extern int pciehp_event_start_thread(void);
|
||||
extern void pciehp_event_stop_thread(void);
|
||||
extern int pciehp_enable_slot(struct slot *slot);
|
||||
extern int pciehp_disable_slot(struct slot *slot);
|
||||
extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
|
||||
extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
|
||||
extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
|
||||
extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
|
||||
extern int pciehp_configure_device(struct slot *p_slot);
|
||||
extern int pciehp_unconfigure_device(struct slot *p_slot);
|
||||
int pcie_init(struct controller *ctrl, struct pcie_device *dev);
|
||||
|
||||
/* Global variables */
|
||||
extern struct controller *pciehp_ctrl_list;
|
||||
|
||||
/* Inline functions */
|
||||
|
||||
static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
|
||||
{
|
||||
struct slot *p_slot, *tmp_slot = NULL;
|
||||
struct slot *slot;
|
||||
|
||||
p_slot = ctrl->slot;
|
||||
|
||||
while (p_slot && (p_slot->device != device)) {
|
||||
tmp_slot = p_slot;
|
||||
p_slot = p_slot->next;
|
||||
}
|
||||
if (p_slot == NULL) {
|
||||
err("ERROR: pciehp_find_slot device=0x%x\n", device);
|
||||
p_slot = tmp_slot;
|
||||
list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
|
||||
if (slot->device == device)
|
||||
return slot;
|
||||
}
|
||||
|
||||
return p_slot;
|
||||
err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int wait_for_ctrl_irq(struct controller *ctrl)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
add_wait_queue(&ctrl->queue, &wait);
|
||||
if (!pciehp_poll_mode)
|
||||
/* Sleep for up to 1 second */
|
||||
msleep_interruptible(1000);
|
||||
else
|
||||
msleep_interruptible(2500);
|
||||
|
||||
remove_wait_queue(&ctrl->queue, &wait);
|
||||
if (signal_pending(current))
|
||||
retval = -EINTR;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define SLOT_NAME_SIZE 10
|
||||
|
||||
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
|
||||
{
|
||||
snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number);
|
||||
}
|
||||
|
||||
enum php_ctlr_type {
|
||||
PCI,
|
||||
ISA,
|
||||
ACPI
|
||||
};
|
||||
|
||||
int pcie_init(struct controller *ctrl, struct pcie_device *dev);
|
||||
|
||||
/* This has no meaning for PCI Express, as there is only 1 slot per port */
|
||||
int pcie_get_ctlr_slot_config(struct controller *ctrl,
|
||||
int *num_ctlr_slots,
|
||||
int *first_device_num,
|
||||
int *physical_slot_num,
|
||||
u8 *ctrlcap);
|
||||
|
||||
struct hpc_ops {
|
||||
int (*power_on_slot) (struct slot *slot);
|
||||
int (*power_off_slot) (struct slot *slot);
|
||||
int (*get_power_status) (struct slot *slot, u8 *status);
|
||||
int (*get_attention_status) (struct slot *slot, u8 *status);
|
||||
int (*set_attention_status) (struct slot *slot, u8 status);
|
||||
int (*get_latch_status) (struct slot *slot, u8 *status);
|
||||
int (*get_adapter_status) (struct slot *slot, u8 *status);
|
||||
|
||||
int (*get_max_bus_speed) (struct slot *slot, enum pci_bus_speed *speed);
|
||||
int (*get_cur_bus_speed) (struct slot *slot, enum pci_bus_speed *speed);
|
||||
|
||||
int (*get_max_lnk_width) (struct slot *slot, enum pcie_link_width *value);
|
||||
int (*get_cur_lnk_width) (struct slot *slot, enum pcie_link_width *value);
|
||||
|
||||
int (*query_power_fault) (struct slot *slot);
|
||||
void (*green_led_on) (struct slot *slot);
|
||||
void (*green_led_off) (struct slot *slot);
|
||||
void (*green_led_blink) (struct slot *slot);
|
||||
void (*release_ctlr) (struct controller *ctrl);
|
||||
int (*check_lnk_status) (struct controller *ctrl);
|
||||
int (*power_on_slot)(struct slot *slot);
|
||||
int (*power_off_slot)(struct slot *slot);
|
||||
int (*get_power_status)(struct slot *slot, u8 *status);
|
||||
int (*get_attention_status)(struct slot *slot, u8 *status);
|
||||
int (*set_attention_status)(struct slot *slot, u8 status);
|
||||
int (*get_latch_status)(struct slot *slot, u8 *status);
|
||||
int (*get_adapter_status)(struct slot *slot, u8 *status);
|
||||
int (*get_emi_status)(struct slot *slot, u8 *status);
|
||||
int (*toggle_emi)(struct slot *slot);
|
||||
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_max_lnk_width)(struct slot *slot, enum pcie_link_width *val);
|
||||
int (*get_cur_lnk_width)(struct slot *slot, enum pcie_link_width *val);
|
||||
int (*query_power_fault)(struct slot *slot);
|
||||
void (*green_led_on)(struct slot *slot);
|
||||
void (*green_led_off)(struct slot *slot);
|
||||
void (*green_led_blink)(struct slot *slot);
|
||||
void (*release_ctlr)(struct controller *ctrl);
|
||||
int (*check_lnk_status)(struct controller *ctrl);
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/actypes.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
|
||||
#define pciehp_get_hp_hw_control_from_firmware(dev) \
|
||||
#define pciehp_get_hp_hw_control_from_firmware(dev) \
|
||||
pciehp_acpi_get_hp_hw_control_from_firmware(dev)
|
||||
static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include "pciehp.h"
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
/* Global variables */
|
||||
int pciehp_debug;
|
||||
|
@ -87,6 +88,95 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
|
|||
.get_cur_bus_speed = get_cur_bus_speed,
|
||||
};
|
||||
|
||||
/*
|
||||
* Check the status of the Electro Mechanical Interlock (EMI)
|
||||
*/
|
||||
static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = hotplug_slot->private;
|
||||
return (slot->hpc_ops->get_emi_status(slot, value));
|
||||
}
|
||||
|
||||
/*
|
||||
* sysfs interface for the Electro Mechanical Interlock (EMI)
|
||||
* 1 == locked, 0 == unlocked
|
||||
*/
|
||||
static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf)
|
||||
{
|
||||
int retval;
|
||||
u8 value;
|
||||
|
||||
retval = get_lock_status(slot, &value);
|
||||
if (retval)
|
||||
goto lock_read_exit;
|
||||
retval = sprintf (buf, "%d\n", value);
|
||||
|
||||
lock_read_exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the status of the Electro Mechanical Interlock (EMI)
|
||||
* This is a toggle - in addition there must be at least 1 second
|
||||
* in between toggles.
|
||||
*/
|
||||
static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status)
|
||||
{
|
||||
struct slot *slot = hotplug_slot->private;
|
||||
int retval;
|
||||
u8 value;
|
||||
|
||||
mutex_lock(&slot->ctrl->crit_sect);
|
||||
|
||||
/* has it been >1 sec since our last toggle? */
|
||||
if ((get_seconds() - slot->last_emi_toggle) < 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* see what our current state is */
|
||||
retval = get_lock_status(hotplug_slot, &value);
|
||||
if (retval || (value == status))
|
||||
goto set_lock_exit;
|
||||
|
||||
slot->hpc_ops->toggle_emi(slot);
|
||||
set_lock_exit:
|
||||
mutex_unlock(&slot->ctrl->crit_sect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sysfs interface which allows the user to toggle the Electro Mechanical
|
||||
* Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock
|
||||
*/
|
||||
static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
unsigned long llock;
|
||||
u8 lock;
|
||||
int retval = 0;
|
||||
|
||||
llock = simple_strtoul(buf, NULL, 10);
|
||||
lock = (u8)(llock & 0xff);
|
||||
|
||||
switch (lock) {
|
||||
case 0:
|
||||
case 1:
|
||||
retval = set_lock_status(slot, lock);
|
||||
break;
|
||||
default:
|
||||
err ("%d is an invalid lock value\n", lock);
|
||||
retval = -EINVAL;
|
||||
}
|
||||
if (retval)
|
||||
return retval;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
|
||||
.attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR},
|
||||
.show = lock_read_file,
|
||||
.store = lock_write_file
|
||||
};
|
||||
|
||||
/**
|
||||
* release_slot - free up the memory used by a slot
|
||||
* @hotplug_slot: slot to free
|
||||
|
@ -98,148 +188,108 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
|
|||
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
|
||||
|
||||
kfree(slot->hotplug_slot->info);
|
||||
kfree(slot->hotplug_slot->name);
|
||||
kfree(slot->hotplug_slot);
|
||||
kfree(slot);
|
||||
}
|
||||
|
||||
static void make_slot_name(struct slot *slot)
|
||||
{
|
||||
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
|
||||
slot->bus, slot->number);
|
||||
}
|
||||
|
||||
static int init_slots(struct controller *ctrl)
|
||||
{
|
||||
struct slot *slot;
|
||||
struct hpc_ops *hpc_ops;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct hotplug_slot_info *hotplug_slot_info;
|
||||
u8 number_of_slots;
|
||||
u8 slot_device;
|
||||
u32 slot_number;
|
||||
int result = -ENOMEM;
|
||||
struct hotplug_slot_info *info;
|
||||
int retval = -ENOMEM;
|
||||
int i;
|
||||
|
||||
number_of_slots = ctrl->num_slots;
|
||||
slot_device = ctrl->slot_device_offset;
|
||||
slot_number = ctrl->first_slot;
|
||||
|
||||
while (number_of_slots) {
|
||||
for (i = 0; i < ctrl->num_slots; i++) {
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
goto error;
|
||||
|
||||
slot->hotplug_slot =
|
||||
kzalloc(sizeof(*(slot->hotplug_slot)),
|
||||
GFP_KERNEL);
|
||||
if (!slot->hotplug_slot)
|
||||
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
|
||||
if (!hotplug_slot)
|
||||
goto error_slot;
|
||||
hotplug_slot = slot->hotplug_slot;
|
||||
slot->hotplug_slot = hotplug_slot;
|
||||
|
||||
hotplug_slot->info =
|
||||
kzalloc(sizeof(*(hotplug_slot->info)),
|
||||
GFP_KERNEL);
|
||||
if (!hotplug_slot->info)
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
goto error_hpslot;
|
||||
hotplug_slot_info = hotplug_slot->info;
|
||||
hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
|
||||
if (!hotplug_slot->name)
|
||||
goto error_info;
|
||||
hotplug_slot->info = info;
|
||||
|
||||
hotplug_slot->name = slot->name;
|
||||
|
||||
slot->hp_slot = i;
|
||||
slot->ctrl = ctrl;
|
||||
slot->bus = ctrl->slot_bus;
|
||||
slot->device = slot_device;
|
||||
slot->hpc_ops = hpc_ops = ctrl->hpc_ops;
|
||||
|
||||
slot->bus = ctrl->pci_dev->subordinate->number;
|
||||
slot->device = ctrl->slot_device_offset + i;
|
||||
slot->hpc_ops = ctrl->hpc_ops;
|
||||
slot->number = ctrl->first_slot;
|
||||
slot->hp_slot = slot_device - ctrl->slot_device_offset;
|
||||
|
||||
/* register this slot with the hotplug pci core */
|
||||
hotplug_slot->private = slot;
|
||||
hotplug_slot->release = &release_slot;
|
||||
make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot);
|
||||
make_slot_name(slot);
|
||||
hotplug_slot->ops = &pciehp_hotplug_slot_ops;
|
||||
|
||||
hpc_ops->get_power_status(slot,
|
||||
&(hotplug_slot_info->power_status));
|
||||
hpc_ops->get_attention_status(slot,
|
||||
&(hotplug_slot_info->attention_status));
|
||||
hpc_ops->get_latch_status(slot,
|
||||
&(hotplug_slot_info->latch_status));
|
||||
hpc_ops->get_adapter_status(slot,
|
||||
&(hotplug_slot_info->adapter_status));
|
||||
get_power_status(hotplug_slot, &info->power_status);
|
||||
get_attention_status(hotplug_slot, &info->attention_status);
|
||||
get_latch_status(hotplug_slot, &info->latch_status);
|
||||
get_adapter_status(hotplug_slot, &info->adapter_status);
|
||||
|
||||
dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
|
||||
"slot_device_offset=%x\n",
|
||||
slot->bus, slot->device, slot->hp_slot, slot->number,
|
||||
ctrl->slot_device_offset);
|
||||
result = pci_hp_register(hotplug_slot);
|
||||
if (result) {
|
||||
err ("pci_hp_register failed with error %d\n", result);
|
||||
goto error_name;
|
||||
"slot_device_offset=%x\n", slot->bus, slot->device,
|
||||
slot->hp_slot, slot->number, ctrl->slot_device_offset);
|
||||
retval = pci_hp_register(hotplug_slot);
|
||||
if (retval) {
|
||||
err ("pci_hp_register failed with error %d\n", retval);
|
||||
goto error_info;
|
||||
}
|
||||
/* create additional sysfs entries */
|
||||
if (EMI(ctrl->ctrlcap)) {
|
||||
retval = sysfs_create_file(&hotplug_slot->kobj,
|
||||
&hotplug_slot_attr_lock.attr);
|
||||
if (retval) {
|
||||
pci_hp_deregister(hotplug_slot);
|
||||
err("cannot create additional sysfs entries\n");
|
||||
goto error_info;
|
||||
}
|
||||
}
|
||||
|
||||
slot->next = ctrl->slot;
|
||||
ctrl->slot = slot;
|
||||
|
||||
number_of_slots--;
|
||||
slot_device++;
|
||||
slot_number += ctrl->slot_num_inc;
|
||||
list_add(&slot->slot_list, &ctrl->slot_list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_name:
|
||||
kfree(hotplug_slot->name);
|
||||
error_info:
|
||||
kfree(hotplug_slot_info);
|
||||
kfree(info);
|
||||
error_hpslot:
|
||||
kfree(hotplug_slot);
|
||||
error_slot:
|
||||
kfree(slot);
|
||||
error:
|
||||
return result;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static int cleanup_slots (struct controller * ctrl)
|
||||
static void cleanup_slots(struct controller *ctrl)
|
||||
{
|
||||
struct slot *old_slot, *next_slot;
|
||||
struct list_head *tmp;
|
||||
struct list_head *next;
|
||||
struct slot *slot;
|
||||
|
||||
old_slot = ctrl->slot;
|
||||
ctrl->slot = NULL;
|
||||
|
||||
while (old_slot) {
|
||||
next_slot = old_slot->next;
|
||||
pci_hp_deregister (old_slot->hotplug_slot);
|
||||
old_slot = next_slot;
|
||||
list_for_each_safe(tmp, next, &ctrl->slot_list) {
|
||||
slot = list_entry(tmp, struct slot, slot_list);
|
||||
list_del(&slot->slot_list);
|
||||
if (EMI(ctrl->ctrlcap))
|
||||
sysfs_remove_file(&slot->hotplug_slot->kobj,
|
||||
&hotplug_slot_attr_lock.attr);
|
||||
pci_hp_deregister(slot->hotplug_slot);
|
||||
}
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int get_ctlr_slot_config(struct controller *ctrl)
|
||||
{
|
||||
int num_ctlr_slots; /* Not needed; PCI Express has 1 slot per port*/
|
||||
int first_device_num; /* Not needed */
|
||||
int physical_slot_num;
|
||||
u8 ctrlcap;
|
||||
int rc;
|
||||
|
||||
rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &ctrlcap);
|
||||
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; /* PCI Express has 1 slot per port */
|
||||
ctrl->slot_device_offset = first_device_num;
|
||||
ctrl->first_slot = physical_slot_num;
|
||||
ctrl->ctrlcap = ctrlcap;
|
||||
|
||||
dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) ctrlcap(%x) for b:d (%x:%x)\n",
|
||||
__FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, ctrlcap,
|
||||
ctrl->bus, ctrl->device);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set_attention_status - Turns the Amber LED for a slot on, off or blink
|
||||
*/
|
||||
|
@ -378,8 +428,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
int rc;
|
||||
struct controller *ctrl;
|
||||
struct slot *t_slot;
|
||||
int first_device_num = 0 ; /* first PCI device number supported by this PCIE */
|
||||
int num_ctlr_slots; /* number of slots supported by this HPC */
|
||||
u8 value;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
|
@ -388,6 +436,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
err("%s : out of memory\n", __FUNCTION__);
|
||||
goto err_out_none;
|
||||
}
|
||||
INIT_LIST_HEAD(&ctrl->slot_list);
|
||||
|
||||
pdev = dev->port;
|
||||
ctrl->pci_dev = pdev;
|
||||
|
@ -400,13 +449,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
|
||||
pci_set_drvdata(pdev, ctrl);
|
||||
|
||||
ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL);
|
||||
if (!ctrl->pci_bus) {
|
||||
err("%s: out of memory\n", __FUNCTION__);
|
||||
rc = -ENOMEM;
|
||||
goto err_out_unmap_mmio_region;
|
||||
}
|
||||
memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
|
||||
ctrl->bus = pdev->bus->number; /* ctrl bus */
|
||||
ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */
|
||||
|
||||
|
@ -415,26 +457,14 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
|
||||
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_free_ctrl_bus;
|
||||
}
|
||||
first_device_num = ctrl->slot_device_offset;
|
||||
num_ctlr_slots = ctrl->num_slots;
|
||||
|
||||
/* Setup the slot information structures */
|
||||
rc = init_slots(ctrl);
|
||||
if (rc) {
|
||||
err(msg_initialization_err, 6);
|
||||
goto err_out_free_ctrl_slot;
|
||||
err("%s: slot initialization failed\n", PCIE_MODULE_NAME);
|
||||
goto err_out_release_ctlr;
|
||||
}
|
||||
|
||||
t_slot = pciehp_find_slot(ctrl, first_device_num);
|
||||
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
|
||||
|
||||
/* Finish setting up the hot plug ctrl device */
|
||||
ctrl->next_event = 0;
|
||||
|
@ -447,32 +477,18 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
pciehp_ctrl_list = ctrl;
|
||||
}
|
||||
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
|
||||
|
||||
if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
|
||||
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
|
||||
if (rc) {
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
if (rc)
|
||||
goto err_out_free_ctrl_slot;
|
||||
} else
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_free_ctrl_slot:
|
||||
cleanup_slots(ctrl);
|
||||
err_out_free_ctrl_bus:
|
||||
kfree(ctrl->pci_bus);
|
||||
err_out_unmap_mmio_region:
|
||||
err_out_release_ctlr:
|
||||
ctrl->hpc_ops->release_ctlr(ctrl);
|
||||
err_out_free_ctrl:
|
||||
kfree(ctrl);
|
||||
|
@ -506,8 +522,6 @@ static void __exit unload_pciehpd(void)
|
|||
while (ctrl) {
|
||||
cleanup_slots(ctrl);
|
||||
|
||||
kfree (ctrl->pci_bus);
|
||||
|
||||
ctrl->hpc_ops->release_ctlr(ctrl);
|
||||
|
||||
tctrl = ctrl;
|
||||
|
|
|
@ -48,9 +48,8 @@ static inline char *slot_name(struct slot *p_slot)
|
|||
return p_slot->hotplug_slot->name;
|
||||
}
|
||||
|
||||
u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
|
||||
u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *) inst_id;
|
||||
struct slot *p_slot;
|
||||
u8 rc = 0;
|
||||
u8 getstatus;
|
||||
|
@ -101,9 +100,8 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
|
|||
|
||||
}
|
||||
|
||||
u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
|
||||
u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *) inst_id;
|
||||
struct slot *p_slot;
|
||||
u8 rc = 0;
|
||||
u8 getstatus;
|
||||
|
@ -143,9 +141,8 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
|
|||
return rc;
|
||||
}
|
||||
|
||||
u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id)
|
||||
u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *) inst_id;
|
||||
struct slot *p_slot;
|
||||
u8 presence_save, rc = 0;
|
||||
struct event_info *taskInfo;
|
||||
|
@ -187,9 +184,8 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id)
|
|||
return rc;
|
||||
}
|
||||
|
||||
u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
|
||||
u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
|
||||
{
|
||||
struct controller *ctrl = (struct controller *) inst_id;
|
||||
struct slot *p_slot;
|
||||
u8 rc = 0;
|
||||
struct event_info *taskInfo;
|
||||
|
@ -233,35 +229,25 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
|
|||
|
||||
static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
||||
{
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
|
||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
||||
if (pslot->hpc_ops->power_off_slot(pslot)) {
|
||||
err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
err("%s: Issue of Slot Power Off command failed\n",
|
||||
__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
pslot->hpc_ops->green_led_off(pslot);
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
if (ATTN_LED(ctrl->ctrlcap)) {
|
||||
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
|
||||
err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
if (ATTN_LED(ctrl->ctrlcap)) {
|
||||
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
|
||||
err("%s: Issue of Set Attention Led command failed\n",
|
||||
__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -274,7 +260,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
|||
static int board_added(struct slot *p_slot)
|
||||
{
|
||||
u8 hp_slot;
|
||||
int rc = 0;
|
||||
int retval = 0;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
hp_slot = p_slot->device - ctrl->slot_device_offset;
|
||||
|
@ -283,53 +269,38 @@ static int board_added(struct slot *p_slot)
|
|||
__FUNCTION__, p_slot->device,
|
||||
ctrl->slot_device_offset, hp_slot);
|
||||
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
||||
/* Power on slot */
|
||||
rc = p_slot->hpc_ops->power_on_slot(p_slot);
|
||||
if (rc) {
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
retval = p_slot->hpc_ops->power_on_slot(p_slot);
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->green_led_blink(p_slot);
|
||||
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
|
||||
/* Wait for ~1 second */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
msleep(1000);
|
||||
|
||||
/* Check link training status */
|
||||
rc = p_slot->hpc_ops->check_lnk_status(ctrl);
|
||||
if (rc) {
|
||||
/* Check link training status */
|
||||
retval = p_slot->hpc_ops->check_lnk_status(ctrl);
|
||||
if (retval) {
|
||||
err("%s: Failed to check link status\n", __FUNCTION__);
|
||||
set_slot_off(ctrl, p_slot);
|
||||
return rc;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Check for a power fault */
|
||||
if (p_slot->hpc_ops->query_power_fault(p_slot)) {
|
||||
dbg("%s: power fault detected\n", __FUNCTION__);
|
||||
rc = POWER_FAILURE;
|
||||
retval = POWER_FAILURE;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
rc = pciehp_configure_device(p_slot);
|
||||
if (rc) {
|
||||
retval = pciehp_configure_device(p_slot);
|
||||
if (retval) {
|
||||
err("Cannot add device 0x%x:%x\n", p_slot->bus,
|
||||
p_slot->device);
|
||||
p_slot->device);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
|
@ -338,26 +309,16 @@ static int board_added(struct slot *p_slot)
|
|||
*/
|
||||
if (pcie_mch_quirk)
|
||||
pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->green_led_on(p_slot);
|
||||
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
set_slot_off(ctrl, p_slot);
|
||||
return -1;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* remove_board - Turns off slot and LED's
|
||||
*
|
||||
|
@ -366,44 +327,32 @@ static int remove_board(struct slot *p_slot)
|
|||
{
|
||||
u8 device;
|
||||
u8 hp_slot;
|
||||
int rc;
|
||||
int retval = 0;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
if (pciehp_unconfigure_device(p_slot))
|
||||
return 1;
|
||||
retval = pciehp_unconfigure_device(p_slot);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
device = p_slot->device;
|
||||
|
||||
hp_slot = p_slot->device - ctrl->slot_device_offset;
|
||||
p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
|
||||
|
||||
dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
|
||||
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
||||
/* power off slot */
|
||||
rc = p_slot->hpc_ops->power_off_slot(p_slot);
|
||||
if (rc) {
|
||||
err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
return rc;
|
||||
retval = p_slot->hpc_ops->power_off_slot(p_slot);
|
||||
if (retval) {
|
||||
err("%s: Issue of Slot Disable command failed\n",
|
||||
__FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
/* turn off Green LED */
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -448,18 +397,10 @@ static void pciehp_pushbutton_thread(unsigned long slot)
|
|||
dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__,
|
||||
p_slot->bus, p_slot->device);
|
||||
|
||||
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&p_slot->ctrl->ctrl_lock);
|
||||
|
||||
if (pciehp_enable_slot(p_slot) &&
|
||||
PWR_LED(p_slot->ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (p_slot->ctrl);
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&p_slot->ctrl->ctrl_lock);
|
||||
}
|
||||
p_slot->state = STATIC_STATE;
|
||||
}
|
||||
|
||||
|
@ -498,18 +439,10 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
|
|||
dbg("%s: adding bus:device(%x:%x)\n",
|
||||
__FUNCTION__, p_slot->bus, p_slot->device);
|
||||
|
||||
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&p_slot->ctrl->ctrl_lock);
|
||||
|
||||
if (pciehp_enable_slot(p_slot) &&
|
||||
PWR_LED(p_slot->ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (p_slot->ctrl);
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&p_slot->ctrl->ctrl_lock);
|
||||
}
|
||||
p_slot->state = STATIC_STATE;
|
||||
}
|
||||
|
||||
|
@ -620,46 +553,24 @@ static void interrupt_event_handler(struct controller *ctrl)
|
|||
|
||||
switch (p_slot->state) {
|
||||
case BLINKINGOFF_STATE:
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->green_led_on(p_slot);
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
if (ATTN_LED(ctrl->ctrlcap)) {
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
if (ATTN_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||
break;
|
||||
case BLINKINGON_STATE:
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
if (ATTN_LED(ctrl->ctrlcap)){
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
|
||||
if (ATTN_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||
break;
|
||||
default:
|
||||
warn("Not a valid state\n");
|
||||
return;
|
||||
}
|
||||
info(msg_button_cancel, slot_name(p_slot));
|
||||
info("PCI slot #%s - action canceled due to button press.\n", slot_name(p_slot));
|
||||
p_slot->state = STATIC_STATE;
|
||||
}
|
||||
/* ***********Button Pressed (No action on 1st press...) */
|
||||
|
@ -672,34 +583,21 @@ static void interrupt_event_handler(struct controller *ctrl)
|
|||
/* slot is on */
|
||||
dbg("slot is on\n");
|
||||
p_slot->state = BLINKINGOFF_STATE;
|
||||
info(msg_button_off, slot_name(p_slot));
|
||||
info("PCI slot #%s - powering off due to button press.\n", slot_name(p_slot));
|
||||
} else {
|
||||
/* slot is off */
|
||||
dbg("slot is off\n");
|
||||
p_slot->state = BLINKINGON_STATE;
|
||||
info(msg_button_on, slot_name(p_slot));
|
||||
info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot));
|
||||
}
|
||||
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
/* blink green LED and turn off amber */
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->green_led_blink(p_slot);
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
if (ATTN_LED(ctrl->ctrlcap)) {
|
||||
if (ATTN_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||
|
||||
/* Wait for the command to complete */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
|
||||
init_timer(&p_slot->task_event);
|
||||
p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */
|
||||
p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
|
||||
|
@ -712,21 +610,11 @@ static void interrupt_event_handler(struct controller *ctrl)
|
|||
else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
|
||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
||||
dbg("power fault\n");
|
||||
/* Wait for exclusive access to hardware */
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
|
||||
if (ATTN_LED(ctrl->ctrlcap)) {
|
||||
if (ATTN_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->set_attention_status(p_slot, 1);
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
if (PWR_LED(ctrl->ctrlcap)) {
|
||||
if (PWR_LED(ctrl->ctrlcap))
|
||||
p_slot->hpc_ops->green_led_off(p_slot);
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
}
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->ctrl_lock);
|
||||
}
|
||||
}
|
||||
/***********SURPRISE REMOVAL********************/
|
||||
|
@ -754,7 +642,6 @@ static void interrupt_event_handler(struct controller *ctrl)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int pciehp_enable_slot(struct slot *p_slot)
|
||||
{
|
||||
u8 getstatus = 0;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -106,7 +106,7 @@ struct controller {
|
|||
};
|
||||
|
||||
/* 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
|
||||
|
||||
/* AMD PCIX bridge registers */
|
||||
|
@ -221,7 +221,7 @@ enum ctrl_offsets {
|
|||
};
|
||||
|
||||
static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
{
|
||||
return hotplug_slot->private;
|
||||
}
|
||||
|
||||
|
|
|
@ -401,10 +401,6 @@ static int __init shpcd_init(void)
|
|||
{
|
||||
int retval = 0;
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE
|
||||
shpchp_poll_mode = 1;
|
||||
#endif
|
||||
|
||||
retval = pci_register_driver(&shpc_driver);
|
||||
dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
|
|
|
@ -64,7 +64,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
|
|||
|
||||
/* Attention Button Change */
|
||||
dbg("shpchp: Attention button interrupt received.\n");
|
||||
|
||||
|
||||
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
|
||||
p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
|
||||
|
||||
|
@ -128,7 +128,7 @@ u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
|
|||
|
||||
p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Save the presence state
|
||||
*/
|
||||
p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
|
||||
|
@ -184,12 +184,12 @@ u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* The following routines constitute the bulk of the
|
||||
/* The following routines constitute the bulk of the
|
||||
hotplug controller logic
|
||||
*/
|
||||
static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
|
||||
enum pci_bus_speed speed)
|
||||
{
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
dbg("%s: change to speed %d\n", __FUNCTION__, speed);
|
||||
|
@ -204,7 +204,7 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
|
|||
static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
|
||||
u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp,
|
||||
enum pci_bus_speed msp)
|
||||
{
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
|
@ -257,23 +257,23 @@ static int board_added(struct slot *p_slot)
|
|||
err("%s: Failed to power on slot\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
|
||||
if (slots_not_empty)
|
||||
return WRONG_BUS_FREQUENCY;
|
||||
|
||||
|
||||
if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
|
||||
err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
|
||||
return WRONG_BUS_FREQUENCY;
|
||||
}
|
||||
|
||||
|
||||
/* turn on board, blink green LED, turn off Amber LED */
|
||||
if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
|
||||
err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp);
|
||||
if (rc) {
|
||||
err("%s: Can't get adapter speed or bus mode mismatch\n",
|
||||
|
@ -378,7 +378,7 @@ static int remove_board(struct slot *p_slot)
|
|||
err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||
if (rc) {
|
||||
err("%s: Issue of Set Attention command failed\n", __FUNCTION__);
|
||||
|
|
|
@ -35,38 +35,6 @@
|
|||
|
||||
#include "shpchp.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */
|
||||
#define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */
|
||||
#define DBG_K_INFO ((unsigned int)0x00000004) /* Info messages */
|
||||
#define DBG_K_ERROR ((unsigned int)0x00000008) /* Error messages */
|
||||
#define DBG_K_TRACE (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT)
|
||||
#define DBG_K_STANDARD (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE)
|
||||
/* Redefine this flagword to set debug level */
|
||||
#define DEBUG_LEVEL DBG_K_STANDARD
|
||||
|
||||
#define DEFINE_DBG_BUFFER char __dbg_str_buf[256];
|
||||
|
||||
#define DBG_PRINT( dbg_flags, args... ) \
|
||||
do { \
|
||||
if ( DEBUG_LEVEL & ( dbg_flags ) ) \
|
||||
{ \
|
||||
int len; \
|
||||
len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \
|
||||
__FILE__, __LINE__, __FUNCTION__ ); \
|
||||
sprintf( __dbg_str_buf + len, args ); \
|
||||
printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DBG_ENTER_ROUTINE DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]");
|
||||
#define DBG_LEAVE_ROUTINE DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]");
|
||||
#else
|
||||
#define DEFINE_DBG_BUFFER
|
||||
#define DBG_ENTER_ROUTINE
|
||||
#define DBG_LEAVE_ROUTINE
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* Slot Available Register I field definition */
|
||||
#define SLOT_33MHZ 0x0000001f
|
||||
#define SLOT_66MHZ_PCIX 0x00001f00
|
||||
|
@ -211,7 +179,6 @@
|
|||
#define SLOT_EVENT_LATCH 0x2
|
||||
#define SLOT_SERR_INT_MASK 0x3
|
||||
|
||||
DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
|
||||
static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
|
||||
|
||||
static irqreturn_t shpc_isr(int irq, void *dev_id);
|
||||
|
@ -268,8 +235,6 @@ static void int_poll_timeout(unsigned long data)
|
|||
{
|
||||
struct controller *ctrl = (struct controller *)data;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
/* Poll for interrupt events. regs == NULL => polling */
|
||||
shpc_isr(0, ctrl);
|
||||
|
||||
|
@ -278,8 +243,6 @@ static void int_poll_timeout(unsigned long data)
|
|||
shpchp_poll_time = 2; /* default polling interval is 2 sec */
|
||||
|
||||
start_int_poll_timer(ctrl, shpchp_poll_time);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -353,8 +316,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
|
|||
int retval = 0;
|
||||
u16 temp_word;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
mutex_lock(&slot->ctrl->cmd_lock);
|
||||
|
||||
if (!shpc_poll_ctrl_busy(ctrl)) {
|
||||
|
@ -368,9 +329,9 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
|
|||
++t_slot;
|
||||
temp_word = (t_slot << 8) | (cmd & 0xFF);
|
||||
dbg("%s: t_slot %x cmd %x\n", __FUNCTION__, t_slot, cmd);
|
||||
|
||||
|
||||
/* To make sure the Controller Busy bit is 0 before we send out the
|
||||
* command.
|
||||
* command.
|
||||
*/
|
||||
shpc_writew(ctrl, CMD, temp_word);
|
||||
|
||||
|
@ -389,20 +350,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
|
|||
}
|
||||
out:
|
||||
mutex_unlock(&slot->ctrl->cmd_lock);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hpc_check_cmd_status(struct controller *ctrl)
|
||||
{
|
||||
u16 cmd_status;
|
||||
int retval = 0;
|
||||
u16 cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F;
|
||||
|
||||
switch (cmd_status >> 1) {
|
||||
case 0:
|
||||
retval = 0;
|
||||
|
@ -423,7 +378,6 @@ static int hpc_check_cmd_status(struct controller *ctrl)
|
|||
retval = cmd_status;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -431,13 +385,8 @@ static int hpc_check_cmd_status(struct controller *ctrl)
|
|||
static int hpc_get_attention_status(struct slot *slot, u8 *status)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u32 slot_reg;
|
||||
u8 state;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT;
|
||||
u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
u8 state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT;
|
||||
|
||||
switch (state) {
|
||||
case ATN_LED_STATE_ON:
|
||||
|
@ -454,20 +403,14 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
|
|||
break;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hpc_get_power_status(struct slot * slot, u8 *status)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u32 slot_reg;
|
||||
u8 state;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT;
|
||||
u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
u8 state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT;
|
||||
|
||||
switch (state) {
|
||||
case SLOT_STATE_PWRONLY:
|
||||
|
@ -484,7 +427,6 @@ static int hpc_get_power_status(struct slot * slot, u8 *status)
|
|||
break;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -492,30 +434,21 @@ static int hpc_get_power_status(struct slot * slot, u8 *status)
|
|||
static int hpc_get_latch_status(struct slot *slot, u8 *status)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u32 slot_reg;
|
||||
u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
*status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hpc_get_adapter_status(struct slot *slot, u8 *status)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u32 slot_reg;
|
||||
u8 state;
|
||||
u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
u8 state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT;
|
||||
*status = (state != 0x3) ? 1 : 0;
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -523,11 +456,8 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
|
|||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
*prog_int = shpc_readb(ctrl, PROG_INTERFACE);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -539,8 +469,6 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
|
|||
u8 m66_cap = !!(slot_reg & MHZ66_CAP);
|
||||
u8 pi, pcix_cap;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if ((retval = hpc_get_prog_int(slot, &pi)))
|
||||
return retval;
|
||||
|
||||
|
@ -582,21 +510,15 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
|
|||
}
|
||||
|
||||
dbg("Adapter speed = %d\n", *value);
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u16 sec_bus_status;
|
||||
u8 pi;
|
||||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
pi = shpc_readb(ctrl, PROG_INTERFACE);
|
||||
sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG);
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u16 sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG);
|
||||
u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
|
||||
|
||||
if (pi == 2) {
|
||||
*mode = (sec_bus_status & 0x0100) >> 8;
|
||||
|
@ -605,21 +527,14 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
|
|||
}
|
||||
|
||||
dbg("Mode 1 ECC cap = %d\n", *mode);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hpc_query_power_fault(struct slot * slot)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
u32 slot_reg;
|
||||
u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
/* Note: Logic 0 => fault */
|
||||
return !(slot_reg & POWER_FAULT);
|
||||
}
|
||||
|
@ -629,7 +544,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
|
|||
u8 slot_cmd = 0;
|
||||
|
||||
switch (value) {
|
||||
case 0 :
|
||||
case 0 :
|
||||
slot_cmd = SET_ATTN_OFF; /* OFF */
|
||||
break;
|
||||
case 1:
|
||||
|
@ -666,8 +581,6 @@ static void hpc_release_ctlr(struct controller *ctrl)
|
|||
int i;
|
||||
u32 slot_reg, serr_int;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
/*
|
||||
* Mask event interrupts and SERRs of all slots
|
||||
*/
|
||||
|
@ -708,61 +621,43 @@ static void hpc_release_ctlr(struct controller *ctrl)
|
|||
*/
|
||||
if (atomic_dec_and_test(&shpchp_num_controllers))
|
||||
destroy_workqueue(shpchp_wq);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
}
|
||||
|
||||
static int hpc_power_on_slot(struct slot * slot)
|
||||
{
|
||||
int retval;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR);
|
||||
if (retval) {
|
||||
if (retval)
|
||||
err("%s: Write command failed!\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hpc_slot_enable(struct slot * slot)
|
||||
{
|
||||
int retval;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
/* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */
|
||||
retval = shpc_write_cmd(slot, slot->hp_slot,
|
||||
SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF);
|
||||
if (retval) {
|
||||
if (retval)
|
||||
err("%s: Write command failed!\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hpc_slot_disable(struct slot * slot)
|
||||
{
|
||||
int retval;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
/* Slot - Disable, Power Indicator - Off, Attention Indicator - On */
|
||||
retval = shpc_write_cmd(slot, slot->hp_slot,
|
||||
SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON);
|
||||
if (retval) {
|
||||
if (retval)
|
||||
err("%s: Write command failed!\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
|
||||
|
@ -771,8 +666,6 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
|
|||
struct controller *ctrl = slot->ctrl;
|
||||
u8 pi, cmd;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
pi = shpc_readb(ctrl, PROG_INTERFACE);
|
||||
if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX))
|
||||
return -EINVAL;
|
||||
|
@ -828,7 +721,6 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
|
|||
if (retval)
|
||||
err("%s: Write command failed!\n", __FUNCTION__);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -843,7 +735,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
|
|||
if (!intr_loc)
|
||||
return IRQ_NONE;
|
||||
|
||||
dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc);
|
||||
dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc);
|
||||
|
||||
if(!shpchp_poll_mode) {
|
||||
/*
|
||||
|
@ -856,12 +748,12 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
|
|||
shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
|
||||
|
||||
intr_loc2 = shpc_readl(ctrl, INTR_LOC);
|
||||
dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2);
|
||||
dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2);
|
||||
}
|
||||
|
||||
if (intr_loc & CMD_INTR_PENDING) {
|
||||
/*
|
||||
* Command Complete Interrupt Pending
|
||||
/*
|
||||
* Command Complete Interrupt Pending
|
||||
* RO only - clear by writing 1 to the Command Completion
|
||||
* Detect bit in Controller SERR-INT register
|
||||
*/
|
||||
|
@ -875,7 +767,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
|
|||
if (!(intr_loc & ~CMD_INTR_PENDING))
|
||||
goto out;
|
||||
|
||||
for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
|
||||
for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
|
||||
/* To find out which slot has interrupt pending */
|
||||
if (!(intr_loc & SLOT_INTR_PENDING(hp_slot)))
|
||||
continue;
|
||||
|
@ -907,7 +799,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
|
|||
serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK);
|
||||
shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
|
||||
}
|
||||
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -920,8 +812,6 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
|
|||
u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1);
|
||||
u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2);
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (pi == 2) {
|
||||
if (slot_avail2 & SLOT_133MHZ_PCIX_533)
|
||||
bus_speed = PCI_SPEED_133MHz_PCIX_533;
|
||||
|
@ -954,7 +844,7 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
|
|||
|
||||
*value = bus_speed;
|
||||
dbg("Max bus speed = %d\n", bus_speed);
|
||||
DBG_LEAVE_ROUTINE
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -967,8 +857,6 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
|
|||
u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
|
||||
u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7);
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if ((pi == 1) && (speed_mode > 4)) {
|
||||
*value = PCI_SPEED_UNKNOWN;
|
||||
return -ENODEV;
|
||||
|
@ -1024,7 +912,6 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
|
|||
}
|
||||
|
||||
dbg("Current bus speed = %d\n", bus_speed);
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -1032,7 +919,7 @@ static struct hpc_ops shpchp_hpc_ops = {
|
|||
.power_on_slot = hpc_power_on_slot,
|
||||
.slot_enable = hpc_slot_enable,
|
||||
.slot_disable = hpc_slot_disable,
|
||||
.set_bus_speed_mode = hpc_set_bus_speed_mode,
|
||||
.set_bus_speed_mode = hpc_set_bus_speed_mode,
|
||||
.set_attention_status = hpc_set_attention_status,
|
||||
.get_power_status = hpc_get_power_status,
|
||||
.get_attention_status = hpc_get_attention_status,
|
||||
|
@ -1049,7 +936,7 @@ static struct hpc_ops shpchp_hpc_ops = {
|
|||
.green_led_on = hpc_set_green_led_on,
|
||||
.green_led_off = hpc_set_green_led_off,
|
||||
.green_led_blink = hpc_set_green_led_blink,
|
||||
|
||||
|
||||
.release_ctlr = hpc_release_ctlr,
|
||||
};
|
||||
|
||||
|
@ -1061,8 +948,6 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
|
|||
u32 tempdword, slot_reg, slot_config;
|
||||
u8 i;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
|
||||
|
||||
if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
|
||||
|
@ -1108,9 +993,9 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
|
|||
ctrl->mmio_size = 0x24 + 0x4 * num_slots;
|
||||
}
|
||||
|
||||
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor,
|
||||
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor,
|
||||
pdev->subsystem_device);
|
||||
|
||||
|
||||
rc = pci_enable_device(pdev);
|
||||
if (rc) {
|
||||
err("%s: pci_enable_device failed\n", __FUNCTION__);
|
||||
|
@ -1172,7 +1057,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
|
|||
slot_reg &= ~SLOT_REG_RSVDZ_MASK;
|
||||
shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
|
||||
}
|
||||
|
||||
|
||||
if (shpchp_poll_mode) {
|
||||
/* Install interrupt polling timer. Start with 10 sec delay */
|
||||
init_timer(&ctrl->poll_timer);
|
||||
|
@ -1184,7 +1069,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
|
|||
info("Can't get msi for the hotplug controller\n");
|
||||
info("Use INTx for the hotplug controller\n");
|
||||
}
|
||||
|
||||
|
||||
rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
|
||||
MY_NAME, (void *)ctrl);
|
||||
dbg("%s: request_irq %d for hpc%d (returns %d)\n",
|
||||
|
@ -1235,13 +1120,11 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
|
|||
dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
|
||||
}
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return 0;
|
||||
|
||||
/* We end up here for the many possible ways to fail this API. */
|
||||
abort_iounmap:
|
||||
iounmap(ctrl->creg);
|
||||
abort:
|
||||
DBG_LEAVE_ROUTINE
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#include "pci.h"
|
||||
#include "msi.h"
|
||||
|
||||
static DEFINE_SPINLOCK(msi_lock);
|
||||
static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
|
||||
static struct kmem_cache* msi_cachep;
|
||||
|
||||
static int pci_msi_enable = 1;
|
||||
|
@ -44,13 +42,13 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
|
|||
{
|
||||
struct msi_desc *entry;
|
||||
|
||||
entry = msi_desc[irq];
|
||||
entry = get_irq_msi(irq);
|
||||
BUG_ON(!entry || !entry->dev);
|
||||
switch (entry->msi_attrib.type) {
|
||||
case PCI_CAP_ID_MSI:
|
||||
if (entry->msi_attrib.maskbit) {
|
||||
int pos;
|
||||
u32 mask_bits;
|
||||
int pos;
|
||||
u32 mask_bits;
|
||||
|
||||
pos = (long)entry->mask_base;
|
||||
pci_read_config_dword(entry->dev, pos, &mask_bits);
|
||||
|
@ -74,7 +72,7 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
|
|||
|
||||
void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
||||
{
|
||||
struct msi_desc *entry = get_irq_data(irq);
|
||||
struct msi_desc *entry = get_irq_msi(irq);
|
||||
switch(entry->msi_attrib.type) {
|
||||
case PCI_CAP_ID_MSI:
|
||||
{
|
||||
|
@ -113,7 +111,7 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
|||
|
||||
void write_msi_msg(unsigned int irq, struct msi_msg *msg)
|
||||
{
|
||||
struct msi_desc *entry = get_irq_data(irq);
|
||||
struct msi_desc *entry = get_irq_msi(irq);
|
||||
switch (entry->msi_attrib.type) {
|
||||
case PCI_CAP_ID_MSI:
|
||||
{
|
||||
|
@ -162,6 +160,7 @@ void unmask_msi_irq(unsigned int irq)
|
|||
}
|
||||
|
||||
static int msi_free_irq(struct pci_dev* dev, int irq);
|
||||
|
||||
static int msi_init(void)
|
||||
{
|
||||
static int status = -ENOMEM;
|
||||
|
@ -169,13 +168,6 @@ static int msi_init(void)
|
|||
if (!status)
|
||||
return status;
|
||||
|
||||
if (pci_msi_quirk) {
|
||||
pci_msi_enable = 0;
|
||||
printk(KERN_WARNING "PCI: MSI quirk detected. MSI disabled.\n");
|
||||
status = -EINVAL;
|
||||
return status;
|
||||
}
|
||||
|
||||
status = msi_cache_init();
|
||||
if (status < 0) {
|
||||
pci_msi_enable = 0;
|
||||
|
@ -200,46 +192,6 @@ static struct msi_desc* alloc_msi_entry(void)
|
|||
return entry;
|
||||
}
|
||||
|
||||
static void attach_msi_entry(struct msi_desc *entry, int irq)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&msi_lock, flags);
|
||||
msi_desc[irq] = entry;
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
}
|
||||
|
||||
static int create_msi_irq(void)
|
||||
{
|
||||
struct msi_desc *entry;
|
||||
int irq;
|
||||
|
||||
entry = alloc_msi_entry();
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
irq = create_irq();
|
||||
if (irq < 0) {
|
||||
kmem_cache_free(msi_cachep, entry);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
set_irq_data(irq, entry);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static void destroy_msi_irq(unsigned int irq)
|
||||
{
|
||||
struct msi_desc *entry;
|
||||
|
||||
entry = get_irq_data(irq);
|
||||
set_irq_chip(irq, NULL);
|
||||
set_irq_data(irq, NULL);
|
||||
destroy_irq(irq);
|
||||
kmem_cache_free(msi_cachep, entry);
|
||||
}
|
||||
|
||||
static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
|
||||
{
|
||||
u16 control;
|
||||
|
@ -278,36 +230,8 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type)
|
|||
pci_intx(dev, 1); /* enable intx */
|
||||
}
|
||||
|
||||
static int msi_lookup_irq(struct pci_dev *dev, int type)
|
||||
{
|
||||
int irq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&msi_lock, flags);
|
||||
for (irq = 0; irq < NR_IRQS; irq++) {
|
||||
if (!msi_desc[irq] || msi_desc[irq]->dev != dev ||
|
||||
msi_desc[irq]->msi_attrib.type != type ||
|
||||
msi_desc[irq]->msi_attrib.default_irq != dev->irq)
|
||||
continue;
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
/* This pre-assigned MSI irq for this device
|
||||
already exits. Override dev->irq with this irq */
|
||||
dev->irq = irq;
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
void pci_scan_msi_device(struct pci_dev *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int pci_save_msi_state(struct pci_dev *dev)
|
||||
static int __pci_save_msi_state(struct pci_dev *dev)
|
||||
{
|
||||
int pos, i = 0;
|
||||
u16 control;
|
||||
|
@ -345,7 +269,7 @@ int pci_save_msi_state(struct pci_dev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void pci_restore_msi_state(struct pci_dev *dev)
|
||||
static void __pci_restore_msi_state(struct pci_dev *dev)
|
||||
{
|
||||
int i = 0, pos;
|
||||
u16 control;
|
||||
|
@ -373,14 +297,16 @@ void pci_restore_msi_state(struct pci_dev *dev)
|
|||
kfree(save_state);
|
||||
}
|
||||
|
||||
int pci_save_msix_state(struct pci_dev *dev)
|
||||
static int __pci_save_msix_state(struct pci_dev *dev)
|
||||
{
|
||||
int pos;
|
||||
int temp;
|
||||
int irq, head, tail = 0;
|
||||
u16 control;
|
||||
struct pci_cap_saved_state *save_state;
|
||||
|
||||
if (!dev->msix_enabled)
|
||||
return 0;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (pos <= 0 || dev->no_msi)
|
||||
return 0;
|
||||
|
@ -398,38 +324,46 @@ int pci_save_msix_state(struct pci_dev *dev)
|
|||
*((u16 *)&save_state->data[0]) = control;
|
||||
|
||||
/* save the table */
|
||||
temp = dev->irq;
|
||||
if (msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) {
|
||||
kfree(save_state);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
irq = head = dev->irq;
|
||||
irq = head = dev->first_msi_irq;
|
||||
while (head != tail) {
|
||||
struct msi_desc *entry;
|
||||
|
||||
entry = msi_desc[irq];
|
||||
entry = get_irq_msi(irq);
|
||||
read_msi_msg(irq, &entry->msg_save);
|
||||
|
||||
tail = msi_desc[irq]->link.tail;
|
||||
tail = entry->link.tail;
|
||||
irq = tail;
|
||||
}
|
||||
dev->irq = temp;
|
||||
|
||||
save_state->cap_nr = PCI_CAP_ID_MSIX;
|
||||
pci_add_saved_cap(dev, save_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pci_restore_msix_state(struct pci_dev *dev)
|
||||
int pci_save_msi_state(struct pci_dev *dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = __pci_save_msi_state(dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = __pci_save_msix_state(dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __pci_restore_msix_state(struct pci_dev *dev)
|
||||
{
|
||||
u16 save;
|
||||
int pos;
|
||||
int irq, head, tail = 0;
|
||||
struct msi_desc *entry;
|
||||
int temp;
|
||||
struct pci_cap_saved_state *save_state;
|
||||
|
||||
if (!dev->msix_enabled)
|
||||
return;
|
||||
|
||||
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
|
||||
if (!save_state)
|
||||
return;
|
||||
|
@ -442,23 +376,25 @@ void pci_restore_msix_state(struct pci_dev *dev)
|
|||
return;
|
||||
|
||||
/* route the table */
|
||||
temp = dev->irq;
|
||||
if (msi_lookup_irq(dev, PCI_CAP_ID_MSIX))
|
||||
return;
|
||||
irq = head = dev->irq;
|
||||
irq = head = dev->first_msi_irq;
|
||||
while (head != tail) {
|
||||
entry = msi_desc[irq];
|
||||
entry = get_irq_msi(irq);
|
||||
write_msi_msg(irq, &entry->msg_save);
|
||||
|
||||
tail = msi_desc[irq]->link.tail;
|
||||
tail = entry->link.tail;
|
||||
irq = tail;
|
||||
}
|
||||
dev->irq = temp;
|
||||
|
||||
pci_write_config_word(dev, msi_control_reg(pos), save);
|
||||
enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
|
||||
}
|
||||
#endif
|
||||
|
||||
void pci_restore_msi_state(struct pci_dev *dev)
|
||||
{
|
||||
__pci_restore_msi_state(dev);
|
||||
__pci_restore_msix_state(dev);
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
/**
|
||||
* msi_capability_init - configure device's MSI capability structure
|
||||
|
@ -471,7 +407,6 @@ void pci_restore_msix_state(struct pci_dev *dev)
|
|||
**/
|
||||
static int msi_capability_init(struct pci_dev *dev)
|
||||
{
|
||||
int status;
|
||||
struct msi_desc *entry;
|
||||
int pos, irq;
|
||||
u16 control;
|
||||
|
@ -479,13 +414,10 @@ static int msi_capability_init(struct pci_dev *dev)
|
|||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
pci_read_config_word(dev, msi_control_reg(pos), &control);
|
||||
/* MSI Entry Initialization */
|
||||
irq = create_msi_irq();
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
entry = alloc_msi_entry();
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
entry = get_irq_data(irq);
|
||||
entry->link.head = irq;
|
||||
entry->link.tail = irq;
|
||||
entry->msi_attrib.type = PCI_CAP_ID_MSI;
|
||||
entry->msi_attrib.is_64 = is_64bit_address(control);
|
||||
entry->msi_attrib.entry_nr = 0;
|
||||
|
@ -511,13 +443,16 @@ static int msi_capability_init(struct pci_dev *dev)
|
|||
maskbits);
|
||||
}
|
||||
/* Configure MSI capability structure */
|
||||
status = arch_setup_msi_irq(irq, dev);
|
||||
if (status < 0) {
|
||||
destroy_msi_irq(irq);
|
||||
return status;
|
||||
irq = arch_setup_msi_irq(dev, entry);
|
||||
if (irq < 0) {
|
||||
kmem_cache_free(msi_cachep, entry);
|
||||
return irq;
|
||||
}
|
||||
entry->link.head = irq;
|
||||
entry->link.tail = irq;
|
||||
dev->first_msi_irq = irq;
|
||||
set_irq_msi(irq, entry);
|
||||
|
||||
attach_msi_entry(entry, irq);
|
||||
/* Set MSI enabled bits */
|
||||
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
||||
|
||||
|
@ -539,7 +474,6 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||
struct msix_entry *entries, int nvec)
|
||||
{
|
||||
struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
|
||||
int status;
|
||||
int irq, pos, i, j, nr_entries, temp = 0;
|
||||
unsigned long phys_addr;
|
||||
u32 table_offset;
|
||||
|
@ -562,13 +496,11 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||
|
||||
/* MSI-X Table Initialization */
|
||||
for (i = 0; i < nvec; i++) {
|
||||
irq = create_msi_irq();
|
||||
if (irq < 0)
|
||||
entry = alloc_msi_entry();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
entry = get_irq_data(irq);
|
||||
j = entries[i].entry;
|
||||
entries[i].vector = irq;
|
||||
entry->msi_attrib.type = PCI_CAP_ID_MSIX;
|
||||
entry->msi_attrib.is_64 = 1;
|
||||
entry->msi_attrib.entry_nr = j;
|
||||
|
@ -577,6 +509,14 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||
entry->msi_attrib.pos = pos;
|
||||
entry->dev = dev;
|
||||
entry->mask_base = base;
|
||||
|
||||
/* Configure MSI-X capability structure */
|
||||
irq = arch_setup_msi_irq(dev, entry);
|
||||
if (irq < 0) {
|
||||
kmem_cache_free(msi_cachep, entry);
|
||||
break;
|
||||
}
|
||||
entries[i].vector = irq;
|
||||
if (!head) {
|
||||
entry->link.head = irq;
|
||||
entry->link.tail = irq;
|
||||
|
@ -589,14 +529,8 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||
}
|
||||
temp = irq;
|
||||
tail = entry;
|
||||
/* Configure MSI-X capability structure */
|
||||
status = arch_setup_msi_irq(irq, dev);
|
||||
if (status < 0) {
|
||||
destroy_msi_irq(irq);
|
||||
break;
|
||||
}
|
||||
|
||||
attach_msi_entry(entry, irq);
|
||||
set_irq_msi(irq, entry);
|
||||
}
|
||||
if (i != nvec) {
|
||||
int avail = i - 1;
|
||||
|
@ -613,6 +547,7 @@ static int msix_capability_init(struct pci_dev *dev,
|
|||
avail = -EBUSY;
|
||||
return avail;
|
||||
}
|
||||
dev->first_msi_irq = entries[0].vector;
|
||||
/* Set MSI-X enabled bits */
|
||||
enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
|
||||
|
||||
|
@ -660,13 +595,11 @@ int pci_msi_supported(struct pci_dev * dev)
|
|||
**/
|
||||
int pci_enable_msi(struct pci_dev* dev)
|
||||
{
|
||||
int pos, temp, status;
|
||||
int pos, status;
|
||||
|
||||
if (pci_msi_supported(dev) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
temp = dev->irq;
|
||||
|
||||
status = msi_init();
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
@ -675,15 +608,14 @@ int pci_enable_msi(struct pci_dev* dev)
|
|||
if (!pos)
|
||||
return -EINVAL;
|
||||
|
||||
WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSI));
|
||||
WARN_ON(!!dev->msi_enabled);
|
||||
|
||||
/* Check whether driver already requested for MSI-X irqs */
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) {
|
||||
if (pos > 0 && dev->msix_enabled) {
|
||||
printk(KERN_INFO "PCI: %s: Can't enable MSI. "
|
||||
"Device already has MSI-X irq assigned\n",
|
||||
"Device already has MSI-X enabled\n",
|
||||
pci_name(dev));
|
||||
dev->irq = temp;
|
||||
return -EINVAL;
|
||||
}
|
||||
status = msi_capability_init(dev);
|
||||
|
@ -695,13 +627,15 @@ void pci_disable_msi(struct pci_dev* dev)
|
|||
struct msi_desc *entry;
|
||||
int pos, default_irq;
|
||||
u16 control;
|
||||
unsigned long flags;
|
||||
|
||||
if (!pci_msi_enable)
|
||||
return;
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
if (!dev->msi_enabled)
|
||||
return;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
if (!pos)
|
||||
return;
|
||||
|
@ -710,28 +644,26 @@ void pci_disable_msi(struct pci_dev* dev)
|
|||
if (!(control & PCI_MSI_FLAGS_ENABLE))
|
||||
return;
|
||||
|
||||
|
||||
disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
|
||||
|
||||
spin_lock_irqsave(&msi_lock, flags);
|
||||
entry = msi_desc[dev->irq];
|
||||
entry = get_irq_msi(dev->first_msi_irq);
|
||||
if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
return;
|
||||
}
|
||||
if (irq_has_action(dev->irq)) {
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
if (irq_has_action(dev->first_msi_irq)) {
|
||||
printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without "
|
||||
"free_irq() on MSI irq %d\n",
|
||||
pci_name(dev), dev->irq);
|
||||
BUG_ON(irq_has_action(dev->irq));
|
||||
pci_name(dev), dev->first_msi_irq);
|
||||
BUG_ON(irq_has_action(dev->first_msi_irq));
|
||||
} else {
|
||||
default_irq = entry->msi_attrib.default_irq;
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
msi_free_irq(dev, dev->irq);
|
||||
msi_free_irq(dev, dev->first_msi_irq);
|
||||
|
||||
/* Restore dev->irq to its default pin-assertion irq */
|
||||
dev->irq = default_irq;
|
||||
}
|
||||
dev->first_msi_irq = 0;
|
||||
}
|
||||
|
||||
static int msi_free_irq(struct pci_dev* dev, int irq)
|
||||
|
@ -739,27 +671,20 @@ static int msi_free_irq(struct pci_dev* dev, int irq)
|
|||
struct msi_desc *entry;
|
||||
int head, entry_nr, type;
|
||||
void __iomem *base;
|
||||
unsigned long flags;
|
||||
|
||||
arch_teardown_msi_irq(irq);
|
||||
|
||||
spin_lock_irqsave(&msi_lock, flags);
|
||||
entry = msi_desc[irq];
|
||||
entry = get_irq_msi(irq);
|
||||
if (!entry || entry->dev != dev) {
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
type = entry->msi_attrib.type;
|
||||
entry_nr = entry->msi_attrib.entry_nr;
|
||||
head = entry->link.head;
|
||||
base = entry->mask_base;
|
||||
msi_desc[entry->link.head]->link.tail = entry->link.tail;
|
||||
msi_desc[entry->link.tail]->link.head = entry->link.head;
|
||||
entry->dev = NULL;
|
||||
msi_desc[irq] = NULL;
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
get_irq_msi(entry->link.head)->link.tail = entry->link.tail;
|
||||
get_irq_msi(entry->link.tail)->link.head = entry->link.head;
|
||||
|
||||
destroy_msi_irq(irq);
|
||||
arch_teardown_msi_irq(irq);
|
||||
kmem_cache_free(msi_cachep, entry);
|
||||
|
||||
if (type == PCI_CAP_ID_MSIX) {
|
||||
writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE +
|
||||
|
@ -790,7 +715,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq)
|
|||
int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
|
||||
{
|
||||
int status, pos, nr_entries;
|
||||
int i, j, temp;
|
||||
int i, j;
|
||||
u16 control;
|
||||
|
||||
if (!entries || pci_msi_supported(dev) < 0)
|
||||
|
@ -818,16 +743,14 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
|
|||
return -EINVAL; /* duplicate entry */
|
||||
}
|
||||
}
|
||||
temp = dev->irq;
|
||||
WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSIX));
|
||||
WARN_ON(!!dev->msix_enabled);
|
||||
|
||||
/* Check whether driver already requested for MSI irq */
|
||||
if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 &&
|
||||
!msi_lookup_irq(dev, PCI_CAP_ID_MSI)) {
|
||||
dev->msi_enabled) {
|
||||
printk(KERN_INFO "PCI: %s: Can't enable MSI-X. "
|
||||
"Device already has an MSI irq assigned\n",
|
||||
pci_name(dev));
|
||||
dev->irq = temp;
|
||||
return -EINVAL;
|
||||
}
|
||||
status = msix_capability_init(dev, entries, nvec);
|
||||
|
@ -836,7 +759,8 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
|
|||
|
||||
void pci_disable_msix(struct pci_dev* dev)
|
||||
{
|
||||
int pos, temp;
|
||||
int irq, head, tail = 0, warning = 0;
|
||||
int pos;
|
||||
u16 control;
|
||||
|
||||
if (!pci_msi_enable)
|
||||
|
@ -844,6 +768,9 @@ void pci_disable_msix(struct pci_dev* dev)
|
|||
if (!dev)
|
||||
return;
|
||||
|
||||
if (!dev->msix_enabled)
|
||||
return;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (!pos)
|
||||
return;
|
||||
|
@ -854,31 +781,23 @@ void pci_disable_msix(struct pci_dev* dev)
|
|||
|
||||
disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
|
||||
|
||||
temp = dev->irq;
|
||||
if (!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) {
|
||||
int irq, head, tail = 0, warning = 0;
|
||||
unsigned long flags;
|
||||
|
||||
irq = head = dev->irq;
|
||||
dev->irq = temp; /* Restore pin IRQ */
|
||||
while (head != tail) {
|
||||
spin_lock_irqsave(&msi_lock, flags);
|
||||
tail = msi_desc[irq]->link.tail;
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
if (irq_has_action(irq))
|
||||
warning = 1;
|
||||
else if (irq != head) /* Release MSI-X irq */
|
||||
msi_free_irq(dev, irq);
|
||||
irq = tail;
|
||||
}
|
||||
msi_free_irq(dev, irq);
|
||||
if (warning) {
|
||||
printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without "
|
||||
"free_irq() on all MSI-X irqs\n",
|
||||
pci_name(dev));
|
||||
BUG_ON(warning > 0);
|
||||
}
|
||||
irq = head = dev->first_msi_irq;
|
||||
while (head != tail) {
|
||||
tail = get_irq_msi(irq)->link.tail;
|
||||
if (irq_has_action(irq))
|
||||
warning = 1;
|
||||
else if (irq != head) /* Release MSI-X irq */
|
||||
msi_free_irq(dev, irq);
|
||||
irq = tail;
|
||||
}
|
||||
msi_free_irq(dev, irq);
|
||||
if (warning) {
|
||||
printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without "
|
||||
"free_irq() on all MSI-X irqs\n",
|
||||
pci_name(dev));
|
||||
BUG_ON(warning > 0);
|
||||
}
|
||||
dev->first_msi_irq = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -892,35 +811,26 @@ void pci_disable_msix(struct pci_dev* dev)
|
|||
**/
|
||||
void msi_remove_pci_irq_vectors(struct pci_dev* dev)
|
||||
{
|
||||
int pos, temp;
|
||||
unsigned long flags;
|
||||
|
||||
if (!pci_msi_enable || !dev)
|
||||
return;
|
||||
|
||||
temp = dev->irq; /* Save IOAPIC IRQ */
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
||||
if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) {
|
||||
if (irq_has_action(dev->irq)) {
|
||||
if (dev->msi_enabled) {
|
||||
if (irq_has_action(dev->first_msi_irq)) {
|
||||
printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
|
||||
"called without free_irq() on MSI irq %d\n",
|
||||
pci_name(dev), dev->irq);
|
||||
BUG_ON(irq_has_action(dev->irq));
|
||||
pci_name(dev), dev->first_msi_irq);
|
||||
BUG_ON(irq_has_action(dev->first_msi_irq));
|
||||
} else /* Release MSI irq assigned to this device */
|
||||
msi_free_irq(dev, dev->irq);
|
||||
dev->irq = temp; /* Restore IOAPIC IRQ */
|
||||
msi_free_irq(dev, dev->first_msi_irq);
|
||||
}
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) {
|
||||
if (dev->msix_enabled) {
|
||||
int irq, head, tail = 0, warning = 0;
|
||||
void __iomem *base = NULL;
|
||||
|
||||
irq = head = dev->irq;
|
||||
irq = head = dev->first_msi_irq;
|
||||
while (head != tail) {
|
||||
spin_lock_irqsave(&msi_lock, flags);
|
||||
tail = msi_desc[irq]->link.tail;
|
||||
base = msi_desc[irq]->mask_base;
|
||||
spin_unlock_irqrestore(&msi_lock, flags);
|
||||
tail = get_irq_msi(irq)->link.tail;
|
||||
base = get_irq_msi(irq)->mask_base;
|
||||
if (irq_has_action(irq))
|
||||
warning = 1;
|
||||
else if (irq != head) /* Release MSI-X irq */
|
||||
|
@ -935,7 +845,6 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
|
|||
pci_name(dev));
|
||||
BUG_ON(warning > 0);
|
||||
}
|
||||
dev->irq = temp; /* Restore IOAPIC IRQ */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -324,8 +324,7 @@ static int pci_default_resume(struct pci_dev *pci_dev)
|
|||
/* restore the PCI config space */
|
||||
pci_restore_state(pci_dev);
|
||||
/* if the device was enabled before suspend, reenable */
|
||||
if (atomic_read(&pci_dev->enable_cnt))
|
||||
retval = __pci_enable_device(pci_dev);
|
||||
retval = __pci_reenable_device(pci_dev);
|
||||
/* if the device was busmaster before the suspend, make it busmaster again */
|
||||
if (pci_dev->is_busmaster)
|
||||
pci_set_master(pci_dev);
|
||||
|
|
|
@ -392,6 +392,14 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||
if (state > PCI_D3hot)
|
||||
state = PCI_D3hot;
|
||||
|
||||
/*
|
||||
* If the device or the parent bridge can't support PCI PM, ignore
|
||||
* the request if we're doing anything besides putting it into D0
|
||||
* (which would only happen on boot).
|
||||
*/
|
||||
if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
|
||||
return 0;
|
||||
|
||||
/* Validate current state:
|
||||
* Can enter D0 from any state, but if we can only go deeper
|
||||
* to sleep if we're already in a low power state
|
||||
|
@ -403,13 +411,6 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||
} else if (dev->current_state == state)
|
||||
return 0; /* we're already there */
|
||||
|
||||
/*
|
||||
* If the device or the parent bridge can't support PCI PM, ignore
|
||||
* the request if we're doing anything besides putting it into D0
|
||||
* (which would only happen on boot).
|
||||
*/
|
||||
if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
|
||||
return 0;
|
||||
|
||||
/* find PCI PM capability in list */
|
||||
pm = pci_find_capability(dev, PCI_CAP_ID_PM);
|
||||
|
@ -633,8 +634,6 @@ pci_save_state(struct pci_dev *dev)
|
|||
pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
|
||||
if ((i = pci_save_msi_state(dev)) != 0)
|
||||
return i;
|
||||
if ((i = pci_save_msix_state(dev)) != 0)
|
||||
return i;
|
||||
if ((i = pci_save_pcie_state(dev)) != 0)
|
||||
return i;
|
||||
if ((i = pci_save_pcix_state(dev)) != 0)
|
||||
|
@ -672,22 +671,11 @@ pci_restore_state(struct pci_dev *dev)
|
|||
}
|
||||
pci_restore_pcix_state(dev);
|
||||
pci_restore_msi_state(dev);
|
||||
pci_restore_msix_state(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_enable_device_bars - Initialize some of a device for use
|
||||
* @dev: PCI device to be initialized
|
||||
* @bars: bitmask of BAR's that must be configured
|
||||
*
|
||||
* Initialize device before it's used by a driver. Ask low-level code
|
||||
* to enable selected I/O and memory resources. Wake up the device if it
|
||||
* was suspended. Beware, this function can fail.
|
||||
*/
|
||||
|
||||
int
|
||||
pci_enable_device_bars(struct pci_dev *dev, int bars)
|
||||
static int do_pci_enable_device(struct pci_dev *dev, int bars)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -697,30 +685,47 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
|
|||
err = pcibios_enable_device(dev, bars);
|
||||
if (err < 0)
|
||||
return err;
|
||||
pci_fixup_device(pci_fixup_enable, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* __pci_enable_device - Initialize device before it's used by a driver.
|
||||
* @dev: PCI device to be initialized
|
||||
* __pci_reenable_device - Resume abandoned device
|
||||
* @dev: PCI device to be resumed
|
||||
*
|
||||
* Initialize device before it's used by a driver. Ask low-level code
|
||||
* to enable I/O and memory. Wake up the device if it was suspended.
|
||||
* Beware, this function can fail.
|
||||
*
|
||||
* Note this function is a backend and is not supposed to be called by
|
||||
* normal code, use pci_enable_device() instead.
|
||||
* Note this function is a backend of pci_default_resume and is not supposed
|
||||
* to be called by normal code, write proper resume handler and use it instead.
|
||||
*/
|
||||
int
|
||||
__pci_enable_device(struct pci_dev *dev)
|
||||
__pci_reenable_device(struct pci_dev *dev)
|
||||
{
|
||||
if (atomic_read(&dev->enable_cnt))
|
||||
return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_enable_device_bars - Initialize some of a device for use
|
||||
* @dev: PCI device to be initialized
|
||||
* @bars: bitmask of BAR's that must be configured
|
||||
*
|
||||
* Initialize device before it's used by a driver. Ask low-level code
|
||||
* to enable selected I/O and memory resources. Wake up the device if it
|
||||
* was suspended. Beware, this function can fail.
|
||||
*/
|
||||
int
|
||||
pci_enable_device_bars(struct pci_dev *dev, int bars)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
|
||||
if (err)
|
||||
return err;
|
||||
pci_fixup_device(pci_fixup_enable, dev);
|
||||
return 0;
|
||||
if (atomic_add_return(1, &dev->enable_cnt) > 1)
|
||||
return 0; /* already enabled */
|
||||
|
||||
err = do_pci_enable_device(dev, bars);
|
||||
if (err < 0)
|
||||
atomic_dec(&dev->enable_cnt);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -736,13 +741,7 @@ __pci_enable_device(struct pci_dev *dev)
|
|||
*/
|
||||
int pci_enable_device(struct pci_dev *dev)
|
||||
{
|
||||
int result;
|
||||
if (atomic_add_return(1, &dev->enable_cnt) > 1)
|
||||
return 0; /* already enabled */
|
||||
result = __pci_enable_device(dev);
|
||||
if (result < 0)
|
||||
atomic_dec(&dev->enable_cnt);
|
||||
return result;
|
||||
return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -921,6 +920,47 @@ err_out:
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_release_selected_regions - Release selected PCI I/O and memory resources
|
||||
* @pdev: PCI device whose resources were previously reserved
|
||||
* @bars: Bitmask of BARs to be released
|
||||
*
|
||||
* Release selected PCI I/O and memory resources previously reserved.
|
||||
* Call this function only after all use of the PCI regions has ceased.
|
||||
*/
|
||||
void pci_release_selected_regions(struct pci_dev *pdev, int bars)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
if (bars & (1 << i))
|
||||
pci_release_region(pdev, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_request_selected_regions - Reserve selected PCI I/O and memory resources
|
||||
* @pdev: PCI device whose resources are to be reserved
|
||||
* @bars: Bitmask of BARs to be requested
|
||||
* @res_name: Name to be associated with resource
|
||||
*/
|
||||
int pci_request_selected_regions(struct pci_dev *pdev, int bars,
|
||||
const char *res_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
if (bars & (1 << i))
|
||||
if(pci_request_region(pdev, i, res_name))
|
||||
goto err_out;
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
while(--i >= 0)
|
||||
if (bars & (1 << i))
|
||||
pci_release_region(pdev, i);
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_release_regions - Release reserved PCI I/O and memory resources
|
||||
|
@ -933,10 +973,7 @@ err_out:
|
|||
|
||||
void pci_release_regions(struct pci_dev *pdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
pci_release_region(pdev, i);
|
||||
pci_release_selected_regions(pdev, (1 << 6) - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -954,18 +991,7 @@ void pci_release_regions(struct pci_dev *pdev)
|
|||
*/
|
||||
int pci_request_regions(struct pci_dev *pdev, const char *res_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
if(pci_request_region(pdev, i, res_name))
|
||||
goto err_out;
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
while(--i >= 0)
|
||||
pci_release_region(pdev, i);
|
||||
|
||||
return -EBUSY;
|
||||
return pci_request_selected_regions(pdev, ((1 << 6) - 1), res_name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1148,7 +1174,23 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* pci_select_bars - Make BAR mask from the type of resource
|
||||
* @pdev: the PCI device for which BAR mask is made
|
||||
* @flags: resource type mask to be selected
|
||||
*
|
||||
* This helper routine makes bar mask from the type of resource.
|
||||
*/
|
||||
int pci_select_bars(struct pci_dev *dev, unsigned long flags)
|
||||
{
|
||||
int i, bars = 0;
|
||||
for (i = 0; i < PCI_NUM_RESOURCES; i++)
|
||||
if (pci_resource_flags(dev, i) & flags)
|
||||
bars |= (1 << i);
|
||||
return bars;
|
||||
}
|
||||
|
||||
static int __devinit pci_init(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
|
@ -1181,12 +1223,6 @@ early_param("pci", pci_setup);
|
|||
|
||||
device_initcall(pci_init);
|
||||
|
||||
#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
|
||||
/* FIXME: Some boxes have multiple ISA bridges! */
|
||||
struct pci_dev *isa_bridge;
|
||||
EXPORT_SYMBOL(isa_bridge);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL_GPL(pci_restore_bars);
|
||||
EXPORT_SYMBOL(pci_enable_device_bars);
|
||||
EXPORT_SYMBOL(pci_enable_device);
|
||||
|
@ -1197,6 +1233,8 @@ EXPORT_SYMBOL(pci_release_regions);
|
|||
EXPORT_SYMBOL(pci_request_regions);
|
||||
EXPORT_SYMBOL(pci_release_region);
|
||||
EXPORT_SYMBOL(pci_request_region);
|
||||
EXPORT_SYMBOL(pci_release_selected_regions);
|
||||
EXPORT_SYMBOL(pci_request_selected_regions);
|
||||
EXPORT_SYMBOL(pci_set_master);
|
||||
EXPORT_SYMBOL(pci_set_mwi);
|
||||
EXPORT_SYMBOL(pci_clear_mwi);
|
||||
|
@ -1205,13 +1243,10 @@ EXPORT_SYMBOL(pci_set_dma_mask);
|
|||
EXPORT_SYMBOL(pci_set_consistent_dma_mask);
|
||||
EXPORT_SYMBOL(pci_assign_resource);
|
||||
EXPORT_SYMBOL(pci_find_parent_resource);
|
||||
EXPORT_SYMBOL(pci_select_bars);
|
||||
|
||||
EXPORT_SYMBOL(pci_set_power_state);
|
||||
EXPORT_SYMBOL(pci_save_state);
|
||||
EXPORT_SYMBOL(pci_restore_state);
|
||||
EXPORT_SYMBOL(pci_enable_wake);
|
||||
|
||||
/* Quirk info */
|
||||
|
||||
EXPORT_SYMBOL(isa_dma_bridge_buggy);
|
||||
EXPORT_SYMBOL(pci_pci_problems);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Functions internal to the PCI core code */
|
||||
|
||||
extern int __must_check __pci_enable_device(struct pci_dev *);
|
||||
extern int __must_check __pci_reenable_device(struct pci_dev *);
|
||||
extern int pci_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size);
|
||||
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
|
||||
|
@ -43,12 +43,8 @@ extern void pci_remove_legacy_files(struct pci_bus *bus);
|
|||
/* Lock for read/write access to pci device and bus lists */
|
||||
extern struct rw_semaphore pci_bus_sem;
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
extern int pci_msi_quirk;
|
||||
#else
|
||||
#define pci_msi_quirk 0
|
||||
#endif
|
||||
extern unsigned int pci_pm_d3_delay;
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
void disable_msi_mode(struct pci_dev *dev, int pos, int type);
|
||||
void pci_no_msi(void);
|
||||
|
@ -56,17 +52,15 @@ void pci_no_msi(void);
|
|||
static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
|
||||
static inline void pci_no_msi(void) { }
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
|
||||
int pci_save_msi_state(struct pci_dev *dev);
|
||||
int pci_save_msix_state(struct pci_dev *dev);
|
||||
void pci_restore_msi_state(struct pci_dev *dev);
|
||||
void pci_restore_msix_state(struct pci_dev *dev);
|
||||
#else
|
||||
static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; }
|
||||
static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; }
|
||||
static inline void pci_restore_msi_state(struct pci_dev *dev) {}
|
||||
static inline void pci_restore_msix_state(struct pci_dev *dev) {}
|
||||
#endif
|
||||
|
||||
static inline int pci_no_d1d2(struct pci_dev *dev)
|
||||
{
|
||||
unsigned int parent_dstates = 0;
|
||||
|
|
|
@ -144,6 +144,32 @@ static u32 pci_size(u32 base, u32 maxbase, u32 mask)
|
|||
return size;
|
||||
}
|
||||
|
||||
static u64 pci_size64(u64 base, u64 maxbase, u64 mask)
|
||||
{
|
||||
u64 size = mask & maxbase; /* Find the significant bits */
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
/* Get the lowest of them to find the decode size, and
|
||||
from that the extent. */
|
||||
size = (size & ~(size-1)) - 1;
|
||||
|
||||
/* base == maxbase can be valid only if the BAR has
|
||||
already been programmed with all 1s. */
|
||||
if (base == maxbase && ((base | size) & mask) != mask)
|
||||
return 0;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline int is_64bit_memory(u32 mask)
|
||||
{
|
||||
if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
|
||||
(PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
|
||||
{
|
||||
unsigned int pos, reg, next;
|
||||
|
@ -151,6 +177,10 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
|
|||
struct resource *res;
|
||||
|
||||
for(pos=0; pos<howmany; pos = next) {
|
||||
u64 l64;
|
||||
u64 sz64;
|
||||
u32 raw_sz;
|
||||
|
||||
next = pos+1;
|
||||
res = &dev->resource[pos];
|
||||
res->name = pci_name(dev);
|
||||
|
@ -163,9 +193,16 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
|
|||
continue;
|
||||
if (l == 0xffffffff)
|
||||
l = 0;
|
||||
if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
|
||||
raw_sz = sz;
|
||||
if ((l & PCI_BASE_ADDRESS_SPACE) ==
|
||||
PCI_BASE_ADDRESS_SPACE_MEMORY) {
|
||||
sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK);
|
||||
if (!sz)
|
||||
/*
|
||||
* For 64bit prefetchable memory sz could be 0, if the
|
||||
* real size is bigger than 4G, so we need to check
|
||||
* szhi for that.
|
||||
*/
|
||||
if (!is_64bit_memory(l) && !sz)
|
||||
continue;
|
||||
res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK;
|
||||
|
@ -178,30 +215,36 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
|
|||
}
|
||||
res->end = res->start + (unsigned long) sz;
|
||||
res->flags |= pci_calc_resource_flags(l);
|
||||
if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
|
||||
== (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
|
||||
if (is_64bit_memory(l)) {
|
||||
u32 szhi, lhi;
|
||||
|
||||
pci_read_config_dword(dev, reg+4, &lhi);
|
||||
pci_write_config_dword(dev, reg+4, ~0);
|
||||
pci_read_config_dword(dev, reg+4, &szhi);
|
||||
pci_write_config_dword(dev, reg+4, lhi);
|
||||
szhi = pci_size(lhi, szhi, 0xffffffff);
|
||||
sz64 = ((u64)szhi << 32) | raw_sz;
|
||||
l64 = ((u64)lhi << 32) | l;
|
||||
sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK);
|
||||
next++;
|
||||
#if BITS_PER_LONG == 64
|
||||
res->start |= ((unsigned long) lhi) << 32;
|
||||
res->end = res->start + sz;
|
||||
if (szhi) {
|
||||
/* This BAR needs > 4GB? Wow. */
|
||||
res->end |= (unsigned long)szhi<<32;
|
||||
if (!sz64) {
|
||||
res->start = 0;
|
||||
res->end = 0;
|
||||
res->flags = 0;
|
||||
continue;
|
||||
}
|
||||
res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
res->end = res->start + sz64;
|
||||
#else
|
||||
if (szhi) {
|
||||
printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev));
|
||||
if (sz64 > 0x100000000ULL) {
|
||||
printk(KERN_ERR "PCI: Unable to handle 64-bit "
|
||||
"BAR for device %s\n", pci_name(dev));
|
||||
res->start = 0;
|
||||
res->flags = 0;
|
||||
} else if (lhi) {
|
||||
/* 64-bit wide address, treat as disabled */
|
||||
pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK);
|
||||
pci_write_config_dword(dev, reg,
|
||||
l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK);
|
||||
pci_write_config_dword(dev, reg+4, 0);
|
||||
res->start = 0;
|
||||
res->end = sz;
|
||||
|
@ -902,7 +945,6 @@ pci_scan_single_device(struct pci_bus *bus, int devfn)
|
|||
return NULL;
|
||||
|
||||
pci_device_add(dev, bus);
|
||||
pci_scan_msi_device(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,8 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_p
|
|||
|
||||
This appears to be BIOS not version dependent. So presumably there is a
|
||||
chipset level fix */
|
||||
int isa_dma_bridge_buggy; /* Exported */
|
||||
int isa_dma_bridge_buggy;
|
||||
EXPORT_SYMBOL(isa_dma_bridge_buggy);
|
||||
|
||||
static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
|
||||
{
|
||||
|
@ -83,6 +84,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_d
|
|||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs );
|
||||
|
||||
int pci_pci_problems;
|
||||
EXPORT_SYMBOL(pci_pci_problems);
|
||||
|
||||
/*
|
||||
* Chipsets where PCI->PCI transfers vanish or hang
|
||||
|
@ -94,6 +96,8 @@ static void __devinit quirk_nopcipci(struct pci_dev *dev)
|
|||
pci_pci_problems |= PCIPCI_FAIL;
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci );
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci );
|
||||
|
||||
static void __devinit quirk_nopciamd(struct pci_dev *dev)
|
||||
{
|
||||
|
@ -105,9 +109,6 @@ static void __devinit quirk_nopciamd(struct pci_dev *dev)
|
|||
pci_pci_problems |= PCIAGP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci );
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci );
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopciamd );
|
||||
|
||||
/*
|
||||
|
@ -976,52 +977,51 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
|
|||
case 0x1626: /* L3C notebook */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB)
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB)
|
||||
switch(dev->subsystem_device) {
|
||||
case 0x80b1: /* P4GE-V */
|
||||
case 0x80b2: /* P4PE */
|
||||
case 0x8093: /* P4B533-V */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82850_HB)
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_82850_HB)
|
||||
switch(dev->subsystem_device) {
|
||||
case 0x8030: /* P4T533 */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_7205_0)
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_7205_0)
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x8070: /* P4G8X Deluxe */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH)
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH)
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x80c9: /* PU-DLS */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x1751: /* M2N notebook */
|
||||
case 0x1821: /* M5N notebook */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x184b: /* W1N notebook */
|
||||
case 0x186a: /* M6Ne notebook */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x80f2: /* P4P800-X */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x1882: /* M6V notebook */
|
||||
case 0x1977: /* A6VA notebook */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
}
|
||||
} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) {
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
|
||||
switch(dev->subsystem_device) {
|
||||
|
@ -1029,25 +1029,24 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
|
|||
case 0x0890: /* HP Compaq nc6000 */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x12bc: /* HP D330L */
|
||||
case 0x12bd: /* HP D530 */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
|
||||
switch (dev->subsystem_device) {
|
||||
case 0x099c: /* HP Compaq nx6110 */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
}
|
||||
} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
|
||||
switch(dev->subsystem_device) {
|
||||
case 0x0001: /* Toshiba Satellite A40 */
|
||||
asus_hides_smbus = 1;
|
||||
}
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
|
||||
else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
|
||||
switch(dev->subsystem_device) {
|
||||
case 0x0001: /* Toshiba Tecra M2 */
|
||||
asus_hides_smbus = 1;
|
||||
|
@ -1136,6 +1135,14 @@ static void quirk_sis_96x_smbus(struct pci_dev *dev)
|
|||
pci_write_config_byte(dev, 0x77, val & ~0x10);
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, 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_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 );
|
||||
|
||||
/*
|
||||
* ... This is further complicated by the fact that some SiS96x south
|
||||
|
@ -1145,8 +1152,6 @@ static void quirk_sis_96x_smbus(struct pci_dev *dev)
|
|||
*
|
||||
* We can also enable the sis96x bit in the discovery register..
|
||||
*/
|
||||
static int __devinitdata sis_96x_compatible = 0;
|
||||
|
||||
#define SIS_DETECT_REGISTER 0x40
|
||||
|
||||
static void quirk_sis_503(struct pci_dev *dev)
|
||||
|
@ -1162,9 +1167,6 @@ static void quirk_sis_503(struct pci_dev *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Make people aware that we changed the config.. */
|
||||
printk(KERN_WARNING "Uncovering SIS%x that hid as a SIS503 (compatible=%d)\n", devid, sis_96x_compatible);
|
||||
|
||||
/*
|
||||
* Ok, it now shows up as a 96x.. run the 96x quirk by
|
||||
* hand in case it has already been processed.
|
||||
|
@ -1173,20 +1175,10 @@ static void quirk_sis_503(struct pci_dev *dev)
|
|||
dev->device = devid;
|
||||
quirk_sis_96x_smbus(dev);
|
||||
}
|
||||
|
||||
static void __init quirk_sis_96x_compatible(struct pci_dev *dev)
|
||||
{
|
||||
sis_96x_compatible = 1;
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_645, quirk_sis_96x_compatible );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_646, quirk_sis_96x_compatible );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_648, quirk_sis_96x_compatible );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650, quirk_sis_96x_compatible );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, 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_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
|
||||
|
||||
|
||||
/*
|
||||
* On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller
|
||||
* and MC97 modem controller are disabled when a second PCI soundcard is
|
||||
|
@ -1217,21 +1209,8 @@ static void asus_hides_ac97_lpc(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
|
||||
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus );
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, 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_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)
|
||||
|
||||
/*
|
||||
|
@ -1276,7 +1255,6 @@ static void quirk_jmicron_dualfn(struct pci_dev *pdev)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -1420,6 +1398,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_co
|
|||
|
||||
|
||||
int pcie_mch_quirk;
|
||||
EXPORT_SYMBOL(pcie_mch_quirk);
|
||||
|
||||
static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
|
||||
{
|
||||
|
@ -1646,6 +1625,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
|
|||
}
|
||||
pci_do_fixups(dev, start, end);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_fixup_device);
|
||||
|
||||
/* Enable 1k I/O space granularity on the Intel P64H2 */
|
||||
static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
|
||||
|
@ -1673,6 +1653,31 @@ static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
|
|||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io);
|
||||
|
||||
/* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2
|
||||
* The IOBL_ADR gets re-written to 4k boundaries in pci_setup_bridge()
|
||||
* in drivers/pci/setup-bus.c
|
||||
*/
|
||||
static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev)
|
||||
{
|
||||
u16 en1k, iobl_adr, iobl_adr_1k;
|
||||
struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES;
|
||||
|
||||
pci_read_config_word(dev, 0x40, &en1k);
|
||||
|
||||
if (en1k & 0x200) {
|
||||
pci_read_config_word(dev, PCI_IO_BASE, &iobl_adr);
|
||||
|
||||
iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00);
|
||||
|
||||
if (iobl_adr != iobl_adr_1k) {
|
||||
printk(KERN_INFO "PCI: Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1 KB Granularity\n",
|
||||
iobl_adr,iobl_adr_1k);
|
||||
pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k);
|
||||
}
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io_fix_iobl);
|
||||
|
||||
/* Under some circumstances, AER is not linked with extended capabilities.
|
||||
* Force it to be linked by setting the corresponding control bit in the
|
||||
* config space.
|
||||
|
@ -1695,9 +1700,6 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
|
|||
quirk_nvidia_ck804_pcie_aer_ext_cap);
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
/* To disable MSI globally */
|
||||
int pci_msi_quirk;
|
||||
|
||||
/* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely
|
||||
* on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
|
||||
* some other busses controlled by the chipset even if Linux is not aware of it.
|
||||
|
@ -1706,8 +1708,8 @@ int pci_msi_quirk;
|
|||
*/
|
||||
static void __init quirk_svw_msi(struct pci_dev *dev)
|
||||
{
|
||||
pci_msi_quirk = 1;
|
||||
printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
|
||||
pci_no_msi();
|
||||
printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n");
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi);
|
||||
|
||||
|
@ -1788,8 +1790,3 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
|
|||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
|
||||
quirk_nvidia_ck804_msi_ht_cap);
|
||||
#endif /* CONFIG_PCI_MSI */
|
||||
|
||||
EXPORT_SYMBOL(pcie_mch_quirk);
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
EXPORT_SYMBOL(pci_fixup_device);
|
||||
#endif
|
||||
|
|
|
@ -357,43 +357,6 @@ exit:
|
|||
return dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id
|
||||
* @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
|
||||
* @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
|
||||
* @from: Previous PCI device found in search, or %NULL for new search.
|
||||
*
|
||||
* Iterates through the list of known PCI devices in the reverse order of
|
||||
* pci_find_device().
|
||||
* If a PCI device is found with a matching @vendor and @device, a pointer to
|
||||
* its device structure is returned. Otherwise, %NULL is returned.
|
||||
* A new search is initiated by passing %NULL as the @from argument.
|
||||
* Otherwise if @from is not %NULL, searches continue from previous device
|
||||
* on the global list.
|
||||
*/
|
||||
struct pci_dev *
|
||||
pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from)
|
||||
{
|
||||
struct list_head *n;
|
||||
struct pci_dev *dev;
|
||||
|
||||
WARN_ON(in_interrupt());
|
||||
down_read(&pci_bus_sem);
|
||||
n = from ? from->global_list.prev : pci_devices.prev;
|
||||
|
||||
while (n && (n != &pci_devices)) {
|
||||
dev = pci_dev_g(n);
|
||||
if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
|
||||
(device == PCI_ANY_ID || dev->device == device))
|
||||
goto exit;
|
||||
n = n->prev;
|
||||
}
|
||||
dev = NULL;
|
||||
exit:
|
||||
up_read(&pci_bus_sem);
|
||||
return dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_get_class - begin or continue searching for a PCI device by class
|
||||
* @class: search for a PCI device with this class designation
|
||||
|
@ -469,7 +432,6 @@ EXPORT_SYMBOL(pci_dev_present);
|
|||
EXPORT_SYMBOL(pci_find_present);
|
||||
|
||||
EXPORT_SYMBOL(pci_find_device);
|
||||
EXPORT_SYMBOL(pci_find_device_reverse);
|
||||
EXPORT_SYMBOL(pci_find_slot);
|
||||
/* For boot time work */
|
||||
EXPORT_SYMBOL(pci_find_bus);
|
||||
|
|
|
@ -7558,9 +7558,6 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
|
|||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C,
|
||||
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8,
|
||||
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7,
|
||||
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
|
||||
|
|
|
@ -293,4 +293,6 @@ struct pci_dev *alpha_gendev_to_pci(struct device *dev);
|
|||
#define IOBASE_ROOT_BUS 5
|
||||
#define IOBASE_FROM_HOSE 0x10000
|
||||
|
||||
extern struct pci_dev *isa_bridge;
|
||||
|
||||
#endif /* __ALPHA_PCI_H */
|
||||
|
|
|
@ -21,6 +21,7 @@ struct mm_struct;
|
|||
struct pci_bus;
|
||||
struct task_struct;
|
||||
struct pci_dev;
|
||||
struct msi_desc;
|
||||
|
||||
typedef void ia64_mv_setup_t (char **);
|
||||
typedef void ia64_mv_cpu_init_t (void);
|
||||
|
@ -79,7 +80,7 @@ typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *);
|
|||
typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
|
||||
typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
|
||||
|
||||
typedef int ia64_mv_setup_msi_irq_t (unsigned int irq, struct pci_dev *pdev);
|
||||
typedef int ia64_mv_setup_msi_irq_t (struct pci_dev *pdev, struct msi_desc *);
|
||||
typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq);
|
||||
|
||||
static inline void
|
||||
|
|
|
@ -68,6 +68,7 @@ typedef void fastcall (*irq_flow_handler_t)(unsigned int irq,
|
|||
#define IRQ_MOVE_PENDING 0x40000000 /* need to re-target IRQ destination */
|
||||
|
||||
struct proc_dir_entry;
|
||||
struct msi_desc;
|
||||
|
||||
/**
|
||||
* struct irq_chip - hardware interrupt chip descriptor
|
||||
|
@ -148,6 +149,7 @@ struct irq_chip {
|
|||
struct irq_desc {
|
||||
irq_flow_handler_t handle_irq;
|
||||
struct irq_chip *chip;
|
||||
struct msi_desc *msi_desc;
|
||||
void *handler_data;
|
||||
void *chip_data;
|
||||
struct irqaction *action; /* IRQ action list */
|
||||
|
@ -373,10 +375,12 @@ extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
|
|||
extern int set_irq_data(unsigned int irq, void *data);
|
||||
extern int set_irq_chip_data(unsigned int irq, void *data);
|
||||
extern int set_irq_type(unsigned int irq, unsigned int type);
|
||||
extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
|
||||
|
||||
#define get_irq_chip(irq) (irq_desc[irq].chip)
|
||||
#define get_irq_chip_data(irq) (irq_desc[irq].chip_data)
|
||||
#define get_irq_data(irq) (irq_desc[irq].handler_data)
|
||||
#define get_irq_msi(irq) (irq_desc[irq].msi_desc)
|
||||
|
||||
#endif /* CONFIG_GENERIC_HARDIRQS */
|
||||
|
||||
|
|
|
@ -7,11 +7,10 @@ struct msi_msg {
|
|||
u32 data; /* 16 bits of msi message data */
|
||||
};
|
||||
|
||||
/* Heper functions */
|
||||
/* Helper functions */
|
||||
extern void mask_msi_irq(unsigned int irq);
|
||||
extern void unmask_msi_irq(unsigned int irq);
|
||||
extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
|
||||
|
||||
extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
|
||||
|
||||
struct msi_desc {
|
||||
|
@ -42,7 +41,7 @@ struct msi_desc {
|
|||
/*
|
||||
* The arch hook for setup up msi irqs
|
||||
*/
|
||||
int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev);
|
||||
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
|
||||
void arch_teardown_msi_irq(unsigned int irq);
|
||||
|
||||
|
||||
|
|
|
@ -174,6 +174,9 @@ struct pci_dev {
|
|||
struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
|
||||
int rom_attr_enabled; /* has display of the rom attribute been enabled? */
|
||||
struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
unsigned int first_msi_irq;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
|
||||
|
@ -181,6 +184,11 @@ struct pci_dev {
|
|||
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
|
||||
#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
|
||||
|
||||
static inline int pci_channel_offline(struct pci_dev *pdev)
|
||||
{
|
||||
return (pdev->error_state != pci_channel_io_normal);
|
||||
}
|
||||
|
||||
static inline struct pci_cap_saved_state *pci_find_saved_cap(
|
||||
struct pci_dev *pci_dev,char cap)
|
||||
{
|
||||
|
@ -463,8 +471,7 @@ extern void pci_sort_breadthfirst(void);
|
|||
|
||||
/* Generic PCI functions exported to card drivers */
|
||||
|
||||
struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from);
|
||||
struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from);
|
||||
struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from);
|
||||
struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
|
||||
int pci_find_capability (struct pci_dev *dev, int cap);
|
||||
int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
|
||||
|
@ -533,6 +540,7 @@ void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
|
|||
int __must_check pci_assign_resource(struct pci_dev *dev, int i);
|
||||
int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
|
||||
void pci_restore_bars(struct pci_dev *dev);
|
||||
int pci_select_bars(struct pci_dev *dev, unsigned long flags);
|
||||
|
||||
/* ROM control related routines */
|
||||
void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
|
||||
|
@ -561,6 +569,8 @@ int __must_check pci_request_regions(struct pci_dev *, const char *);
|
|||
void pci_release_regions(struct pci_dev *);
|
||||
int __must_check pci_request_region(struct pci_dev *, int, const char *);
|
||||
void pci_release_region(struct pci_dev *, int);
|
||||
int pci_request_selected_regions(struct pci_dev *, int, const char *);
|
||||
void pci_release_selected_regions(struct pci_dev *, int);
|
||||
|
||||
/* drivers/pci/bus.c */
|
||||
int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
|
||||
|
@ -612,10 +622,6 @@ enum pci_dma_burst_strategy {
|
|||
strategy_parameter byte boundaries */
|
||||
};
|
||||
|
||||
#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
|
||||
extern struct pci_dev *isa_bridge;
|
||||
#endif
|
||||
|
||||
struct msix_entry {
|
||||
u16 vector; /* kernel uses to write allocated vector */
|
||||
u16 entry; /* driver uses to specify entry, OS writes */
|
||||
|
@ -623,7 +629,6 @@ struct msix_entry {
|
|||
|
||||
|
||||
#ifndef CONFIG_PCI_MSI
|
||||
static inline void pci_scan_msi_device(struct pci_dev *dev) {}
|
||||
static inline int pci_enable_msi(struct pci_dev *dev) {return -1;}
|
||||
static inline void pci_disable_msi(struct pci_dev *dev) {}
|
||||
static inline int pci_enable_msix(struct pci_dev* dev,
|
||||
|
@ -631,7 +636,6 @@ static inline int pci_enable_msix(struct pci_dev* dev,
|
|||
static inline void pci_disable_msix(struct pci_dev *dev) {}
|
||||
static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
|
||||
#else
|
||||
extern void pci_scan_msi_device(struct pci_dev *dev);
|
||||
extern int pci_enable_msi(struct pci_dev *dev);
|
||||
extern void pci_disable_msi(struct pci_dev *dev);
|
||||
extern int pci_enable_msix(struct pci_dev* dev,
|
||||
|
@ -723,8 +727,6 @@ static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) {
|
|||
static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; }
|
||||
static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; }
|
||||
|
||||
#define isa_bridge ((struct pci_dev *)NULL)
|
||||
|
||||
#define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
|
||||
|
||||
static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
|
||||
|
|
|
@ -39,6 +39,7 @@ void dynamic_irq_init(unsigned int irq)
|
|||
desc->chip = &no_irq_chip;
|
||||
desc->handle_irq = handle_bad_irq;
|
||||
desc->depth = 1;
|
||||
desc->msi_desc = NULL;
|
||||
desc->handler_data = NULL;
|
||||
desc->chip_data = NULL;
|
||||
desc->action = NULL;
|
||||
|
@ -74,6 +75,9 @@ void dynamic_irq_cleanup(unsigned int irq)
|
|||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
desc->msi_desc = NULL;
|
||||
desc->handler_data = NULL;
|
||||
desc->chip_data = NULL;
|
||||
desc->handle_irq = handle_bad_irq;
|
||||
desc->chip = &no_irq_chip;
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
|
@ -161,6 +165,30 @@ int set_irq_data(unsigned int irq, void *data)
|
|||
}
|
||||
EXPORT_SYMBOL(set_irq_data);
|
||||
|
||||
/**
|
||||
* set_irq_data - set irq type data for an irq
|
||||
* @irq: Interrupt number
|
||||
* @data: Pointer to interrupt specific data
|
||||
*
|
||||
* Set the hardware irq controller data for an irq
|
||||
*/
|
||||
int set_irq_msi(unsigned int irq, struct msi_desc *entry)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= NR_IRQS) {
|
||||
printk(KERN_ERR
|
||||
"Trying to install msi data for IRQ%d\n", irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
desc = irq_desc + irq;
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
desc->msi_desc = entry;
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_irq_chip_data - set irq chip data for an irq
|
||||
* @irq: Interrupt number
|
||||
|
|
Loading…
Reference in New Issue