Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
This commit is contained in:
commit
84cdda8a19
130 changed files with 1011 additions and 5555 deletions
|
@ -433,9 +433,8 @@ static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
|
|||
return; /* only applies to certain Toshibas (so far) */
|
||||
|
||||
/* Restore config space on Toshiba laptops */
|
||||
mdelay(10);
|
||||
pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size);
|
||||
pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq);
|
||||
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, (u8 *)&dev->irq);
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
|
||||
pci_resource_start(dev, 0));
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
|
||||
|
|
|
@ -987,7 +987,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
|
|||
break;
|
||||
}
|
||||
|
||||
if ((res = kcalloc(1, sizeof(struct resource), GFP_KERNEL)) == NULL) {
|
||||
if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
|
||||
printk(KERN_ERR "failed to alocate resource for iomem\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -347,7 +347,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
|
|||
((struct fnptr *)kretprobe_trampoline)->ip;
|
||||
|
||||
spin_lock_irqsave(&kretprobe_lock, flags);
|
||||
head = kretprobe_inst_table_head(current);
|
||||
head = kretprobe_inst_table_head(current);
|
||||
|
||||
/*
|
||||
* It is possible to have multiple instances associated with a given
|
||||
|
@ -363,9 +363,9 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
|
|||
* kretprobe_trampoline
|
||||
*/
|
||||
hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
|
||||
if (ri->task != current)
|
||||
if (ri->task != current)
|
||||
/* another task is sharing our hash bucket */
|
||||
continue;
|
||||
continue;
|
||||
|
||||
if (ri->rp && ri->rp->handler)
|
||||
ri->rp->handler(ri, regs);
|
||||
|
@ -394,7 +394,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
|
|||
* kprobe_handler() that we don't want the post_handler
|
||||
* to run (and have re-enabled preemption)
|
||||
*/
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Called with kretprobe_lock held */
|
||||
|
@ -739,12 +739,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
|
|||
|
||||
switch(val) {
|
||||
case DIE_BREAK:
|
||||
if (pre_kprobes_handler(args))
|
||||
ret = NOTIFY_STOP;
|
||||
/* err is break number from ia64_bad_break() */
|
||||
if (args->err == 0x80200 || args->err == 0x80300)
|
||||
if (pre_kprobes_handler(args))
|
||||
ret = NOTIFY_STOP;
|
||||
break;
|
||||
case DIE_SS:
|
||||
if (post_kprobes_handler(args->regs))
|
||||
ret = NOTIFY_STOP;
|
||||
case DIE_FAULT:
|
||||
/* err is vector number from ia64_fault() */
|
||||
if (args->err == 36)
|
||||
if (post_kprobes_handler(args->regs))
|
||||
ret = NOTIFY_STOP;
|
||||
break;
|
||||
case DIE_PAGE_FAULT:
|
||||
/* kprobe_running() needs smp_processor_id() */
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
*
|
||||
* 2005-08-12 Keith Owens <kaos@sgi.com>
|
||||
* Convert MCA/INIT handlers to use per event stacks and SAL/OS state.
|
||||
*
|
||||
* 2005-10-07 Keith Owens <kaos@sgi.com>
|
||||
* Add notify_die() hooks.
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -58,7 +61,6 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/acpi.h>
|
||||
|
@ -69,6 +71,7 @@
|
|||
#include <linux/workqueue.h>
|
||||
|
||||
#include <asm/delay.h>
|
||||
#include <asm/kdebug.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/meminit.h>
|
||||
#include <asm/page.h>
|
||||
|
@ -132,6 +135,14 @@ extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
|
|||
|
||||
static int mca_init;
|
||||
|
||||
|
||||
static void inline
|
||||
ia64_mca_spin(const char *func)
|
||||
{
|
||||
printk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func);
|
||||
while (1)
|
||||
cpu_relax();
|
||||
}
|
||||
/*
|
||||
* IA64_MCA log support
|
||||
*/
|
||||
|
@ -526,13 +537,16 @@ ia64_mca_wakeup_all(void)
|
|||
* Outputs : None
|
||||
*/
|
||||
static irqreturn_t
|
||||
ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
|
||||
ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
/* Mask all interrupts */
|
||||
local_irq_save(flags);
|
||||
if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
|
||||
ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE;
|
||||
/* Register with the SAL monarch that the slave has
|
||||
|
@ -540,10 +554,18 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
|
|||
*/
|
||||
ia64_sal_mc_rendez();
|
||||
|
||||
if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
|
||||
/* Wait for the monarch cpu to exit. */
|
||||
while (monarch_cpu != -1)
|
||||
cpu_relax(); /* spin until monarch leaves */
|
||||
|
||||
if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
|
||||
/* Enable all interrupts */
|
||||
local_irq_restore(flags);
|
||||
return IRQ_HANDLED;
|
||||
|
@ -933,6 +955,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
|
|||
oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
|
||||
previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
|
||||
monarch_cpu = cpu;
|
||||
if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
ia64_wait_for_slaves(cpu);
|
||||
|
||||
/* Wakeup all the processors which are spinning in the rendezvous loop.
|
||||
|
@ -942,6 +967,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
|
|||
* spinning in SAL does not work.
|
||||
*/
|
||||
ia64_mca_wakeup_all();
|
||||
if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
|
||||
/* Get the MCA error record and log it */
|
||||
ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
|
||||
|
@ -960,6 +988,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
|
|||
ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
|
||||
sos->os_status = IA64_MCA_CORRECTED;
|
||||
}
|
||||
if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, 0, 0, recover)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
|
||||
set_curr_task(cpu, previous_current);
|
||||
monarch_cpu = -1;
|
||||
|
@ -1188,6 +1219,37 @@ ia64_mca_cpe_poll (unsigned long dummy)
|
|||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
static int
|
||||
default_monarch_init_process(struct notifier_block *self, unsigned long val, void *data)
|
||||
{
|
||||
int c;
|
||||
struct task_struct *g, *t;
|
||||
if (val != DIE_INIT_MONARCH_PROCESS)
|
||||
return NOTIFY_DONE;
|
||||
printk(KERN_ERR "Processes interrupted by INIT -");
|
||||
for_each_online_cpu(c) {
|
||||
struct ia64_sal_os_state *s;
|
||||
t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET);
|
||||
s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET);
|
||||
g = s->prev_task;
|
||||
if (g) {
|
||||
if (g->pid)
|
||||
printk(" %d", g->pid);
|
||||
else
|
||||
printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g);
|
||||
}
|
||||
}
|
||||
printk("\n\n");
|
||||
if (read_trylock(&tasklist_lock)) {
|
||||
do_each_thread (g, t) {
|
||||
printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
|
||||
show_stack(t, NULL);
|
||||
} while_each_thread (g, t);
|
||||
read_unlock(&tasklist_lock);
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* C portion of the OS INIT handler
|
||||
*
|
||||
|
@ -1212,8 +1274,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
|
|||
static atomic_t slaves;
|
||||
static atomic_t monarchs;
|
||||
task_t *previous_current;
|
||||
int cpu = smp_processor_id(), c;
|
||||
struct task_struct *g, *t;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */
|
||||
console_loglevel = 15; /* make sure printks make it to console */
|
||||
|
@ -1253,8 +1314,17 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
|
|||
ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
|
||||
while (monarch_cpu == -1)
|
||||
cpu_relax(); /* spin until monarch enters */
|
||||
if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
while (monarch_cpu != -1)
|
||||
cpu_relax(); /* spin until monarch leaves */
|
||||
if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
printk("Slave on cpu %d returning to normal service.\n", cpu);
|
||||
set_curr_task(cpu, previous_current);
|
||||
ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
|
||||
|
@ -1263,6 +1333,9 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
|
|||
}
|
||||
|
||||
monarch_cpu = cpu;
|
||||
if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
|
||||
/*
|
||||
* Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be
|
||||
|
@ -1273,27 +1346,16 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
|
|||
printk("Delaying for 5 seconds...\n");
|
||||
udelay(5*1000000);
|
||||
ia64_wait_for_slaves(cpu);
|
||||
printk(KERN_ERR "Processes interrupted by INIT -");
|
||||
for_each_online_cpu(c) {
|
||||
struct ia64_sal_os_state *s;
|
||||
t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET);
|
||||
s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET);
|
||||
g = s->prev_task;
|
||||
if (g) {
|
||||
if (g->pid)
|
||||
printk(" %d", g->pid);
|
||||
else
|
||||
printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g);
|
||||
}
|
||||
}
|
||||
printk("\n\n");
|
||||
if (read_trylock(&tasklist_lock)) {
|
||||
do_each_thread (g, t) {
|
||||
printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
|
||||
show_stack(t, NULL);
|
||||
} while_each_thread (g, t);
|
||||
read_unlock(&tasklist_lock);
|
||||
}
|
||||
/* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
|
||||
* to default_monarch_init_process() above and just print all the
|
||||
* tasks.
|
||||
*/
|
||||
if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, 0, 0, 0)
|
||||
== NOTIFY_STOP)
|
||||
ia64_mca_spin(__FUNCTION__);
|
||||
printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu);
|
||||
atomic_dec(&monarchs);
|
||||
set_curr_task(cpu, previous_current);
|
||||
|
@ -1462,6 +1524,10 @@ ia64_mca_init(void)
|
|||
s64 rc;
|
||||
struct ia64_sal_retval isrv;
|
||||
u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */
|
||||
static struct notifier_block default_init_monarch_nb = {
|
||||
.notifier_call = default_monarch_init_process,
|
||||
.priority = 0/* we need to notified last */
|
||||
};
|
||||
|
||||
IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__);
|
||||
|
||||
|
@ -1555,6 +1621,10 @@ ia64_mca_init(void)
|
|||
"(status %ld)\n", rc);
|
||||
return;
|
||||
}
|
||||
if (register_die_notifier(&default_init_monarch_nb)) {
|
||||
printk(KERN_ERR "Failed to register default monarch INIT process\n");
|
||||
return;
|
||||
}
|
||||
|
||||
IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__);
|
||||
|
||||
|
|
|
@ -547,9 +547,20 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
|
|||
(pal_processor_state_info_t*)peidx_psp(peidx);
|
||||
|
||||
/*
|
||||
* We cannot recover errors with other than bus_check.
|
||||
* Processor recovery status must key off of the PAL recovery
|
||||
* status in the Processor State Parameter.
|
||||
*/
|
||||
if (psp->cc || psp->rc || psp->uc)
|
||||
|
||||
/*
|
||||
* The machine check is corrected.
|
||||
*/
|
||||
if (psp->cm == 1)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* The error was not contained. Software must be reset.
|
||||
*/
|
||||
if (psp->us || psp->ci == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
@ -570,8 +581,6 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
|
|||
return 0;
|
||||
if (pbci->eb && pbci->bsi > 0)
|
||||
return 0;
|
||||
if (psp->ci == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* This is a local MCA and estimated as recoverble external bus error.
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
* Copyright (C) 1998-2003 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
* 04/11/17 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support
|
||||
*
|
||||
* 2005-10-07 Keith Owens <kaos@sgi.com>
|
||||
* Add notify_die() hooks.
|
||||
*/
|
||||
#define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */
|
||||
#include <linux/config.h>
|
||||
|
@ -34,6 +37,7 @@
|
|||
#include <asm/elf.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/kdebug.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/sal.h>
|
||||
|
@ -808,12 +812,14 @@ cpu_halt (void)
|
|||
void
|
||||
machine_restart (char *restart_cmd)
|
||||
{
|
||||
(void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0);
|
||||
(*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
machine_halt (void)
|
||||
{
|
||||
(void) notify_die(DIE_MACHINE_HALT, "", NULL, 0, 0, 0);
|
||||
cpu_halt();
|
||||
}
|
||||
|
||||
|
|
|
@ -461,6 +461,7 @@ setup_arch (char **cmdline_p)
|
|||
#endif
|
||||
|
||||
cpu_init(); /* initialize the bootstrap CPU */
|
||||
mmu_context_init(); /* initialize context_id bitmap */
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
acpi_boot_init();
|
||||
|
|
|
@ -387,15 +387,14 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
|
|||
struct sigscratch *scr)
|
||||
{
|
||||
extern char __kernel_sigtramp[];
|
||||
unsigned long tramp_addr, new_rbs = 0;
|
||||
unsigned long tramp_addr, new_rbs = 0, new_sp;
|
||||
struct sigframe __user *frame;
|
||||
long err;
|
||||
|
||||
frame = (void __user *) scr->pt.r12;
|
||||
new_sp = scr->pt.r12;
|
||||
tramp_addr = (unsigned long) __kernel_sigtramp;
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags((unsigned long) frame) == 0) {
|
||||
frame = (void __user *) ((current->sas_ss_sp + current->sas_ss_size)
|
||||
& ~(STACK_ALIGN - 1));
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(new_sp) == 0) {
|
||||
new_sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
/*
|
||||
* We need to check for the register stack being on the signal stack
|
||||
* separately, because it's switched separately (memory stack is switched
|
||||
|
@ -404,7 +403,7 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
|
|||
if (!rbs_on_sig_stack(scr->pt.ar_bspstore))
|
||||
new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
|
||||
}
|
||||
frame = (void __user *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1));
|
||||
frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN);
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
return force_sigsegv_info(sig, frame);
|
||||
|
|
|
@ -30,17 +30,20 @@ fpswa_interface_t *fpswa_interface;
|
|||
EXPORT_SYMBOL(fpswa_interface);
|
||||
|
||||
struct notifier_block *ia64die_chain;
|
||||
static DEFINE_SPINLOCK(die_notifier_lock);
|
||||
|
||||
int register_die_notifier(struct notifier_block *nb)
|
||||
int
|
||||
register_die_notifier(struct notifier_block *nb)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&die_notifier_lock, flags);
|
||||
err = notifier_chain_register(&ia64die_chain, nb);
|
||||
spin_unlock_irqrestore(&die_notifier_lock, flags);
|
||||
return err;
|
||||
return notifier_chain_register(&ia64die_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_die_notifier);
|
||||
|
||||
int
|
||||
unregister_die_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return notifier_chain_unregister(&ia64die_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_die_notifier);
|
||||
|
||||
void __init
|
||||
trap_init (void)
|
||||
|
@ -105,6 +108,7 @@ die (const char *str, struct pt_regs *regs, long err)
|
|||
if (++die.lock_owner_depth < 3) {
|
||||
printk("%s[%d]: %s %ld [%d]\n",
|
||||
current->comm, current->pid, str, err, ++die_counter);
|
||||
(void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
|
||||
show_regs(regs);
|
||||
} else
|
||||
printk(KERN_ERR "Recursive die() failure, output suppressed\n");
|
||||
|
@ -155,9 +159,8 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
|
|||
switch (break_num) {
|
||||
case 0: /* unknown error (used by GCC for __builtin_abort()) */
|
||||
if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
|
||||
== NOTIFY_STOP) {
|
||||
== NOTIFY_STOP)
|
||||
return;
|
||||
}
|
||||
die_if_kernel("bugcheck!", regs, break_num);
|
||||
sig = SIGILL; code = ILL_ILLOPC;
|
||||
break;
|
||||
|
@ -210,15 +213,6 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
|
|||
sig = SIGILL; code = __ILL_BNDMOD;
|
||||
break;
|
||||
|
||||
case 0x80200:
|
||||
case 0x80300:
|
||||
if (notify_die(DIE_BREAK, "kprobe", regs, break_num, TRAP_BRKPT, SIGTRAP)
|
||||
== NOTIFY_STOP) {
|
||||
return;
|
||||
}
|
||||
sig = SIGTRAP; code = TRAP_BRKPT;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (break_num < 0x40000 || break_num > 0x100000)
|
||||
die_if_kernel("Bad break", regs, break_num);
|
||||
|
@ -226,6 +220,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
|
|||
if (break_num < 0x80000) {
|
||||
sig = SIGILL; code = __ILL_BREAK;
|
||||
} else {
|
||||
if (notify_die(DIE_BREAK, "bad break", regs, break_num, TRAP_BRKPT, SIGTRAP)
|
||||
== NOTIFY_STOP)
|
||||
return;
|
||||
sig = SIGTRAP; code = TRAP_BRKPT;
|
||||
}
|
||||
}
|
||||
|
@ -578,12 +575,11 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
#endif
|
||||
break;
|
||||
case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
|
||||
case 36:
|
||||
if (notify_die(DIE_SS, "ss", ®s, vector,
|
||||
vector, SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
siginfo.si_code = TRAP_TRACE; ifa = 0; break;
|
||||
case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
|
||||
}
|
||||
if (notify_die(DIE_FAULT, "ia64_fault", ®s, vector, siginfo.si_code, SIGTRAP)
|
||||
== NOTIFY_STOP)
|
||||
return;
|
||||
siginfo.si_signo = SIGTRAP;
|
||||
siginfo.si_errno = 0;
|
||||
siginfo.si_addr = (void __user *) ifa;
|
||||
|
|
|
@ -350,14 +350,12 @@ static void __init initialize_pernode_data(void)
|
|||
* for best.
|
||||
* @nid: node id
|
||||
* @pernodesize: size of this node's pernode data
|
||||
* @align: alignment to use for this node's pernode data
|
||||
*/
|
||||
static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize,
|
||||
unsigned long align)
|
||||
static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
u8 best = 0xff;
|
||||
int bestnode = -1, node;
|
||||
int bestnode = -1, node, anynode = 0;
|
||||
|
||||
for_each_online_node(node) {
|
||||
if (node_isset(node, memory_less_mask))
|
||||
|
@ -366,13 +364,15 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize,
|
|||
best = node_distance(nid, node);
|
||||
bestnode = node;
|
||||
}
|
||||
anynode = node;
|
||||
}
|
||||
|
||||
ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat,
|
||||
pernodesize, align, __pa(MAX_DMA_ADDRESS));
|
||||
if (bestnode == -1)
|
||||
bestnode = anynode;
|
||||
|
||||
ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat, pernodesize,
|
||||
PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
|
||||
|
||||
if (!ptr)
|
||||
panic("NO memory for memory less node\n");
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -413,8 +413,7 @@ static void __init memory_less_nodes(void)
|
|||
|
||||
for_each_node_mask(node, memory_less_mask) {
|
||||
pernodesize = compute_pernodesize(node);
|
||||
pernode = memory_less_node_alloc(node, pernodesize,
|
||||
(node) ? (node * PERCPU_PAGE_SIZE) : (1024*1024));
|
||||
pernode = memory_less_node_alloc(node, pernodesize);
|
||||
fill_pernode(node, __pa(pernode), pernodesize);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
* Modified RID allocation for SMP
|
||||
* Goutham Rao <goutham.rao@intel.com>
|
||||
* IPI based ptc implementation and A-step IPI implementation.
|
||||
* Rohit Seth <rohit.seth@intel.com>
|
||||
* Ken Chen <kenneth.w.chen@intel.com>
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -16,78 +18,75 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <asm/delay.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/pal.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/dma.h>
|
||||
|
||||
static struct {
|
||||
unsigned long mask; /* mask of supported purge page-sizes */
|
||||
unsigned long max_bits; /* log2() of largest supported purge page-size */
|
||||
unsigned long max_bits; /* log2 of largest supported purge page-size */
|
||||
} purge;
|
||||
|
||||
struct ia64_ctx ia64_ctx = {
|
||||
.lock = SPIN_LOCK_UNLOCKED,
|
||||
.next = 1,
|
||||
.limit = (1 << 15) - 1, /* start out with the safe (architected) limit */
|
||||
.max_ctx = ~0U
|
||||
};
|
||||
|
||||
DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
|
||||
|
||||
/*
|
||||
* Initializes the ia64_ctx.bitmap array based on max_ctx+1.
|
||||
* Called after cpu_init() has setup ia64_ctx.max_ctx based on
|
||||
* maximum RID that is supported by boot CPU.
|
||||
*/
|
||||
void __init
|
||||
mmu_context_init (void)
|
||||
{
|
||||
ia64_ctx.bitmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3);
|
||||
ia64_ctx.flushmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Acquire the ia64_ctx.lock before calling this function!
|
||||
*/
|
||||
void
|
||||
wrap_mmu_context (struct mm_struct *mm)
|
||||
{
|
||||
unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx;
|
||||
struct task_struct *tsk;
|
||||
int i;
|
||||
int i, cpu;
|
||||
unsigned long flush_bit;
|
||||
|
||||
if (ia64_ctx.next > max_ctx)
|
||||
ia64_ctx.next = 300; /* skip daemons */
|
||||
ia64_ctx.limit = max_ctx + 1;
|
||||
for (i=0; i <= ia64_ctx.max_ctx / BITS_PER_LONG; i++) {
|
||||
flush_bit = xchg(&ia64_ctx.flushmap[i], 0);
|
||||
ia64_ctx.bitmap[i] ^= flush_bit;
|
||||
}
|
||||
|
||||
/* use offset at 300 to skip daemons */
|
||||
ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap,
|
||||
ia64_ctx.max_ctx, 300);
|
||||
ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap,
|
||||
ia64_ctx.max_ctx, ia64_ctx.next);
|
||||
|
||||
/*
|
||||
* Scan all the task's mm->context and set proper safe range
|
||||
* can't call flush_tlb_all() here because of race condition
|
||||
* with O(1) scheduler [EF]
|
||||
*/
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
repeat:
|
||||
for_each_process(tsk) {
|
||||
if (!tsk->mm)
|
||||
continue;
|
||||
tsk_context = tsk->mm->context;
|
||||
if (tsk_context == ia64_ctx.next) {
|
||||
if (++ia64_ctx.next >= ia64_ctx.limit) {
|
||||
/* empty range: reset the range limit and start over */
|
||||
if (ia64_ctx.next > max_ctx)
|
||||
ia64_ctx.next = 300;
|
||||
ia64_ctx.limit = max_ctx + 1;
|
||||
goto repeat;
|
||||
}
|
||||
}
|
||||
if ((tsk_context > ia64_ctx.next) && (tsk_context < ia64_ctx.limit))
|
||||
ia64_ctx.limit = tsk_context;
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
/* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */
|
||||
{
|
||||
int cpu = get_cpu(); /* prevent preemption/migration */
|
||||
for_each_online_cpu(i) {
|
||||
if (i != cpu)
|
||||
per_cpu(ia64_need_tlb_flush, i) = 1;
|
||||
}
|
||||
put_cpu();
|
||||
}
|
||||
cpu = get_cpu(); /* prevent preemption/migration */
|
||||
for_each_online_cpu(i)
|
||||
if (i != cpu)
|
||||
per_cpu(ia64_need_tlb_flush, i) = 1;
|
||||
put_cpu();
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
void
|
||||
ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits)
|
||||
ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, unsigned long nbits)
|
||||
{
|
||||
static DEFINE_SPINLOCK(ptcg_lock);
|
||||
|
||||
|
@ -135,7 +134,8 @@ local_flush_tlb_all (void)
|
|||
}
|
||||
|
||||
void
|
||||
flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end)
|
||||
flush_tlb_range (struct vm_area_struct *vma, unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
unsigned long size = end - start;
|
||||
|
@ -149,7 +149,8 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long
|
|||
#endif
|
||||
|
||||
nbits = ia64_fls(size + 0xfff);
|
||||
while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits))
|
||||
while (unlikely (((1UL << nbits) & purge.mask) == 0) &&
|
||||
(nbits < purge.max_bits))
|
||||
++nbits;
|
||||
if (nbits > purge.max_bits)
|
||||
nbits = purge.max_bits;
|
||||
|
@ -191,5 +192,5 @@ ia64_tlb_init (void)
|
|||
local_cpu_data->ptce_stride[0] = ptce_info.stride[0];
|
||||
local_cpu_data->ptce_stride[1] = ptce_info.stride[1];
|
||||
|
||||
local_flush_tlb_all(); /* nuke left overs from bootstrapping... */
|
||||
local_flush_tlb_all(); /* nuke left overs from bootstrapping... */
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn,
|
|||
}
|
||||
|
||||
static struct pci_raw_ops pci_sal_ops = {
|
||||
.read = pci_sal_read,
|
||||
.read = pci_sal_read,
|
||||
.write = pci_sal_write
|
||||
};
|
||||
|
||||
|
@ -137,35 +137,98 @@ alloc_pci_controller (int seg)
|
|||
return controller;
|
||||
}
|
||||
|
||||
static u64 __devinit
|
||||
add_io_space (struct acpi_resource_address64 *addr)
|
||||
struct pci_root_info {
|
||||
struct pci_controller *controller;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static unsigned int
|
||||
new_space (u64 phys_base, int sparse)
|
||||
{
|
||||
u64 offset;
|
||||
int sparse = 0;
|
||||
u64 mmio_base;
|
||||
int i;
|
||||
|
||||
if (addr->address_translation_offset == 0)
|
||||
return IO_SPACE_BASE(0); /* part of legacy IO space */
|
||||
if (phys_base == 0)
|
||||
return 0; /* legacy I/O port space */
|
||||
|
||||
if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION)
|
||||
sparse = 1;
|
||||
|
||||
offset = (u64) ioremap(addr->address_translation_offset, 0);
|
||||
mmio_base = (u64) ioremap(phys_base, 0);
|
||||
for (i = 0; i < num_io_spaces; i++)
|
||||
if (io_space[i].mmio_base == offset &&
|
||||
if (io_space[i].mmio_base == mmio_base &&
|
||||
io_space[i].sparse == sparse)
|
||||
return IO_SPACE_BASE(i);
|
||||
return i;
|
||||
|
||||
if (num_io_spaces == MAX_IO_SPACES) {
|
||||
printk("Too many IO port spaces\n");
|
||||
printk(KERN_ERR "PCI: Too many IO port spaces "
|
||||
"(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES);
|
||||
return ~0;
|
||||
}
|
||||
|
||||
i = num_io_spaces++;
|
||||
io_space[i].mmio_base = offset;
|
||||
io_space[i].mmio_base = mmio_base;
|
||||
io_space[i].sparse = sparse;
|
||||
|
||||
return IO_SPACE_BASE(i);
|
||||
return i;
|
||||
}
|
||||
|
||||
static u64 __devinit
|
||||
add_io_space (struct pci_root_info *info, struct acpi_resource_address64 *addr)
|
||||
{
|
||||
struct resource *resource;
|
||||
char *name;
|
||||
u64 base, min, max, base_port;
|
||||
unsigned int sparse = 0, space_nr, len;
|
||||
|
||||
resource = kzalloc(sizeof(*resource), GFP_KERNEL);
|
||||
if (!resource) {
|
||||
printk(KERN_ERR "PCI: No memory for %s I/O port space\n",
|
||||
info->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = strlen(info->name) + 32;
|
||||
name = kzalloc(len, GFP_KERNEL);
|
||||
if (!name) {
|
||||
printk(KERN_ERR "PCI: No memory for %s I/O port space name\n",
|
||||
info->name);
|
||||
goto free_resource;
|
||||
}
|
||||
|
||||
min = addr->min_address_range;
|
||||
max = min + addr->address_length - 1;
|
||||
if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION)
|
||||
sparse = 1;
|
||||
|
||||
space_nr = new_space(addr->address_translation_offset, sparse);
|
||||
if (space_nr == ~0)
|
||||
goto free_name;
|
||||
|
||||
base = __pa(io_space[space_nr].mmio_base);
|
||||
base_port = IO_SPACE_BASE(space_nr);
|
||||
snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name,
|
||||
base_port + min, base_port + max);
|
||||
|
||||
/*
|
||||
* The SDM guarantees the legacy 0-64K space is sparse, but if the
|
||||
* mapping is done by the processor (not the bridge), ACPI may not
|
||||
* mark it as sparse.
|
||||
*/
|
||||
if (space_nr == 0)
|
||||
sparse = 1;
|
||||
|
||||
resource->name = name;
|
||||
resource->flags = IORESOURCE_MEM;
|
||||
resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
|
||||
resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max);
|
||||
insert_resource(&iomem_resource, resource);
|
||||
|
||||
return base_port;
|
||||
|
||||
free_name:
|
||||
kfree(name);
|
||||
free_resource:
|
||||
kfree(resource);
|
||||
out:
|
||||
return ~0;
|
||||
}
|
||||
|
||||
static acpi_status __devinit resource_to_window(struct acpi_resource *resource,
|
||||
|
@ -205,11 +268,6 @@ count_window (struct acpi_resource *resource, void *data)
|
|||
return AE_OK;
|
||||
}
|
||||
|
||||
struct pci_root_info {
|
||||
struct pci_controller *controller;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
|
||||
{
|
||||
struct pci_root_info *info = data;
|
||||
|
@ -231,7 +289,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
|
|||
} else if (addr.resource_type == ACPI_IO_RANGE) {
|
||||
flags = IORESOURCE_IO;
|
||||
root = &ioport_resource;
|
||||
offset = add_io_space(&addr);
|
||||
offset = add_io_space(info, &addr);
|
||||
if (offset == ~0)
|
||||
return AE_OK;
|
||||
} else
|
||||
|
@ -241,7 +299,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
|
|||
window->resource.name = info->name;
|
||||
window->resource.flags = flags;
|
||||
window->resource.start = addr.min_address_range + offset;
|
||||
window->resource.end = addr.max_address_range + offset;
|
||||
window->resource.end = window->resource.start + addr.address_length - 1;
|
||||
window->resource.child = NULL;
|
||||
window->offset = offset;
|
||||
|
||||
|
@ -739,7 +797,7 @@ int pci_vector_resources(int last, int nr_released)
|
|||
{
|
||||
int count = nr_released;
|
||||
|
||||
count += (IA64_LAST_DEVICE_VECTOR - last);
|
||||
count += (IA64_LAST_DEVICE_VECTOR - last);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -349,7 +349,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
|
|||
return; /*bus # does not exist */
|
||||
prom_bussoft_ptr = __va(prom_bussoft_ptr);
|
||||
|
||||
controller = kcalloc(1,sizeof(struct pci_controller), GFP_KERNEL);
|
||||
controller = kzalloc(sizeof(struct pci_controller), GFP_KERNEL);
|
||||
controller->segment = segment;
|
||||
if (!controller)
|
||||
BUG();
|
||||
|
|
|
@ -163,7 +163,7 @@ struct xpc_vars {
|
|||
u8 version;
|
||||
u64 heartbeat;
|
||||
u64 heartbeating_to_mask;
|
||||
u64 kdb_status; /* 0 = machine running */
|
||||
u64 heartbeat_offline; /* if 0, heartbeat should be changing */
|
||||
int act_nasid;
|
||||
int act_phys_cpuid;
|
||||
u64 vars_part_pa;
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include <linux/reboot.h>
|
||||
#include <asm/sn/intr.h>
|
||||
#include <asm/sn/sn_sal.h>
|
||||
#include <asm/kdebug.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "xpc.h"
|
||||
|
||||
|
@ -188,6 +189,11 @@ static struct notifier_block xpc_reboot_notifier = {
|
|||
.notifier_call = xpc_system_reboot,
|
||||
};
|
||||
|
||||
static int xpc_system_die(struct notifier_block *, unsigned long, void *);
|
||||
static struct notifier_block xpc_die_notifier = {
|
||||
.notifier_call = xpc_system_die,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Timer function to enforce the timelimit on the partition disengage request.
|
||||
|
@ -997,6 +1003,9 @@ xpc_do_exit(enum xpc_retval reason)
|
|||
/* take ourselves off of the reboot_notifier_list */
|
||||
(void) unregister_reboot_notifier(&xpc_reboot_notifier);
|
||||
|
||||
/* take ourselves off of the die_notifier list */
|
||||
(void) unregister_die_notifier(&xpc_die_notifier);
|
||||
|
||||
/* close down protections for IPI operations */
|
||||
xpc_restrict_IPI_ops();
|
||||
|
||||
|
@ -1010,6 +1019,63 @@ xpc_do_exit(enum xpc_retval reason)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called when the system is about to be either restarted or halted.
|
||||
*/
|
||||
static void
|
||||
xpc_die_disengage(void)
|
||||
{
|
||||
struct xpc_partition *part;
|
||||
partid_t partid;
|
||||
unsigned long engaged;
|
||||
long time, print_time, disengage_request_timeout;
|
||||
|
||||
|
||||
/* keep xpc_hb_checker thread from doing anything (just in case) */
|
||||
xpc_exiting = 1;
|
||||
|
||||
xpc_vars->heartbeating_to_mask = 0; /* indicate we're deactivated */
|
||||
|
||||
for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
|
||||
part = &xpc_partitions[partid];
|
||||
|
||||
if (!XPC_SUPPORTS_DISENGAGE_REQUEST(part->
|
||||
remote_vars_version)) {
|
||||
|
||||
/* just in case it was left set by an earlier XPC */
|
||||
xpc_clear_partition_engaged(1UL << partid);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (xpc_partition_engaged(1UL << partid) ||
|
||||
part->act_state != XPC_P_INACTIVE) {
|
||||
xpc_request_partition_disengage(part);
|
||||
xpc_mark_partition_disengaged(part);
|
||||
xpc_IPI_send_disengage(part);
|
||||
}
|
||||
}
|
||||
|
||||
print_time = rtc_time();
|
||||
disengage_request_timeout = print_time +
|
||||
(xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);
|
||||
|
||||
/* wait for all other partitions to disengage from us */
|
||||
|
||||
while ((engaged = xpc_partition_engaged(-1UL)) &&
|
||||
(time = rtc_time()) < disengage_request_timeout) {
|
||||
|
||||
if (time >= print_time) {
|
||||
dev_info(xpc_part, "waiting for remote partitions to "
|
||||
"disengage, engaged=0x%lx\n", engaged);
|
||||
print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL *
|
||||
sn_rtc_cycles_per_second);
|
||||
}
|
||||
}
|
||||
dev_info(xpc_part, "finished waiting for remote partitions to "
|
||||
"disengage, engaged=0x%lx\n", engaged);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function is called when the system is being rebooted.
|
||||
*/
|
||||
|
@ -1038,6 +1104,33 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function is called when the system is being rebooted.
|
||||
*/
|
||||
static int
|
||||
xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
|
||||
{
|
||||
switch (event) {
|
||||
case DIE_MACHINE_RESTART:
|
||||
case DIE_MACHINE_HALT:
|
||||
xpc_die_disengage();
|
||||
break;
|
||||
case DIE_MCA_MONARCH_ENTER:
|
||||
case DIE_INIT_MONARCH_ENTER:
|
||||
xpc_vars->heartbeat++;
|
||||
xpc_vars->heartbeat_offline = 1;
|
||||
break;
|
||||
case DIE_MCA_MONARCH_LEAVE:
|
||||
case DIE_INIT_MONARCH_LEAVE:
|
||||
xpc_vars->heartbeat++;
|
||||
xpc_vars->heartbeat_offline = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
|
||||
int __init
|
||||
xpc_init(void)
|
||||
{
|
||||
|
@ -1154,6 +1247,12 @@ xpc_init(void)
|
|||
dev_warn(xpc_part, "can't register reboot notifier\n");
|
||||
}
|
||||
|
||||
/* add ourselves to the die_notifier list (i.e., ia64die_chain) */
|
||||
ret = register_die_notifier(&xpc_die_notifier);
|
||||
if (ret != 0) {
|
||||
dev_warn(xpc_part, "can't register die notifier\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the beating to other partitions into motion. This is
|
||||
|
@ -1179,6 +1278,9 @@ xpc_init(void)
|
|||
/* take ourselves off of the reboot_notifier_list */
|
||||
(void) unregister_reboot_notifier(&xpc_reboot_notifier);
|
||||
|
||||
/* take ourselves off of the die_notifier list */
|
||||
(void) unregister_die_notifier(&xpc_die_notifier);
|
||||
|
||||
del_timer_sync(&xpc_hb_timer);
|
||||
free_irq(SGI_XPC_ACTIVATE, NULL);
|
||||
xpc_restrict_IPI_ops();
|
||||
|
|
|
@ -436,13 +436,13 @@ xpc_check_remote_hb(void)
|
|||
}
|
||||
|
||||
dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
|
||||
" = %ld, kdb_status = %ld, HB_mask = 0x%lx\n", partid,
|
||||
remote_vars->heartbeat, part->last_heartbeat,
|
||||
remote_vars->kdb_status,
|
||||
" = %ld, heartbeat_offline = %ld, HB_mask = 0x%lx\n",
|
||||
partid, remote_vars->heartbeat, part->last_heartbeat,
|
||||
remote_vars->heartbeat_offline,
|
||||
remote_vars->heartbeating_to_mask);
|
||||
|
||||
if (((remote_vars->heartbeat == part->last_heartbeat) &&
|
||||
(remote_vars->kdb_status == 0)) ||
|
||||
(remote_vars->heartbeat_offline == 0)) ||
|
||||
!xpc_hb_allowed(sn_partition_id, remote_vars)) {
|
||||
|
||||
XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);
|
||||
|
|
|
@ -218,7 +218,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
|
|||
if (i > last)
|
||||
return 0;
|
||||
|
||||
map = kcalloc(1, sizeof(struct tioce_dmamap), GFP_ATOMIC);
|
||||
map = kzalloc(sizeof(struct tioce_dmamap), GFP_ATOMIC);
|
||||
if (!map)
|
||||
return 0;
|
||||
|
||||
|
@ -555,7 +555,7 @@ tioce_kern_init(struct tioce_common *tioce_common)
|
|||
struct tioce *tioce_mmr;
|
||||
struct tioce_kernel *tioce_kern;
|
||||
|
||||
tioce_kern = kcalloc(1, sizeof(struct tioce_kernel), GFP_KERNEL);
|
||||
tioce_kern = kzalloc(sizeof(struct tioce_kernel), GFP_KERNEL);
|
||||
if (!tioce_kern) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -727,7 +727,7 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
|
|||
* Allocate kernel bus soft and copy from prom.
|
||||
*/
|
||||
|
||||
tioce_common = kcalloc(1, sizeof(struct tioce_common), GFP_KERNEL);
|
||||
tioce_common = kzalloc(sizeof(struct tioce_common), GFP_KERNEL);
|
||||
if (!tioce_common)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -61,20 +61,6 @@ struct pci_controller** hose_tail = &hose_head;
|
|||
|
||||
static int pci_bus_count;
|
||||
|
||||
static void
|
||||
fixup_rev1_53c810(struct pci_dev* dev)
|
||||
{
|
||||
/* rev 1 ncr53c810 chips don't set the class at all which means
|
||||
* they don't get their resources remapped. Fix that here.
|
||||
*/
|
||||
|
||||
if ((dev->class == PCI_CLASS_NOT_DEFINED)) {
|
||||
printk("NCR 53c810 rev 1 detected, setting PCI class.\n");
|
||||
dev->class = PCI_CLASS_STORAGE_SCSI;
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
|
||||
|
||||
static void
|
||||
fixup_broken_pcnet32(struct pci_dev* dev)
|
||||
{
|
||||
|
|
|
@ -203,6 +203,7 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
|
|||
acpi_get_devices(PCI_ROOT_HID_STRING, find_pci_rootbridge, &find, NULL);
|
||||
return find.handle;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
|
||||
|
||||
/* Get device's handler per its address under its parent */
|
||||
struct acpi_find_child {
|
||||
|
|
|
@ -389,7 +389,6 @@ static struct pci_device_id agp_ali_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_ali_pci_table);
|
||||
|
||||
static struct pci_driver agp_ali_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-ali",
|
||||
.id_table = agp_ali_pci_table,
|
||||
.probe = agp_ali_probe,
|
||||
|
|
|
@ -515,7 +515,6 @@ static struct pci_device_id agp_amdk7_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_amdk7_pci_table);
|
||||
|
||||
static struct pci_driver agp_amdk7_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-amdk7",
|
||||
.id_table = agp_amdk7_pci_table,
|
||||
.probe = agp_amdk7_probe,
|
||||
|
|
|
@ -703,7 +703,6 @@ static struct pci_device_id agp_amd64_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table);
|
||||
|
||||
static struct pci_driver agp_amd64_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-amd64",
|
||||
.id_table = agp_amd64_pci_table,
|
||||
.probe = agp_amd64_probe,
|
||||
|
|
|
@ -521,7 +521,6 @@ static struct pci_device_id agp_ati_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_ati_pci_table);
|
||||
|
||||
static struct pci_driver agp_ati_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-ati",
|
||||
.id_table = agp_ati_pci_table,
|
||||
.probe = agp_ati_probe,
|
||||
|
|
|
@ -429,7 +429,6 @@ static struct pci_device_id agp_efficeon_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table);
|
||||
|
||||
static struct pci_driver agp_efficeon_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-efficeon",
|
||||
.id_table = agp_efficeon_pci_table,
|
||||
.probe = agp_efficeon_probe,
|
||||
|
|
|
@ -622,7 +622,6 @@ static struct pci_device_id agp_intel_i460_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table);
|
||||
|
||||
static struct pci_driver agp_intel_i460_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-intel-i460",
|
||||
.id_table = agp_intel_i460_pci_table,
|
||||
.probe = agp_intel_i460_probe,
|
||||
|
|
|
@ -1827,7 +1827,6 @@ static struct pci_device_id agp_intel_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
|
||||
|
||||
static struct pci_driver agp_intel_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-intel",
|
||||
.id_table = agp_intel_pci_table,
|
||||
.probe = agp_intel_probe,
|
||||
|
|
|
@ -398,7 +398,6 @@ static struct pci_device_id agp_nvidia_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table);
|
||||
|
||||
static struct pci_driver agp_nvidia_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-nvidia",
|
||||
.id_table = agp_nvidia_pci_table,
|
||||
.probe = agp_nvidia_probe,
|
||||
|
|
|
@ -332,7 +332,6 @@ static struct pci_device_id agp_sis_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_sis_pci_table);
|
||||
|
||||
static struct pci_driver agp_sis_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-sis",
|
||||
.id_table = agp_sis_pci_table,
|
||||
.probe = agp_sis_probe,
|
||||
|
|
|
@ -545,7 +545,6 @@ static struct pci_device_id agp_serverworks_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_serverworks_pci_table);
|
||||
|
||||
static struct pci_driver agp_serverworks_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-serverworks",
|
||||
.id_table = agp_serverworks_pci_table,
|
||||
.probe = agp_serverworks_probe,
|
||||
|
|
|
@ -658,7 +658,6 @@ static struct pci_device_id agp_uninorth_pci_table[] = {
|
|||
MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table);
|
||||
|
||||
static struct pci_driver agp_uninorth_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-uninorth",
|
||||
.id_table = agp_uninorth_pci_table,
|
||||
.probe = agp_uninorth_probe,
|
||||
|
|
|
@ -518,7 +518,6 @@ MODULE_DEVICE_TABLE(pci, agp_via_pci_table);
|
|||
|
||||
|
||||
static struct pci_driver agp_via_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "agpgart-via",
|
||||
.id_table = agp_via_pci_table,
|
||||
.probe = agp_via_probe,
|
||||
|
|
|
@ -3113,7 +3113,6 @@ MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
|
|||
int __init init_PCI (void)
|
||||
{ /* Begin init_PCI */
|
||||
memset (&epca_driver, 0, sizeof (epca_driver));
|
||||
epca_driver.owner = THIS_MODULE;
|
||||
epca_driver.name = "epca";
|
||||
epca_driver.id_table = epca_pci_tbl;
|
||||
epca_driver.probe = epca_init_one;
|
||||
|
|
|
@ -912,7 +912,6 @@ MODULE_DEVICE_TABLE(pci, synclink_pci_tbl);
|
|||
MODULE_LICENSE("GPL");
|
||||
|
||||
static struct pci_driver synclink_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "synclink",
|
||||
.id_table = synclink_pci_tbl,
|
||||
.probe = synclink_init_one,
|
||||
|
|
|
@ -500,7 +500,6 @@ MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl);
|
|||
MODULE_LICENSE("GPL");
|
||||
|
||||
static struct pci_driver synclinkmp_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "synclinkmp",
|
||||
.id_table = synclinkmp_pci_tbl,
|
||||
.probe = synclinkmp_init_one,
|
||||
|
|
|
@ -755,7 +755,6 @@ static struct pci_device_id pcipcwd_pci_tbl[] = {
|
|||
MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl);
|
||||
|
||||
static struct pci_driver pcipcwd_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = WATCHDOG_NAME,
|
||||
.id_table = pcipcwd_pci_tbl,
|
||||
.probe = pcipcwd_card_init,
|
||||
|
|
|
@ -711,7 +711,6 @@ MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
|
|||
|
||||
|
||||
static struct pci_driver wdtpci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "wdt_pci",
|
||||
.id_table = wdtpci_pci_tbl,
|
||||
.probe = wdtpci_init_one,
|
||||
|
|
|
@ -513,7 +513,6 @@ static void __devexit ali1535_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver ali1535_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ali1535_smbus",
|
||||
.id_table = ali1535_ids,
|
||||
.probe = ali1535_probe,
|
||||
|
|
|
@ -408,7 +408,6 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = {
|
|||
MODULE_DEVICE_TABLE (pci, ali1563_id_table);
|
||||
|
||||
static struct pci_driver ali1563_pci_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ali1563_smbus",
|
||||
.id_table = ali1563_id_table,
|
||||
.probe = ali1563_probe,
|
||||
|
|
|
@ -504,7 +504,6 @@ static void __devexit ali15x3_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver ali15x3_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ali15x3_smbus",
|
||||
.id_table = ali15x3_ids,
|
||||
.probe = ali15x3_probe,
|
||||
|
|
|
@ -401,7 +401,6 @@ static void __devexit amd756_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver amd756_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "amd756_smbus",
|
||||
.id_table = amd756_ids,
|
||||
.probe = amd756_probe,
|
||||
|
|
|
@ -384,7 +384,6 @@ static void __devexit amd8111_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver amd8111_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "amd8111_smbus2",
|
||||
.id_table = amd8111_ids,
|
||||
.probe = amd8111_probe,
|
||||
|
|
|
@ -155,7 +155,6 @@ static void __devexit hydra_remove(struct pci_dev *dev)
|
|||
|
||||
|
||||
static struct pci_driver hydra_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "hydra_smbus",
|
||||
.id_table = hydra_ids,
|
||||
.probe = hydra_probe,
|
||||
|
|
|
@ -560,7 +560,6 @@ static void __devexit i801_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver i801_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i801_smbus",
|
||||
.id_table = i801_ids,
|
||||
.probe = i801_probe,
|
||||
|
|
|
@ -233,7 +233,6 @@ static void __devexit i810_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver i810_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i810_smbus",
|
||||
.id_table = i810_ids,
|
||||
.probe = i810_probe,
|
||||
|
|
|
@ -347,7 +347,6 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver nforce2_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "nForce2_smbus",
|
||||
.id_table = nforce2_ids,
|
||||
.probe = nforce2_probe,
|
||||
|
|
|
@ -462,7 +462,6 @@ static void __devexit piix4_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver piix4_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "piix4_smbus",
|
||||
.id_table = piix4_ids,
|
||||
.probe = piix4_probe,
|
||||
|
|
|
@ -301,7 +301,6 @@ static struct pci_device_id prosavage_pci_tbl[] = {
|
|||
MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
|
||||
|
||||
static struct pci_driver prosavage_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "prosavage_smbus",
|
||||
.id_table = prosavage_pci_tbl,
|
||||
.probe = prosavage_probe,
|
||||
|
|
|
@ -179,7 +179,6 @@ static void __devexit savage4_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver savage4_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "savage4_smbus",
|
||||
.id_table = savage4_ids,
|
||||
.probe = savage4_probe,
|
||||
|
|
|
@ -398,7 +398,6 @@ static void __devexit sis5595_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver sis5595_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "sis5595_smbus",
|
||||
.id_table = sis5595_ids,
|
||||
.probe = sis5595_probe,
|
||||
|
|
|
@ -496,7 +496,6 @@ static void __devexit sis630_remove(struct pci_dev *dev)
|
|||
|
||||
|
||||
static struct pci_driver sis630_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "sis630_smbus",
|
||||
.id_table = sis630_ids,
|
||||
.probe = sis630_probe,
|
||||
|
|
|
@ -329,7 +329,6 @@ static void __devexit sis96x_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver sis96x_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "sis96x_smbus",
|
||||
.id_table = sis96x_ids,
|
||||
.probe = sis96x_probe,
|
||||
|
|
|
@ -159,7 +159,6 @@ static void __devexit vt586b_remove(struct pci_dev *dev)
|
|||
|
||||
|
||||
static struct pci_driver vt586b_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "vt586b_smbus",
|
||||
.id_table = vt586b_ids,
|
||||
.probe = vt586b_probe,
|
||||
|
|
|
@ -440,7 +440,6 @@ static struct pci_device_id vt596_ids[] = {
|
|||
MODULE_DEVICE_TABLE(pci, vt596_ids);
|
||||
|
||||
static struct pci_driver vt596_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "vt596_smbus",
|
||||
.id_table = vt596_ids,
|
||||
.probe = vt596_probe,
|
||||
|
|
|
@ -225,7 +225,6 @@ static void __devexit voodoo3_remove(struct pci_dev *dev)
|
|||
}
|
||||
|
||||
static struct pci_driver voodoo3_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "voodoo3_smbus",
|
||||
.id_table = voodoo3_ids,
|
||||
.probe = voodoo3_probe,
|
||||
|
|
|
@ -787,8 +787,9 @@ static int pre_init = 1; /* Before first ordered IDE scan */
|
|||
static LIST_HEAD(ide_pci_drivers);
|
||||
|
||||
/*
|
||||
* ide_register_pci_driver - attach IDE driver
|
||||
* __ide_register_pci_driver - attach IDE driver
|
||||
* @driver: pci driver
|
||||
* @module: owner module of the driver
|
||||
*
|
||||
* Registers a driver with the IDE layer. The IDE layer arranges that
|
||||
* boot time setup is done in the expected device order and then
|
||||
|
@ -801,15 +802,16 @@ static LIST_HEAD(ide_pci_drivers);
|
|||
* Returns are the same as for pci_register_driver
|
||||
*/
|
||||
|
||||
int ide_pci_register_driver(struct pci_driver *driver)
|
||||
int __ide_pci_register_driver(struct pci_driver *driver, struct module *module)
|
||||
{
|
||||
if(!pre_init)
|
||||
return pci_module_init(driver);
|
||||
return __pci_register_driver(driver, module);
|
||||
driver->driver.owner = module;
|
||||
list_add_tail(&driver->node, &ide_pci_drivers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_pci_register_driver);
|
||||
EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
|
||||
|
||||
/**
|
||||
* ide_unregister_pci_driver - unregister an IDE driver
|
||||
|
@ -897,6 +899,6 @@ void __init ide_scan_pcibus (int scan_direction)
|
|||
{
|
||||
list_del(l);
|
||||
d = list_entry(l, struct pci_driver, node);
|
||||
pci_register_driver(d);
|
||||
__pci_register_driver(d, d->driver.owner);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1198,7 +1198,6 @@ MODULE_DEVICE_TABLE(pci, mthca_pci_table);
|
|||
|
||||
static struct pci_driver mthca_driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = mthca_pci_table,
|
||||
.probe = mthca_init_one,
|
||||
.remove = __devexit_p(mthca_remove_one)
|
||||
|
|
|
@ -2290,7 +2290,6 @@ spider_net_remove(struct pci_dev *pdev)
|
|||
}
|
||||
|
||||
static struct pci_driver spider_net_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = spider_net_driver_name,
|
||||
.id_table = spider_net_pci_tbl,
|
||||
.probe = spider_net_probe,
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
/*
|
||||
* This interrupt-safe spinlock protects all accesses to PCI
|
||||
* configuration space.
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/pcieport_if.h>
|
||||
#include "pci_hotplug.h"
|
||||
|
||||
|
@ -42,6 +40,7 @@
|
|||
extern int pciehp_poll_mode;
|
||||
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)
|
||||
|
@ -49,39 +48,20 @@ extern int pciehp_debug;
|
|||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
|
||||
struct pci_func {
|
||||
struct pci_func *next;
|
||||
u8 bus;
|
||||
u8 device;
|
||||
u8 function;
|
||||
u8 is_a_board;
|
||||
u16 status;
|
||||
u8 configured;
|
||||
u8 switch_save;
|
||||
u8 presence_save;
|
||||
u32 base_length[0x06];
|
||||
u8 base_type[0x06];
|
||||
u16 reserved2;
|
||||
u32 config_space[0x20];
|
||||
struct pci_resource *mem_head;
|
||||
struct pci_resource *p_mem_head;
|
||||
struct pci_resource *io_head;
|
||||
struct pci_resource *bus_head;
|
||||
struct pci_dev* pci_dev;
|
||||
struct hotplug_params {
|
||||
u8 cache_line_size;
|
||||
u8 latency_timer;
|
||||
u8 enable_serr;
|
||||
u8 enable_perr;
|
||||
};
|
||||
|
||||
struct slot {
|
||||
struct slot *next;
|
||||
u8 bus;
|
||||
u8 device;
|
||||
u16 status;
|
||||
u32 number;
|
||||
u8 is_a_board;
|
||||
u8 configured;
|
||||
u8 state;
|
||||
u8 switch_save;
|
||||
u8 presence_save;
|
||||
u32 capabilities;
|
||||
u16 reserved2;
|
||||
struct timer_list task_event;
|
||||
u8 hp_slot;
|
||||
struct controller *ctrl;
|
||||
|
@ -90,42 +70,47 @@ struct slot {
|
|||
struct list_head slot_list;
|
||||
};
|
||||
|
||||
struct pci_resource {
|
||||
struct pci_resource * next;
|
||||
u32 base;
|
||||
u32 length;
|
||||
};
|
||||
|
||||
struct event_info {
|
||||
u32 event_type;
|
||||
u8 hp_slot;
|
||||
};
|
||||
|
||||
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 semaphore crit_sect; /* critical section semaphore */
|
||||
void *hpc_ctlr_handle; /* HPC controller handle */
|
||||
struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
|
||||
int num_slots; /* Number of slots on ctlr */
|
||||
int slot_num_inc; /* 1 or -1 */
|
||||
struct pci_resource *mem_head;
|
||||
struct pci_resource *p_mem_head;
|
||||
struct pci_resource *io_head;
|
||||
struct pci_resource *bus_head;
|
||||
struct pci_dev *pci_dev;
|
||||
struct pci_bus *pci_bus;
|
||||
struct event_info event_queue[10];
|
||||
struct event_info event_queue[MAX_EVENTS];
|
||||
struct slot *slot;
|
||||
struct hpc_ops *hpc_ops;
|
||||
wait_queue_head_t queue; /* sleep & wake process */
|
||||
u8 next_event;
|
||||
u8 seg;
|
||||
u8 bus;
|
||||
u8 device;
|
||||
u8 function;
|
||||
u8 rev;
|
||||
u8 slot_device_offset;
|
||||
u8 add_support;
|
||||
enum pci_bus_speed speed;
|
||||
u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */
|
||||
u8 slot_bus; /* Bus where the slots handled by this controller sit */
|
||||
u8 ctrlcap;
|
||||
|
@ -133,20 +118,6 @@ struct controller {
|
|||
u8 cap_base;
|
||||
};
|
||||
|
||||
struct irq_mapping {
|
||||
u8 barber_pole;
|
||||
u8 valid_INT;
|
||||
u8 interrupt[4];
|
||||
};
|
||||
|
||||
struct resource_lists {
|
||||
struct pci_resource *mem_head;
|
||||
struct pci_resource *p_mem_head;
|
||||
struct pci_resource *io_head;
|
||||
struct pci_resource *bus_head;
|
||||
struct irq_mapping *irqs;
|
||||
};
|
||||
|
||||
#define INT_BUTTON_IGNORE 0
|
||||
#define INT_PRESENCE_ON 1
|
||||
#define INT_PRESENCE_OFF 2
|
||||
|
@ -200,21 +171,14 @@ struct resource_lists {
|
|||
* error Messages
|
||||
*/
|
||||
#define msg_initialization_err "Initialization failure, error=%d\n"
|
||||
#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
|
||||
#define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n"
|
||||
#define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n"
|
||||
#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
|
||||
#define msg_button_on "PCI slot #%d - powering on due to button press.\n"
|
||||
#define msg_button_off "PCI slot #%d - powering off due to button press.\n"
|
||||
#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
|
||||
#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n"
|
||||
|
||||
/* controller functions */
|
||||
extern int pciehprm_find_available_resources (struct controller *ctrl);
|
||||
extern int pciehp_event_start_thread (void);
|
||||
extern void pciehp_event_stop_thread (void);
|
||||
extern struct pci_func *pciehp_slot_create (unsigned char busnumber);
|
||||
extern struct pci_func *pciehp_slot_find (unsigned char bus, unsigned char device, unsigned char index);
|
||||
extern int pciehp_enable_slot (struct slot *slot);
|
||||
extern int pciehp_disable_slot (struct slot *slot);
|
||||
|
||||
|
@ -224,25 +188,17 @@ 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); */
|
||||
|
||||
/* resource functions */
|
||||
extern int pciehp_resource_sort_and_combine (struct pci_resource **head);
|
||||
|
||||
/* pci functions */
|
||||
extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
|
||||
/*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
|
||||
extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
|
||||
extern int pciehp_save_used_resources (struct controller *ctrl, struct pci_func * func, int flag);
|
||||
extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot);
|
||||
extern void pciehp_destroy_board_resources (struct pci_func * func);
|
||||
extern int pciehp_return_board_resources (struct pci_func * func, struct resource_lists * resources);
|
||||
extern void pciehp_destroy_resource_list (struct resource_lists * resources);
|
||||
extern int pciehp_configure_device (struct controller* ctrl, struct pci_func* func);
|
||||
extern int pciehp_unconfigure_device (struct pci_func* func);
|
||||
extern int pciehp_configure_device (struct slot *p_slot);
|
||||
extern int pciehp_unconfigure_device (struct slot *p_slot);
|
||||
extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev);
|
||||
extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp);
|
||||
|
||||
|
||||
|
||||
/* Global variables */
|
||||
extern struct controller *pciehp_ctrl_list;
|
||||
extern struct pci_func *pciehp_slot_list[256];
|
||||
|
||||
/* Inline functions */
|
||||
|
||||
|
@ -252,12 +208,9 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
|
|||
|
||||
p_slot = ctrl->slot;
|
||||
|
||||
dbg("p_slot = %p\n", p_slot);
|
||||
|
||||
while (p_slot && (p_slot->device != device)) {
|
||||
tmp_slot = p_slot;
|
||||
p_slot = p_slot->next;
|
||||
dbg("In while loop, p_slot = %p\n", p_slot);
|
||||
}
|
||||
if (p_slot == NULL) {
|
||||
err("ERROR: pciehp_find_slot device=0x%x\n", device);
|
||||
|
@ -273,7 +226,6 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
|
|||
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
dbg("%s : start\n", __FUNCTION__);
|
||||
add_wait_queue(&ctrl->queue, &wait);
|
||||
if (!pciehp_poll_mode)
|
||||
/* Sleep for up to 1 second */
|
||||
|
@ -285,19 +237,9 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
|
|||
if (signal_pending(current))
|
||||
retval = -EINTR;
|
||||
|
||||
dbg("%s : end\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Puts node back in the resource list pointed to by head */
|
||||
static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
|
||||
{
|
||||
if (!node || !head)
|
||||
return;
|
||||
node->next = *head;
|
||||
*head = node;
|
||||
}
|
||||
|
||||
#define SLOT_NAME_SIZE 10
|
||||
|
||||
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
|
||||
|
@ -311,14 +253,7 @@ enum php_ctlr_type {
|
|||
ACPI
|
||||
};
|
||||
|
||||
typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
|
||||
|
||||
int pcie_init(struct controller *ctrl, struct pcie_device *dev,
|
||||
php_intr_callback_t attention_button_callback,
|
||||
php_intr_callback_t switch_change_callback,
|
||||
php_intr_callback_t presence_change_callback,
|
||||
php_intr_callback_t power_fault_callback);
|
||||
|
||||
int 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,
|
||||
|
|
|
@ -27,27 +27,20 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "pciehp.h"
|
||||
#include "pciehprm.h"
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
/* Global variables */
|
||||
int pciehp_debug;
|
||||
int pciehp_poll_mode;
|
||||
int pciehp_poll_time;
|
||||
int pciehp_force;
|
||||
struct controller *pciehp_ctrl_list;
|
||||
struct pci_func *pciehp_slot_list[256];
|
||||
|
||||
#define DRIVER_VERSION "0.4"
|
||||
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
|
||||
|
@ -60,9 +53,11 @@ MODULE_LICENSE("GPL");
|
|||
module_param(pciehp_debug, bool, 0644);
|
||||
module_param(pciehp_poll_mode, bool, 0644);
|
||||
module_param(pciehp_poll_time, int, 0644);
|
||||
module_param(pciehp_force, bool, 0644);
|
||||
MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
|
||||
MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
|
||||
MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
|
||||
MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
|
||||
|
||||
#define PCIE_MODULE_NAME "pciehp"
|
||||
|
||||
|
@ -114,8 +109,6 @@ static int init_slots(struct controller *ctrl)
|
|||
u32 slot_number;
|
||||
int result = -ENOMEM;
|
||||
|
||||
dbg("%s\n",__FUNCTION__);
|
||||
|
||||
number_of_slots = ctrl->num_slots;
|
||||
slot_device = ctrl->slot_device_offset;
|
||||
slot_number = ctrl->first_slot;
|
||||
|
@ -370,7 +363,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
u8 value;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
dbg("%s: Called by hp_drv\n", __FUNCTION__);
|
||||
ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL);
|
||||
if (!ctrl) {
|
||||
err("%s : out of memory\n", __FUNCTION__);
|
||||
|
@ -378,22 +370,15 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
}
|
||||
memset(ctrl, 0, sizeof(struct controller));
|
||||
|
||||
dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid);
|
||||
|
||||
pdev = dev->port;
|
||||
ctrl->pci_dev = pdev;
|
||||
|
||||
rc = pcie_init(ctrl, dev,
|
||||
(php_intr_callback_t) pciehp_handle_attention_button,
|
||||
(php_intr_callback_t) pciehp_handle_switch_change,
|
||||
(php_intr_callback_t) pciehp_handle_presence_change,
|
||||
(php_intr_callback_t) pciehp_handle_power_fault);
|
||||
rc = pcie_init(ctrl, dev);
|
||||
if (rc) {
|
||||
dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
|
||||
goto err_out_free_ctrl;
|
||||
}
|
||||
|
||||
ctrl->pci_dev = pdev;
|
||||
|
||||
pci_set_drvdata(pdev, ctrl);
|
||||
|
||||
ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL);
|
||||
|
@ -402,7 +387,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
rc = -ENOMEM;
|
||||
goto err_out_unmap_mmio_region;
|
||||
}
|
||||
dbg("%s: ctrl->pci_bus %p\n", __FUNCTION__, ctrl->pci_bus);
|
||||
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 */
|
||||
|
@ -424,25 +408,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
first_device_num = ctrl->slot_device_offset;
|
||||
num_ctlr_slots = ctrl->num_slots;
|
||||
|
||||
/* Store PCI Config Space for all devices on this bus */
|
||||
dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n",
|
||||
__FUNCTION__,ctrl->bus, ctrl->slot_bus);
|
||||
rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
|
||||
if (rc) {
|
||||
err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
|
||||
goto err_out_free_ctrl_bus;
|
||||
}
|
||||
|
||||
/* Get IO, memory, and IRQ resources for new devices */
|
||||
rc = pciehprm_find_available_resources(ctrl);
|
||||
ctrl->add_support = !rc;
|
||||
|
||||
if (rc) {
|
||||
dbg("pciehprm_find_available_resources = %#x\n", rc);
|
||||
err("unable to locate PCI configuration resources for hot plug add.\n");
|
||||
goto err_out_free_ctrl_bus;
|
||||
}
|
||||
|
||||
/* Setup the slot information structures */
|
||||
rc = init_slots(ctrl);
|
||||
if (rc) {
|
||||
|
@ -451,7 +416,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
}
|
||||
|
||||
t_slot = pciehp_find_slot(ctrl, first_device_num);
|
||||
dbg("%s: t_slot %p\n", __FUNCTION__, t_slot);
|
||||
|
||||
/* Finish setting up the hot plug ctrl device */
|
||||
ctrl->next_event = 0;
|
||||
|
@ -468,7 +432,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
down(&ctrl->crit_sect);
|
||||
|
||||
t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
|
||||
dbg("%s: adpater value %x\n", __FUNCTION__, value);
|
||||
|
||||
if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
|
||||
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
|
||||
|
@ -501,7 +464,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
|||
|
||||
static int pcie_start_thread(void)
|
||||
{
|
||||
int loop;
|
||||
int retval = 0;
|
||||
|
||||
dbg("Initialize + Start the notification/polling mechanism \n");
|
||||
|
@ -512,32 +474,11 @@ static int pcie_start_thread(void)
|
|||
return retval;
|
||||
}
|
||||
|
||||
dbg("Initialize slot lists\n");
|
||||
/* One slot list for each bus in the system */
|
||||
for (loop = 0; loop < 256; loop++) {
|
||||
pciehp_slot_list[loop] = NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline void __exit
|
||||
free_pciehp_res(struct pci_resource *res)
|
||||
{
|
||||
struct pci_resource *tres;
|
||||
|
||||
while (res) {
|
||||
tres = res;
|
||||
res = res->next;
|
||||
kfree(tres);
|
||||
}
|
||||
}
|
||||
|
||||
static void __exit unload_pciehpd(void)
|
||||
{
|
||||
struct pci_func *next;
|
||||
struct pci_func *TempSlot;
|
||||
int loop;
|
||||
struct controller *ctrl;
|
||||
struct controller *tctrl;
|
||||
|
||||
|
@ -546,11 +487,6 @@ static void __exit unload_pciehpd(void)
|
|||
while (ctrl) {
|
||||
cleanup_slots(ctrl);
|
||||
|
||||
free_pciehp_res(ctrl->io_head);
|
||||
free_pciehp_res(ctrl->mem_head);
|
||||
free_pciehp_res(ctrl->p_mem_head);
|
||||
free_pciehp_res(ctrl->bus_head);
|
||||
|
||||
kfree (ctrl->pci_bus);
|
||||
|
||||
ctrl->hpc_ops->release_ctlr(ctrl);
|
||||
|
@ -561,20 +497,6 @@ static void __exit unload_pciehpd(void)
|
|||
kfree(tctrl);
|
||||
}
|
||||
|
||||
for (loop = 0; loop < 256; loop++) {
|
||||
next = pciehp_slot_list[loop];
|
||||
while (next != NULL) {
|
||||
free_pciehp_res(next->io_head);
|
||||
free_pciehp_res(next->mem_head);
|
||||
free_pciehp_res(next->p_mem_head);
|
||||
free_pciehp_res(next->bus_head);
|
||||
|
||||
TempSlot = next;
|
||||
next = next->next;
|
||||
kfree(TempSlot);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop the notification mechanism */
|
||||
pciehp_event_stop_thread();
|
||||
|
||||
|
@ -639,21 +561,16 @@ static int __init pcied_init(void)
|
|||
if (retval)
|
||||
goto error_hpc_init;
|
||||
|
||||
retval = pciehprm_init(PCI);
|
||||
if (!retval) {
|
||||
retval = pcie_port_service_register(&hpdriver_portdrv);
|
||||
dbg("pcie_port_service_register = %d\n", retval);
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
if (retval)
|
||||
dbg("%s: Failure to register service\n", __FUNCTION__);
|
||||
}
|
||||
retval = pcie_port_service_register(&hpdriver_portdrv);
|
||||
dbg("pcie_port_service_register = %d\n", retval);
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
if (retval)
|
||||
dbg("%s: Failure to register service\n", __FUNCTION__);
|
||||
|
||||
error_hpc_init:
|
||||
if (retval) {
|
||||
pciehprm_cleanup();
|
||||
pciehp_event_stop_thread();
|
||||
} else
|
||||
pciehprm_print_pirt();
|
||||
};
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -663,9 +580,6 @@ static void __exit pcied_cleanup(void)
|
|||
dbg("unload_pciehpd()\n");
|
||||
unload_pciehpd();
|
||||
|
||||
pciehprm_cleanup();
|
||||
|
||||
dbg("pcie_port_service_unregister\n");
|
||||
pcie_port_service_unregister(&hpdriver_portdrv);
|
||||
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,16 +27,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/system.h>
|
||||
#include "../pci.h"
|
||||
#include "pciehp.h"
|
||||
|
||||
|
@ -217,23 +211,6 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct
|
|||
#define MRL_STATE 0x0020
|
||||
#define PRSN_STATE 0x0040
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
|
||||
static spinlock_t hpc_event_lock;
|
||||
|
||||
DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
|
||||
|
@ -297,7 +274,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
|
|||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
dbg("%s : Enter\n", __FUNCTION__);
|
||||
if (!php_ctlr) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return -1;
|
||||
|
@ -308,7 +284,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
|
|||
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status);
|
||||
|
||||
if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) {
|
||||
/* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue
|
||||
|
@ -316,14 +291,11 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
|
|||
dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
|
||||
retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE);
|
||||
if (retval) {
|
||||
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd | CMD_CMPL_INTR_ENABLE);
|
||||
dbg("%s : Exit\n", __FUNCTION__);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return retval;
|
||||
|
@ -509,7 +481,6 @@ static int hpc_query_power_fault(struct slot * slot)
|
|||
u16 slot_status;
|
||||
u8 pwr_fault;
|
||||
int retval = 0;
|
||||
u8 status;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
|
@ -521,15 +492,13 @@ static int hpc_query_power_fault(struct slot * slot)
|
|||
retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
|
||||
|
||||
if (retval) {
|
||||
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
err("%s : Cannot check for power fault\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
|
||||
status = (pwr_fault != 1) ? 1 : 0;
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
/* Note: Logic 0 => fault */
|
||||
return status;
|
||||
return pwr_fault;
|
||||
}
|
||||
|
||||
static int hpc_set_attention_status(struct slot *slot, u8 value)
|
||||
|
@ -539,7 +508,8 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
|
|||
u16 slot_ctrl;
|
||||
int rc = 0;
|
||||
|
||||
dbg("%s: \n", __FUNCTION__);
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (!php_ctlr) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return -1;
|
||||
|
@ -555,7 +525,6 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
|
|||
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
return rc;
|
||||
}
|
||||
dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
|
||||
|
||||
switch (value) {
|
||||
case 0 : /* turn off */
|
||||
|
@ -576,6 +545,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
|
|||
pcie_write_cmd(slot, slot_cmd);
|
||||
dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -587,7 +557,8 @@ static void hpc_set_green_led_on(struct slot *slot)
|
|||
u16 slot_ctrl;
|
||||
int rc = 0;
|
||||
|
||||
dbg("%s: \n", __FUNCTION__);
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (!php_ctlr) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return ;
|
||||
|
@ -604,7 +575,6 @@ static void hpc_set_green_led_on(struct slot *slot)
|
|||
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
|
||||
slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
|
||||
if (!pciehp_poll_mode)
|
||||
slot_cmd = slot_cmd | HP_INTR_ENABLE;
|
||||
|
@ -612,6 +582,7 @@ static void hpc_set_green_led_on(struct slot *slot)
|
|||
pcie_write_cmd(slot, slot_cmd);
|
||||
|
||||
dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
|
||||
DBG_LEAVE_ROUTINE
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -622,7 +593,8 @@ static void hpc_set_green_led_off(struct slot *slot)
|
|||
u16 slot_ctrl;
|
||||
int rc = 0;
|
||||
|
||||
dbg("%s: \n", __FUNCTION__);
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (!php_ctlr) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return ;
|
||||
|
@ -639,7 +611,6 @@ static void hpc_set_green_led_off(struct slot *slot)
|
|||
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
|
||||
|
||||
slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
|
||||
|
||||
|
@ -648,6 +619,7 @@ static void hpc_set_green_led_off(struct slot *slot)
|
|||
pcie_write_cmd(slot, slot_cmd);
|
||||
dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
|
||||
|
||||
DBG_LEAVE_ROUTINE
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -658,7 +630,8 @@ static void hpc_set_green_led_blink(struct slot *slot)
|
|||
u16 slot_ctrl;
|
||||
int rc = 0;
|
||||
|
||||
dbg("%s: \n", __FUNCTION__);
|
||||
DBG_ENTER_ROUTINE
|
||||
|
||||
if (!php_ctlr) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
return ;
|
||||
|
@ -675,7 +648,6 @@ static void hpc_set_green_led_blink(struct slot *slot)
|
|||
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
|
||||
|
||||
slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200;
|
||||
|
||||
|
@ -684,6 +656,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
|
|||
pcie_write_cmd(slot, slot_cmd);
|
||||
|
||||
dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
|
||||
DBG_LEAVE_ROUTINE
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -780,7 +753,6 @@ static int hpc_power_on_slot(struct slot * slot)
|
|||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
dbg("%s: \n", __FUNCTION__);
|
||||
|
||||
if (!php_ctlr) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
|
@ -799,8 +771,6 @@ static int hpc_power_on_slot(struct slot * slot)
|
|||
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
|
||||
slot_ctrl);
|
||||
|
||||
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
|
||||
|
||||
|
@ -829,7 +799,6 @@ static int hpc_power_off_slot(struct slot * slot)
|
|||
int retval = 0;
|
||||
|
||||
DBG_ENTER_ROUTINE
|
||||
dbg("%s: \n", __FUNCTION__);
|
||||
|
||||
if (!php_ctlr) {
|
||||
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
|
||||
|
@ -848,8 +817,6 @@ static int hpc_power_off_slot(struct slot * slot)
|
|||
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
return retval;
|
||||
}
|
||||
dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
|
||||
slot_ctrl);
|
||||
|
||||
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
|
||||
|
||||
|
@ -924,7 +891,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__);
|
||||
dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
|
||||
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
|
||||
|
||||
|
@ -933,7 +899,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
|
|||
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
|
||||
|
||||
rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
|
||||
if (rc) {
|
||||
|
@ -949,14 +914,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
|
|||
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word);
|
||||
}
|
||||
|
||||
if (intr_loc & CMD_COMPLETED) {
|
||||
/*
|
||||
* Command Complete Interrupt Pending
|
||||
*/
|
||||
dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__);
|
||||
wake_up_interruptible(&ctrl->queue);
|
||||
}
|
||||
|
||||
|
@ -989,7 +952,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
|
|||
}
|
||||
|
||||
dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
|
||||
dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
|
||||
temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
|
||||
|
||||
rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
|
||||
|
@ -997,14 +959,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
|
|||
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
|
||||
|
||||
rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
|
||||
if (rc) {
|
||||
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status);
|
||||
|
||||
/* Clear command complete interrupt caused by this write */
|
||||
temp_word = 0x1F;
|
||||
|
@ -1248,12 +1208,7 @@ static struct hpc_ops pciehp_hpc_ops = {
|
|||
.check_lnk_status = hpc_check_lnk_status,
|
||||
};
|
||||
|
||||
int pcie_init(struct controller * ctrl,
|
||||
struct pcie_device *dev,
|
||||
php_intr_callback_t attention_button_callback,
|
||||
php_intr_callback_t switch_change_callback,
|
||||
php_intr_callback_t presence_change_callback,
|
||||
php_intr_callback_t power_fault_callback)
|
||||
int pcie_init(struct controller * ctrl, struct pcie_device *dev)
|
||||
{
|
||||
struct php_ctlr_state_s *php_ctlr, *p;
|
||||
void *instance_id = ctrl;
|
||||
|
@ -1282,8 +1237,8 @@ int pcie_init(struct controller * ctrl,
|
|||
pdev = dev->port;
|
||||
php_ctlr->pci_dev = pdev; /* save pci_dev in context */
|
||||
|
||||
dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__,
|
||||
pdev->vendor, pdev->device);
|
||||
dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
|
||||
__FUNCTION__, pdev->vendor, pdev->device);
|
||||
|
||||
saved_cap_base = pcie_cap_base;
|
||||
|
||||
|
@ -1340,8 +1295,6 @@ int pcie_init(struct controller * ctrl,
|
|||
first = 0;
|
||||
}
|
||||
|
||||
dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number,
|
||||
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
|
||||
for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
|
||||
if (pci_resource_len(pdev, rc) > 0)
|
||||
dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
|
||||
|
@ -1359,13 +1312,12 @@ int pcie_init(struct controller * ctrl,
|
|||
|
||||
/* find the IRQ */
|
||||
php_ctlr->irq = dev->irq;
|
||||
dbg("HPC interrupt = %d\n", php_ctlr->irq);
|
||||
|
||||
/* Save interrupt callback info */
|
||||
php_ctlr->attention_button_callback = attention_button_callback;
|
||||
php_ctlr->switch_change_callback = switch_change_callback;
|
||||
php_ctlr->presence_change_callback = presence_change_callback;
|
||||
php_ctlr->power_fault_callback = power_fault_callback;
|
||||
php_ctlr->attention_button_callback = pciehp_handle_attention_button;
|
||||
php_ctlr->switch_change_callback = pciehp_handle_switch_change;
|
||||
php_ctlr->presence_change_callback = pciehp_handle_presence_change;
|
||||
php_ctlr->power_fault_callback = pciehp_handle_power_fault;
|
||||
php_ctlr->callback_instance_id = instance_id;
|
||||
|
||||
/* return PCI Controller Info */
|
||||
|
@ -1387,15 +1339,12 @@ int pcie_init(struct controller * ctrl,
|
|||
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
}
|
||||
dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word);
|
||||
|
||||
rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
|
||||
if (rc) {
|
||||
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
}
|
||||
dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base)
|
||||
, slot_status);
|
||||
|
||||
temp_word = 0x1F; /* Clear all events */
|
||||
rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
|
||||
|
@ -1403,7 +1352,6 @@ int pcie_init(struct controller * ctrl,
|
|||
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
}
|
||||
dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
|
||||
|
||||
if (pciehp_poll_mode) {/* Install interrupt polling code */
|
||||
/* Install and start the interrupt polling timer */
|
||||
|
@ -1419,13 +1367,14 @@ int pcie_init(struct controller * ctrl,
|
|||
}
|
||||
}
|
||||
|
||||
dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
|
||||
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
|
||||
|
||||
rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
|
||||
if (rc) {
|
||||
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
}
|
||||
dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);
|
||||
dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
|
||||
|
||||
intr_enable = intr_enable | PRSN_DETECT_ENABLE;
|
||||
|
||||
|
@ -1445,7 +1394,6 @@ int pcie_init(struct controller * ctrl,
|
|||
} else {
|
||||
temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
|
||||
}
|
||||
dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);
|
||||
|
||||
/* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
|
||||
rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
|
||||
|
@ -1453,14 +1401,11 @@ int pcie_init(struct controller * ctrl,
|
|||
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
}
|
||||
dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);
|
||||
rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
|
||||
if (rc) {
|
||||
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
}
|
||||
dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__,
|
||||
SLOT_STATUS(ctrl->cap_base), slot_status);
|
||||
|
||||
temp_word = 0x1F; /* Clear all events */
|
||||
rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
|
||||
|
@ -1468,8 +1413,16 @@ int pcie_init(struct controller * ctrl,
|
|||
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
|
||||
goto abort_free_ctlr;
|
||||
}
|
||||
dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
|
||||
|
||||
if (pciehp_force) {
|
||||
dbg("Bypassing BIOS check for pciehp use on %s\n",
|
||||
pci_name(ctrl->pci_dev));
|
||||
} else {
|
||||
rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
|
||||
if (rc)
|
||||
goto abort_free_ctlr;
|
||||
}
|
||||
|
||||
/* Add this HPC instance into the HPC list */
|
||||
spin_lock(&list_lock);
|
||||
if (php_ctlr_list_head == 0) {
|
||||
|
|
|
@ -27,801 +27,111 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/pci.h>
|
||||
#include "../pci.h"
|
||||
#include "pciehp.h"
|
||||
#ifndef CONFIG_IA64
|
||||
#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
|
||||
#endif
|
||||
|
||||
|
||||
int pciehp_configure_device (struct controller* ctrl, struct pci_func* func)
|
||||
int pciehp_configure_device(struct slot *p_slot)
|
||||
{
|
||||
unsigned char bus;
|
||||
struct pci_bus *child;
|
||||
int num;
|
||||
struct pci_dev *dev;
|
||||
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
|
||||
int num, fn;
|
||||
|
||||
if (func->pci_dev == NULL)
|
||||
func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
|
||||
dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
|
||||
if (dev) {
|
||||
err("Device %s already exists at %x:%x, cannot hot-add\n",
|
||||
pci_name(dev), p_slot->bus, p_slot->device);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Still NULL ? Well then scan for it ! */
|
||||
if (func->pci_dev == NULL) {
|
||||
dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__);
|
||||
num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
|
||||
if (num == 0) {
|
||||
err("No new device found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
|
||||
|
||||
if (num)
|
||||
pci_bus_add_devices(ctrl->pci_dev->subordinate);
|
||||
|
||||
func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
|
||||
if (func->pci_dev == NULL) {
|
||||
dbg("ERROR: pci_dev still null\n");
|
||||
return 0;
|
||||
for (fn = 0; fn < 8; fn++) {
|
||||
if (!(dev = pci_find_slot(p_slot->bus,
|
||||
PCI_DEVFN(p_slot->device, fn))))
|
||||
continue;
|
||||
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
|
||||
err("Cannot hot-add display device %s\n",
|
||||
pci_name(dev));
|
||||
continue;
|
||||
}
|
||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
|
||||
/* Find an unused bus number for the new bridge */
|
||||
struct pci_bus *child;
|
||||
unsigned char busnr, start = parent->secondary;
|
||||
unsigned char end = parent->subordinate;
|
||||
for (busnr = start; busnr <= end; busnr++) {
|
||||
if (!pci_find_bus(pci_domain_nr(parent),
|
||||
busnr))
|
||||
break;
|
||||
}
|
||||
if (busnr >= end) {
|
||||
err("No free bus for hot-added bridge\n");
|
||||
continue;
|
||||
}
|
||||
child = pci_add_new_bus(parent, dev, busnr);
|
||||
if (!child) {
|
||||
err("Cannot add new bus for %s\n",
|
||||
pci_name(dev));
|
||||
continue;
|
||||
}
|
||||
child->subordinate = pci_do_scan_bus(child);
|
||||
pci_bus_size_bridges(child);
|
||||
}
|
||||
/* TBD: program firmware provided _HPP values */
|
||||
/* program_fw_provided_values(dev); */
|
||||
}
|
||||
|
||||
if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
|
||||
child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
|
||||
pci_do_scan_bus(child);
|
||||
|
||||
}
|
||||
|
||||
pci_bus_assign_resources(parent);
|
||||
pci_bus_add_devices(parent);
|
||||
pci_enable_bridges(parent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pciehp_unconfigure_device(struct pci_func* func)
|
||||
int pciehp_unconfigure_device(struct slot *p_slot)
|
||||
{
|
||||
int rc = 0;
|
||||
int j;
|
||||
struct pci_bus *pbus;
|
||||
u8 bctl = 0;
|
||||
|
||||
dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
|
||||
func->device, func->function);
|
||||
pbus = func->pci_dev->bus;
|
||||
dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
|
||||
p_slot->device);
|
||||
|
||||
for (j=0; j<8 ; j++) {
|
||||
struct pci_dev* temp = pci_find_slot(func->bus,
|
||||
(func->device << 3) | j);
|
||||
if (temp) {
|
||||
pci_remove_bus_device(temp);
|
||||
struct pci_dev* temp = pci_find_slot(p_slot->bus,
|
||||
(p_slot->device << 3) | j);
|
||||
if (!temp)
|
||||
continue;
|
||||
if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
|
||||
err("Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
continue;
|
||||
}
|
||||
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
|
||||
if (bctl & PCI_BRIDGE_CTL_VGA) {
|
||||
err("Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pci_remove_bus_device(temp);
|
||||
}
|
||||
/*
|
||||
* Some PCI Express root ports require fixup after hot-plug operation.
|
||||
*/
|
||||
if (pcie_mch_quirk)
|
||||
pci_fixup_device(pci_fixup_final, pbus->self);
|
||||
pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* pciehp_set_irq
|
||||
*
|
||||
* @bus_num: bus number of PCI device
|
||||
* @dev_num: device number of PCI device
|
||||
* @slot: pointer to u8 where slot number will be returned
|
||||
*/
|
||||
int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
|
||||
{
|
||||
#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC)
|
||||
int rc;
|
||||
u16 temp_word;
|
||||
struct pci_dev fakedev;
|
||||
struct pci_bus fakebus;
|
||||
|
||||
fakedev.devfn = dev_num << 3;
|
||||
fakedev.bus = &fakebus;
|
||||
fakebus.number = bus_num;
|
||||
dbg("%s: dev %d, bus %d, pin %d, num %d\n",
|
||||
__FUNCTION__, dev_num, bus_num, int_pin, irq_num);
|
||||
rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
|
||||
dbg("%s: rc %d\n", __FUNCTION__, rc);
|
||||
if (!rc)
|
||||
return !rc;
|
||||
|
||||
/* set the Edge Level Control Register (ELCR) */
|
||||
temp_word = inb(0x4d0);
|
||||
temp_word |= inb(0x4d1) << 8;
|
||||
|
||||
temp_word |= 0x01 << irq_num;
|
||||
|
||||
/* This should only be for x86 as it sets the Edge Level Control Register */
|
||||
outb((u8) (temp_word & 0xFF), 0x4d0);
|
||||
outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* More PCI configuration routines; this time centered around hotplug controller */
|
||||
|
||||
|
||||
/*
|
||||
* pciehp_save_config
|
||||
*
|
||||
* Reads configuration for all slots in a PCI bus and saves info.
|
||||
*
|
||||
* Note: For non-hot plug busses, the slot # saved is the device #
|
||||
*
|
||||
* returns 0 if success
|
||||
*/
|
||||
int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
|
||||
{
|
||||
int rc;
|
||||
u8 class_code;
|
||||
u8 header_type;
|
||||
u32 ID;
|
||||
u8 secondary_bus;
|
||||
struct pci_func *new_slot;
|
||||
int sub_bus;
|
||||
int max_functions;
|
||||
int function;
|
||||
u8 DevError;
|
||||
int device = 0;
|
||||
int cloop = 0;
|
||||
int stop_it;
|
||||
int index;
|
||||
int is_hot_plug = num_ctlr_slots || first_device_num;
|
||||
struct pci_bus lpci_bus, *pci_bus;
|
||||
int FirstSupported, LastSupported;
|
||||
|
||||
dbg("%s: Enter\n", __FUNCTION__);
|
||||
|
||||
memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
|
||||
pci_bus = &lpci_bus;
|
||||
|
||||
dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
|
||||
num_ctlr_slots, first_device_num);
|
||||
|
||||
/* Decide which slots are supported */
|
||||
if (is_hot_plug) {
|
||||
/*********************************
|
||||
* is_hot_plug is the slot mask
|
||||
*********************************/
|
||||
FirstSupported = first_device_num;
|
||||
LastSupported = FirstSupported + num_ctlr_slots - 1;
|
||||
} else {
|
||||
FirstSupported = 0;
|
||||
LastSupported = 0x1F;
|
||||
}
|
||||
|
||||
dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
|
||||
LastSupported);
|
||||
|
||||
/* Save PCI configuration space for all devices in supported slots */
|
||||
dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number);
|
||||
pci_bus->number = busnumber;
|
||||
dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device);
|
||||
for (device = FirstSupported; device <= LastSupported; device++) {
|
||||
ID = 0xFFFFFFFF;
|
||||
rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
|
||||
PCI_VENDOR_ID, &ID);
|
||||
|
||||
if (ID != 0xFFFFFFFF) { /* device in slot */
|
||||
dbg("%s: ID = %x\n", __FUNCTION__, ID);
|
||||
rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
|
||||
0x0B, &class_code);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
|
||||
PCI_HEADER_TYPE, &header_type);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
dbg("class_code = %x, header_type = %x\n", class_code, header_type);
|
||||
|
||||
/* If multi-function device, set max_functions to 8 */
|
||||
if (header_type & 0x80)
|
||||
max_functions = 8;
|
||||
else
|
||||
max_functions = 1;
|
||||
|
||||
function = 0;
|
||||
|
||||
do {
|
||||
DevError = 0;
|
||||
dbg("%s: In do loop\n", __FUNCTION__);
|
||||
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */
|
||||
/* Recurse the subordinate bus
|
||||
* get the subordinate bus number
|
||||
*/
|
||||
rc = pci_bus_read_config_byte(pci_bus,
|
||||
PCI_DEVFN(device, function),
|
||||
PCI_SECONDARY_BUS, &secondary_bus);
|
||||
if (rc) {
|
||||
return rc;
|
||||
} else {
|
||||
sub_bus = (int) secondary_bus;
|
||||
|
||||
/* Save secondary bus cfg spc with this recursive call. */
|
||||
rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
index = 0;
|
||||
new_slot = pciehp_slot_find(busnumber, device, index++);
|
||||
|
||||
dbg("%s: new_slot = %p bus %x dev %x fun %x\n",
|
||||
__FUNCTION__, new_slot, busnumber, device, index-1);
|
||||
|
||||
while (new_slot && (new_slot->function != (u8) function)) {
|
||||
new_slot = pciehp_slot_find(busnumber, device, index++);
|
||||
dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n",
|
||||
__FUNCTION__, new_slot, busnumber, device, index-1);
|
||||
}
|
||||
if (!new_slot) {
|
||||
/* Setup slot structure. */
|
||||
new_slot = pciehp_slot_create(busnumber);
|
||||
dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n",
|
||||
__FUNCTION__, new_slot, busnumber, device, function);
|
||||
|
||||
if (new_slot == NULL)
|
||||
return(1);
|
||||
}
|
||||
|
||||
new_slot->bus = (u8) busnumber;
|
||||
new_slot->device = (u8) device;
|
||||
new_slot->function = (u8) function;
|
||||
new_slot->is_a_board = 1;
|
||||
new_slot->switch_save = 0x10;
|
||||
/* In case of unsupported board */
|
||||
new_slot->status = DevError;
|
||||
new_slot->pci_dev = pci_find_slot(new_slot->bus,
|
||||
(new_slot->device << 3) | new_slot->function);
|
||||
dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
|
||||
|
||||
for (cloop = 0; cloop < 0x20; cloop++) {
|
||||
rc = pci_bus_read_config_dword(pci_bus,
|
||||
PCI_DEVFN(device, function),
|
||||
cloop << 2,
|
||||
(u32 *) &(new_slot->config_space [cloop]));
|
||||
/* dbg("new_slot->config_space[%x] = %x\n",
|
||||
cloop, new_slot->config_space[cloop]); */
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
function++;
|
||||
|
||||
stop_it = 0;
|
||||
|
||||
/* this loop skips to the next present function
|
||||
* reading in Class Code and Header type.
|
||||
*/
|
||||
|
||||
while ((function < max_functions)&&(!stop_it)) {
|
||||
dbg("%s: In while loop \n", __FUNCTION__);
|
||||
rc = pci_bus_read_config_dword(pci_bus,
|
||||
PCI_DEVFN(device, function),
|
||||
PCI_VENDOR_ID, &ID);
|
||||
|
||||
if (ID == 0xFFFFFFFF) { /* nothing there. */
|
||||
function++;
|
||||
dbg("Nothing there\n");
|
||||
} else { /* Something there */
|
||||
rc = pci_bus_read_config_byte(pci_bus,
|
||||
PCI_DEVFN(device, function),
|
||||
0x0B, &class_code);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = pci_bus_read_config_byte(pci_bus,
|
||||
PCI_DEVFN(device, function),
|
||||
PCI_HEADER_TYPE, &header_type);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
dbg("class_code = %x, header_type = %x\n", class_code, header_type);
|
||||
stop_it++;
|
||||
}
|
||||
}
|
||||
|
||||
} while (function < max_functions);
|
||||
/* End of IF (device in slot?) */
|
||||
} else if (is_hot_plug) {
|
||||
/* Setup slot structure with entry for empty slot */
|
||||
new_slot = pciehp_slot_create(busnumber);
|
||||
|
||||
if (new_slot == NULL) {
|
||||
return(1);
|
||||
}
|
||||
dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot,
|
||||
new_slot->bus, new_slot->device, new_slot->function);
|
||||
|
||||
new_slot->bus = (u8) busnumber;
|
||||
new_slot->device = (u8) device;
|
||||
new_slot->function = 0;
|
||||
new_slot->is_a_board = 0;
|
||||
new_slot->presence_save = 0;
|
||||
new_slot->switch_save = 0;
|
||||
}
|
||||
} /* End of FOR loop */
|
||||
|
||||
dbg("%s: Exit\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pciehp_save_slot_config
|
||||
*
|
||||
* Saves configuration info for all PCI devices in a given slot
|
||||
* including subordinate busses.
|
||||
*
|
||||
* returns 0 if success
|
||||
*/
|
||||
int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
|
||||
{
|
||||
int rc;
|
||||
u8 class_code;
|
||||
u8 header_type;
|
||||
u32 ID;
|
||||
u8 secondary_bus;
|
||||
int sub_bus;
|
||||
int max_functions;
|
||||
int function;
|
||||
int cloop = 0;
|
||||
int stop_it;
|
||||
struct pci_bus lpci_bus, *pci_bus;
|
||||
memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
|
||||
pci_bus = &lpci_bus;
|
||||
pci_bus->number = new_slot->bus;
|
||||
|
||||
ID = 0xFFFFFFFF;
|
||||
|
||||
pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
|
||||
PCI_VENDOR_ID, &ID);
|
||||
|
||||
if (ID != 0xFFFFFFFF) { /* device in slot */
|
||||
pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
|
||||
0x0B, &class_code);
|
||||
|
||||
pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
|
||||
PCI_HEADER_TYPE, &header_type);
|
||||
|
||||
if (header_type & 0x80) /* Multi-function device */
|
||||
max_functions = 8;
|
||||
else
|
||||
max_functions = 1;
|
||||
|
||||
function = 0;
|
||||
|
||||
do {
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
|
||||
/* Recurse the subordinate bus */
|
||||
pci_bus_read_config_byte(pci_bus,
|
||||
PCI_DEVFN(new_slot->device, function),
|
||||
PCI_SECONDARY_BUS, &secondary_bus);
|
||||
|
||||
sub_bus = (int) secondary_bus;
|
||||
|
||||
/* Save the config headers for the secondary bus. */
|
||||
rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
} /* End of IF */
|
||||
|
||||
new_slot->status = 0;
|
||||
|
||||
for (cloop = 0; cloop < 0x20; cloop++) {
|
||||
pci_bus_read_config_dword(pci_bus,
|
||||
PCI_DEVFN(new_slot->device, function),
|
||||
cloop << 2,
|
||||
(u32 *) &(new_slot->config_space [cloop]));
|
||||
}
|
||||
|
||||
function++;
|
||||
|
||||
stop_it = 0;
|
||||
|
||||
/* this loop skips to the next present function
|
||||
* reading in the Class Code and the Header type.
|
||||
*/
|
||||
|
||||
while ((function < max_functions) && (!stop_it)) {
|
||||
pci_bus_read_config_dword(pci_bus,
|
||||
PCI_DEVFN(new_slot->device, function),
|
||||
PCI_VENDOR_ID, &ID);
|
||||
|
||||
if (ID == 0xFFFFFFFF) { /* nothing there. */
|
||||
function++;
|
||||
} else { /* Something there */
|
||||
pci_bus_read_config_byte(pci_bus,
|
||||
PCI_DEVFN(new_slot->device, function),
|
||||
0x0B, &class_code);
|
||||
|
||||
pci_bus_read_config_byte(pci_bus,
|
||||
PCI_DEVFN(new_slot->device, function),
|
||||
PCI_HEADER_TYPE, &header_type);
|
||||
|
||||
stop_it++;
|
||||
}
|
||||
}
|
||||
|
||||
} while (function < max_functions);
|
||||
} /* End of IF (device in slot?) */
|
||||
else {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pciehp_save_used_resources
|
||||
*
|
||||
* Stores used resource information for existing boards. this is
|
||||
* for boards that were in the system when this driver was loaded.
|
||||
* this function is for hot plug ADD
|
||||
*
|
||||
* returns 0 if success
|
||||
* if disable == 1(DISABLE_CARD),
|
||||
* it loops for all functions of the slot and disables them.
|
||||
* else, it just get resources of the function and return.
|
||||
*/
|
||||
int pciehp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable)
|
||||
{
|
||||
u8 cloop;
|
||||
u8 header_type;
|
||||
u8 secondary_bus;
|
||||
u8 temp_byte;
|
||||
u16 command;
|
||||
u16 save_command;
|
||||
u16 w_base, w_length;
|
||||
u32 temp_register;
|
||||
u32 save_base;
|
||||
u32 base, length;
|
||||
u64 base64 = 0;
|
||||
int index = 0;
|
||||
unsigned int devfn;
|
||||
struct pci_resource *mem_node = NULL;
|
||||
struct pci_resource *p_mem_node = NULL;
|
||||
struct pci_resource *t_mem_node;
|
||||
struct pci_resource *io_node;
|
||||
struct pci_resource *bus_node;
|
||||
struct pci_bus lpci_bus, *pci_bus;
|
||||
memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
|
||||
pci_bus = &lpci_bus;
|
||||
|
||||
if (disable)
|
||||
func = pciehp_slot_find(func->bus, func->device, index++);
|
||||
|
||||
while ((func != NULL) && func->is_a_board) {
|
||||
pci_bus->number = func->bus;
|
||||
devfn = PCI_DEVFN(func->device, func->function);
|
||||
|
||||
/* Save the command register */
|
||||
pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
|
||||
|
||||
if (disable) {
|
||||
/* disable card */
|
||||
command = 0x00;
|
||||
pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
|
||||
}
|
||||
|
||||
/* Check for Bridge */
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
|
||||
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
|
||||
dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
|
||||
func->bus, func->device, save_command);
|
||||
if (disable) {
|
||||
/* Clear Bridge Control Register */
|
||||
command = 0x00;
|
||||
pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
|
||||
}
|
||||
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
|
||||
|
||||
bus_node = kmalloc(sizeof(struct pci_resource),
|
||||
GFP_KERNEL);
|
||||
if (!bus_node)
|
||||
return -ENOMEM;
|
||||
|
||||
bus_node->base = (ulong)secondary_bus;
|
||||
bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
|
||||
|
||||
bus_node->next = func->bus_head;
|
||||
func->bus_head = bus_node;
|
||||
|
||||
/* Save IO base and Limit registers */
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte);
|
||||
base = temp_byte;
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
|
||||
length = temp_byte;
|
||||
|
||||
if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
|
||||
io_node = kmalloc(sizeof(struct pci_resource),
|
||||
GFP_KERNEL);
|
||||
if (!io_node)
|
||||
return -ENOMEM;
|
||||
|
||||
io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
|
||||
io_node->length = (ulong)(length - base + 0x10) << 8;
|
||||
|
||||
io_node->next = func->io_head;
|
||||
func->io_head = io_node;
|
||||
}
|
||||
|
||||
/* Save memory base and Limit registers */
|
||||
pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
|
||||
pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
|
||||
|
||||
if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
|
||||
mem_node = kmalloc(sizeof(struct pci_resource),
|
||||
GFP_KERNEL);
|
||||
if (!mem_node)
|
||||
return -ENOMEM;
|
||||
|
||||
mem_node->base = (ulong)w_base << 16;
|
||||
mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
|
||||
|
||||
mem_node->next = func->mem_head;
|
||||
func->mem_head = mem_node;
|
||||
}
|
||||
/* Save prefetchable memory base and Limit registers */
|
||||
pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
|
||||
pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
|
||||
|
||||
if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
|
||||
p_mem_node = kmalloc(sizeof(struct pci_resource),
|
||||
GFP_KERNEL);
|
||||
if (!p_mem_node)
|
||||
return -ENOMEM;
|
||||
|
||||
p_mem_node->base = (ulong)w_base << 16;
|
||||
p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
|
||||
|
||||
p_mem_node->next = func->p_mem_head;
|
||||
func->p_mem_head = p_mem_node;
|
||||
}
|
||||
} else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
|
||||
dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
|
||||
func->bus, func->device, save_command);
|
||||
|
||||
/* Figure out IO and memory base lengths */
|
||||
for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
|
||||
pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
|
||||
|
||||
temp_register = 0xFFFFFFFF;
|
||||
pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
|
||||
pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
|
||||
|
||||
if (!disable)
|
||||
pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
|
||||
|
||||
if (!temp_register)
|
||||
continue;
|
||||
|
||||
base = temp_register;
|
||||
|
||||
if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
|
||||
(!disable || (save_command & PCI_COMMAND_IO))) {
|
||||
/* IO base */
|
||||
/* set temp_register = amount of IO space requested */
|
||||
base = base & 0xFFFFFFFCL;
|
||||
base = (~base) + 1;
|
||||
|
||||
io_node = kmalloc(sizeof (struct pci_resource),
|
||||
GFP_KERNEL);
|
||||
if (!io_node)
|
||||
return -ENOMEM;
|
||||
|
||||
io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
|
||||
io_node->length = (ulong)base;
|
||||
dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
|
||||
io_node->base, io_node->length);
|
||||
|
||||
io_node->next = func->io_head;
|
||||
func->io_head = io_node;
|
||||
} else { /* map Memory */
|
||||
int prefetchable = 1;
|
||||
/* struct pci_resources **res_node; */
|
||||
char *res_type_str = "PMEM";
|
||||
u32 temp_register2;
|
||||
|
||||
t_mem_node = kmalloc(sizeof (struct pci_resource),
|
||||
GFP_KERNEL);
|
||||
if (!t_mem_node)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
|
||||
(!disable || (save_command & PCI_COMMAND_MEMORY))) {
|
||||
prefetchable = 0;
|
||||
mem_node = t_mem_node;
|
||||
res_type_str++;
|
||||
} else
|
||||
p_mem_node = t_mem_node;
|
||||
|
||||
base = base & 0xFFFFFFF0L;
|
||||
base = (~base) + 1;
|
||||
|
||||
switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
|
||||
case PCI_BASE_ADDRESS_MEM_TYPE_32:
|
||||
if (prefetchable) {
|
||||
p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
p_mem_node->length = (ulong)base;
|
||||
dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
|
||||
res_type_str,
|
||||
p_mem_node->base,
|
||||
p_mem_node->length);
|
||||
|
||||
p_mem_node->next = func->p_mem_head;
|
||||
func->p_mem_head = p_mem_node;
|
||||
} else {
|
||||
mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
mem_node->length = (ulong)base;
|
||||
dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
|
||||
res_type_str,
|
||||
mem_node->base,
|
||||
mem_node->length);
|
||||
|
||||
mem_node->next = func->mem_head;
|
||||
func->mem_head = mem_node;
|
||||
}
|
||||
break;
|
||||
case PCI_BASE_ADDRESS_MEM_TYPE_64:
|
||||
pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
|
||||
base64 = temp_register2;
|
||||
base64 = (base64 << 32) | save_base;
|
||||
|
||||
if (temp_register2) {
|
||||
dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n",
|
||||
res_type_str, temp_register2, (u32)base64);
|
||||
base64 &= 0x00000000FFFFFFFFL;
|
||||
}
|
||||
|
||||
if (prefetchable) {
|
||||
p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
p_mem_node->length = base;
|
||||
dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
|
||||
res_type_str,
|
||||
p_mem_node->base,
|
||||
p_mem_node->length);
|
||||
|
||||
p_mem_node->next = func->p_mem_head;
|
||||
func->p_mem_head = p_mem_node;
|
||||
} else {
|
||||
mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
|
||||
mem_node->length = base;
|
||||
dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
|
||||
res_type_str,
|
||||
mem_node->base,
|
||||
mem_node->length);
|
||||
|
||||
mem_node->next = func->mem_head;
|
||||
func->mem_head = mem_node;
|
||||
}
|
||||
cloop += 4;
|
||||
break;
|
||||
default:
|
||||
dbg("asur: reserved BAR type=0x%x\n",
|
||||
temp_register);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* End of base register loop */
|
||||
} else { /* Some other unknown header type */
|
||||
dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
|
||||
func->bus, func->device);
|
||||
}
|
||||
|
||||
/* find the next device in this slot */
|
||||
if (!disable)
|
||||
break;
|
||||
func = pciehp_slot_find(func->bus, func->device, index++);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* kfree_resource_list: release memory of all list members
|
||||
* @res: resource list to free
|
||||
*/
|
||||
static inline void
|
||||
return_resource_list(struct pci_resource **func, struct pci_resource **res)
|
||||
{
|
||||
struct pci_resource *node;
|
||||
struct pci_resource *t_node;
|
||||
|
||||
node = *func;
|
||||
*func = NULL;
|
||||
while (node) {
|
||||
t_node = node->next;
|
||||
return_resource(res, node);
|
||||
node = t_node;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* pciehp_return_board_resources
|
||||
*
|
||||
* this routine returns all resources allocated to a board to
|
||||
* the available pool.
|
||||
*
|
||||
* returns 0 if success
|
||||
*/
|
||||
int pciehp_return_board_resources(struct pci_func * func,
|
||||
struct resource_lists * resources)
|
||||
{
|
||||
int rc;
|
||||
|
||||
dbg("%s\n", __FUNCTION__);
|
||||
|
||||
if (!func)
|
||||
return 1;
|
||||
|
||||
return_resource_list(&(func->io_head),&(resources->io_head));
|
||||
return_resource_list(&(func->mem_head),&(resources->mem_head));
|
||||
return_resource_list(&(func->p_mem_head),&(resources->p_mem_head));
|
||||
return_resource_list(&(func->bus_head),&(resources->bus_head));
|
||||
|
||||
rc = pciehp_resource_sort_and_combine(&(resources->mem_head));
|
||||
rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head));
|
||||
rc |= pciehp_resource_sort_and_combine(&(resources->io_head));
|
||||
rc |= pciehp_resource_sort_and_combine(&(resources->bus_head));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* kfree_resource_list: release memory of all list members
|
||||
* @res: resource list to free
|
||||
*/
|
||||
static inline void
|
||||
kfree_resource_list(struct pci_resource **r)
|
||||
{
|
||||
struct pci_resource *res, *tres;
|
||||
|
||||
res = *r;
|
||||
*r = NULL;
|
||||
|
||||
while (res) {
|
||||
tres = res;
|
||||
res = res->next;
|
||||
kfree(tres);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pciehp_destroy_resource_list: put node back in the resource list
|
||||
* @resources: list to put nodes back
|
||||
*/
|
||||
void pciehp_destroy_resource_list(struct resource_lists * resources)
|
||||
{
|
||||
kfree_resource_list(&(resources->io_head));
|
||||
kfree_resource_list(&(resources->mem_head));
|
||||
kfree_resource_list(&(resources->p_mem_head));
|
||||
kfree_resource_list(&(resources->bus_head));
|
||||
}
|
||||
|
||||
/**
|
||||
* pciehp_destroy_board_resources: put node back in the resource list
|
||||
* @resources: list to put nodes back
|
||||
*/
|
||||
void pciehp_destroy_board_resources(struct pci_func * func)
|
||||
{
|
||||
kfree_resource_list(&(func->io_head));
|
||||
kfree_resource_list(&(func->mem_head));
|
||||
kfree_resource_list(&(func->p_mem_head));
|
||||
kfree_resource_list(&(func->bus_head));
|
||||
}
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* PCIEHPRM : PCIEHP Resource Manager for ACPI/non-ACPI platform
|
||||
*
|
||||
* Copyright (C) 1995,2001 Compaq Computer Corporation
|
||||
* Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
|
||||
* Copyright (C) 2001 IBM Corp.
|
||||
* Copyright (C) 2003-2004 Intel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PCIEHPRM_H_
|
||||
#define _PCIEHPRM_H_
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI
|
||||
#include "pciehprm_nonacpi.h"
|
||||
#endif
|
||||
|
||||
int pciehprm_init(enum php_ctlr_type ct);
|
||||
void pciehprm_cleanup(void);
|
||||
int pciehprm_print_pirt(void);
|
||||
int pciehprm_find_available_resources(struct controller *ctrl);
|
||||
int pciehprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
|
||||
void pciehprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define RES_CHECK(this, bits) \
|
||||
{ if (((this) & (bits - 1))) \
|
||||
printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
|
||||
#else
|
||||
#define RES_CHECK(this, bits)
|
||||
#endif
|
||||
|
||||
#endif /* _PCIEHPRM_H_ */
|
File diff suppressed because it is too large
Load diff
|
@ -27,479 +27,21 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#ifdef CONFIG_IA64
|
||||
#include <asm/iosapic.h>
|
||||
#endif
|
||||
|
||||
#include "pciehp.h"
|
||||
#include "pciehprm.h"
|
||||
#include "pciehprm_nonacpi.h"
|
||||
|
||||
|
||||
void pciehprm_cleanup(void)
|
||||
void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
|
||||
struct hotplug_params *hpp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int pciehprm_print_pirt(void)
|
||||
int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
|
||||
{
|
||||
|
||||
*sun = (u8) (ctrl->first_slot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void print_pci_resource ( struct pci_resource *aprh)
|
||||
{
|
||||
struct pci_resource *res;
|
||||
|
||||
for (res = aprh; res; res = res->next)
|
||||
dbg(" base= 0x%x length= 0x%x\n", res->base, res->length);
|
||||
}
|
||||
|
||||
|
||||
static void phprm_dump_func_res( struct pci_func *fun)
|
||||
{
|
||||
struct pci_func *func = fun;
|
||||
|
||||
if (func->bus_head) {
|
||||
dbg(": BUS Resources:\n");
|
||||
print_pci_resource (func->bus_head);
|
||||
}
|
||||
if (func->io_head) {
|
||||
dbg(": IO Resources:\n");
|
||||
print_pci_resource (func->io_head);
|
||||
}
|
||||
if (func->mem_head) {
|
||||
dbg(": MEM Resources:\n");
|
||||
print_pci_resource (func->mem_head);
|
||||
}
|
||||
if (func->p_mem_head) {
|
||||
dbg(": PMEM Resources:\n");
|
||||
print_pci_resource (func->p_mem_head);
|
||||
}
|
||||
}
|
||||
|
||||
static int phprm_get_used_resources (
|
||||
struct controller *ctrl,
|
||||
struct pci_func *func
|
||||
)
|
||||
{
|
||||
return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD);
|
||||
}
|
||||
|
||||
static int phprm_delete_resource(
|
||||
struct pci_resource **aprh,
|
||||
ulong base,
|
||||
ulong size)
|
||||
{
|
||||
struct pci_resource *res;
|
||||
struct pci_resource *prevnode;
|
||||
struct pci_resource *split_node;
|
||||
ulong tbase;
|
||||
|
||||
pciehp_resource_sort_and_combine(aprh);
|
||||
|
||||
for (res = *aprh; res; res = res->next) {
|
||||
if (res->base > base)
|
||||
continue;
|
||||
|
||||
if ((res->base + res->length) < (base + size))
|
||||
continue;
|
||||
|
||||
if (res->base < base) {
|
||||
tbase = base;
|
||||
|
||||
if ((res->length - (tbase - res->base)) < size)
|
||||
continue;
|
||||
|
||||
split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
|
||||
if (!split_node)
|
||||
return -ENOMEM;
|
||||
|
||||
split_node->base = res->base;
|
||||
split_node->length = tbase - res->base;
|
||||
res->base = tbase;
|
||||
res->length -= split_node->length;
|
||||
|
||||
split_node->next = res->next;
|
||||
res->next = split_node;
|
||||
}
|
||||
|
||||
if (res->length >= size) {
|
||||
split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
|
||||
if (!split_node)
|
||||
return -ENOMEM;
|
||||
|
||||
split_node->base = res->base + size;
|
||||
split_node->length = res->length - size;
|
||||
res->length = size;
|
||||
|
||||
split_node->next = res->next;
|
||||
res->next = split_node;
|
||||
}
|
||||
|
||||
if (*aprh == res) {
|
||||
*aprh = res->next;
|
||||
} else {
|
||||
prevnode = *aprh;
|
||||
while (prevnode->next != res)
|
||||
prevnode = prevnode->next;
|
||||
|
||||
prevnode->next = res->next;
|
||||
}
|
||||
res->next = NULL;
|
||||
kfree(res);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int phprm_delete_resources(
|
||||
struct pci_resource **aprh,
|
||||
struct pci_resource *this
|
||||
)
|
||||
{
|
||||
struct pci_resource *res;
|
||||
|
||||
for (res = this; res; res = res->next)
|
||||
phprm_delete_resource(aprh, res->base, res->length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int configure_existing_function(
|
||||
struct controller *ctrl,
|
||||
struct pci_func *func
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* see how much resources the func has used. */
|
||||
rc = phprm_get_used_resources (ctrl, func);
|
||||
|
||||
if (!rc) {
|
||||
/* subtract the resources used by the func from ctrl resources */
|
||||
rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head);
|
||||
rc |= phprm_delete_resources (&ctrl->io_head, func->io_head);
|
||||
rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head);
|
||||
rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
|
||||
if (rc)
|
||||
warn("aCEF: cannot del used resources\n");
|
||||
} else
|
||||
err("aCEF: cannot get used resources\n");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int pciehprm_delete_resource(
|
||||
struct pci_resource **aprh,
|
||||
ulong base,
|
||||
ulong size)
|
||||
{
|
||||
struct pci_resource *res;
|
||||
struct pci_resource *prevnode;
|
||||
struct pci_resource *split_node;
|
||||
ulong tbase;
|
||||
|
||||
pciehp_resource_sort_and_combine(aprh);
|
||||
|
||||
for (res = *aprh; res; res = res->next) {
|
||||
if (res->base > base)
|
||||
continue;
|
||||
|
||||
if ((res->base + res->length) < (base + size))
|
||||
continue;
|
||||
|
||||
if (res->base < base) {
|
||||
tbase = base;
|
||||
|
||||
if ((res->length - (tbase - res->base)) < size)
|
||||
continue;
|
||||
|
||||
split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
|
||||
if (!split_node)
|
||||
return -ENOMEM;
|
||||
|
||||
split_node->base = res->base;
|
||||
split_node->length = tbase - res->base;
|
||||
res->base = tbase;
|
||||
res->length -= split_node->length;
|
||||
|
||||
split_node->next = res->next;
|
||||
res->next = split_node;
|
||||
}
|
||||
|
||||
if (res->length >= size) {
|
||||
split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
|
||||
if (!split_node)
|
||||
return -ENOMEM;
|
||||
|
||||
split_node->base = res->base + size;
|
||||
split_node->length = res->length - size;
|
||||
res->length = size;
|
||||
|
||||
split_node->next = res->next;
|
||||
res->next = split_node;
|
||||
}
|
||||
|
||||
if (*aprh == res) {
|
||||
*aprh = res->next;
|
||||
} else {
|
||||
prevnode = *aprh;
|
||||
while (prevnode->next != res)
|
||||
prevnode = prevnode->next;
|
||||
|
||||
prevnode->next = res->next;
|
||||
}
|
||||
res->next = NULL;
|
||||
kfree(res);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bind_pci_resources_to_slots ( struct controller *ctrl)
|
||||
{
|
||||
struct pci_func *func, new_func;
|
||||
int busn = ctrl->slot_bus;
|
||||
int devn, funn;
|
||||
u32 vid;
|
||||
|
||||
for (devn = 0; devn < 32; devn++) {
|
||||
for (funn = 0; funn < 8; funn++) {
|
||||
/*
|
||||
if (devn == ctrl->device && funn == ctrl->function)
|
||||
continue;
|
||||
*/
|
||||
/* find out if this entry is for an occupied slot */
|
||||
vid = 0xFFFFFFFF;
|
||||
|
||||
pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
|
||||
|
||||
if (vid != 0xFFFFFFFF) {
|
||||
dbg("%s: vid = %x bus %x dev %x fun %x\n", __FUNCTION__,
|
||||
vid, busn, devn, funn);
|
||||
func = pciehp_slot_find(busn, devn, funn);
|
||||
dbg("%s: func = %p\n", __FUNCTION__,func);
|
||||
if (!func) {
|
||||
memset(&new_func, 0, sizeof(struct pci_func));
|
||||
new_func.bus = busn;
|
||||
new_func.device = devn;
|
||||
new_func.function = funn;
|
||||
new_func.is_a_board = 1;
|
||||
configure_existing_function(ctrl, &new_func);
|
||||
phprm_dump_func_res(&new_func);
|
||||
} else {
|
||||
configure_existing_function(ctrl, func);
|
||||
phprm_dump_func_res(func);
|
||||
}
|
||||
dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void phprm_dump_ctrl_res( struct controller *ctlr)
|
||||
{
|
||||
struct controller *ctrl = ctlr;
|
||||
|
||||
if (ctrl->bus_head) {
|
||||
dbg(": BUS Resources:\n");
|
||||
print_pci_resource (ctrl->bus_head);
|
||||
}
|
||||
if (ctrl->io_head) {
|
||||
dbg(": IO Resources:\n");
|
||||
print_pci_resource (ctrl->io_head);
|
||||
}
|
||||
if (ctrl->mem_head) {
|
||||
dbg(": MEM Resources:\n");
|
||||
print_pci_resource (ctrl->mem_head);
|
||||
}
|
||||
if (ctrl->p_mem_head) {
|
||||
dbg(": PMEM Resources:\n");
|
||||
print_pci_resource (ctrl->p_mem_head);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* phprm_find_available_resources
|
||||
*
|
||||
* Finds available memory, IO, and IRQ resources for programming
|
||||
* devices which may be added to the system
|
||||
* this function is for hot plug ADD!
|
||||
*
|
||||
* returns 0 if success
|
||||
*/
|
||||
int pciehprm_find_available_resources(struct controller *ctrl)
|
||||
{
|
||||
struct pci_func func;
|
||||
u32 rc;
|
||||
|
||||
memset(&func, 0, sizeof(struct pci_func));
|
||||
|
||||
func.bus = ctrl->bus;
|
||||
func.device = ctrl->device;
|
||||
func.function = ctrl->function;
|
||||
func.is_a_board = 1;
|
||||
|
||||
/* Get resources for this PCI bridge */
|
||||
rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD);
|
||||
dbg("%s: pciehp_save_used_resources rc = %d\n", __FUNCTION__, rc);
|
||||
|
||||
if (func.mem_head)
|
||||
func.mem_head->next = ctrl->mem_head;
|
||||
ctrl->mem_head = func.mem_head;
|
||||
|
||||
if (func.p_mem_head)
|
||||
func.p_mem_head->next = ctrl->p_mem_head;
|
||||
ctrl->p_mem_head = func.p_mem_head;
|
||||
|
||||
if (func.io_head)
|
||||
func.io_head->next = ctrl->io_head;
|
||||
ctrl->io_head = func.io_head;
|
||||
|
||||
if(func.bus_head)
|
||||
func.bus_head->next = ctrl->bus_head;
|
||||
ctrl->bus_head = func.bus_head;
|
||||
|
||||
if (ctrl->bus_head)
|
||||
pciehprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1);
|
||||
|
||||
dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
|
||||
phprm_dump_ctrl_res(ctrl);
|
||||
|
||||
dbg("%s: before bind_pci_resources_to slots\n", __FUNCTION__);
|
||||
|
||||
bind_pci_resources_to_slots (ctrl);
|
||||
|
||||
dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
|
||||
phprm_dump_ctrl_res(ctrl);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
int pciehprm_set_hpp(
|
||||
struct controller *ctrl,
|
||||
struct pci_func *func,
|
||||
u8 card_type)
|
||||
{
|
||||
u32 rc;
|
||||
u8 temp_byte;
|
||||
struct pci_bus lpci_bus, *pci_bus;
|
||||
unsigned int devfn;
|
||||
memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
|
||||
pci_bus = &lpci_bus;
|
||||
pci_bus->number = func->bus;
|
||||
devfn = PCI_DEVFN(func->device, func->function);
|
||||
|
||||
temp_byte = 0x40; /* hard coded value for LT */
|
||||
if (card_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
/* set subordinate Latency Timer */
|
||||
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
|
||||
|
||||
if (rc) {
|
||||
dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__,
|
||||
func->bus, func->device, func->function);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* set base Latency Timer */
|
||||
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
|
||||
|
||||
if (rc) {
|
||||
dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* set Cache Line size */
|
||||
temp_byte = 0x08; /* hard coded value for CLS */
|
||||
|
||||
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
|
||||
|
||||
if (rc) {
|
||||
dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
|
||||
}
|
||||
|
||||
/* set enable_perr */
|
||||
/* set enable_serr */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void pciehprm_enable_card(
|
||||
struct controller *ctrl,
|
||||
struct pci_func *func,
|
||||
u8 card_type)
|
||||
{
|
||||
u16 command, bcommand;
|
||||
struct pci_bus lpci_bus, *pci_bus;
|
||||
unsigned int devfn;
|
||||
int rc;
|
||||
|
||||
memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
|
||||
pci_bus = &lpci_bus;
|
||||
pci_bus->number = func->bus;
|
||||
devfn = PCI_DEVFN(func->device, func->function);
|
||||
|
||||
rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
|
||||
|
||||
command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
|
||||
| PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
|
||||
| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
|
||||
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
|
||||
|
||||
if (card_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
|
||||
rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
|
||||
|
||||
bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
|
||||
| PCI_BRIDGE_CTL_NO_ISA;
|
||||
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
|
||||
}
|
||||
}
|
||||
|
||||
static int legacy_pciehprm_init_pci(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pciehprm_init(enum php_ctlr_type ctrl_type)
|
||||
{
|
||||
int retval;
|
||||
|
||||
switch (ctrl_type) {
|
||||
case PCI:
|
||||
retval = legacy_pciehprm_init_pci();
|
||||
break;
|
||||
default:
|
||||
retval = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
|
||||
*
|
||||
* Copyright (C) 1995,2001 Compaq Computer Corporation
|
||||
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
|
||||
* Copyright (C) 2001 IBM Corp.
|
||||
* Copyright (C) 2003-2004 Intel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PCIEHPRM_NONACPI_H_
|
||||
#define _PCIEHPRM_NONACPI_H_
|
||||
|
||||
struct irq_info {
|
||||
u8 bus, devfn; /* bus, device and function */
|
||||
struct {
|
||||
u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
|
||||
u16 bitmap; /* Available IRQs */
|
||||
} __attribute__ ((packed)) irq[4];
|
||||
u8 slot; /* slot number, 0=onboard */
|
||||
u8 rfu;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct irq_routing_table {
|
||||
u32 signature; /* PIRQ_SIGNATURE should be here */
|
||||
u16 version; /* PIRQ_VERSION */
|
||||
u16 size; /* Table size in bytes */
|
||||
u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
|
||||
u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
|
||||
u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
|
||||
u32 miniport_data; /* Crap */
|
||||
u8 rfu[11];
|
||||
u8 checksum; /* Modulo 256 checksum must give zero */
|
||||
struct irq_info slots[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif /* _PCIEHPRM_NONACPI_H_ */
|
|
@ -134,43 +134,6 @@ static void rpadlpar_claim_one_bus(struct pci_bus *b)
|
|||
rpadlpar_claim_one_bus(child_bus);
|
||||
}
|
||||
|
||||
static int pci_add_secondary_bus(struct device_node *dn,
|
||||
struct pci_dev *bridge_dev)
|
||||
{
|
||||
struct pci_dn *pdn = dn->data;
|
||||
struct pci_controller *hose = pdn->phb;
|
||||
struct pci_bus *child;
|
||||
u8 sec_busno;
|
||||
|
||||
/* Get busno of downstream bus */
|
||||
pci_read_config_byte(bridge_dev, PCI_SECONDARY_BUS, &sec_busno);
|
||||
|
||||
/* Allocate and add to children of bridge_dev->bus */
|
||||
child = pci_add_new_bus(bridge_dev->bus, bridge_dev, sec_busno);
|
||||
if (!child) {
|
||||
printk(KERN_ERR "%s: could not add secondary bus\n", __FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sprintf(child->name, "PCI Bus #%02x", child->number);
|
||||
|
||||
/* Fixup subordinate bridge bases and resources */
|
||||
pcibios_fixup_bus(child);
|
||||
|
||||
/* Claim new bus resources */
|
||||
rpadlpar_claim_one_bus(bridge_dev->bus);
|
||||
|
||||
if (hose->last_busno < child->number)
|
||||
hose->last_busno = child->number;
|
||||
|
||||
pdn->bussubno = child->number;
|
||||
|
||||
/* ioremap() for child bus, which may or may not succeed */
|
||||
remap_bus_range(child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
|
||||
struct device_node *dev_dn)
|
||||
{
|
||||
|
@ -188,29 +151,41 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
|
|||
static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
|
||||
{
|
||||
struct pci_dn *pdn = dn->data;
|
||||
struct pci_controller *hose = pdn->phb;
|
||||
struct pci_controller *phb = pdn->phb;
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
/* Scan phb bus for EADS device, adding new one to bus->devices */
|
||||
if (!pci_scan_single_device(hose->bus, pdn->devfn)) {
|
||||
printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__);
|
||||
rpaphp_eeh_init_nodes(dn);
|
||||
/* Add EADS device to PHB bus, adding new entry to bus->devices */
|
||||
dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
|
||||
if (!dev) {
|
||||
printk(KERN_ERR "%s: failed to create pci dev for %s\n",
|
||||
__FUNCTION__, dn->full_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
|
||||
of_scan_pci_bridge(dn, dev);
|
||||
|
||||
rpaphp_init_new_devs(dev->subordinate);
|
||||
|
||||
/* Claim new bus resources */
|
||||
rpadlpar_claim_one_bus(dev->bus);
|
||||
|
||||
/* ioremap() for child bus, which may or may not succeed */
|
||||
(void) remap_bus_range(dev->bus);
|
||||
|
||||
/* Add new devices to global lists. Register in proc, sysfs. */
|
||||
pci_bus_add_devices(hose->bus);
|
||||
pci_bus_add_devices(phb->bus);
|
||||
|
||||
/* Confirm new bridge dev was created */
|
||||
dev = dlpar_find_new_dev(hose->bus, dn);
|
||||
dev = dlpar_find_new_dev(phb->bus, dn);
|
||||
if (dev) {
|
||||
if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
|
||||
printk(KERN_ERR "%s: unexpected header type %d\n",
|
||||
__FUNCTION__, dev->hdr_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pci_add_secondary_bus(dn, dev))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
|
@ -219,7 +194,6 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
|
|||
static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
int rc;
|
||||
|
||||
if (rpaphp_find_pci_bus(dn))
|
||||
return -EINVAL;
|
||||
|
@ -232,15 +206,6 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (dn->child) {
|
||||
rc = rpaphp_config_pci_adapter(dev->subordinate);
|
||||
if (rc < 0) {
|
||||
printk(KERN_ERR "%s: unable to enable slot %s\n",
|
||||
__FUNCTION__, drc_name);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add hotplug slot */
|
||||
if (rpaphp_add_slot(dn)) {
|
||||
printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
|
||||
|
@ -435,6 +400,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
|
|||
__FUNCTION__, drc_name);
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
rpaphp_unconfig_pci_adapter(bus);
|
||||
}
|
||||
|
||||
if (unmap_bus_range(bus)) {
|
||||
|
|
|
@ -93,6 +93,8 @@ extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
|
|||
extern int rpaphp_enable_pci_slot(struct slot *slot);
|
||||
extern int register_pci_slot(struct slot *slot);
|
||||
extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
|
||||
extern void rpaphp_init_new_devs(struct pci_bus *bus);
|
||||
extern void rpaphp_eeh_init_nodes(struct device_node *dn);
|
||||
|
||||
extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
|
||||
extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
|
||||
|
|
|
@ -154,8 +154,7 @@ int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
|
|||
}
|
||||
|
||||
/* Must be called before pci_bus_add_devices */
|
||||
static void
|
||||
rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
|
||||
void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
|
@ -184,6 +183,20 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
|
|||
}
|
||||
}
|
||||
|
||||
static void rpaphp_eeh_add_bus_device(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
eeh_add_device_late(dev);
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
struct pci_bus *subbus = dev->subordinate;
|
||||
if (subbus)
|
||||
rpaphp_eeh_add_bus_device (subbus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int rpaphp_pci_config_bridge(struct pci_dev *dev)
|
||||
{
|
||||
u8 sec_busno;
|
||||
|
@ -217,6 +230,13 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void rpaphp_init_new_devs(struct pci_bus *bus)
|
||||
{
|
||||
rpaphp_fixup_new_pci_devices(bus, 0);
|
||||
rpaphp_eeh_add_bus_device(bus);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpaphp_init_new_devs);
|
||||
|
||||
/*****************************************************************************
|
||||
rpaphp_pci_config_slot() will configure all devices under the
|
||||
given slot->dn and return the the first pci_dev.
|
||||
|
@ -233,36 +253,51 @@ rpaphp_pci_config_slot(struct pci_bus *bus)
|
|||
if (!dn || !dn->child)
|
||||
return NULL;
|
||||
|
||||
slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
|
||||
if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
|
||||
of_scan_bus(dn, bus);
|
||||
if (list_empty(&bus->devices)) {
|
||||
err("%s: No new device found\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* pci_scan_slot should find all children */
|
||||
num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
|
||||
if (num) {
|
||||
rpaphp_fixup_new_pci_devices(bus, 1);
|
||||
rpaphp_init_new_devs(bus);
|
||||
pci_bus_add_devices(bus);
|
||||
}
|
||||
if (list_empty(&bus->devices)) {
|
||||
err("%s: No new device found\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
|
||||
rpaphp_pci_config_bridge(dev);
|
||||
dev = list_entry(&bus->devices, struct pci_dev, bus_list);
|
||||
} else {
|
||||
slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
|
||||
|
||||
/* pci_scan_slot should find all children */
|
||||
num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
|
||||
if (num) {
|
||||
rpaphp_fixup_new_pci_devices(bus, 1);
|
||||
pci_bus_add_devices(bus);
|
||||
}
|
||||
if (list_empty(&bus->devices)) {
|
||||
err("%s: No new device found\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
|
||||
rpaphp_pci_config_bridge(dev);
|
||||
|
||||
rpaphp_eeh_add_bus_device(bus);
|
||||
}
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void enable_eeh(struct device_node *dn)
|
||||
void rpaphp_eeh_init_nodes(struct device_node *dn)
|
||||
{
|
||||
struct device_node *sib;
|
||||
|
||||
for (sib = dn->child; sib; sib = sib->sibling)
|
||||
enable_eeh(sib);
|
||||
rpaphp_eeh_init_nodes(sib);
|
||||
eeh_add_device_early(dn);
|
||||
return;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes);
|
||||
|
||||
static void print_slot_pci_funcs(struct pci_bus *bus)
|
||||
{
|
||||
|
@ -289,7 +324,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus)
|
|||
if (!dn)
|
||||
goto exit;
|
||||
|
||||
enable_eeh(dn);
|
||||
rpaphp_eeh_init_nodes(dn);
|
||||
dev = rpaphp_pci_config_slot(bus);
|
||||
if (!dev) {
|
||||
err("%s: can't find any devices.\n", __FUNCTION__);
|
||||
|
@ -331,6 +366,7 @@ int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
|
||||
|
||||
static int setup_pci_hotplug_slot_info(struct slot *slot)
|
||||
{
|
||||
|
@ -444,8 +480,8 @@ int rpaphp_enable_pci_slot(struct slot *slot)
|
|||
retval = rpaphp_config_pci_adapter(slot->bus);
|
||||
if (!retval) {
|
||||
slot->state = CONFIGURED;
|
||||
dbg("%s: PCI devices in slot[%s] has been configured\n",
|
||||
__FUNCTION__, slot->name);
|
||||
info("%s: devices in slot[%s] configured\n",
|
||||
__FUNCTION__, slot->name);
|
||||
} else {
|
||||
slot->state = NOT_CONFIGURED;
|
||||
dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "../pci.h"
|
||||
#include "shpchp.h"
|
||||
|
||||
void program_fw_provided_values(struct pci_dev *dev)
|
||||
static void program_fw_provided_values(struct pci_dev *dev)
|
||||
{
|
||||
u16 pci_cmd, pci_bctl;
|
||||
struct pci_dev *cdev;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "pci.h"
|
||||
#include "msi.h"
|
||||
|
||||
#define MSI_TARGET_CPU first_cpu(cpu_online_map)
|
||||
|
||||
static DEFINE_SPINLOCK(msi_lock);
|
||||
static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
|
||||
static kmem_cache_t* msi_cachep;
|
||||
|
@ -92,6 +94,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
|
|||
struct msi_desc *entry;
|
||||
struct msg_address address;
|
||||
unsigned int irq = vector;
|
||||
unsigned int dest_cpu = first_cpu(cpu_mask);
|
||||
|
||||
entry = (struct msi_desc *)msi_desc[vector];
|
||||
if (!entry || !entry->dev)
|
||||
|
@ -108,9 +111,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
|
|||
pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
|
||||
&address.lo_address.value);
|
||||
address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
|
||||
address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) <<
|
||||
MSI_TARGET_CPU_SHIFT);
|
||||
entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
|
||||
address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
|
||||
MSI_TARGET_CPU_SHIFT);
|
||||
entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
|
||||
pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
|
||||
address.lo_address.value);
|
||||
set_native_irq_info(irq, cpu_mask);
|
||||
|
@ -123,9 +126,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
|
|||
|
||||
address.lo_address.value = readl(entry->mask_base + offset);
|
||||
address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
|
||||
address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) <<
|
||||
MSI_TARGET_CPU_SHIFT);
|
||||
entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
|
||||
address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
|
||||
MSI_TARGET_CPU_SHIFT);
|
||||
entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
|
||||
writel(address.lo_address.value, entry->mask_base + offset);
|
||||
set_native_irq_info(irq, cpu_mask);
|
||||
break;
|
||||
|
@ -259,14 +262,15 @@ static void msi_data_init(struct msg_data *msi_data,
|
|||
static void msi_address_init(struct msg_address *msi_address)
|
||||
{
|
||||
unsigned int dest_id;
|
||||
unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU);
|
||||
|
||||
memset(msi_address, 0, sizeof(struct msg_address));
|
||||
msi_address->hi_address = (u32)0;
|
||||
dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT);
|
||||
msi_address->lo_address.u.dest_mode = MSI_DEST_MODE;
|
||||
msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE;
|
||||
msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE;
|
||||
msi_address->lo_address.u.dest_id = dest_id;
|
||||
msi_address->lo_address.value |= (MSI_TARGET_CPU << MSI_TARGET_CPU_SHIFT);
|
||||
msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT);
|
||||
}
|
||||
|
||||
static int msi_free_vector(struct pci_dev* dev, int vector, int reassign);
|
||||
|
|
|
@ -91,9 +91,7 @@ acpi_query_osc (
|
|||
static acpi_status
|
||||
acpi_run_osc (
|
||||
acpi_handle handle,
|
||||
u32 level,
|
||||
void *context,
|
||||
void **retval )
|
||||
void *context)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_object_list input;
|
||||
|
@ -184,7 +182,7 @@ EXPORT_SYMBOL(pci_osc_support_set);
|
|||
*
|
||||
* Attempt to take control from Firmware on requested control bits.
|
||||
**/
|
||||
acpi_status pci_osc_control_set(u32 flags)
|
||||
acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 ctrlset;
|
||||
|
@ -198,10 +196,7 @@ acpi_status pci_osc_control_set(u32 flags)
|
|||
return AE_SUPPORT;
|
||||
}
|
||||
ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset;
|
||||
status = acpi_get_devices ( PCI_ROOT_HID_STRING,
|
||||
acpi_run_osc,
|
||||
ctrlset_buf,
|
||||
NULL );
|
||||
status = acpi_run_osc(handle, ctrlset_buf);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ struct pci_dynid {
|
|||
* Adds a new dynamic pci device ID to this driver,
|
||||
* and causes the driver to probe for all devices again.
|
||||
*/
|
||||
static inline ssize_t
|
||||
static ssize_t
|
||||
store_new_id(struct device_driver *driver, const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dynid *dynid;
|
||||
|
@ -364,15 +364,16 @@ static struct kobj_type pci_driver_kobj_type = {
|
|||
};
|
||||
|
||||
/**
|
||||
* pci_register_driver - register a new pci driver
|
||||
* __pci_register_driver - register a new pci driver
|
||||
* @drv: the driver structure to register
|
||||
* @owner: owner module of drv
|
||||
*
|
||||
* Adds the driver structure to the list of registered drivers.
|
||||
* Returns a negative value on error, otherwise 0.
|
||||
* If no error occurred, the driver remains registered even if
|
||||
* no device was claimed during registration.
|
||||
*/
|
||||
int pci_register_driver(struct pci_driver *drv)
|
||||
int __pci_register_driver(struct pci_driver *drv, struct module *owner)
|
||||
{
|
||||
int error;
|
||||
|
||||
|
@ -389,7 +390,7 @@ int pci_register_driver(struct pci_driver *drv)
|
|||
printk(KERN_WARNING "Warning: PCI driver %s has a struct "
|
||||
"device_driver shutdown method, please update!\n",
|
||||
drv->name);
|
||||
drv->driver.owner = drv->owner;
|
||||
drv->driver.owner = owner;
|
||||
drv->driver.kobj.ktype = &pci_driver_kobj_type;
|
||||
|
||||
spin_lock_init(&drv->dynids.lock);
|
||||
|
@ -526,7 +527,7 @@ postcore_initcall(pci_driver_init);
|
|||
|
||||
EXPORT_SYMBOL(pci_match_id);
|
||||
EXPORT_SYMBOL(pci_match_device);
|
||||
EXPORT_SYMBOL(pci_register_driver);
|
||||
EXPORT_SYMBOL(__pci_register_driver);
|
||||
EXPORT_SYMBOL(pci_unregister_driver);
|
||||
EXPORT_SYMBOL(pci_dev_driver);
|
||||
EXPORT_SYMBOL(pci_bus_type);
|
||||
|
|
|
@ -63,11 +63,38 @@ pci_max_busnr(void)
|
|||
return max;
|
||||
}
|
||||
|
||||
static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap)
|
||||
{
|
||||
u8 id;
|
||||
int ttl = 48;
|
||||
|
||||
while (ttl--) {
|
||||
pci_bus_read_config_byte(bus, devfn, pos, &pos);
|
||||
if (pos < 0x40)
|
||||
break;
|
||||
pos &= ~3;
|
||||
pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID,
|
||||
&id);
|
||||
if (id == 0xff)
|
||||
break;
|
||||
if (id == cap)
|
||||
return pos;
|
||||
pos += PCI_CAP_LIST_NEXT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
|
||||
{
|
||||
return __pci_find_next_cap(dev->bus, dev->devfn,
|
||||
pos + PCI_CAP_LIST_NEXT, cap);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_find_next_capability);
|
||||
|
||||
static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap)
|
||||
{
|
||||
u16 status;
|
||||
u8 pos, id;
|
||||
int ttl = 48;
|
||||
u8 pos;
|
||||
|
||||
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
|
||||
if (!(status & PCI_STATUS_CAP_LIST))
|
||||
|
@ -76,24 +103,15 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
|
|||
switch (hdr_type) {
|
||||
case PCI_HEADER_TYPE_NORMAL:
|
||||
case PCI_HEADER_TYPE_BRIDGE:
|
||||
pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
|
||||
pos = PCI_CAPABILITY_LIST;
|
||||
break;
|
||||
case PCI_HEADER_TYPE_CARDBUS:
|
||||
pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
|
||||
pos = PCI_CB_CAPABILITY_LIST;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
while (ttl-- && pos >= 0x40) {
|
||||
pos &= ~3;
|
||||
pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id);
|
||||
if (id == 0xff)
|
||||
break;
|
||||
if (id == cap)
|
||||
return pos;
|
||||
pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos);
|
||||
}
|
||||
return 0;
|
||||
return __pci_find_next_cap(bus, devfn, pos, cap);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -462,11 +462,11 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
|
|||
|
||||
pci_read_config_word(dev, 0x70, &hm);
|
||||
hm &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c868 HW-mon");
|
||||
quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon");
|
||||
|
||||
pci_read_config_dword(dev, 0x90, &smb);
|
||||
smb &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c868 SMB");
|
||||
quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB");
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi );
|
||||
|
||||
|
@ -1243,6 +1243,21 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
|
|||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
|
||||
|
||||
|
||||
static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
|
||||
{
|
||||
/* rev 1 ncr53c810 chips don't set the class at all which means
|
||||
* they don't get their resources remapped. Fix that here.
|
||||
*/
|
||||
|
||||
if (dev->class == PCI_CLASS_NOT_DEFINED) {
|
||||
printk(KERN_INFO "NCR 53c810 rev 1 detected, setting PCI class.\n");
|
||||
dev->class = PCI_CLASS_STORAGE_SCSI;
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
|
||||
|
||||
|
||||
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
|
||||
{
|
||||
while (f < end) {
|
||||
|
|
|
@ -1970,7 +1970,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
|
|||
static struct pci_driver goku_pci_driver = {
|
||||
.name = (char *) driver_name,
|
||||
.id_table = pci_ids,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
.probe = goku_probe,
|
||||
.remove = goku_remove,
|
||||
|
|
|
@ -2948,7 +2948,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
|
|||
static struct pci_driver net2280_pci_driver = {
|
||||
.name = (char *) driver_name,
|
||||
.id_table = pci_ids,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
.probe = net2280_probe,
|
||||
.remove = net2280_remove,
|
||||
|
|
|
@ -383,7 +383,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
|
|||
static struct pci_driver ehci_pci_driver = {
|
||||
.name = (char *) hcd_name,
|
||||
.id_table = pci_ids,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
.probe = usb_hcd_pci_probe,
|
||||
.remove = usb_hcd_pci_remove,
|
||||
|
|
|
@ -218,7 +218,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
|
|||
static struct pci_driver ohci_pci_driver = {
|
||||
.name = (char *) hcd_name,
|
||||
.id_table = pci_ids,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
.probe = usb_hcd_pci_probe,
|
||||
.remove = usb_hcd_pci_remove,
|
||||
|
|
|
@ -831,7 +831,6 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
|
|||
static struct pci_driver uhci_pci_driver = {
|
||||
.name = (char *)hcd_name,
|
||||
.id_table = uhci_pci_ids,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
.probe = usb_hcd_pci_probe,
|
||||
.remove = usb_hcd_pci_remove,
|
||||
|
|
|
@ -10,13 +10,6 @@
|
|||
#include <mach_apic.h>
|
||||
|
||||
#define LAST_DEVICE_VECTOR 232
|
||||
#define MSI_DEST_MODE MSI_LOGICAL_MODE
|
||||
#define MSI_TARGET_CPU_SHIFT 12
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define MSI_TARGET_CPU logical_smp_processor_id()
|
||||
#else
|
||||
#define MSI_TARGET_CPU cpu_to_logical_apicid(first_cpu(cpu_online_map))
|
||||
#endif
|
||||
#define MSI_TARGET_CPU_SHIFT 12
|
||||
|
||||
#endif /* ASM_MSI_H */
|
||||
|
|
|
@ -45,6 +45,8 @@ extern void unlock_ipi_call_lock(void);
|
|||
#define MAX_APICID 256
|
||||
extern u8 x86_cpu_to_apicid[];
|
||||
|
||||
#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu]
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
extern void cpu_exit_clear(void);
|
||||
extern void cpu_uninit(void);
|
||||
|
@ -92,6 +94,10 @@ extern int __cpu_disable(void);
|
|||
extern void __cpu_die(unsigned int cpu);
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#else /* CONFIG_SMP */
|
||||
|
||||
#define cpu_physical_id(cpu) boot_cpu_physical_apicid
|
||||
|
||||
#define NO_PROC_ID 0xFF /* No processor magic marker */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
* 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
|
||||
* <anil.s.keshavamurthy@intel.com> adopted from
|
||||
* include/asm-x86_64/kdebug.h
|
||||
*
|
||||
* 2005-Oct Keith Owens <kaos@sgi.com>. Expand notify_die to cover more
|
||||
* events.
|
||||
*/
|
||||
#include <linux/notifier.h>
|
||||
|
||||
|
@ -35,13 +38,36 @@ struct die_args {
|
|||
int signr;
|
||||
};
|
||||
|
||||
int register_die_notifier(struct notifier_block *nb);
|
||||
extern int register_die_notifier(struct notifier_block *);
|
||||
extern int unregister_die_notifier(struct notifier_block *);
|
||||
extern struct notifier_block *ia64die_chain;
|
||||
|
||||
enum die_val {
|
||||
DIE_BREAK = 1,
|
||||
DIE_SS,
|
||||
DIE_FAULT,
|
||||
DIE_OOPS,
|
||||
DIE_PAGE_FAULT,
|
||||
DIE_MACHINE_HALT,
|
||||
DIE_MACHINE_RESTART,
|
||||
DIE_MCA_MONARCH_ENTER,
|
||||
DIE_MCA_MONARCH_PROCESS,
|
||||
DIE_MCA_MONARCH_LEAVE,
|
||||
DIE_MCA_SLAVE_ENTER,
|
||||
DIE_MCA_SLAVE_PROCESS,
|
||||
DIE_MCA_SLAVE_LEAVE,
|
||||
DIE_MCA_RENDZVOUS_ENTER,
|
||||
DIE_MCA_RENDZVOUS_PROCESS,
|
||||
DIE_MCA_RENDZVOUS_LEAVE,
|
||||
DIE_INIT_MONARCH_ENTER,
|
||||
DIE_INIT_MONARCH_PROCESS,
|
||||
DIE_INIT_MONARCH_LEAVE,
|
||||
DIE_INIT_SLAVE_ENTER,
|
||||
DIE_INIT_SLAVE_PROCESS,
|
||||
DIE_INIT_SLAVE_LEAVE,
|
||||
DIE_KDEBUG_ENTER,
|
||||
DIE_KDEBUG_LEAVE,
|
||||
DIE_KDUMP_ENTER,
|
||||
DIE_KDUMP_LEAVE,
|
||||
};
|
||||
|
||||
static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs,
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Routines to manage the allocation of task context numbers. Task context numbers are
|
||||
* used to reduce or eliminate the need to perform TLB flushes due to context switches.
|
||||
* Context numbers are implemented using ia-64 region ids. Since the IA-64 TLB does not
|
||||
* consider the region number when performing a TLB lookup, we need to assign a unique
|
||||
* region id to each region in a process. We use the least significant three bits in a
|
||||
* region id for this purpose.
|
||||
* Routines to manage the allocation of task context numbers. Task context
|
||||
* numbers are used to reduce or eliminate the need to perform TLB flushes
|
||||
* due to context switches. Context numbers are implemented using ia-64
|
||||
* region ids. Since the IA-64 TLB does not consider the region number when
|
||||
* performing a TLB lookup, we need to assign a unique region id to each
|
||||
* region in a process. We use the least significant three bits in aregion
|
||||
* id for this purpose.
|
||||
*/
|
||||
|
||||
#define IA64_REGION_ID_KERNEL 0 /* the kernel's region id (tlb.c depends on this being 0) */
|
||||
|
@ -32,13 +33,17 @@
|
|||
struct ia64_ctx {
|
||||
spinlock_t lock;
|
||||
unsigned int next; /* next context number to use */
|
||||
unsigned int limit; /* next >= limit => must call wrap_mmu_context() */
|
||||
unsigned int max_ctx; /* max. context value supported by all CPUs */
|
||||
unsigned int limit; /* available free range */
|
||||
unsigned int max_ctx; /* max. context value supported by all CPUs */
|
||||
/* call wrap_mmu_context when next >= max */
|
||||
unsigned long *bitmap; /* bitmap size is max_ctx+1 */
|
||||
unsigned long *flushmap;/* pending rid to be flushed */
|
||||
};
|
||||
|
||||
extern struct ia64_ctx ia64_ctx;
|
||||
DECLARE_PER_CPU(u8, ia64_need_tlb_flush);
|
||||
|
||||
extern void mmu_context_init (void);
|
||||
extern void wrap_mmu_context (struct mm_struct *mm);
|
||||
|
||||
static inline void
|
||||
|
@ -47,10 +52,10 @@ enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk)
|
|||
}
|
||||
|
||||
/*
|
||||
* When the context counter wraps around all TLBs need to be flushed because an old
|
||||
* context number might have been reused. This is signalled by the ia64_need_tlb_flush
|
||||
* per-CPU variable, which is checked in the routine below. Called by activate_mm().
|
||||
* <efocht@ess.nec.de>
|
||||
* When the context counter wraps around all TLBs need to be flushed because
|
||||
* an old context number might have been reused. This is signalled by the
|
||||
* ia64_need_tlb_flush per-CPU variable, which is checked in the routine
|
||||
* below. Called by activate_mm(). <efocht@ess.nec.de>
|
||||
*/
|
||||
static inline void
|
||||
delayed_tlb_flush (void)
|
||||
|
@ -60,11 +65,9 @@ delayed_tlb_flush (void)
|
|||
|
||||
if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) {
|
||||
spin_lock_irqsave(&ia64_ctx.lock, flags);
|
||||
{
|
||||
if (__ia64_per_cpu_var(ia64_need_tlb_flush)) {
|
||||
local_flush_tlb_all();
|
||||
__ia64_per_cpu_var(ia64_need_tlb_flush) = 0;
|
||||
}
|
||||
if (__ia64_per_cpu_var(ia64_need_tlb_flush)) {
|
||||
local_flush_tlb_all();
|
||||
__ia64_per_cpu_var(ia64_need_tlb_flush) = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&ia64_ctx.lock, flags);
|
||||
}
|
||||
|
@ -76,20 +79,27 @@ get_mmu_context (struct mm_struct *mm)
|
|||
unsigned long flags;
|
||||
nv_mm_context_t context = mm->context;
|
||||
|
||||
if (unlikely(!context)) {
|
||||
spin_lock_irqsave(&ia64_ctx.lock, flags);
|
||||
{
|
||||
/* re-check, now that we've got the lock: */
|
||||
context = mm->context;
|
||||
if (context == 0) {
|
||||
cpus_clear(mm->cpu_vm_mask);
|
||||
if (ia64_ctx.next >= ia64_ctx.limit)
|
||||
wrap_mmu_context(mm);
|
||||
mm->context = context = ia64_ctx.next++;
|
||||
}
|
||||
if (likely(context))
|
||||
goto out;
|
||||
|
||||
spin_lock_irqsave(&ia64_ctx.lock, flags);
|
||||
/* re-check, now that we've got the lock: */
|
||||
context = mm->context;
|
||||
if (context == 0) {
|
||||
cpus_clear(mm->cpu_vm_mask);
|
||||
if (ia64_ctx.next >= ia64_ctx.limit) {
|
||||
ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap,
|
||||
ia64_ctx.max_ctx, ia64_ctx.next);
|
||||
ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap,
|
||||
ia64_ctx.max_ctx, ia64_ctx.next);
|
||||
if (ia64_ctx.next >= ia64_ctx.max_ctx)
|
||||
wrap_mmu_context(mm);
|
||||
}
|
||||
spin_unlock_irqrestore(&ia64_ctx.lock, flags);
|
||||
mm->context = context = ia64_ctx.next++;
|
||||
__set_bit(context, ia64_ctx.bitmap);
|
||||
}
|
||||
spin_unlock_irqrestore(&ia64_ctx.lock, flags);
|
||||
out:
|
||||
/*
|
||||
* Ensure we're not starting to use "context" before any old
|
||||
* uses of it are gone from our TLB.
|
||||
|
@ -100,8 +110,8 @@ get_mmu_context (struct mm_struct *mm)
|
|||
}
|
||||
|
||||
/*
|
||||
* Initialize context number to some sane value. MM is guaranteed to be a brand-new
|
||||
* address-space, so no TLB flushing is needed, ever.
|
||||
* Initialize context number to some sane value. MM is guaranteed to be a
|
||||
* brand-new address-space, so no TLB flushing is needed, ever.
|
||||
*/
|
||||
static inline int
|
||||
init_new_context (struct task_struct *p, struct mm_struct *mm)
|
||||
|
@ -162,7 +172,10 @@ activate_context (struct mm_struct *mm)
|
|||
if (!cpu_isset(smp_processor_id(), mm->cpu_vm_mask))
|
||||
cpu_set(smp_processor_id(), mm->cpu_vm_mask);
|
||||
reload_context(context);
|
||||
/* in the unlikely event of a TLB-flush by another thread, redo the load: */
|
||||
/*
|
||||
* in the unlikely event of a TLB-flush by another thread,
|
||||
* redo the load.
|
||||
*/
|
||||
} while (unlikely(context != mm->context));
|
||||
}
|
||||
|
||||
|
@ -175,8 +188,8 @@ static inline void
|
|||
activate_mm (struct mm_struct *prev, struct mm_struct *next)
|
||||
{
|
||||
/*
|
||||
* We may get interrupts here, but that's OK because interrupt handlers cannot
|
||||
* touch user-space.
|
||||
* We may get interrupts here, but that's OK because interrupt
|
||||
* handlers cannot touch user-space.
|
||||
*/
|
||||
ia64_set_kr(IA64_KR_PT_BASE, __pa(next->pgd));
|
||||
activate_context(next);
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
static inline void set_intr_gate (int nr, void *func) {}
|
||||
#define IO_APIC_VECTOR(irq) (irq)
|
||||
#define ack_APIC_irq ia64_eoi
|
||||
#define cpu_mask_to_apicid(mask) cpu_physical_id(first_cpu(mask))
|
||||
#define MSI_DEST_MODE MSI_PHYSICAL_MODE
|
||||
#define MSI_TARGET_CPU ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
|
||||
#define MSI_TARGET_CPU_SHIFT 4
|
||||
|
||||
#endif /* ASM_MSI_H */
|
||||
|
|
|
@ -51,6 +51,7 @@ flush_tlb_mm (struct mm_struct *mm)
|
|||
if (!mm)
|
||||
return;
|
||||
|
||||
set_bit(mm->context, ia64_ctx.flushmap);
|
||||
mm->context = 0;
|
||||
|
||||
if (atomic_read(&mm->mm_users) == 0)
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
#include <asm/smp.h>
|
||||
|
||||
#define LAST_DEVICE_VECTOR 232
|
||||
#define MSI_DEST_MODE MSI_LOGICAL_MODE
|
||||
#define MSI_TARGET_CPU_SHIFT 12
|
||||
#define MSI_TARGET_CPU logical_smp_processor_id()
|
||||
#define MSI_TARGET_CPU_SHIFT 12
|
||||
|
||||
#endif /* ASM_MSI_H */
|
||||
|
|
|
@ -135,5 +135,11 @@ static __inline int logical_smp_processor_id(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define cpu_physical_id(cpu) x86_cpu_to_apicid[cpu]
|
||||
#else
|
||||
#define cpu_physical_id(cpu) boot_cpu_id
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1329,7 +1329,8 @@ void ide_init_disk(struct gendisk *, ide_drive_t *);
|
|||
extern int ideprobe_init(void);
|
||||
|
||||
extern void ide_scan_pcibus(int scan_direction) __init;
|
||||
extern int ide_pci_register_driver(struct pci_driver *driver);
|
||||
extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner);
|
||||
#define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE)
|
||||
extern void ide_pci_unregister_driver(struct pci_driver *driver);
|
||||
void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *);
|
||||
extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d);
|
||||
|
|
|
@ -47,14 +47,15 @@
|
|||
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
extern acpi_status pci_osc_control_set(u32 flags);
|
||||
extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
|
||||
extern acpi_status pci_osc_support_set(u32 flags);
|
||||
#else
|
||||
#if !defined(acpi_status)
|
||||
typedef u32 acpi_status;
|
||||
#define AE_ERROR (acpi_status) (0x0001)
|
||||
#endif
|
||||
static inline acpi_status pci_osc_control_set(u32 flags) {return AE_ERROR;}
|
||||
static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
|
||||
{return AE_ERROR;}
|
||||
static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -236,7 +236,6 @@ struct module;
|
|||
struct pci_driver {
|
||||
struct list_head node;
|
||||
char *name;
|
||||
struct module *owner;
|
||||
const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */
|
||||
int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
|
||||
void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
|
||||
|
@ -338,6 +337,7 @@ struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, const
|
|||
struct pci_dev *pci_find_device_reverse (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);
|
||||
int pci_find_ext_capability (struct pci_dev *dev, int cap);
|
||||
struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
|
||||
|
||||
|
@ -432,8 +432,13 @@ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
|
|||
void *alignf_data);
|
||||
void pci_enable_bridges(struct pci_bus *bus);
|
||||
|
||||
/* New-style probing supporting hot-pluggable devices */
|
||||
int pci_register_driver(struct pci_driver *);
|
||||
/* Proper probing supporting hot-pluggable devices */
|
||||
int __pci_register_driver(struct pci_driver *, struct module *);
|
||||
static inline int pci_register_driver(struct pci_driver *driver)
|
||||
{
|
||||
return __pci_register_driver(driver, THIS_MODULE);
|
||||
}
|
||||
|
||||
void pci_unregister_driver(struct pci_driver *);
|
||||
void pci_remove_behind_bridge(struct pci_dev *);
|
||||
struct pci_driver *pci_dev_driver(const struct pci_dev *);
|
||||
|
@ -547,9 +552,11 @@ static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
|
|||
static inline void pci_disable_device(struct pci_dev *dev) { }
|
||||
static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; }
|
||||
static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;}
|
||||
static inline int __pci_register_driver(struct pci_driver *drv, struct module *owner) { return 0;}
|
||||
static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
|
||||
static inline void pci_unregister_driver(struct pci_driver *drv) { }
|
||||
static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
|
||||
static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
|
||||
static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
|
||||
static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
|
||||
|
||||
|
|
|
@ -1067,7 +1067,6 @@ MODULE_DEVICE_TABLE(pci, snd_ad1889_ids);
|
|||
|
||||
static struct pci_driver ad1889_pci = {
|
||||
.name = "AD1889 Audio",
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = snd_ad1889_ids,
|
||||
.probe = snd_ad1889_probe,
|
||||
.remove = __devexit_p(snd_ad1889_remove),
|
||||
|
|
|
@ -2403,7 +2403,6 @@ static void __devexit snd_ali_remove(struct pci_dev *pci)
|
|||
|
||||
static struct pci_driver driver = {
|
||||
.name = "ALI 5451",
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = snd_ali_ids,
|
||||
.probe = snd_ali_probe,
|
||||
.remove = __devexit_p(snd_ali_remove),
|
||||
|
|
|
@ -768,7 +768,6 @@ static void __devexit snd_card_als4000_remove(struct pci_dev *pci)
|
|||
|
||||
static struct pci_driver driver = {
|
||||
.name = "ALS4000",
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = snd_als4000_ids,
|
||||
.probe = snd_card_als4000_probe,
|
||||
.remove = __devexit_p(snd_card_als4000_remove),
|
||||
|
|
|
@ -1635,7 +1635,6 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
|
|||
|
||||
static struct pci_driver driver = {
|
||||
.name = "ATI IXP AC97 controller",
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = snd_atiixp_ids,
|
||||
.probe = snd_atiixp_probe,
|
||||
.remove = __devexit_p(snd_atiixp_remove),
|
||||
|
|
|
@ -1309,7 +1309,6 @@ static void __devexit snd_atiixp_remove(struct pci_dev *pci)
|
|||
|
||||
static struct pci_driver driver = {
|
||||
.name = "ATI IXP MC97 controller",
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = snd_atiixp_ids,
|
||||
.probe = snd_atiixp_probe,
|
||||
.remove = __devexit_p(snd_atiixp_remove),
|
||||
|
|
|
@ -373,7 +373,6 @@ static void __devexit snd_vortex_remove(struct pci_dev *pci)
|
|||
// pci_driver definition
|
||||
static struct pci_driver driver = {
|
||||
.name = CARD_NAME_SHORT,
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = snd_vortex_ids,
|
||||
.probe = snd_vortex_probe,
|
||||
.remove = __devexit_p(snd_vortex_remove),
|
||||
|
|
|
@ -1838,7 +1838,6 @@ snd_azf3328_remove(struct pci_dev *pci)
|
|||
|
||||
static struct pci_driver driver = {
|
||||
.name = "AZF3328",
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = snd_azf3328_ids,
|
||||
.probe = snd_azf3328_probe,
|
||||
.remove = __devexit_p(snd_azf3328_remove),
|
||||
|
|
|
@ -897,14 +897,13 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci)
|
|||
/* default entries for all Bt87x cards - it's not exported */
|
||||
/* driver_data is set to 0 to call detection */
|
||||
static struct pci_device_id snd_bt87x_default_ids[] = {
|
||||
BT_DEVICE(878, PCI_ANY_ID, PCI_ANY_ID, 0),
|
||||
BT_DEVICE(879, PCI_ANY_ID, PCI_ANY_ID, 0),
|
||||
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0),
|
||||
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct pci_driver driver = {
|
||||
.name = "Bt87x",
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = snd_bt87x_ids,
|
||||
.probe = snd_bt87x_probe,
|
||||
.remove = __devexit_p(snd_bt87x_remove),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue