Commit edb74dc6 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/linux-2.5_work
parents 94934195 456f17cd
......@@ -299,6 +299,8 @@ KAO -->
EHCI, OHCI, or UHCI.
</para>
!Edrivers/usb/core/hcd.c
!Edrivers/usb/core/hcd-pci.c
!Edrivers/usb/core/buffer.c
</sect1>
</chapter>
......
......@@ -283,10 +283,6 @@ source drivers/block/Config.in
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
mainmenu_option next_comment
comment 'ATA/ATAPI/MFM/RLL support'
......@@ -314,6 +310,8 @@ if [ "$CONFIG_PCI" = "y" ]; then
fi
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......
......@@ -135,12 +135,6 @@ source drivers/block/Config.in
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
source drivers/telephony/Config.in
mainmenu_option next_comment
comment 'ATA/IDE/MFM/RLL support'
......@@ -168,6 +162,8 @@ source drivers/ieee1394/Config.in
source drivers/message/i2o/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......@@ -187,6 +183,8 @@ source net/irda/Config.in
source drivers/isdn/Config.in
source drivers/telephony/Config.in
mainmenu_option next_comment
comment 'Old CD-ROM drivers (not SCSI, not IDE)'
......
......@@ -332,12 +332,6 @@ endmenu
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
source drivers/telephony/Config.in
source drivers/message/fusion/Config.in
source drivers/ieee1394/Config.in
......@@ -345,6 +339,8 @@ source drivers/ieee1394/Config.in
source drivers/message/i2o/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......@@ -364,6 +360,8 @@ source net/irda/Config.in
source drivers/isdn/Config.in
source drivers/telephony/Config.in
#
# input before char - char/joystick depends on it. As does USB.
#
......
......@@ -214,6 +214,7 @@
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/system.h>
......@@ -419,6 +420,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
static struct apm_user * user_list;
static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
static char driver_version[] = "1.16"; /* no spaces */
......@@ -568,7 +570,12 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
{
APM_DECL_SEGS
unsigned long flags;
unsigned long flags;
int cpu = smp_processor_id();
struct desc_struct save_desc_40;
save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
local_save_flags(flags);
APM_DO_CLI;
......@@ -591,6 +598,7 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
: "memory", "cc");
APM_DO_RESTORE_SEGS;
local_irq_restore(flags);
cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
return *eax & 0xff;
}
......@@ -613,6 +621,11 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
u8 error;
APM_DECL_SEGS
unsigned long flags;
int cpu = smp_processor_id();
struct desc_struct save_desc_40;
save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
local_save_flags(flags);
APM_DO_CLI;
......@@ -639,6 +652,7 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
}
APM_DO_RESTORE_SEGS;
local_irq_restore(flags);
cpu_gdt_table[smp_processor_id()][0x40 / 8] = save_desc_40;
return error;
}
......@@ -931,9 +945,9 @@ static void handle_poweroff (int key, struct pt_regs *pt_regs,
}
static struct sysrq_key_op sysrq_poweroff_op = {
handler: handle_poweroff,
help_msg: "Off",
action_msg: "Power Off\n"
.handler = handle_poweroff,
.help_msg = "Off",
.action_msg = "Power Off\n"
};
......@@ -1826,12 +1840,12 @@ __setup("apm=", apm_setup);
#endif
static struct file_operations apm_bios_fops = {
owner: THIS_MODULE,
read: do_read,
poll: do_poll,
ioctl: do_ioctl,
open: do_open,
release: do_release,
.owner = THIS_MODULE,
.read = do_read,
.poll = do_poll,
.ioctl = do_ioctl,
.open = do_open,
.release = do_release,
};
static struct miscdevice apm_device = {
......@@ -1927,13 +1941,13 @@ static int __init apm_init(void)
* NOTE: on SMP we call into the APM BIOS only on CPU#0, so it's
* enough to modify CPU#0's GDT.
*/
for (i = 0; i < NR_CPUS; i++) {
set_base(cpu_gdt_table[i][APM_40 >> 3],
__va((unsigned long)0x40 << 4));
_set_limit((char *)&cpu_gdt_table[i][APM_40 >> 3], 4095 - (0x40 << 4));
set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
apm_bios_entry.offset = apm_info.bios.offset;
apm_bios_entry.segment = APM_CS;
apm_bios_entry.offset = apm_info.bios.offset;
apm_bios_entry.segment = APM_CS;
for (i = 0; i < NR_CPUS; i++) {
set_base(cpu_gdt_table[i][APM_CS >> 3],
__va((unsigned long)apm_info.bios.cseg << 4));
set_base(cpu_gdt_table[i][APM_CS_16 >> 3],
......
......@@ -307,7 +307,7 @@ static void do_mce_timer(void *data)
}
static struct tq_struct mce_task = {
routine: do_mce_timer
.routine = do_mce_timer
};
static void mce_timerfunc (unsigned long data)
......
......@@ -189,8 +189,8 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
}
static struct cpu_dev amd_cpu_dev __initdata = {
c_vendor: "AMD",
c_ident: { "AuthenticAMD" },
.c_vendor = "AMD",
.c_ident = { "AuthenticAMD" },
c_models: {
{ X86_VENDOR_AMD, 4,
{
......@@ -203,9 +203,9 @@ static struct cpu_dev amd_cpu_dev __initdata = {
}
},
},
c_init: init_amd,
c_identify: amd_identify,
c_size_cache: amd_size_cache,
.c_init = init_amd,
.c_identify = amd_identify,
.c_size_cache = amd_size_cache,
};
int __init amd_init_cpu(void)
......
......@@ -411,10 +411,10 @@ static unsigned int centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size
}
static struct cpu_dev centaur_cpu_dev __initdata = {
c_vendor: "Centaur",
c_ident: { "CentaurHauls" },
c_init: init_centaur,
c_size_cache: centaur_size_cache,
.c_vendor = "Centaur",
.c_ident = { "CentaurHauls" },
.c_init = init_centaur,
.c_size_cache = centaur_size_cache,
};
int __init centaur_init_cpu(void)
......
......@@ -31,7 +31,7 @@ static void default_init(struct cpuinfo_x86 * c)
}
static struct cpu_dev default_cpu = {
c_init: default_init,
.c_init = default_init,
};
static struct cpu_dev * this_cpu = &default_cpu;
......
......@@ -322,10 +322,10 @@ static void cyrix_identify(struct cpuinfo_x86 * c)
}
static struct cpu_dev cyrix_cpu_dev __initdata = {
c_vendor: "Cyrix",
c_ident: { "CyrixInstead" },
c_init: init_cyrix,
c_identify: cyrix_identify,
.c_vendor = "Cyrix",
.c_ident = { "CyrixInstead" },
.c_init = init_cyrix,
.c_identify = cyrix_identify,
};
int __init cyrix_init_cpu(void)
......@@ -337,10 +337,10 @@ int __init cyrix_init_cpu(void)
//early_arch_initcall(cyrix_init_cpu);
static struct cpu_dev nsc_cpu_dev __initdata = {
c_vendor: "NSC",
c_ident: { "Geode by NSC" },
c_init: init_cyrix,
c_identify: generic_identify,
.c_vendor = "NSC",
.c_ident = { "Geode by NSC" },
.c_init = init_cyrix,
.c_identify = generic_identify,
};
int __init nsc_init_cpu(void)
......
......@@ -327,8 +327,8 @@ static unsigned int intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
}
static struct cpu_dev intel_cpu_dev __initdata = {
c_vendor: "Intel",
c_ident: { "GenuineIntel" },
.c_vendor = "Intel",
.c_ident = { "GenuineIntel" },
c_models: {
{ X86_VENDOR_INTEL, 4,
{
......@@ -375,9 +375,9 @@ static struct cpu_dev intel_cpu_dev __initdata = {
}
},
},
c_init: init_intel,
c_identify: generic_identify,
c_size_cache: intel_size_cache,
.c_init = init_intel,
.c_identify = generic_identify,
.c_size_cache = intel_size_cache,
};
__init int intel_cpu_init(void)
......
......@@ -42,13 +42,13 @@ static void nexgen_identify(struct cpuinfo_x86 * c)
}
static struct cpu_dev nexgen_cpu_dev __initdata = {
c_vendor: "Nexgen",
c_ident: { "NexGenDriven" },
.c_vendor = "Nexgen",
.c_ident = { "NexGenDriven" },
c_models: {
{ X86_VENDOR_NEXGEN,5, { [1] "Nx586" } },
},
c_init: init_nexgen,
c_identify: nexgen_identify,
.c_init = init_nexgen,
.c_identify = nexgen_identify,
};
int __init nexgen_init_cpu(void)
......
......@@ -119,8 +119,8 @@ static void c_stop(struct seq_file *m, void *v)
{
}
struct seq_operations cpuinfo_op = {
start: c_start,
next: c_next,
stop: c_stop,
show: show_cpuinfo,
.start = c_start,
.next = c_next,
.stop = c_stop,
.show = show_cpuinfo,
};
......@@ -29,8 +29,8 @@ static void __init init_rise(struct cpuinfo_x86 *c)
}
static struct cpu_dev rise_cpu_dev __initdata = {
c_vendor: "Rise",
c_ident: { "RiseRiseRise" },
.c_vendor = "Rise",
.c_ident = { "RiseRiseRise" },
c_models: {
{ X86_VENDOR_RISE, 5,
{
......@@ -41,7 +41,7 @@ static struct cpu_dev rise_cpu_dev __initdata = {
}
},
},
c_init: init_rise,
.c_init = init_rise,
};
int __init rise_init_cpu(void)
......
......@@ -80,10 +80,10 @@ static void transmeta_identify(struct cpuinfo_x86 * c)
}
static struct cpu_dev transmeta_cpu_dev __initdata = {
c_vendor: "Transmeta",
c_ident: { "GenuineTMx86", "TransmetaCPU" },
c_init: init_transmeta,
c_identify: transmeta_identify,
.c_vendor = "Transmeta",
.c_ident = { "GenuineTMx86", "TransmetaCPU" },
.c_init = init_transmeta,
.c_identify = transmeta_identify,
};
int __init transmeta_init_cpu(void)
......
......@@ -11,8 +11,8 @@ static void __init init_umc(struct cpuinfo_x86 * c)
}
static struct cpu_dev umc_cpu_dev __initdata = {
c_vendor: "UMC",
c_ident: { "UMC UMC UMC" },
.c_vendor = "UMC",
.c_ident = { "UMC UMC UMC" },
c_models: {
{ X86_VENDOR_UMC, 4,
{
......@@ -21,7 +21,7 @@ static struct cpu_dev umc_cpu_dev __initdata = {
}
},
},
c_init: init_umc,
.c_init = init_umc,
};
int __init umc_init_cpu(void)
......
......@@ -146,10 +146,10 @@ static int cpuid_open(struct inode *inode, struct file *file)
* File operations we support
*/
static struct file_operations cpuid_fops = {
owner: THIS_MODULE,
llseek: cpuid_seek,
read: cpuid_read,
open: cpuid_open,
.owner = THIS_MODULE,
.llseek = cpuid_seek,
.read = cpuid_read,
.open = cpuid_open,
};
int __init cpuid_init(void)
......
......@@ -247,13 +247,13 @@ static int i8259A_resume(struct device *dev, u32 level)
}
static struct device_driver driver_i8259A = {
resume: i8259A_resume,
.resume = i8259A_resume,
};
static struct device device_i8259A = {
name: "i8259A",
bus_id: "0020",
driver: &driver_i8259A,
.name = "i8259A",
.bus_id = "0020",
.driver = &driver_i8259A,
};
static int __init init_8259A_devicefs(void)
......
......@@ -109,17 +109,17 @@ static unsigned int mc_fsize; /* file size of /dev/cpu/microcode */
/* we share file_operations between misc and devfs mechanisms */
static struct file_operations microcode_fops = {
owner: THIS_MODULE,
read: microcode_read,
write: microcode_write,
ioctl: microcode_ioctl,
open: microcode_open,
.owner = THIS_MODULE,
.read = microcode_read,
.write = microcode_write,
.ioctl = microcode_ioctl,
.open = microcode_open,
};
static struct miscdevice microcode_dev = {
minor: MICROCODE_MINOR,
name: "microcode",
fops: &microcode_fops,
.minor = MICROCODE_MINOR,
.name = "microcode",
.fops = &microcode_fops,
};
static devfs_handle_t devfs_handle;
......
......@@ -246,11 +246,11 @@ static int msr_open(struct inode *inode, struct file *file)
* File operations we support
*/
static struct file_operations msr_fops = {
owner: THIS_MODULE,
llseek: msr_seek,
read: msr_read,
write: msr_write,
open: msr_open,
.owner = THIS_MODULE,
.llseek = msr_seek,
.read = msr_read,
.write = msr_write,
.open = msr_open,
};
int __init msr_init(void)
......
......@@ -1836,11 +1836,11 @@ static int mtrr_close (struct inode *ino, struct file *file)
static struct file_operations mtrr_fops =
{
owner: THIS_MODULE,
read: mtrr_read,
write: mtrr_write,
ioctl: mtrr_ioctl,
release: mtrr_close,
.owner = THIS_MODULE,
.read = mtrr_read,
.write = mtrr_write,
.ioctl = mtrr_ioctl,
.release = mtrr_close,
};
# ifdef CONFIG_PROC_FS
......
......@@ -566,6 +566,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
struct_cpy(childregs, regs);
childregs->eax = 0;
childregs->esp = esp;
p->user_vm_lock = NULL;
p->thread.esp = (unsigned long) childregs;
p->thread.esp0 = (unsigned long) (childregs+1);
......@@ -587,6 +588,47 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
IO_BITMAP_BYTES);
}
/*
* The common fastpath:
*/
if (!(clone_flags & (CLONE_SETTLS | CLONE_SETTID | CLONE_RELEASE_VM)))
return 0;
/*
* Set a new TLS for the child thread?
*/
if (clone_flags & CLONE_SETTLS) {
struct desc_struct *desc;
struct user_desc info;
int idx;
if (copy_from_user(&info, (void *)childregs->esi, sizeof(info)))
return -EFAULT;
if (LDT_empty(&info))
return -EINVAL;
idx = info.entry_number;
if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
return -EINVAL;
desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
desc->a = LDT_entry_a(&info);
desc->b = LDT_entry_b(&info);
}
/*
* Notify the child of the TID?
*/
if (clone_flags & CLONE_SETTID)
if (put_user(p->pid, (pid_t *)childregs->edx))
return -EFAULT;
/*
* Does the userspace VM want any unlock on mm_release()?
*/
if (clone_flags & CLONE_RELEASE_VM) {
childregs->esp -= sizeof(0UL);
p->user_vm_lock = (long *) esp;
}
return 0;
}
......
......@@ -968,16 +968,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
{
int apicid, cpu, bit;
if (clustered_apic_mode && (numnodes > 1)) {
printk("Remapping cross-quad port I/O for %d quads\n",
numnodes);
printk("xquad_portio vaddr 0x%08lx, len %08lx\n",
(u_long) xquad_portio,
(u_long) numnodes * XQUAD_PORTIO_LEN);
xquad_portio = ioremap (XQUAD_PORTIO_BASE,
numnodes * XQUAD_PORTIO_LEN);
}
#ifdef CONFIG_MTRR
/* Must be done before other processors booted */
mtrr_init_boot_cpu ();
......@@ -1076,6 +1066,16 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid)
BUG();
if (clustered_apic_mode && (numnodes > 1)) {
printk("Remapping cross-quad port I/O for %d quads\n",
numnodes);
printk("xquad_portio vaddr 0x%08lx, len %08lx\n",
(u_long) xquad_portio,
(u_long) numnodes * XQUAD_PORTIO_LEN);
xquad_portio = ioremap (XQUAD_PORTIO_BASE,
numnodes * XQUAD_PORTIO_LEN);
}
/*
* Scan the CPU present map and fire up the other CPUs via do_boot_cpu
*
......
......@@ -639,8 +639,8 @@ static unsigned long __init calibrate_tsc(void)
}
static struct device device_i8253 = {
name: "i8253",
bus_id: "0040",
.name = "i8253",
.bus_id = "0040",
};
static int time_init_driverfs(void)
......
......@@ -159,7 +159,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
area->phys_addr = phys_addr;
addr = area->addr;
if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
vfree(addr);
vunmap(addr);
return NULL;
}
return (void *) (offset + (char *)addr);
......@@ -215,13 +215,13 @@ void iounmap(void *addr)
struct vm_struct *p;
if (addr <= high_memory)
return;
p = remove_kernel_area((void *) (PAGE_MASK & (unsigned long) addr));
p = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr));
if (!p) {
printk("__iounmap: bad address %p\n", addr);
return;
}
vmfree_area_pages(VMALLOC_VMADDR(p->addr), p->size);
unmap_vm_area(p);
if (p->flags && p->phys_addr < virt_to_phys(high_memory)) {
change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT,
......
......@@ -118,10 +118,6 @@ fi # !HP_SIM
endmenu
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
source drivers/mtd/Config.in
source drivers/pnp/Config.in
......@@ -154,6 +150,10 @@ if [ "$CONFIG_SCSI" != "n" ]; then
fi
endmenu
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
if [ "$CONFIG_NET" = "y" ]; then
mainmenu_option next_comment
......
......@@ -375,8 +375,8 @@ static pmu_config_t pmu_conf; /* PMU configuration */
static pfm_session_t pfm_sessions; /* global sessions information */
static struct proc_dir_entry *perfmon_dir; /* for debug only */
static pfm_stats_t pfm_stats;
int __per_cpu_data pfm_syst_wide;
static int __per_cpu_data pfm_dcr_pp;
DEFINE_PER_CPU(int, pfm_syst_wide);
static DEFINE_PER_CPU(int, pfm_dcr_pp);
/* sysctl() controls */
static pfm_sysctl_t pfm_sysctl;
......@@ -1764,7 +1764,7 @@ pfm_stop(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
ia64_srlz_i();
#ifdef CONFIG_SMP
this_cpu(pfm_dcr_pp) = 0;
__get_cpu_var(pfm_dcr_pp) = 0;
#else
pfm_tasklist_toggle_pp(0);
#endif
......@@ -2172,7 +2172,7 @@ pfm_start(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
if (ctx->ctx_fl_system) {
#ifdef CONFIG_SMP
this_cpu(pfm_dcr_pp) = 1;
__get_cpu_var(pfm_dcr_pp) = 1;
#else
pfm_tasklist_toggle_pp(1);
#endif
......@@ -2227,8 +2227,8 @@ pfm_enable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
ia64_srlz_i();
#ifdef CONFIG_SMP
this_cpu(pfm_syst_wide) = 1;
this_cpu(pfm_dcr_pp) = 0;
__get_cpu_var(pfm_syst_wide) = 1;
__get_cpu_var(pfm_dcr_pp) = 0;
#endif
} else {
/*
......@@ -2980,9 +2980,9 @@ perfmon_proc_info(char *page)
p += sprintf(p, "CPU%d syst_wide : %d\n"
"CPU%d dcr_pp : %d\n",
smp_processor_id(),
this_cpu(pfm_syst_wide),
__get_cpu_var(pfm_syst_wide),
smp_processor_id(),
this_cpu(pfm_dcr_pp));
__get_cpu_var(pfm_dcr_pp));
#endif
LOCK_PFS();
......@@ -3052,7 +3052,7 @@ pfm_syst_wide_update_task(struct task_struct *task, int mode)
/*
* propagate the value of the dcr_pp bit to the psr
*/
ia64_psr(regs)->pp = mode ? this_cpu(pfm_dcr_pp) : 0;
ia64_psr(regs)->pp = mode ? __get_cpu_var(pfm_dcr_pp) : 0;
}
#endif
......@@ -3546,8 +3546,8 @@ pfm_flush_regs (struct task_struct *task)
ia64_srlz_i();
#ifdef CONFIG_SMP
this_cpu(pfm_syst_wide) = 0;
this_cpu(pfm_dcr_pp) = 0;
__get_cpu_var(pfm_syst_wide) = 0;
__get_cpu_var(pfm_dcr_pp) = 0;
#else
pfm_tasklist_toggle_pp(0);
#endif
......
......@@ -194,7 +194,7 @@ ia64_save_extra (struct task_struct *task)
pfm_save_regs(task);
# ifdef CONFIG_SMP
if (this_cpu(pfm_syst_wide))
if (__get_cpu_var(pfm_syst_wide))
pfm_syst_wide_update_task(task, 0);
# endif
#endif
......@@ -216,7 +216,7 @@ ia64_load_extra (struct task_struct *task)
pfm_load_regs(task);
# ifdef CONFIG_SMP
if (this_cpu(pfm_syst_wide)) pfm_syst_wide_update_task(task, 1);
if (__get_cpu_var(pfm_syst_wide)) pfm_syst_wide_update_task(task, 1);
# endif
#endif
......
......@@ -58,7 +58,7 @@ extern char _end;
unsigned long __per_cpu_offset[NR_CPUS];
#endif
struct cpuinfo_ia64 cpu_info __per_cpu_data;
DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info);
unsigned long ia64_phys_stacked_size_p8;
unsigned long ia64_cycles_per_usec;
......
......@@ -80,7 +80,7 @@ static volatile struct call_data_struct *call_data;
#define IPI_CPU_STOP 1
/* This needs to be cacheline aligned because it is written to by *other* CPUs. */
static __u64 ipi_operation __per_cpu_data ____cacheline_aligned;
static DECLARE_PER_CPU(__u64, ipi_operation) ____cacheline_aligned;
static void
stop_this_cpu (void)
......@@ -99,7 +99,7 @@ void
handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
{
int this_cpu = smp_processor_id();
unsigned long *pending_ipis = &this_cpu(ipi_operation);
unsigned long *pending_ipis = &__get_cpu_var(ipi_operation);
unsigned long ops;
/* Count this now; we may make a call that never returns. */
......
......@@ -152,10 +152,6 @@ source drivers/block/Config.in
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
if [ "$CONFIG_MAC" = "y" ]; then
source drivers/input/Config.in
fi
......@@ -271,6 +267,7 @@ fi
endmenu
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......
......@@ -334,12 +334,6 @@ source drivers/block/Config.in
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
source drivers/telephony/Config.in
if [ "$CONFIG_SGI_IP22" != "y" -a \
"$CONFIG_DECSTATION" != "y" ]; then
......@@ -372,6 +366,8 @@ if [ "$CONFIG_DECSTATION" != "y" -a \
fi
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......@@ -391,6 +387,8 @@ source net/irda/Config.in
source drivers/isdn/Config.in
source drivers/telephony/Config.in
mainmenu_option next_comment
comment 'Old CD-ROM drivers (not SCSI, not IDE)'
......
......@@ -132,12 +132,6 @@ source drivers/block/Config.in
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
source drivers/telephony/Config.in
mainmenu_option next_comment
comment 'ATA/ATAPI/MFM/RLL support'
......@@ -163,6 +157,8 @@ endmenu
#source drivers/message/i2o/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......@@ -182,6 +178,8 @@ source net/irda/Config.in
source drivers/isdn/Config.in
source drivers/telephony/Config.in
mainmenu_option next_comment
comment 'Old CD-ROM drivers (not SCSI, not IDE)'
......
......@@ -99,10 +99,6 @@ endmenu
source drivers/block/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
mainmenu_option next_comment
comment 'SCSI support'
......@@ -149,6 +145,8 @@ fi
endmenu
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......
......@@ -419,10 +419,6 @@ source drivers/pnp/Config.in
source drivers/block/Config.in
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
mainmenu_option next_comment
comment 'ATA/IDE/MFM/RLL support'
......@@ -449,6 +445,8 @@ source drivers/ieee1394/Config.in
source drivers/message/i2o/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......
......@@ -87,10 +87,6 @@ source drivers/pnp/Config.in
source drivers/block/Config.in
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
mainmenu_option next_comment
comment 'ATA/ATAPI/MFM/RLL support'
......@@ -118,6 +114,8 @@ source drivers/ieee1394/Config.in
source drivers/message/i2o/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......
......@@ -207,10 +207,6 @@ source drivers/block/Config.in
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
mainmenu_option next_comment
comment 'ATA/ATAPI/MFM/RLL support'
......@@ -236,6 +232,8 @@ endmenu
source drivers/ieee1394/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......
......@@ -87,10 +87,6 @@ dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK
endmenu
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
# Don't frighten a common SBus user
if [ "$CONFIG_PCI" = "y" ]; then
......@@ -158,6 +154,8 @@ endmenu
source drivers/fc4/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......
......@@ -95,10 +95,6 @@ dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK
endmenu
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
mainmenu_option next_comment
comment 'ATA/ATAPI/MFM/RLL device support'
......@@ -207,6 +203,8 @@ fi
source drivers/ieee1394/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......
......@@ -4,6 +4,8 @@
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Based upon code written by Linus Torvalds and others.
*/
#warning "major untested changes to this file --hch (2002/08/05)"
#include <linux/slab.h>
#include <linux/vmalloc.h>
......@@ -16,6 +18,7 @@ static struct vm_struct * modvmlist = NULL;
void module_unmap (void * addr)
{
struct vm_struct **p, *tmp;
int i;
if (!addr)
return;
......@@ -23,21 +26,38 @@ void module_unmap (void * addr)
printk("Trying to unmap module with bad address (%p)\n", addr);
return;
}
for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
*p = tmp->next;
vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
kfree(tmp);
return;
}
}
printk("Trying to unmap nonexistent module vm area (%p)\n", addr);
return;
found:
unmap_vm_area(tmp);
for (i = 0; i < tmp->nr_pages; i++) {
if (unlikely(!tmp->pages[i]))
BUG();
__free_page(tmp->pages[i]);
}
kfree(tmp->pages);
kfree(tmp);
}
void * module_map (unsigned long size)
{
void * addr;
struct vm_struct **p, *tmp, *area;
struct vm_struct *area;
struct page **pages;
void * addr;
unsigned int nr_pages, array_size, i;
size = PAGE_ALIGN(size);
if (!size || size > MODULES_LEN) return NULL;
......@@ -55,11 +75,32 @@ void * module_map (unsigned long size)
area->size = size + PAGE_SIZE;
area->addr = addr;
area->next = *p;
area->pages = NULL;
area->nr_pages = 0;
area->phys_addr = 0;
*p = area;
if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, GFP_KERNEL, PAGE_KERNEL)) {
module_unmap(addr);
nr_pages = (size+PAGE_SIZE) >> PAGE_SHIFT;
array_size = (nr_pages * sizeof(struct page *));
area->nr_pages = nr_pages;
area->pages = pages = kmalloc(array_size, (gfp_mask & ~__GFP_HIGHMEM));
if (!area->pages)
return NULL;
memset(area->pages, 0, array_size);
for (i = 0; i < area->nr_pages; i++) {
area->pages[i] = alloc_page(gfp_mask);
if (unlikely(!area->pages[i]))
goto fail;
}
return addr;
if (map_vm_area(area, prot, &pages))
goto fail;
return area->addr;
fail:
vfree(area->addr);
return NULL;
}
}
......@@ -119,12 +119,6 @@ source drivers/block/Config.in
source drivers/md/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
fi
source drivers/telephony/Config.in
mainmenu_option next_comment
comment 'ATA/ATAPI/MFM/RLL support'
......@@ -155,6 +149,8 @@ source drivers/ieee1394/Config.in
#source drivers/message/i2o/Config.in
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
mainmenu_option next_comment
comment 'Network device support'
......@@ -175,6 +171,8 @@ source net/irda/Config.in
source drivers/isdn/Config.in
source drivers/telephony/Config.in
# no support for non IDE/SCSI cdroms as they were all ISA only
#
......
This diff is collapsed.
......@@ -81,7 +81,8 @@ struct ctlr_info
int nr_frees;
// Disk structures we need to pass back
struct gendisk gendisk;
struct gendisk gendisk[NWD];
char names[12 * NWD];
// indexed by minor numbers
struct hd_struct hd[256];
int sizes[256];
......
......@@ -1483,6 +1483,7 @@ static int revalidate_allvol(kdev_t dev)
if (!drv->nr_blks)
continue;
(BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->blk_size;
disk->major_name = ida_names + (ctlr*NWD+i)*10;
add_gendisk(disk);
register_disk(disk,
mk_kdev(disk->major,disk->first_minor),
......
......@@ -969,6 +969,31 @@ CONFIG_RTC
The module is called rtc.o. If you want to compile it as a module,
say M here and read <file:Documentation/modules.txt>.
Generic Real Time Clock Support
CONFIG_GEN_RTC
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
will get access to the real time clock (or hardware clock) built
into your computer.
It reports status information via the file /proc/driver/rtc and its
behaviour is set by various ioctls on /dev/rtc. If you enable the
"extended RTC operation" below it will also provide an emulation
for RTC_UIE which is required by some programs and may improve
precision in some cases.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module is called genrtc.o. If you want to compile it as a module,
say M here and read <file:Documentation/modules.txt>. To load the
module automaticaly add 'alias char-major-10-135 genrtc' to your
/etc/modules.conf
Extended RTC operation
CONFIG_GEN_RTC_X
Provides an emulation for RTC_UIE which is required by some programs
and may improve precision of the generic RTC support in some cases.
CONFIG_H8
The Hitachi H8/337 is a microcontroller used to deal with the power
and thermal environment. If you say Y here, you will be able to
......
......@@ -151,6 +151,12 @@ if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then
fi
tristate '/dev/nvram support' CONFIG_NVRAM
tristate 'Enhanced Real Time Clock Support' CONFIG_RTC
if [ "$CONFIG_RTC" != "y" ]; then
tristate 'Generic /dev/rtc emulation' CONFIG_GEN_RTC
if [ "$CONFIG_GEN_RTC" != "n" ]; then
bool ' Extended RTC operation' CONFIG_GEN_RTC_X
fi
fi
if [ "$CONFIG_IA64" = "y" ]; then
bool 'EFI Real Time Clock Services' CONFIG_EFI_RTC
fi
......
......@@ -167,6 +167,7 @@ obj-$(CONFIG_APPLICOM) += applicom.o
obj-$(CONFIG_SONYPI) += sonypi.o
obj-$(CONFIG_ATARIMOUSE) += atarimouse.o
obj-$(CONFIG_RTC) += rtc.o
obj-$(CONFIG_GEN_RTC) += genrtc.o
obj-$(CONFIG_EFI_RTC) += efirtc.o
ifeq ($(CONFIG_PPC),)
obj-$(CONFIG_NVRAM) += nvram.o
......
This diff is collapsed.
......@@ -210,6 +210,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
return 0;
}
extern long vread(char *buf, char *addr, unsigned long count);
extern long vwrite(char *buf, char *addr, unsigned long count);
/*
* This function reads the *virtual* memory as seen by the kernel.
*/
......@@ -273,8 +276,6 @@ static ssize_t read_kmem(struct file *file, char *buf,
return virtr + read;
}
extern long vwrite(char *buf, char *addr, unsigned long count);
/*
* This function writes to the *virtual* memory as seen by the kernel.
*/
......
......@@ -32,10 +32,10 @@ if [ "$CONFIG_I2C" != "n" ]; then
dep_tristate ' Embedded Planet RPX Lite/Classic suppoort' CONFIG_I2C_RPXLITE $CONFIG_I2C_ALGO8XX
fi
fi
if [ "$CONFIG_405" = "y" ]; then
dep_tristate 'PPC 405 I2C Algorithm' CONFIG_I2C_PPC405_ALGO $CONFIG_I2C
if [ "$CONFIG_I2C_PPC405_ALGO" != "n" ]; then
dep_tristate ' PPC 405 I2C Adapter' CONFIG_I2C_PPC405_ADAP $CONFIG_I2C_PPC405_ALGO
if [ "$CONFIG_IBM_OCP" = "y" ]; then
dep_tristate 'IBM on-chip I2C Algorithm' CONFIG_I2C_IBM_OCP_ALGO $CONFIG_I2C
if [ "$CONFIG_I2C_IBM_OCP_ALGO" != "n" ]; then
dep_tristate ' IBM on-chip I2C Adapter' CONFIG_I2C_IBM_OCP_ADAP $CONFIG_I2C_IBM_OCP_ALGO
fi
fi
......
......@@ -1107,7 +1107,6 @@ static void sym_eh_timeout(u_long p) { __sym_eh_done((Scsi_Cmnd *)p, 1); }
static int sym_eh_handler(int op, char *opname, Scsi_Cmnd *cmd)
{
hcb_p np = SYM_SOFTC_PTR(cmd);
unsigned long flags;
SYM_QUEHEAD *qp;
int to_do = SYM_EH_DO_IGNORE;
int sts = -1;
......@@ -1118,8 +1117,6 @@ static int sym_eh_handler(int op, char *opname, Scsi_Cmnd *cmd)
printf_warning("%s: %s operation started.\n", devname, opname);
SYM_LOCK_HCB(np, flags);
#if 0
/* This one should be the result of some race, thus to ignore */
if (cmd->serial_number != cmd->serial_number_at_timeout)
......@@ -1198,8 +1195,6 @@ static int sym_eh_handler(int op, char *opname, Scsi_Cmnd *cmd)
if (to_do == SYM_EH_DO_COMPLETE)
sym_xpt_done2(np, cmd, CAM_REQ_ABORTED);
SYM_UNLOCK_HCB(np, flags);
/* Wait for completion with locks released, as required by kernel */
if (to_do == SYM_EH_DO_WAIT) {
init_timer(&ep->timer);
......
......@@ -2,10 +2,10 @@
# Makefile for USB Core files and filesystem
#
export-objs := usb.o hcd.o hcd-pci.o urb.o message.o file.o
export-objs := usb.o hcd.o hcd-pci.o urb.o message.o file.o buffer.o
usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \
config.o file.o
config.o file.o buffer.o
ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o
......
/*
* DMA memory management for framework level HCD code (hc_driver)
*
* This implementation plugs in through generic "usb_bus" level methods,
* and works with real PCI, or when "pci device == null" makes sense.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pci.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h>
#include "hcd.h"
/*
* DMA-Consistent Buffers
*/
/* FIXME tune these based on pool statistics ... */
static const size_t pool_max [HCD_BUFFER_POOLS] = {
32,
128,
512,
PAGE_SIZE / 2
/* bigger --> allocate pages */
};
/* SETUP primitives */
/**
* hcd_buffer_create - initialize buffer pools
* @hcd: the bus whose buffer pools are to be initialized
*
* Call this as part of initializing a host controller that uses the pci dma
* memory allocators. It initializes some pools of dma-consistent memory that
* will be shared by all drivers using that controller, or returns a negative
* errno value on error.
*
* Call hcd_buffer_destroy() to clean up after using those pools.
*/
int hcd_buffer_create (struct usb_hcd *hcd)
{
char name [16];
int i, size;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (!(size = pool_max [i]))
continue;
snprintf (name, sizeof name, "buffer-%d", size);
hcd->pool [i] = pci_pool_create (name, hcd->pdev,
size, size, 0, SLAB_KERNEL);
if (!hcd->pool [i]) {
hcd_buffer_destroy (hcd);
return -ENOMEM;
}
}
return 0;
}
EXPORT_SYMBOL (hcd_buffer_create);
/**
* hcd_buffer_destroy - deallocate buffer pools
* @hcd: the bus whose buffer pools are to be destroyed
*
* This frees the buffer pools created by hcd_buffer_create().
*/
void hcd_buffer_destroy (struct usb_hcd *hcd)
{
int i;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
struct pci_pool *pool = hcd->pool [i];
if (pool) {
pci_pool_destroy (pool);
hcd->pool [i] = 0;
}
}
}
EXPORT_SYMBOL (hcd_buffer_destroy);
/* sometimes alloc/free could use kmalloc with SLAB_DMA, for
* better sharing and to leverage mm/slab.c intelligence.
*/
void *hcd_buffer_alloc (
struct usb_bus *bus,
size_t size,
int mem_flags,
dma_addr_t *dma
)
{
struct usb_hcd *hcd = bus->hcpriv;
int i;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (size <= pool_max [i])
return pci_pool_alloc (hcd->pool [i], mem_flags, dma);
}
return pci_alloc_consistent (hcd->pdev, size, dma);
}
void hcd_buffer_free (
struct usb_bus *bus,
size_t size,
void *addr,
dma_addr_t dma
)
{
struct usb_hcd *hcd = bus->hcpriv;
int i;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (size <= pool_max [i]) {
pci_pool_free (hcd->pool [i], addr, dma);
return;
}
}
pci_free_consistent (hcd->pdev, size, addr, dma);
}
/*
* DMA-Mappings for arbitrary memory buffers
*/
int hcd_buffer_map (
struct usb_bus *bus,
void *addr,
dma_addr_t *dma,
size_t size,
int direction
) {
struct usb_hcd *hcd = bus->hcpriv;
// FIXME pci_map_single() has no standard failure mode!
*dma = pci_map_single (hcd->pdev, addr, size,
(direction == USB_DIR_IN)
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
return 0;
}
void hcd_buffer_dmasync (
struct usb_bus *bus,
dma_addr_t dma,
size_t size,
int direction
) {
struct usb_hcd *hcd = bus->hcpriv;
pci_dma_sync_single (hcd->pdev, dma, size,
(direction == USB_DIR_IN)
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
}
void hcd_buffer_unmap (
struct usb_bus *bus,
dma_addr_t dma,
size_t size,
int direction
) {
struct usb_hcd *hcd = bus->hcpriv;
pci_unmap_single (hcd->pdev, dma, size,
(direction == USB_DIR_IN)
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
}
// FIXME DMA-Mappings for struct scatterlist
......@@ -130,10 +130,19 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
return retval;
}
}
pci_set_drvdata(dev, hcd);
pci_set_drvdata (dev, hcd);
hcd->driver = driver;
hcd->description = driver->description;
hcd->pdev = dev;
hcd->self.bus_name = dev->slot_name;
hcd->product_desc = dev->name;
if ((retval = hcd_buffer_create (hcd)) != 0) {
clean_3:
driver->hcd_free (hcd);
goto clean_2;
}
info ("%s @ %s, %s", hcd->description, dev->slot_name, dev->name);
pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
......@@ -154,8 +163,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
!= 0) {
err ("request interrupt %s failed", bufp);
retval = -EBUSY;
driver->hcd_free (hcd);
goto clean_2;
goto clean_3;
}
hcd->irq = dev->irq;
......@@ -168,8 +176,6 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
usb_bus_init (&hcd->self);
hcd->self.op = &usb_hcd_operations;
hcd->self.hcpriv = (void *) hcd;
hcd->self.bus_name = dev->slot_name;
hcd->product_desc = dev->name;
INIT_LIST_HEAD (&hcd->dev_list);
......@@ -216,6 +222,7 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
usb_disconnect (&hub);
hcd->driver->stop (hcd);
hcd_buffer_destroy (hcd);
hcd->state = USB_STATE_HALT;
free_irq (hcd->irq, hcd);
......
......@@ -454,7 +454,6 @@ static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb)
/* rh_timer protected by hcd_data_lock */
if (timer_pending (&hcd->rh_timer)
|| urb->status != -EINPROGRESS
|| !HCD_IS_RUNNING (hcd->state)
|| urb->transfer_buffer_length < len) {
dbg ("not queuing status urb, stat %d", urb->status);
return -EINVAL;
......@@ -508,8 +507,12 @@ static void rh_report_status (unsigned long ptr)
BUG ();
}
spin_unlock_irqrestore (&hcd_data_lock, flags);
} else
} else {
spin_unlock_irqrestore (&urb->lock, flags);
spin_lock_irqsave (&hcd_data_lock, flags);
rh_status_urb (hcd, urb);
spin_unlock_irqrestore (&hcd_data_lock, flags);
}
} else {
/* this urb's been unlinked */
urb->hcpriv = 0;
......@@ -1245,6 +1248,11 @@ struct usb_operations usb_hcd_operations = {
.submit_urb = hcd_submit_urb,
.unlink_urb = hcd_unlink_urb,
.deallocate = hcd_free_dev,
.buffer_alloc = hcd_buffer_alloc,
.buffer_free = hcd_buffer_free,
.buffer_map = hcd_buffer_map,
.buffer_dmasync = hcd_buffer_dmasync,
.buffer_unmap = hcd_buffer_unmap,
};
EXPORT_SYMBOL (usb_hcd_operations);
......
......@@ -58,6 +58,9 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
atomic_t resume_count; /* multiple resumes issue */
#endif
#define HCD_BUFFER_POOLS 4
struct pci_pool *pool [HCD_BUFFER_POOLS];
int state;
# define __ACTIVE 0x01
# define __SLEEPY 0x02
......@@ -109,6 +112,25 @@ struct usb_operations {
int (*get_frame_number) (struct usb_device *usb_dev);
int (*submit_urb) (struct urb *urb, int mem_flags);
int (*unlink_urb) (struct urb *urb);
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
int mem_flags,
dma_addr_t *dma);
void (*buffer_free)(struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
int (*buffer_map) (struct usb_bus *bus,
void *addr, dma_addr_t *dma,
size_t size, int direction);
void (*buffer_dmasync) (struct usb_bus *bus,
dma_addr_t dma,
size_t size, int direction);
void (*buffer_unmap) (struct usb_bus *bus,
dma_addr_t dma,
size_t size, int direction);
// FIXME also: buffer_sg_map (), buffer_sg_unmap ()
};
/* each driver provides one of these, and hardware init support */
......@@ -181,6 +203,25 @@ extern int usb_hcd_pci_resume (struct pci_dev *dev);
#endif /* CONFIG_PCI */
/* pci-ish (pdev null is ok) buffer alloc/mapping support */
int hcd_buffer_create (struct usb_hcd *hcd);
void hcd_buffer_destroy (struct usb_hcd *hcd);
void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
int mem_flags, dma_addr_t *dma);
void hcd_buffer_free (struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
int hcd_buffer_map (struct usb_bus *bus,
void *addr, dma_addr_t *dma,
size_t size, int direction);
void hcd_buffer_dmasync (struct usb_bus *bus,
dma_addr_t dma,
size_t size, int direction);
void hcd_buffer_unmap (struct usb_bus *bus,
dma_addr_t dma,
size_t size, int direction);
/* generic bus glue, needed for host controllers that don't use PCI */
extern struct usb_operations usb_hcd_operations;
extern void usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
......
......@@ -863,9 +863,11 @@ static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t
return 0;
udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE);
len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE);
if (len < 0)
return 0;
buf[len] = '\n';
buf[len+1] = 0x00;
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(product,"product",S_IRUGO,show_product,NULL);
......@@ -881,9 +883,11 @@ show_manufacturer (struct device *dev, char *buf, size_t count, loff_t off)
return 0;
udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE);
len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE);
if (len < 0)
return 0;
buf[len] = '\n';
buf[len+1] = 0x00;
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(manufacturer,"manufacturer",S_IRUGO,show_manufacturer,NULL);
......@@ -899,9 +903,11 @@ show_serial (struct device *dev, char *buf, size_t count, loff_t off)
return 0;
udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE);
len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE);
if (len < 0)
return 0;
buf[len] = '\n';
buf[len+1] = 0x00;
buf[len+1] = 0;
return len+1;
}
static DEVICE_ATTR(serial,"serial",S_IRUGO,show_serial,NULL);
......@@ -918,13 +924,13 @@ static void usb_find_drivers(struct usb_device *dev)
unsigned claimed = 0;
/* FIXME should get called for each new configuration not just the
* first one for a device. switching configs (or altesettings) should
* first one for a device. switching configs (or altsettings) should
* undo driverfs and HCD state for the previous interfaces.
*/
for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {
struct usb_interface *interface = &dev->actconfig->interface[ifnum];
struct usb_interface_descriptor *desc = interface->altsetting;
/* register this interface with driverfs */
interface->dev.parent = &dev->dev;
interface->dev.bus = &usb_bus_type;
......@@ -1455,6 +1461,152 @@ int usb_new_device(struct usb_device *dev)
}
/**
* usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_DMA_MAP
* @dev: device the buffer will be used with
* @size: requested buffer size
* @mem_flags: affect whether allocation may block
* @dma: used to return DMA address of buffer
*
* Return value is either null (indicating no buffer could be allocated), or
* the cpu-space pointer to a buffer that may be used to perform DMA to the
* specified device. Such cpu-space buffers are returned along with the DMA
* address (through the pointer provided).
*
* These buffers are used with URB_NO_DMA_MAP set in urb->transfer_flags to
* avoid behaviors like using "DMA bounce buffers", or tying down I/O mapping
* hardware for long idle periods. The implementation varies between
* platforms, depending on details of how DMA will work to this device.
*
* When the buffer is no longer used, free it with usb_buffer_free().
*/
void *usb_buffer_alloc (
struct usb_device *dev,
size_t size,
int mem_flags,
dma_addr_t *dma
)
{
if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_alloc)
return 0;
return dev->bus->op->buffer_alloc (dev->bus, size, mem_flags, dma);
}
/**
* usb_buffer_free - free memory allocated with usb_buffer_alloc()
* @dev: device the buffer was used with
* @size: requested buffer size
* @addr: CPU address of buffer
* @dma: DMA address of buffer
*
* This reclaims an I/O buffer, letting it be reused. The memory must have
* been allocated using usb_buffer_alloc(), and the parameters must match
* those provided in that allocation request.
*/
void usb_buffer_free (
struct usb_device *dev,
size_t size,
void *addr,
dma_addr_t dma
)
{
if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_free)
return;
dev->bus->op->buffer_free (dev->bus, size, addr, dma);
}
/**
* usb_buffer_map - create DMA mapping(s) for an urb
* @urb: urb whose transfer_buffer will be mapped
*
* Return value is either null (indicating no buffer could be mapped), or
* the parameter. URB_NO_DMA_MAP is added to urb->transfer_flags if the
* operation succeeds.
*
* This call would normally be used for an urb which is reused, perhaps
* as the target of a large periodic transfer, with usb_buffer_dmasync()
* calls to synchronize memory and dma state. It may not be used for
* control requests.
*
* Reverse the effect of this call with usb_buffer_unmap().
*/
struct urb *usb_buffer_map (struct urb *urb)
{
struct usb_bus *bus;
struct usb_operations *op;
if (!urb
|| usb_pipecontrol (urb->pipe)
|| !urb->dev
|| !(bus = urb->dev->bus)
|| !(op = bus->op)
|| !op->buffer_map)
return 0;
if (op->buffer_map (bus,
urb->transfer_buffer,
&urb->transfer_dma,
urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? USB_DIR_IN
: USB_DIR_OUT))
return 0;
urb->transfer_flags |= URB_NO_DMA_MAP;
return urb;
}
/**
* usb_buffer_dmasync - synchronize DMA and CPU view of buffer(s)
* @urb: urb whose transfer_buffer will be synchronized
*/
void usb_buffer_dmasync (struct urb *urb)
{
struct usb_bus *bus;
struct usb_operations *op;
if (!urb
|| !(urb->transfer_flags & URB_NO_DMA_MAP)
|| !urb->dev
|| !(bus = urb->dev->bus)
|| !(op = bus->op)
|| !op->buffer_dmasync)
return;
op->buffer_dmasync (bus,
urb->transfer_dma,
urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? USB_DIR_IN
: USB_DIR_OUT);
}
/**
* usb_buffer_unmap - free DMA mapping(s) for an urb
* @urb: urb whose transfer_buffer will be unmapped
*
* Reverses the effect of usb_buffer_map().
*/
void usb_buffer_unmap (struct urb *urb)
{
struct usb_bus *bus;
struct usb_operations *op;
if (!urb
|| !(urb->transfer_flags & URB_NO_DMA_MAP)
|| !urb->dev
|| !(bus = urb->dev->bus)
|| !(op = bus->op)
|| !op->buffer_unmap)
return;
op->buffer_unmap (bus,
urb->transfer_dma,
urb->transfer_buffer_length,
usb_pipein (urb->pipe)
? USB_DIR_IN
: USB_DIR_OUT);
}
#ifdef CONFIG_PROC_FS
struct list_head *usb_driver_get_list(void)
{
......@@ -1534,4 +1686,11 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_get_current_frame_number);
EXPORT_SYMBOL (usb_buffer_alloc);
EXPORT_SYMBOL (usb_buffer_free);
EXPORT_SYMBOL (usb_buffer_map);
EXPORT_SYMBOL (usb_buffer_dmasync);
EXPORT_SYMBOL (usb_buffer_unmap);
MODULE_LICENSE("GPL");
/*
* Copyright (c) 2001 by David Brownell
* Copyright (c) 2001-2002 by David Brownell
*
* 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
......@@ -175,3 +175,215 @@ dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) {}
(status & PORT_CONNECT) ? " CONNECT" : "" \
)
#ifdef DEBUG
#define speed_char(info1) ({ char tmp; \
switch (info1 & (3 << 12)) { \
case 0 << 12: tmp = 'f'; break; \
case 1 << 12: tmp = 'l'; break; \
case 2 << 12: tmp = 'h'; break; \
default: tmp = '?'; break; \
}; tmp; })
static ssize_t
show_async (struct device *dev, char *buf, size_t count, loff_t off)
{
struct pci_dev *pdev;
struct ehci_hcd *ehci;
unsigned long flags;
unsigned temp, size;
char *next;
struct ehci_qh *qh;
if (off != 0)
return 0;
pdev = container_of (dev, struct pci_dev, dev);
ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
next = buf;
size = count;
/* dumps a snapshot of the async schedule.
* usually empty except for long-term bulk reads, or head.
* one QH per line, and TDs we know about
*/
spin_lock_irqsave (&ehci->lock, flags);
if (ehci->async) {
qh = ehci->async;
do {
u32 scratch;
struct list_head *entry;
struct ehci_qtd *td;
scratch = cpu_to_le32p (&qh->hw_info1);
temp = snprintf (next, size, "qh %p dev%d %cs ep%d",
qh, scratch & 0x007f,
speed_char (scratch),
(scratch >> 8) & 0x000f);
size -= temp;
next += temp;
list_for_each (entry, &qh->qtd_list) {
td = list_entry (entry, struct ehci_qtd,
qtd_list);
scratch = cpu_to_le32p (&td->hw_token);
temp = snprintf (next, size,
", td %p len=%d %s",
td, scratch >> 16,
({ char *tmp;
switch ((scratch>>8)&0x03) {
case 0: tmp = "out"; break;
case 1: tmp = "in"; break;
case 2: tmp = "setup"; break;
default: tmp = "?"; break;
} tmp;})
);
size -= temp;
next += temp;
}
temp = snprintf (next, size, "\n");
size -= temp;
next += temp;
} while ((qh = qh->qh_next.qh) != ehci->async);
}
spin_unlock_irqrestore (&ehci->lock, flags);
return count - size;
}
static DEVICE_ATTR (async, "sched-async", S_IRUSR, show_async, NULL);
#define DBG_SCHED_LIMIT 64
static ssize_t
show_periodic (struct device *dev, char *buf, size_t count, loff_t off)
{
struct pci_dev *pdev;
struct ehci_hcd *ehci;
unsigned long flags;
union ehci_shadow p, *seen;
unsigned temp, size, seen_count;
char *next;
unsigned i, tag;
if (off != 0)
return 0;
if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC)))
return 0;
seen_count = 0;
pdev = container_of (dev, struct pci_dev, dev);
ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
next = buf;
size = count;
temp = snprintf (next, size, "size = %d\n", ehci->periodic_size);
size -= temp;
next += temp;
/* dump a snapshot of the periodic schedule.
* iso changes, interrupt usually doesn't.
*/
spin_lock_irqsave (&ehci->lock, flags);
for (i = 0; i < ehci->periodic_size; i++) {
p = ehci->pshadow [i];
if (!p.ptr)
continue;
tag = Q_NEXT_TYPE (ehci->periodic [i]);
temp = snprintf (next, size, "%4d: ", i);
size -= temp;
next += temp;
do {
switch (tag) {
case Q_TYPE_QH:
temp = snprintf (next, size, " intr-%d %p",
p.qh->period, p.qh);
size -= temp;
next += temp;
for (temp = 0; temp < seen_count; temp++) {
if (seen [temp].ptr == p.ptr)
break;
}
/* show more info the first time around */
if (temp == seen_count) {
u32 scratch = cpu_to_le32p (
&p.qh->hw_info1);
temp = snprintf (next, size,
" (%cs dev%d ep%d)",
speed_char (scratch),
scratch & 0x007f,
(scratch >> 8) & 0x000f);
/* FIXME TDs too */
if (seen_count < DBG_SCHED_LIMIT)
seen [seen_count++].qh = p.qh;
} else
temp = 0;
tag = Q_NEXT_TYPE (p.qh->hw_next);
p = p.qh->qh_next;
break;
case Q_TYPE_FSTN:
temp = snprintf (next, size,
" fstn-%8x/%p", p.fstn->hw_prev,
p.fstn);
tag = Q_NEXT_TYPE (p.fstn->hw_next);
p = p.fstn->fstn_next;
break;
case Q_TYPE_ITD:
temp = snprintf (next, size,
" itd/%p", p.itd);
tag = Q_NEXT_TYPE (p.itd->hw_next);
p = p.itd->itd_next;
break;
case Q_TYPE_SITD:
temp = snprintf (next, size,
" sitd/%p", p.sitd);
tag = Q_NEXT_TYPE (p.sitd->hw_next);
p = p.sitd->sitd_next;
break;
}
size -= temp;
next += temp;
} while (p.ptr);
temp = snprintf (next, size, "\n");
size -= temp;
next += temp;
}
spin_unlock_irqrestore (&ehci->lock, flags);
kfree (seen);
return count - size;
}
static DEVICE_ATTR (periodic, "sched-periodic", S_IRUSR, show_periodic, NULL);
#undef DBG_SCHED_LIMIT
static inline void create_debug_files (struct ehci_hcd *bus)
{
device_create_file (&bus->hcd.pdev->dev, &dev_attr_async);
device_create_file (&bus->hcd.pdev->dev, &dev_attr_periodic);
}
static inline void remove_debug_files (struct ehci_hcd *bus)
{
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_async);
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_periodic);
}
#else /* DEBUG */
static inline void create_debug_files (struct ehci_hcd *bus)
{
}
static inline void remove_debug_files (struct ehci_hcd *bus)
{
}
#endif /* DEBUG */
......@@ -65,6 +65,8 @@
*
* HISTORY:
*
* 2002-08-06 Handling for bulk and interrupt transfers is mostly shared;
* only scheduling is different, no arbitrary limitations.
* 2002-07-25 Sanity check PCI reads, mostly for better cardbus support,
* clean up HC run state handshaking.
* 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts
......@@ -85,7 +87,7 @@
* 2001-June Works with usb-storage and NEC EHCI on 2.4
*/
#define DRIVER_VERSION "2002-Jul-25"
#define DRIVER_VERSION "2002-Aug-06"
#define DRIVER_AUTHOR "David Brownell"
#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
......@@ -93,6 +95,8 @@
// #define EHCI_VERBOSE_DEBUG
// #define have_split_iso
#define INTR_AUTOMAGIC /* to be removed later in 2.5 */
/* magic numbers that can affect system performance */
#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
#define EHCI_TUNE_RL_HS 0 /* nak throttle; see 4.9 */
......@@ -376,6 +380,8 @@ static int ehci_start (struct usb_hcd *hcd)
return -ENOMEM;
}
create_debug_files (ehci);
/*
* Start, enabling full USB 2.0 functionality ... usb 1.1 devices
* are explicitly handed to companion controller(s), so no TT is
......@@ -429,6 +435,8 @@ static void ehci_stop (struct usb_hcd *hcd)
ehci_ready (ehci);
ehci_reset (ehci);
remove_debug_files (ehci);
/* root hub is shut down separately (first, when possible) */
tasklet_disable (&ehci->tasklet);
ehci_tasklet ((unsigned long) ehci);
......@@ -614,7 +622,8 @@ static void ehci_irq (struct usb_hcd *hcd)
*
* hcd-specific init for hcpriv hasn't been done yet
*
* NOTE: EHCI queues control and bulk requests transparently, like OHCI.
* NOTE: control, bulk, and interrupt share the same code to append TDs
* to a (possibly active) QH, and the same QH scanning code.
*/
static int ehci_urb_enqueue (
struct usb_hcd *hcd,
......@@ -626,10 +635,11 @@ static int ehci_urb_enqueue (
urb->transfer_flags &= ~EHCI_STATE_UNLINK;
INIT_LIST_HEAD (&qtd_list);
switch (usb_pipetype (urb->pipe)) {
case PIPE_CONTROL:
case PIPE_BULK:
switch (usb_pipetype (urb->pipe)) {
// case PIPE_CONTROL:
// case PIPE_BULK:
default:
if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
return -ENOMEM;
return submit_async (ehci, urb, &qtd_list, mem_flags);
......@@ -649,9 +659,6 @@ static int ehci_urb_enqueue (
dbg ("no split iso support yet");
return -ENOSYS;
#endif /* have_split_iso */
default: /* can't happen */
return -ENOSYS;
}
}
......@@ -665,15 +672,16 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
unsigned long flags;
dbg ("%s urb_dequeue %p qh state %d",
hcd->self.bus_name, urb, qh->qh_state);
dbg ("%s urb_dequeue %p qh %p state %d",
hcd->self.bus_name, urb, qh, qh->qh_state);
switch (usb_pipetype (urb->pipe)) {
case PIPE_CONTROL:
case PIPE_BULK:
// case PIPE_CONTROL:
// case PIPE_BULK:
default:
spin_lock_irqsave (&ehci->lock, flags);
if (ehci->reclaim) {
dbg ("dq: reclaim busy, %s", RUN_CONTEXT);
dbg ("dq: reclaim busy, %s", RUN_CONTEXT);
if (in_interrupt ()) {
spin_unlock_irqrestore (&ehci->lock, flags);
return -EAGAIN;
......@@ -683,28 +691,43 @@ dbg ("dq: reclaim busy, %s", RUN_CONTEXT);
&& ehci->hcd.state != USB_STATE_HALT
) {
spin_unlock_irqrestore (&ehci->lock, flags);
// yeech ... this could spin for up to two frames!
dbg ("wait for dequeue: state %d, reclaim %p, hcd state %d",
qh->qh_state, ehci->reclaim, ehci->hcd.state
);
udelay (100);
/* let pending unlinks complete */
wait_ms (1);
spin_lock_irqsave (&ehci->lock, flags);
}
}
if (qh->qh_state == QH_STATE_LINKED)
start_unlink_async (ehci, qh);
spin_unlock_irqrestore (&ehci->lock, flags);
return 0;
break;
case PIPE_INTERRUPT:
intr_deschedule (ehci, urb->start_frame, qh,
(urb->dev->speed == USB_SPEED_HIGH)
? urb->interval
: (urb->interval << 3));
if (ehci->hcd.state == USB_STATE_HALT)
urb->status = -ESHUTDOWN;
qh_completions (ehci, qh, 1);
return 0;
if (qh->qh_state == QH_STATE_LINKED) {
/* messy, can spin or block a microframe ... */
intr_deschedule (ehci, qh, 1);
/* qh_state == IDLE */
}
qh_completions (ehci, qh);
/* reschedule QH iff another request is queued */
if (!list_empty (&qh->qtd_list)
&& HCD_IS_RUNNING (ehci->hcd.state)) {
int status;
spin_lock_irqsave (&ehci->lock, flags);
status = qh_schedule (ehci, qh);
spin_unlock_irqrestore (&ehci->lock, flags);
if (status != 0) {
// shouldn't happen often, but ...
// FIXME kill those tds' urbs
err ("can't reschedule qh %p, err %d",
qh, status);
}
return status;
}
break;
case PIPE_ISOCHRONOUS:
// itd or sitd ...
......@@ -712,9 +735,9 @@ dbg ("wait for dequeue: state %d, reclaim %p, hcd state %d",
// wait till next completion, do it then.
// completion irqs can wait up to 1024 msec,
urb->transfer_flags |= EHCI_STATE_UNLINK;
return 0;
break;
}
return -EINVAL;
return 0;
}
/*-------------------------------------------------------------------------*/
......@@ -728,6 +751,7 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
int i;
unsigned long flags;
/* ASSERT: no requests/urbs are still linked (so no TDs) */
/* ASSERT: nobody can be submitting urbs for this any more */
dbg ("%s: free_config devnum %d", hcd->self.bus_name, udev->devnum);
......@@ -736,34 +760,57 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
for (i = 0; i < 32; i++) {
if (dev->ep [i]) {
struct ehci_qh *qh;
char *why;
/* dev->ep never has ITDs or SITDs */
qh = (struct ehci_qh *) dev->ep [i];
vdbg ("free_config, ep 0x%02x qh %p", i, qh);
if (!list_empty (&qh->qtd_list)) {
dbg ("ep 0x%02x qh %p not empty!", i, qh);
/* detect/report non-recoverable errors */
if (in_interrupt ())
why = "disconnect() didn't";
else if ((qh->hw_info2 & cpu_to_le32 (0xffff)) != 0
&& qh->qh_state != QH_STATE_IDLE)
why = "(active periodic)";
else
why = 0;
if (why) {
err ("dev %s-%s ep %d-%s error: %s",
hcd->self.bus_name, udev->devpath,
i & 0xf, (i & 0x10) ? "IN" : "OUT",
why);
BUG ();
}
dev->ep [i] = 0;
/* wait_ms() won't spin here -- we're a thread */
dev->ep [i] = 0;
if (qh->qh_state == QH_STATE_IDLE)
goto idle;
dbg ("free_config, async ep 0x%02x qh %p", i, qh);
/* scan_async() empties the ring as it does its work,
* using IAA, but doesn't (yet?) turn it off. if it
* doesn't empty this qh, likely it's the last entry.
*/
while (qh->qh_state == QH_STATE_LINKED
&& ehci->reclaim
&& ehci->hcd.state != USB_STATE_HALT
) {
spin_unlock_irqrestore (&ehci->lock, flags);
/* wait_ms() won't spin, we're a thread;
* and we know IRQ+tasklet can progress
*/
wait_ms (1);
spin_lock_irqsave (&ehci->lock, flags);
}
if (qh->qh_state == QH_STATE_LINKED) {
if (qh->qh_state == QH_STATE_LINKED)
start_unlink_async (ehci, qh);
while (qh->qh_state != QH_STATE_IDLE) {
spin_unlock_irqrestore (&ehci->lock,
flags);
wait_ms (1);
spin_lock_irqsave (&ehci->lock, flags);
}
while (qh->qh_state != QH_STATE_IDLE
&& ehci->hcd.state != USB_STATE_HALT) {
spin_unlock_irqrestore (&ehci->lock,
flags);
wait_ms (1);
spin_lock_irqsave (&ehci->lock, flags);
}
idle:
qh_put (ehci, qh);
}
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -50,7 +50,7 @@ struct ehci_hcd { /* one per controller */
union ehci_shadow *pshadow; /* mirror hw periodic table */
int next_uframe; /* scan periodic, start here */
unsigned periodic_urbs; /* how many urbs scheduled? */
unsigned periodic_sched; /* periodic activity count */
/* deferred work from IRQ, etc */
struct tasklet_struct tasklet;
......@@ -72,7 +72,7 @@ struct ehci_hcd { /* one per controller */
};
/* unwrap an HCD pointer to get an EHCI_HCD pointer */
#define hcd_to_ehci(hcd_ptr) list_entry(hcd_ptr, struct ehci_hcd, hcd)
#define hcd_to_ehci(hcd_ptr) container_of(hcd_ptr, struct ehci_hcd, hcd)
/* NOTE: urb->transfer_flags expected to not use this bit !!! */
#define EHCI_STATE_UNLINK 0x8000 /* urb being unlinked */
......@@ -287,12 +287,20 @@ struct ehci_qh {
struct list_head qtd_list; /* sw qtd list */
atomic_t refcount;
unsigned short usecs; /* intr bandwidth */
unsigned short c_usecs; /* ... split completion bw */
short qh_state;
u8 qh_state;
#define QH_STATE_LINKED 1 /* HC sees this */
#define QH_STATE_UNLINK 2 /* HC may still see this */
#define QH_STATE_IDLE 3 /* HC doesn't see this */
/* periodic schedule info */
u8 usecs; /* intr bandwidth */
u8 gap_uf; /* uframes split/csplit gap */
u8 c_usecs; /* ... split completion bw */
unsigned short period; /* polling interval */
unsigned short start; /* where polling starts */
#define NO_FRAME ((unsigned short)~0) /* pick new start */
} __attribute__ ((aligned (32)));
/*-------------------------------------------------------------------------*/
......
......@@ -938,7 +938,7 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick)
/* ED's now officially unlinked, hc doesn't see */
ed->state = ED_IDLE;
ed->hwINFO &= ~ED_SKIP;
ed->hwHeadP &= ~cpu_to_le32 (ED_H);
ed->hwHeadP &= ~ED_H;
ed->hwNextED = 0;
/* but if there's work queued, reschedule */
......
This diff is collapsed.
......@@ -41,10 +41,6 @@
#include <linux/ticable.h>
#include "tiglusb.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
# define minor(x) MINOR(x)
#endif
/*
* Version Information
*/
......
// Portions of this file taken from
// Portions of this file taken from
// Petko Manolov - Petkan (petkan@dce.bg)
// from his driver pegasus.c
......@@ -1170,23 +1170,20 @@ static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
if (rc) {
// Nope we couldn't find one we liked.
// This device was not meant for us to control.
kfree( ether_dev );
return NULL;
goto error_all;
}
// Now that we FOUND a configuration. let's try to make the
// Now that we FOUND a configuration. let's try to make the
// device go into it.
if ( usb_set_configuration( usb, ether_dev->bConfigurationValue ) ) {
err("usb_set_configuration() failed");
kfree( ether_dev );
return NULL;
goto error_all;
}
// Now set the communication interface up as required.
if (usb_set_interface(usb, ether_dev->comm_bInterfaceNumber, ether_dev->comm_bAlternateSetting)) {
err("usb_set_interface() failed");
kfree( ether_dev );
return NULL;
goto error_all;
}
// Only turn traffic on right now if we must...
......@@ -1194,23 +1191,21 @@ static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
// We found an alternate setting for the data
// interface that allows us to turn off traffic.
// We should use it.
if (usb_set_interface( usb,
ether_dev->data_bInterfaceNumber,
if (usb_set_interface( usb,
ether_dev->data_bInterfaceNumber,
ether_dev->data_bAlternateSetting_without_traffic)) {
err("usb_set_interface() failed");
kfree( ether_dev );
return NULL;
goto error_all;
}
} else {
// We didn't find an alternate setting for the data
// interface that would let us turn off traffic.
// Oh well, let's go ahead and do what we must...
if (usb_set_interface( usb,
ether_dev->data_bInterfaceNumber,
if (usb_set_interface( usb,
ether_dev->data_bInterfaceNumber,
ether_dev->data_bAlternateSetting_with_traffic)) {
err("usb_set_interface() failed");
kfree( ether_dev );
return NULL;
goto error_all;
}
}
......@@ -1220,8 +1215,7 @@ static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
// Hmm... The kernel is not sharing today...
// Fine, we didn't want it anyway...
err( "Unable to initialize ethernet device" );
kfree( ether_dev );
return NULL;
goto error_all;
}
// Now that we have an ethernet device, let's set it up
......@@ -1241,7 +1235,7 @@ static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
// We'll keep track of this information for later...
ether_dev->usb = usb;
ether_dev->net = net;
// and don't forget the MAC address.
set_ethernet_addr( ether_dev );
......@@ -1249,12 +1243,12 @@ static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
log_device_info( ether_dev );
// I claim this interface to be a CDC Ethernet Networking device
usb_driver_claim_interface( &CDCEther_driver,
&(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]),
usb_driver_claim_interface( &CDCEther_driver,
&(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]),
ether_dev );
// I claim this interface to be a CDC Ethernet Networking device
usb_driver_claim_interface( &CDCEther_driver,
&(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]),
usb_driver_claim_interface( &CDCEther_driver,
&(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]),
ether_dev );
// Does this REALLY do anything???
......@@ -1265,6 +1259,14 @@ static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
// Okay, we are finally done...
return NULL;
// bailing out with our tail between our knees
error_all:
usb_free_urb(ether_dev->tx_urb);
usb_free_urb(ether_dev->rx_urb);
usb_free_urb(ether_dev->intr_urb);
kfree( ether_dev );
return NULL;
}
......
......@@ -147,7 +147,8 @@ static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
srb->host_scribble = (unsigned char *)us;
/* enqueue the command */
BUG_ON(atomic_read(&us->sm_state) != US_STATE_IDLE || us->srb != NULL);
BUG_ON(atomic_read(&us->sm_state) != US_STATE_IDLE);
BUG_ON(us->srb != NULL);
srb->scsi_done = done;
us->srb = srb;
......
......@@ -203,16 +203,9 @@ extern void fill_inquiry_response(struct us_data *us,
/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the
* single queue element srb for write access */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3)
#define scsi_unlock(host) spin_unlock_irq(host->host_lock)
#define scsi_lock(host) spin_lock_irq(host->host_lock)
#define sg_address(psg) (page_address((psg)->page) + (psg)->offset)
#else
#define scsi_unlock(host) spin_unlock_irq(&io_request_lock)
#define scsi_lock(host) spin_lock_irq(&io_request_lock)
#define sg_address(psg) ((psg)->address)
#endif
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment